diff --git a/pandatool/CMakeLists.txt b/pandatool/CMakeLists.txt deleted file mode 100644 index 8db045f4..00000000 --- a/pandatool/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -if(NOT BUILD_PANDA) - message(FATAL_ERROR "Cannot build pandatool without panda! Please enable the BUILD_PANDA option.") -endif() - -# Include pandatool source directories -add_subdirectory(src/assimp) -add_subdirectory(src/bam) -add_subdirectory(src/converter) -add_subdirectory(src/daeegg) -add_subdirectory(src/daeprogs) -add_subdirectory(src/deploy-stub) -add_subdirectory(src/dxf) -add_subdirectory(src/dxfegg) -add_subdirectory(src/dxfprogs) -add_subdirectory(src/eggbase) -add_subdirectory(src/eggcharbase) -add_subdirectory(src/eggprogs) -add_subdirectory(src/egg-mkfont) -add_subdirectory(src/egg-optchar) -add_subdirectory(src/egg-palettize) -add_subdirectory(src/egg-qtess) -add_subdirectory(src/flt) -add_subdirectory(src/fltegg) -add_subdirectory(src/fltprogs) -add_subdirectory(src/gtk-stats) -add_subdirectory(src/imagebase) -add_subdirectory(src/imageprogs) -add_subdirectory(src/lwo) -add_subdirectory(src/lwoegg) -add_subdirectory(src/lwoprogs) -add_subdirectory(src/mac-stats) -add_subdirectory(src/miscprogs) -add_subdirectory(src/objegg) -add_subdirectory(src/objprogs) -add_subdirectory(src/palettizer) -add_subdirectory(src/pandatoolbase) -add_subdirectory(src/pfmprogs) -add_subdirectory(src/progbase) -add_subdirectory(src/pstatserver) -add_subdirectory(src/ptloader) -add_subdirectory(src/text-stats) -add_subdirectory(src/vrml) -add_subdirectory(src/vrmlegg) -add_subdirectory(src/vrmlprogs) -add_subdirectory(src/win-stats) -add_subdirectory(src/xfile) -add_subdirectory(src/xfileegg) -add_subdirectory(src/xfileprogs) - -if(BUILD_TOOLS) - export_targets(Tools) -endif() -export_targets(ToolsDevel NAMESPACE "Panda3D::Tools::" COMPONENT ToolsDevel) diff --git a/pandatool/src/assimp/CMakeLists.txt b/pandatool/src/assimp/CMakeLists.txt deleted file mode 100644 index 5b88e0ef..00000000 --- a/pandatool/src/assimp/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -if(NOT HAVE_ASSIMP) - return() -endif() - -set(P3ASSIMP_HEADERS - assimpLoader.h assimpLoader.I - config_assimp.h - loaderFileTypeAssimp.h - pandaIOStream.h - pandaIOSystem.h - pandaLogger.h -) - -set(P3ASSIMP_SOURCES - assimpLoader.cxx - config_assimp.cxx - loaderFileTypeAssimp.cxx - pandaIOStream.cxx - pandaIOSystem.cxx - pandaLogger.cxx -) - -composite_sources(p3assimp P3ASSIMP_SOURCES) -add_library(p3assimp ${MODULE_TYPE} ${P3ASSIMP_HEADERS} ${P3ASSIMP_SOURCES}) -set_target_properties(p3assimp PROPERTIES DEFINE_SYMBOL BUILDING_ASSIMP) -target_link_libraries(p3assimp PRIVATE p3pandatoolbase) -target_link_libraries(p3assimp PUBLIC PKG::ASSIMP) - -if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang)$") - # Do not re-export symbols from these libraries. - target_link_options(p3assimp PRIVATE "LINKER:--exclude-libs,libassimp.a") - target_link_options(p3assimp PRIVATE "LINKER:--exclude-libs,libIrrXML.a") -endif() - -if(BUILD_SHARED_LIBS) - # We can't install this if we're doing a static build, because it depends on - # a static library that isn't installed. - install(TARGETS p3assimp EXPORT Assimp COMPONENT Assimp DESTINATION ${MODULE_DESTINATION}) -endif() diff --git a/pandatool/src/assimp/assimpLoader.I b/pandatool/src/assimp/assimpLoader.I deleted file mode 100644 index 5ce6c3bf..00000000 --- a/pandatool/src/assimp/assimpLoader.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file assimpLoader.I - * @author rdb - * @date 2011-03-29 - */ diff --git a/pandatool/src/assimp/assimpLoader.cxx b/pandatool/src/assimp/assimpLoader.cxx deleted file mode 100644 index 80b94a7c..00000000 --- a/pandatool/src/assimp/assimpLoader.cxx +++ /dev/null @@ -1,1326 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file assimpLoader.cxx - * @author rdb - * @date 2011-03-29 - */ - -#include "assimpLoader.h" - -#include "geomNode.h" -#include "luse.h" -#include "geomVertexWriter.h" -#include "geomPoints.h" -#include "geomLines.h" -#include "geomTriangles.h" -#include "pnmFileTypeRegistry.h" -#include "pnmImage.h" -#include "alphaTestAttrib.h" -#include "materialAttrib.h" -#include "textureAttrib.h" -#include "cullFaceAttrib.h" -#include "transparencyAttrib.h" -#include "ambientLight.h" -#include "directionalLight.h" -#include "spotlight.h" -#include "pointLight.h" -#include "look_at.h" -#include "texturePool.h" -#include "character.h" -#include "animBundle.h" -#include "animBundleNode.h" -#include "animChannelMatrixXfmTable.h" -#include "pvector.h" -#include "cmath.h" -#include "deg_2_rad.h" -#include "string_utils.h" - -#include "pandaIOSystem.h" -#include "pandaLogger.h" - -#include - -#ifndef AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 -#endif - -#ifndef AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 -#endif - -#ifndef AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 -#endif - -#ifndef AI_MATKEY_GLTF_ALPHAMODE -#define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 -#endif - -#ifndef AI_MATKEY_GLTF_ALPHACUTOFF -#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 -#endif - -// Older versions of Assimp used these glTF-specific keys instead. -#ifndef AI_MATKEY_BASE_COLOR -#define AI_MATKEY_BASE_COLOR AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR -#endif - -#ifndef AI_MATKEY_METALLIC_FACTOR -#define AI_MATKEY_METALLIC_FACTOR AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR -#endif - -#ifndef AI_MATKEY_ROUGHNESS_FACTOR -#define AI_MATKEY_ROUGHNESS_FACTOR AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR -#endif - -using std::ostringstream; -using std::stringstream; -using std::string; - -struct BoneWeight { - CPT(JointVertexTransform) joint_vertex_xform; - float weight; - - BoneWeight(CPT(JointVertexTransform) joint_vertex_xform, float weight) - : joint_vertex_xform(joint_vertex_xform), weight(weight) - {} -}; -typedef pvector BoneWeightList; - -/** - * - */ -AssimpLoader:: -AssimpLoader() : - _error (false), - _geoms (nullptr) { - - PandaLogger::set_default(); - _importer.SetIOHandler(new PandaIOSystem); -} - -/** - * - */ -AssimpLoader:: -~AssimpLoader() { - _importer.FreeScene(); -} - -/** - * Returns a space-separated list of extensions that Assimp can load, without - * the leading dots. - */ -void AssimpLoader:: -get_extensions(string &ext) const { - aiString aexts; - _importer.GetExtensionList(aexts); - - // The format is like: *.mdc;*.mdl;*.mesh.xml;*.mot - char *sub = strtok(aexts.data, ";"); - while (sub != nullptr) { - ext += sub + 2; - sub = strtok(nullptr, ";"); - - if (sub != nullptr) { - ext += ' '; - } - } -} - -/** - * Reads from the indicated file. - */ -bool AssimpLoader:: -read(const Filename &filename) { - _filename = filename; - - unsigned int flags = aiProcess_Triangulate | aiProcess_GenUVCoords; - - if (assimp_calc_tangent_space) { - flags |= aiProcess_CalcTangentSpace; - } - if (assimp_join_identical_vertices) { - flags |= aiProcess_JoinIdenticalVertices; - } - if (assimp_improve_cache_locality) { - flags |= aiProcess_ImproveCacheLocality; - } - if (assimp_remove_redundant_materials) { - flags |= aiProcess_RemoveRedundantMaterials; - } - if (assimp_fix_infacing_normals) { - flags |= aiProcess_FixInfacingNormals; - } - if (assimp_optimize_meshes) { - flags |= aiProcess_OptimizeMeshes; - } - if (assimp_optimize_graph) { - flags |= aiProcess_OptimizeGraph; - } - if (assimp_flip_winding_order) { - flags |= aiProcess_FlipWindingOrder; - } - if (assimp_gen_normals) { - if (assimp_smooth_normal_angle == 0.0) { - flags |= aiProcess_GenNormals; - } - else { - flags |= aiProcess_GenSmoothNormals; - _importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, - assimp_smooth_normal_angle); - } - } - - _scene = _importer.ReadFile(_filename.c_str(), flags); - if (_scene == nullptr) { - _error = true; - return false; - } - - _error = false; - return true; -} - -/** - * Converts scene graph structures into a Panda3D scene graph, with _root - * being the root node. - */ -void AssimpLoader:: -build_graph() { - nassertv(_scene != nullptr); // read() must be called first - nassertv(!_error); // and have succeeded - - // Protect the import process - MutexHolder holder(_lock); - - _root = new ModelRoot(_filename.get_basename()); - - // Import all of the embedded textures first. - _textures = new PT(Texture)[_scene->mNumTextures]; - for (size_t i = 0; i < _scene->mNumTextures; ++i) { - load_texture(i); - } - - // Then the materials. - _mat_states = new CPT(RenderState)[_scene->mNumMaterials]; - for (size_t i = 0; i < _scene->mNumMaterials; ++i) { - load_material(i); - } - - // And then the meshes. - _geoms = new Geoms[_scene->mNumMeshes]; - for (size_t i = 0; i < _scene->mNumMeshes; ++i) { - load_mesh(i); - } - - // And now the node structure. - if (_scene->mRootNode != nullptr) { - load_node(*_scene->mRootNode, _root); - } - - // And lastly, the lights. - for (size_t i = 0; i < _scene->mNumLights; ++i) { - load_light(*_scene->mLights[i]); - } - - delete[] _textures; - delete[] _mat_states; - delete[] _geoms; -} - -/** - * Finds a node by name. - */ -const aiNode *AssimpLoader:: -find_node(const aiNode &root, const aiString &name) { - const aiNode *node; - - if (root.mName == name) { - return &root; - } else { - for (size_t i = 0; i < root.mNumChildren; ++i) { - node = find_node(*root.mChildren[i], name); - if (node) { - return node; - } - } - } - - return nullptr; -} - -/** - * Converts an aiTexture into a Texture. - */ -void AssimpLoader:: -load_texture(size_t index) { - const aiTexture &tex = *_scene->mTextures[index]; - - PT(Texture) ptex = new Texture; - - if (tex.mHeight == 0) { - // Compressed texture. - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Reading embedded compressed texture with format " - << tex.achFormatHint << " and size " << tex.mWidth << "\n"; - } - stringstream str; - str.write((char*) tex.pcData, tex.mWidth); - - if (strncmp(tex.achFormatHint, "dds", 3) == 0) { - ptex->read_dds(str); - - } else { - const PNMFileTypeRegistry *reg = PNMFileTypeRegistry::get_global_ptr(); - PNMFileType *ftype; - PNMImage img; - - // Work around a bug in Assimp, it sometimes writes jp instead of jpg - if (strncmp(tex.achFormatHint, "jp\0", 3) == 0) { - ftype = reg->get_type_from_extension("jpg"); - } else { - ftype = reg->get_type_from_extension(tex.achFormatHint); - } - - if (img.read(str, "", ftype)) { - ptex->load(img); - } else { - ptex = nullptr; - } - } - } else { - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Reading embedded raw texture with size " - << tex.mWidth << "x" << tex.mHeight << "\n"; - } - - ptex->setup_2d_texture(tex.mWidth, tex.mHeight, Texture::T_unsigned_byte, Texture::F_rgba); - PTA_uchar data = ptex->modify_ram_image(); - - size_t p = 0; - for (size_t i = 0; i < tex.mWidth * tex.mHeight; ++i) { - const aiTexel &texel = tex.pcData[i]; - data[p++] = texel.b; - data[p++] = texel.g; - data[p++] = texel.r; - data[p++] = texel.a; - } - } - - // ostringstream path; path << "tmp" << index << ".png"; - // ptex->write(path.str()); - - _textures[index] = ptex; - -} - -/** - * Converts an aiMaterial into a RenderState. - */ -void AssimpLoader:: -load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, - TextureStage::Mode mode, CPT(TextureAttrib) &tattr, - CPT(TexMatrixAttrib) &tmattr) { - aiString path; - aiTextureMapping mapping; - unsigned int uvindex; - float blend; - aiTextureOp op; - aiTextureMapMode mapmode[3]; - - for (size_t i = 0; i < mat.GetTextureCount(ttype); ++i) { - mat.GetTexture(ttype, i, &path, &mapping, nullptr, &blend, &op, mapmode); - - if (AI_SUCCESS != mat.Get(AI_MATKEY_UVWSRC(ttype, i), uvindex)) { - // If there's no texture coordinate set for this texture, assume that - // it's the same as the index on the stack. TODO: if there's only one - // set on the mesh, force everything to use just the first stage. - uvindex = i; - } - - if (ttype == aiTextureType_DIFFUSE && i == 1) { - // The glTF 2 importer duplicates this slot in older versions of Assimp. - // Since glTF doesn't support multiple diffuse textures anyway, we check - // for this old glTF-specific key, and if present, ignore this texture. - aiColor4D col; - if (AI_SUCCESS == mat.Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR, col)) { - return; - } - } - - std::string uvindex_str = format_string(uvindex); - PT(TextureStage) stage = new TextureStage(uvindex_str); - stage->set_mode(mode); - if (uvindex > 0) { - stage->set_texcoord_name(InternalName::get_texcoord_name(uvindex_str)); - } - PT(Texture) ptex; - - // I'm not sure if this is the right way to handle it, as I couldn't find - // much information on embedded textures. - if (path.data[0] == '*') { - long num = strtol(path.data + 1, nullptr, 10); - ptex = _textures[num]; - - } else if (path.length > 0) { - Filename fn = Filename::from_os_specific(string(path.data, path.length)); - - // Try to find the file by moving up twice in the hierarchy. - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - Filename dir (_filename); - _filename.make_canonical(); - dir = _filename.get_dirname(); - - // Quake 3 BSP doesn't specify an extension for textures. - if (vfs->is_regular_file(Filename(dir, fn))) { - fn = Filename(dir, fn); - } else if (vfs->is_regular_file(Filename(dir, fn + ".tga"))) { - fn = Filename(dir, fn + ".tga"); - } else if (vfs->is_regular_file(Filename(dir, fn + ".jpg"))) { - fn = Filename(dir, fn + ".jpg"); - } else { - dir = _filename.get_dirname(); - if (vfs->is_regular_file(Filename(dir, fn))) { - fn = Filename(dir, fn); - } else if (vfs->is_regular_file(Filename(dir, fn + ".tga"))) { - fn = Filename(dir, fn + ".tga"); - } else if (vfs->is_regular_file(Filename(dir, fn + ".jpg"))) { - fn = Filename(dir, fn + ".jpg"); - } - } - - ptex = TexturePool::load_texture(fn); - } - - if (ptex != nullptr) { - // Apply the mapping modes. - switch (mapmode[0]) { - case aiTextureMapMode_Wrap: - ptex->set_wrap_u(SamplerState::WM_repeat); - break; - case aiTextureMapMode_Clamp: - ptex->set_wrap_u(SamplerState::WM_clamp); - break; - case aiTextureMapMode_Decal: - ptex->set_wrap_u(SamplerState::WM_border_color); - ptex->set_border_color(LColor(0, 0, 0, 0)); - break; - case aiTextureMapMode_Mirror: - ptex->set_wrap_u(SamplerState::WM_mirror); - break; - default: - break; - } - switch (mapmode[1]) { - case aiTextureMapMode_Wrap: - ptex->set_wrap_v(SamplerState::WM_repeat); - break; - case aiTextureMapMode_Clamp: - ptex->set_wrap_v(SamplerState::WM_clamp); - break; - case aiTextureMapMode_Decal: - ptex->set_wrap_v(SamplerState::WM_border_color); - ptex->set_border_color(LColor(0, 0, 0, 0)); - break; - case aiTextureMapMode_Mirror: - ptex->set_wrap_v(SamplerState::WM_mirror); - break; - default: - break; - } - switch (mapmode[2]) { - case aiTextureMapMode_Wrap: - ptex->set_wrap_w(SamplerState::WM_repeat); - break; - case aiTextureMapMode_Clamp: - ptex->set_wrap_w(SamplerState::WM_clamp); - break; - case aiTextureMapMode_Decal: - ptex->set_wrap_w(SamplerState::WM_border_color); - ptex->set_border_color(LColor(0, 0, 0, 0)); - break; - case aiTextureMapMode_Mirror: - ptex->set_wrap_w(SamplerState::WM_mirror); - break; - default: - break; - } - - tattr = DCAST(TextureAttrib, tattr->add_on_stage(stage, ptex)); - - // Is there a texture transform? - aiUVTransform transform; - if (AI_SUCCESS == mat.Get(AI_MATKEY_UVTRANSFORM(ttype, i), transform)) { - // Reconstruct the original origin from the glTF file. - PN_stdfloat rcos, rsin; - csincos(-transform.mRotation, &rsin, &rcos); - transform.mTranslation.x -= (0.5 * transform.mScaling.x) * (-rcos + rsin + 1); - transform.mTranslation.y -= ((0.5 * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y; - - LMatrix3 matrix = - LMatrix3::translate_mat(0, -1) * - LMatrix3::scale_mat(transform.mScaling.x, transform.mScaling.y) * - LMatrix3::rotate_mat(rad_2_deg(-transform.mRotation)) * - LMatrix3::translate_mat(transform.mTranslation.x, 1 + transform.mTranslation.y); - - CPT(TransformState) cstate = - TransformState::make_mat3(matrix); - - CPT(RenderAttrib) new_attr = (tmattr == nullptr) - ? TexMatrixAttrib::make(stage, std::move(cstate)) - : tmattr->add_stage(stage, std::move(cstate)); - tmattr = DCAST(TexMatrixAttrib, std::move(new_attr)); - } - } - } -} - -/** - * Converts an aiMaterial into a RenderState. - */ -void AssimpLoader:: -load_material(size_t index) { - const aiMaterial &mat = *_scene->mMaterials[index]; - - CPT(RenderState) state = RenderState::make_empty(); - - aiColor4D col; - bool have; - int ival; - PN_stdfloat fval; - - // XXX a lot of this is untested. - - // First do the material attribute. - PT(Material) pmat = new Material; - have = false; - if (AI_SUCCESS == mat.Get(AI_MATKEY_BASE_COLOR, col)) { - pmat->set_base_color(LColor(col.r, col.g, col.b, col.a)); - have = true; - } - else if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_DIFFUSE, col)) { - pmat->set_diffuse(LColor(col.r, col.g, col.b, 1)); - have = true; - } - if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_SPECULAR, col)) { - if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS_STRENGTH, fval)) { - pmat->set_specular(LColor(col.r * fval, col.g * fval, col.b * fval, 1)); - } else { - pmat->set_specular(LColor(col.r, col.g, col.b, 1)); - } - have = true; - } - //else { - // if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS_STRENGTH, fval)) { - // pmat->set_specular(LColor(fval, fval, fval, 1)); - // } else { - // pmat->set_specular(LColor(1, 1, 1, 1)); - // } - //} - if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_AMBIENT, col)) { - pmat->set_specular(LColor(col.r, col.g, col.b, 1)); - have = true; - } - if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_EMISSIVE, col)) { - pmat->set_emission(LColor(col.r, col.g, col.b, 1)); - have = true; - } - if (AI_SUCCESS == mat.Get(AI_MATKEY_COLOR_TRANSPARENT, col)) { - // FIXME: ??? - } - if (AI_SUCCESS == mat.Get(AI_MATKEY_SHININESS, fval)) { - pmat->set_shininess(fval); - have = true; - } - if (AI_SUCCESS == mat.Get(AI_MATKEY_METALLIC_FACTOR, fval)) { - pmat->set_metallic(fval); - have = true; - } - if (AI_SUCCESS == mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, fval)) { - pmat->set_roughness(fval); - have = true; - } - if (AI_SUCCESS == mat.Get(AI_MATKEY_REFRACTI, fval)) { - pmat->set_refractive_index(fval); - have = true; - } - else if (pmat->has_metallic()) { - // Default refractive index to 1.5 for PBR models - pmat->set_refractive_index(1.5); - } - if (have) { - state = state->add_attrib(MaterialAttrib::make(pmat)); - } - - // Wireframe. - if (AI_SUCCESS == mat.Get(AI_MATKEY_ENABLE_WIREFRAME, ival)) { - if (ival) { - state = state->add_attrib(RenderModeAttrib::make(RenderModeAttrib::M_wireframe)); - } else { - state = state->add_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled)); - } - } - - // Backface culling. Not sure if this is also supposed to set the twoside - // flag in the material, I'm guessing not. - if (AI_SUCCESS == mat.Get(AI_MATKEY_TWOSIDED, ival)) { - if (ival) { - state = state->add_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_none)); - } else { - state = state->add_attrib(CullFaceAttrib::make_default()); - } - } - - // Alpha mode. - aiString alpha_mode; - if (AI_SUCCESS == mat.Get(AI_MATKEY_GLTF_ALPHAMODE, alpha_mode)) { - if (strcmp(alpha_mode.C_Str(), "MASK") == 0) { - PN_stdfloat cutoff = 0.5; - mat.Get(AI_MATKEY_GLTF_ALPHACUTOFF, cutoff); - state = state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, cutoff)); - } - else if (strcmp(alpha_mode.C_Str(), "BLEND") == 0) { - state = state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha)); - } - } - - // And let's not forget the textures! - CPT(TextureAttrib) tattr = DCAST(TextureAttrib, TextureAttrib::make()); - CPT(TexMatrixAttrib) tmattr; - load_texture_stage(mat, aiTextureType_DIFFUSE, TextureStage::M_modulate, tattr, tmattr); - - // Check for an ORM map, from the glTF/OBJ importer. glTF also puts it in the - // LIGHTMAP slot, despite only having the lightmap in the red channel, so we - // have to ignore it. - if (mat.GetTextureCount(aiTextureType_UNKNOWN) > 0) { - load_texture_stage(mat, aiTextureType_UNKNOWN, TextureStage::M_selector, tattr, tmattr); - } else { - load_texture_stage(mat, aiTextureType_LIGHTMAP, TextureStage::M_modulate, tattr, tmattr); - } - - load_texture_stage(mat, aiTextureType_NORMALS, TextureStage::M_normal, tattr, tmattr); - load_texture_stage(mat, aiTextureType_EMISSIVE, TextureStage::M_emission, tattr, tmattr); - load_texture_stage(mat, aiTextureType_HEIGHT, TextureStage::M_height, tattr, tmattr); - if (tattr->get_num_on_stages() > 0) { - state = state->add_attrib(tattr); - } - if (tmattr != nullptr) { - state = state->add_attrib(tmattr); - } - - _mat_states[index] = std::move(state); -} - -/** - * Creates a CharacterJoint from an aiNode - */ -void AssimpLoader:: -create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node) { - const aiMatrix4x4 &t = node.mTransformation; - LMatrix4 mat(t.a1, t.b1, t.c1, t.d1, - t.a2, t.b2, t.c2, t.d2, - t.a3, t.b3, t.c3, t.d3, - t.a4, t.b4, t.c4, t.d4); - PT(CharacterJoint) joint = new CharacterJoint(character, bundle, parent, node.mName.C_Str(), mat); - - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Creating joint for: " << node.mName.C_Str() << "\n"; - } - - for (size_t i = 0; i < node.mNumChildren; ++i) { - if (_bonemap.find(node.mChildren[i]->mName.C_Str()) != _bonemap.end()) { - create_joint(character, bundle, joint, *node.mChildren[i]); - } - } -} - -/** - * Creates a AnimChannelMatrixXfmTable from an aiNodeAnim - */ -void AssimpLoader:: -create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node) { - PT(AnimChannelMatrixXfmTable) group = new AnimChannelMatrixXfmTable(parent, node.mName.C_Str()); - - // See if there is a channel for this node - aiNodeAnim *node_anim = nullptr; - for (size_t i = 0; i < anim.mNumChannels; ++i) { - if (anim.mChannels[i]->mNodeName == node.mName) { - node_anim = anim.mChannels[i]; - } - } - - if (node_anim) { - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Found channel for node: " << node.mName.C_Str() << "\n"; - } - // assimp_cat.debug() << "Num Position Keys " << - // node_anim->mNumPositionKeys << "\n"; assimp_cat.debug() << "Num - // Rotation Keys " << node_anim->mNumRotationKeys << "\n"; - // assimp_cat.debug() << "Num Scaling Keys " << node_anim->mNumScalingKeys - // << "\n"; - - // Convert positions - PTA_stdfloat tablex = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys); - PTA_stdfloat tabley = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys); - PTA_stdfloat tablez = PTA_stdfloat::empty_array(node_anim->mNumPositionKeys); - for (size_t i = 0; i < node_anim->mNumPositionKeys; ++i) { - tablex[i] = node_anim->mPositionKeys[i].mValue.x; - tabley[i] = node_anim->mPositionKeys[i].mValue.y; - tablez[i] = node_anim->mPositionKeys[i].mValue.z; - } - group->set_table('x', tablex); - group->set_table('y', tabley); - group->set_table('z', tablez); - - // Convert rotations - PTA_stdfloat tableh = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys); - PTA_stdfloat tablep = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys); - PTA_stdfloat tabler = PTA_stdfloat::empty_array(node_anim->mNumRotationKeys); - for (size_t i = 0; i < node_anim->mNumRotationKeys; ++i) { - aiQuaternion ai_quat = node_anim->mRotationKeys[i].mValue; - LVecBase3 hpr = LQuaternion(ai_quat.w, ai_quat.x, ai_quat.y, ai_quat.z).get_hpr(); - tableh[i] = hpr.get_x(); - tablep[i] = hpr.get_y(); - tabler[i] = hpr.get_z(); - } - group->set_table('h', tableh); - group->set_table('p', tablep); - group->set_table('r', tabler); - - // Convert scales - PTA_stdfloat tablei = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys); - PTA_stdfloat tablej = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys); - PTA_stdfloat tablek = PTA_stdfloat::empty_array(node_anim->mNumScalingKeys); - for (size_t i = 0; i < node_anim->mNumScalingKeys; ++i) { - tablei[i] = node_anim->mScalingKeys[i].mValue.x; - tablej[i] = node_anim->mScalingKeys[i].mValue.y; - tablek[i] = node_anim->mScalingKeys[i].mValue.z; - } - group->set_table('i', tablei); - group->set_table('j', tablej); - group->set_table('k', tablek); - } - else if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "No channel found for node: " << node.mName.C_Str() << "\n"; - } - - - for (size_t i = 0; i < node.mNumChildren; ++i) { - if (_bonemap.find(node.mChildren[i]->mName.C_Str()) != _bonemap.end()) { - create_anim_channel(anim, bundle, group, *node.mChildren[i]); - } - } -} - -/** - * Converts an aiMesh into a Geom. - */ -void AssimpLoader:: -load_mesh(size_t index) { - const aiMesh &mesh = *_scene->mMeshes[index]; - - // Check if we need to make a Character - PT(Character) character = nullptr; - if (mesh.HasBones()) { - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Creating character for mesh '" << mesh.mName.C_Str() << "' with " - << mesh.mNumBones << " bones\n"; - } - - // Find and add all bone nodes to the bone map - for (size_t i = 0; i < mesh.mNumBones; ++i) { - const aiBone &bone = *mesh.mBones[i]; - const aiNode *node = find_node(*_scene->mRootNode, bone.mName); - _bonemap[bone.mName.C_Str()] = node; - } - - // Now create a character from the bones - character = new Character(mesh.mName.C_Str()); - PT(CharacterJointBundle) bundle = character->get_bundle(0); - PT(PartGroup) skeleton = new PartGroup(bundle, ""); - - for (size_t i = 0; i < mesh.mNumBones; ++i) { - const aiBone &bone = *mesh.mBones[i]; - - // Find the root bone node - const aiNode *root = _bonemap[bone.mName.C_Str()]; - while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) { - root = root->mParent; - } - - // Don't process this root if we already have a joint for it - if (character->find_joint(root->mName.C_Str())) { - continue; - } - - create_joint(character, bundle, skeleton, *root); - } - } - - // Create transform blend table - PT(TransformBlendTable) tbtable = new TransformBlendTable; - pvector bone_weights(mesh.mNumVertices); - if (character) { - for (size_t i = 0; i < mesh.mNumBones; ++i) { - const aiBone &bone = *mesh.mBones[i]; - CharacterJoint *joint = character->find_joint(bone.mName.C_Str()); - if (joint == nullptr) { - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Could not find joint for bone: " << bone.mName.C_Str() << "\n"; - } - continue; - } - - CPT(JointVertexTransform) jvt = new JointVertexTransform(joint); - - for (size_t j = 0; j < bone.mNumWeights; ++j) { - const aiVertexWeight &weight = bone.mWeights[j]; - - bone_weights[weight.mVertexId].push_back(BoneWeight(jvt, weight.mWeight)); - } - } - } - - // Create the vertex format. - PT(GeomVertexArrayFormat) aformat = new GeomVertexArrayFormat; - aformat->add_column(InternalName::get_vertex(), 3, Geom::NT_stdfloat, Geom::C_point); - if (mesh.HasNormals()) { - aformat->add_column(InternalName::get_normal(), 3, Geom::NT_stdfloat, Geom::C_normal); - } - if (mesh.HasVertexColors(0)) { - aformat->add_column(InternalName::get_color(), 4, Geom::NT_stdfloat, Geom::C_color); - } - unsigned int num_uvs = mesh.GetNumUVChannels(); - if (num_uvs > 0) { - // UV sets are named texcoord, texcoord.1, texcoord.2... - aformat->add_column(InternalName::get_texcoord(), 3, Geom::NT_stdfloat, Geom::C_texcoord); - for (unsigned int u = 1; u < num_uvs; ++u) { - ostringstream out; - out << u; - aformat->add_column(InternalName::get_texcoord_name(out.str()), 3, Geom::NT_stdfloat, Geom::C_texcoord); - } - } - if (mesh.HasTangentsAndBitangents()) { - aformat->add_column(InternalName::get_tangent(), 3, Geom::NT_stdfloat, Geom::C_vector); - aformat->add_column(InternalName::get_binormal(), 3, Geom::NT_stdfloat, Geom::C_vector); - } - - PT(GeomVertexArrayFormat) tb_aformat = new GeomVertexArrayFormat; - tb_aformat->add_column(InternalName::make("transform_blend"), 1, Geom::NT_uint16, Geom::C_index); - - // Check to see if we need to convert any animations - for (size_t i = 0; i < _scene->mNumAnimations; ++i) { - aiAnimation &ai_anim = *_scene->mAnimations[i]; - bool convert_anim = false; - - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Checking to see if anim (" << ai_anim.mName.C_Str() - << ") matches character (" << mesh.mName.C_Str() << ")\n"; - } - for (size_t j = 0; j < ai_anim.mNumChannels; ++j) { - if (assimp_cat.is_spam()) { - assimp_cat.spam() - << "Searching for " << ai_anim.mChannels[j]->mNodeName.C_Str() - << " in bone map" << "\n"; - } - if (_bonemap.find(ai_anim.mChannels[j]->mNodeName.C_Str()) != _bonemap.end()) { - convert_anim = true; - break; - } - } - - if (convert_anim) { - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Found animation (" << ai_anim.mName.C_Str() - << ") for character (" << mesh.mName.C_Str() << ")\n"; - } - - // Now create the animation - unsigned int frames = 0; - for (size_t j = 0; j < ai_anim.mNumChannels; ++j) { - if (ai_anim.mChannels[j]->mNumPositionKeys > frames) { - frames = ai_anim.mChannels[j]->mNumPositionKeys; - } - if (ai_anim.mChannels[j]->mNumRotationKeys > frames) { - frames = ai_anim.mChannels[j]->mNumRotationKeys; - } - if (ai_anim.mChannels[j]->mNumScalingKeys > frames) { - frames = ai_anim.mChannels[j]->mNumScalingKeys; - } - } - PN_stdfloat fps = frames / (ai_anim.mTicksPerSecond * ai_anim.mDuration); - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "FPS " << fps << "\n"; - assimp_cat.debug() - << "Frames " << frames << "\n"; - } - - PT(AnimBundle) bundle = new AnimBundle(mesh.mName.C_Str(), fps, frames); - PT(AnimGroup) skeleton = new AnimGroup(bundle, ""); - - for (size_t i = 0; i < mesh.mNumBones; ++i) { - const aiBone &bone = *mesh.mBones[i]; - - // Find the root bone node - const aiNode *root = _bonemap[bone.mName.C_Str()]; - while (root->mParent && _bonemap.find(root->mParent->mName.C_Str()) != _bonemap.end()) { - root = root->mParent; - } - - // Only convert root nodes - if (root->mName == bone.mName) { - create_anim_channel(ai_anim, bundle, skeleton, *root); - - // Attach the animation to the character node - PT(AnimBundleNode) bundle_node = new AnimBundleNode(bone.mName.C_Str(), bundle); - character->add_child(bundle_node); - } - } - } - } - - // TODO: if there is only one UV set, hackily iterate over the texture - // stages and clear the texcoord name things - - PT(GeomVertexFormat) format = new GeomVertexFormat; - format->add_array(aformat); - if (character) { - format->add_array(tb_aformat); - - GeomVertexAnimationSpec aspec; - aspec.set_panda(); - format->set_animation(aspec); - } - - // Create the GeomVertexData. - string name (mesh.mName.data, mesh.mName.length); - PT(GeomVertexData) vdata = new GeomVertexData(name, GeomVertexFormat::register_format(format), Geom::UH_static); - if (character) { - vdata->set_transform_blend_table(tbtable); - } - vdata->unclean_set_num_rows(mesh.mNumVertices); - - // Read out the vertices. - GeomVertexWriter vertex (vdata, InternalName::get_vertex()); - for (size_t i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D &vec = mesh.mVertices[i]; - vertex.set_data3(vec.x, vec.y, vec.z); - } - - // Now the normals, if any. - if (mesh.HasNormals()) { - GeomVertexWriter normal (vdata, InternalName::get_normal()); - for (size_t i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D &vec = mesh.mNormals[i]; - normal.set_data3(vec.x, vec.y, vec.z); - } - } - - // Vertex colors, if any. We only import the first set. - if (mesh.HasVertexColors(0)) { - GeomVertexWriter color (vdata, InternalName::get_color()); - for (size_t i = 0; i < mesh.mNumVertices; ++i) { - const aiColor4D &col = mesh.mColors[0][i]; - color.set_data4(col.r, col.g, col.b, col.a); - } - } - - // Now the texture coordinates. - if (num_uvs > 0) { - // UV sets are named texcoord, texcoord.1, texcoord.2... - GeomVertexWriter texcoord0 (vdata, InternalName::get_texcoord()); - for (size_t i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D &vec = mesh.mTextureCoords[0][i]; - texcoord0.set_data3(vec.x, vec.y, vec.z); - } - for (unsigned int u = 1; u < num_uvs; ++u) { - ostringstream out; - out << u; - GeomVertexWriter texcoord (vdata, InternalName::get_texcoord_name(out.str())); - for (size_t i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D &vec = mesh.mTextureCoords[u][i]; - texcoord.set_data3(vec.x, vec.y, vec.z); - } - } - } - - // Now the tangents and bitangents, if any. - if (mesh.HasTangentsAndBitangents()) { - GeomVertexWriter tangent (vdata, InternalName::get_tangent()); - GeomVertexWriter binormal (vdata, InternalName::get_binormal()); - for (size_t i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D &tvec = mesh.mTangents[i]; - const aiVector3D &bvec = mesh.mBitangents[i]; - tangent.set_data3(tvec.x, tvec.y, tvec.z); - binormal.set_data3(bvec.x, bvec.y, bvec.z); - } - } - - // Now the transform blend table - if (character) { - GeomVertexWriter transform_blend (vdata, InternalName::get_transform_blend()); - - for (size_t i = 0; i < mesh.mNumVertices; ++i) { - TransformBlend tblend; - - for (size_t j = 0; j < bone_weights[i].size(); ++j) { - tblend.add_transform(bone_weights[i][j].joint_vertex_xform, bone_weights[i][j].weight); - } - transform_blend.set_data1i(tbtable->add_blend(tblend)); - } - - tbtable->set_rows(SparseArray::lower_on(vdata->get_num_rows())); - } - - // Now read out the primitives. Keep in mind that we called ReadFile with - // the aiProcess_Triangulate flag earlier, so we don't have to worry about - // polygons. - PT(GeomPoints) points = new GeomPoints(Geom::UH_static); - PT(GeomLines) lines = new GeomLines(Geom::UH_static); - PT(GeomTriangles) triangles = new GeomTriangles(Geom::UH_static); - - // Now add the vertex indices. - for (size_t i = 0; i < mesh.mNumFaces; ++i) { - const aiFace &face = mesh.mFaces[i]; - - if (face.mNumIndices == 0) { - // It happens, strangely enough. - continue; - } else if (face.mNumIndices == 1) { - points->add_vertex(face.mIndices[0]); - points->close_primitive(); - } else if (face.mNumIndices == 2) { - lines->add_vertices(face.mIndices[0], face.mIndices[1]); - lines->close_primitive(); - } else if (face.mNumIndices == 3) { - triangles->add_vertices(face.mIndices[0], face.mIndices[1], face.mIndices[2]); - triangles->close_primitive(); - } else { - nassertd(false) continue; - } - } - - // Create a geom and add the primitives to it. - Geoms &geoms = _geoms[index]; - geoms._mat_index = mesh.mMaterialIndex; - - if (points->get_num_primitives() > 0) { - geoms._points = new Geom(vdata); - geoms._points->add_primitive(points); - } - if (lines->get_num_primitives() > 0) { - geoms._lines = new Geom(vdata); - geoms._lines->add_primitive(lines); - } - if (triangles->get_num_primitives() > 0) { - geoms._triangles = new Geom(vdata); - geoms._triangles->add_primitive(triangles); - } - - if (character) { - geoms._character = character; - - PT(GeomNode) gnode = new GeomNode(""); - if (geoms._points != nullptr) { - gnode->add_geom(geoms._points); - } - if (geoms._lines != nullptr) { - gnode->add_geom(geoms._lines); - } - if (geoms._triangles != nullptr) { - gnode->add_geom(geoms._triangles); - } - gnode->set_state(_mat_states[mesh.mMaterialIndex]); - character->add_child(gnode); - } -} - -/** - * Converts an aiNode into a PandaNode. Returns true if the node had anything - * of interest under it, false otherwise. - */ -bool AssimpLoader:: -load_node(const aiNode &node, PandaNode *parent, bool under_joint) { - PT(PandaNode) pnode; - string name (node.mName.data, node.mName.length); - - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Converting node '" << name << "' with " << node.mNumMeshes - << " meshes and " << node.mNumChildren << " children\n"; - } - - if (!under_joint) { - under_joint = (_bonemap.find(node.mName.C_Str()) != _bonemap.end()); - } - - bool prune = false; - - if (node.mNumMeshes == 0) { - if (parent == _root && assimp_collapse_dummy_root_node && !under_joint && - (name.empty() || name[0] == '$' || name == "RootNode" || name == "ROOT" || name == "Root" || (name.size() > 2 && name[0] == '<' && name[name.size() - 1] == '>') || name == _root->get_name())) { - // Collapse root node. - pnode = _root; - } else { - pnode = new PandaNode(name); - - // Possibly prune this if this is a joint or under a joint. - prune = under_joint; - } - } - else if (node.mNumMeshes == 1) { - size_t meshIndex = node.mMeshes[0]; - const Geoms &geoms = _geoms[meshIndex]; - - if (geoms._character != nullptr) { - pnode = new PandaNode(name); - pnode->add_child(geoms._character); - } - else { - PT(GeomNode) gnode = new GeomNode(name); - const RenderState *state = _mat_states[geoms._mat_index]; - if (geoms._points != nullptr) { - gnode->add_geom(geoms._points); - } - if (geoms._lines != nullptr) { - gnode->add_geom(geoms._lines); - } - if (geoms._triangles != nullptr) { - gnode->add_geom(geoms._triangles); - } - if (state != nullptr) { - // Only set the state on the GeomNode if there are no child nodes. - if (node.mNumChildren == 0) { - gnode->set_state(state); - } else { - for (int i = 0; i < gnode->get_num_geoms(); ++i) { - gnode->set_geom_state(i, state); - } - } - } - pnode = gnode; - } - } - else { - // Do we have regular meshes or just animated meshes? - bool character_only = true; - - // First add all the regular meshes. - for (size_t i = 0; i < node.mNumMeshes; ++i) { - size_t meshIndex = node.mMeshes[i]; - - if (_geoms[meshIndex]._character == nullptr) { - character_only = false; - break; - } - } - - PT(GeomNode) gnode; - if (character_only) { - pnode = new PandaNode(name); - } else { - gnode = new GeomNode(name); - pnode = gnode; - } - - for (size_t i = 0; i < node.mNumMeshes; ++i) { - size_t meshIndex = node.mMeshes[i]; - const Geoms &geoms = _geoms[meshIndex]; - - if (geoms._character != nullptr) { - // An animated mesh, which already is converted as Character with an - // attached GeomNode. - pnode->add_child(geoms._character); - } - else { - // A non-animated mesh. - const RenderState *state = _mat_states[geoms._mat_index]; - if (geoms._points != nullptr) { - gnode->add_geom(geoms._points, state); - } - if (geoms._lines != nullptr) { - gnode->add_geom(geoms._lines, state); - } - if (geoms._triangles != nullptr) { - gnode->add_geom(geoms._triangles, state); - } - } - } - } - - if (parent != pnode) { - parent->add_child(pnode); - } - - if (node.mMetaData != nullptr) { - for (unsigned i = 0; i < node.mMetaData->mNumProperties; ++i) { - const aiMetadataEntry &entry = node.mMetaData->mValues[i]; - std::string value; - switch (entry.mType) { - //case AI_BOOL: - // value = (*static_cast(entry.mData)) ? "1" : ""; - // break; - case AI_INT32: - value = format_string(*static_cast(entry.mData)); - break; - case AI_UINT64: - value = format_string(*static_cast(entry.mData)); - break; - case AI_FLOAT: - value = format_string(*static_cast(entry.mData)); - break; - case AI_DOUBLE: - value = format_string(*static_cast(entry.mData)); - break; - case AI_AISTRING: - { - const aiString *str = static_cast(entry.mData); - value = std::string(str->data, str->length); - } - break; - default: - continue; - } - const aiString &key = node.mMetaData->mKeys[i]; - pnode->set_tag(std::string(key.data, key.length), std::move(value)); - } - } - - // Load in the transformation matrix. - const aiMatrix4x4 &t = node.mTransformation; - if (!t.IsIdentity()) { - LMatrix4 mat(t.a1, t.b1, t.c1, t.d1, - t.a2, t.b2, t.c2, t.d2, - t.a3, t.b3, t.c3, t.d3, - t.a4, t.b4, t.c4, t.d4); - pnode->set_transform(TransformState::make_mat(mat)); - } - - for (size_t i = 0; i < node.mNumChildren; ++i) { - if (load_node(*node.mChildren[i], pnode, under_joint)) { - prune = false; - } - } - - if (prune) { - // This is an empty node in a hierarchy of joints, prune it. - parent->remove_child(pnode); - if (assimp_cat.is_debug()) { - assimp_cat.debug() - << "Pruning node '" << name << "'\n"; - } - return false; - } else { - return true; - } -} - -/** - * Converts an aiLight into a LightNode. - */ -void AssimpLoader:: -load_light(const aiLight &light) { - string name (light.mName.data, light.mName.length); - if (assimp_cat.is_debug()) { - assimp_cat.debug() << "Found light '" << name << "'\n"; - } - - aiColor3D col; - aiVector3D vec; - - switch (light.mType) { - case aiLightSource_DIRECTIONAL: { - PT(DirectionalLight) dlight = new DirectionalLight(name); - _root->add_child(dlight); - - col = light.mColorDiffuse; - dlight->set_color(LColor(col.r, col.g, col.b, 1)); - - col = light.mColorSpecular; - dlight->set_specular_color(LColor(col.r, col.g, col.b, 1)); - - vec = light.mPosition; - dlight->set_point(LPoint3(vec.x, vec.y, vec.z)); - - vec = light.mDirection; - dlight->set_direction(LVector3(vec.x, vec.y, vec.z)); - break; } - - case aiLightSource_POINT: { - PT(PointLight) plight = new PointLight(name); - _root->add_child(plight); - - col = light.mColorDiffuse; - plight->set_color(LColor(col.r, col.g, col.b, 1)); - - col = light.mColorSpecular; - plight->set_specular_color(LColor(col.r, col.g, col.b, 1)); - - vec = light.mPosition; - plight->set_point(LPoint3(vec.x, vec.y, vec.z)); - - plight->set_attenuation(LVecBase3(light.mAttenuationConstant, - light.mAttenuationLinear, - light.mAttenuationQuadratic)); - break; } - - case aiLightSource_SPOT: { - PT(Spotlight) plight = new Spotlight(name); - _root->add_child(plight); - - col = light.mColorDiffuse; - plight->set_color(LColor(col.r, col.g, col.b, 1)); - - col = light.mColorSpecular; - plight->set_specular_color(LColor(col.r, col.g, col.b, 1)); - - plight->set_attenuation(LVecBase3(light.mAttenuationConstant, - light.mAttenuationLinear, - light.mAttenuationQuadratic)); - - plight->get_lens()->set_fov(light.mAngleOuterCone); - // TODO: translate mAngleInnerCone to an exponent, somehow - - // This *should* be about right. - vec = light.mDirection; - LPoint3 pos (light.mPosition.x, light.mPosition.y, light.mPosition.z); - LQuaternion quat; - ::look_at(quat, LPoint3(vec.x, vec.y, vec.z), LVector3::up()); - plight->set_transform(TransformState::make_pos_quat(pos, quat)); - break; } - - case aiLightSource_AMBIENT: - // This is handled below. - break; - - default: - assimp_cat.warning() << "Light '" << name << "' has an unknown type!\n"; - return; - } - - // If there's an ambient color, add it as ambient light. - col = light.mColorAmbient; - LVecBase4 ambient (col.r, col.g, col.b, 0); - if (ambient != LVecBase4::zero()) { - PT(AmbientLight) alight = new AmbientLight(name); - alight->set_color(ambient); - _root->add_child(alight); - } -} diff --git a/pandatool/src/assimp/assimpLoader.h b/pandatool/src/assimp/assimpLoader.h deleted file mode 100644 index e323cb1e..00000000 --- a/pandatool/src/assimp/assimpLoader.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file assimpLoader.h - * @author rdb - * @date 2011-03-29 - */ - -#ifndef ASSIMPLOADER_H -#define ASSIMPLOADER_H - -#include "config_assimp.h" -#include "filename.h" -#include "modelRoot.h" -#include "texture.h" -#include "textureStage.h" -#include "pmap.h" - -#include -#include - -class Character; -class CharacterJointBundle; -class PartGroup; -class AnimBundle; -class AnimGroup; - -struct char_cmp { - bool operator () (const char *a, const char *b) const { - return strcmp(a,b) < 0; - } -}; -typedef pmap BoneMap; - -/** - * Class that interfaces with Assimp and builds Panda nodes to represent the - * Assimp structures. The loader should be reusable. - */ -class AssimpLoader : public TypedReferenceCount { -public: - AssimpLoader(); - virtual ~AssimpLoader(); - - void get_extensions(std::string &ext) const; - - bool read(const Filename &filename); - void build_graph(); - -public: - bool _error; - PT(ModelRoot) _root; - Filename _filename; - Mutex _lock; - -private: - Assimp::Importer _importer; - const aiScene *_scene; - - struct Geoms { - PT(Geom) _points; - PT(Geom) _lines; - PT(Geom) _triangles; - PT(Character) _character; - unsigned int _mat_index = 0; - }; - - // These arrays are temporarily used during the build_graph run. - PT(Texture) *_textures; - CPT(RenderState) *_mat_states; - Geoms *_geoms; - BoneMap _bonemap; - - const aiNode *find_node(const aiNode &root, const aiString &name); - - void load_texture(size_t index); - void load_texture_stage(const aiMaterial &mat, const aiTextureType &ttype, - TextureStage::Mode mode, CPT(TextureAttrib) &tattr, - CPT(TexMatrixAttrib) &tmattr); - void load_material(size_t index); - void create_joint(Character *character, CharacterJointBundle *bundle, PartGroup *parent, const aiNode &node); - void create_anim_channel(const aiAnimation &anim, AnimBundle *bundle, AnimGroup *parent, const aiNode &node); - void load_mesh(size_t index); - bool load_node(const aiNode &node, PandaNode *parent, bool under_joint = false); - void load_light(const aiLight &light); -}; - -#include "assimpLoader.I" - -#endif diff --git a/pandatool/src/assimp/config_assimp.cxx b/pandatool/src/assimp/config_assimp.cxx deleted file mode 100644 index 42446e2b..00000000 --- a/pandatool/src/assimp/config_assimp.cxx +++ /dev/null @@ -1,114 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_assimp.cxx - * @author rdb - * @date 2011-03-29 - */ - -#include "config_assimp.h" - -#include "loaderFileTypeAssimp.h" - -#include "dconfig.h" -#include "loaderFileTypeRegistry.h" - -ConfigureDef(config_assimp); -NotifyCategoryDef(assimp, ""); - -ConfigureFn(config_assimp) { - init_libassimp(); -} - -ConfigVariableBool assimp_calc_tangent_space -("assimp-calc-tangent-space", false, - PRC_DESC("Calculates tangents and binormals for meshes imported via Assimp.")); - -ConfigVariableBool assimp_join_identical_vertices -("assimp-join-identical-vertices", true, - PRC_DESC("Merges duplicate vertices. Set this to false if you want each " - "vertex to only be in use on one triangle.")); - -ConfigVariableBool assimp_improve_cache_locality -("assimp-improve-cache-locality", true, - PRC_DESC("Improves rendering performance of the loaded meshes by reordering " - "triangles for better vertex cache locality. Set this to false if " - "you need geometry to be loaded in the exact order that it was " - "specified in the file, or to improve load performance.")); - -ConfigVariableBool assimp_remove_redundant_materials -("assimp-remove-redundant-materials", true, - PRC_DESC("Removes redundant/unreferenced materials from assets.")); - -ConfigVariableBool assimp_fix_infacing_normals -("assimp-fix-infacing-normals", false, - PRC_DESC("Determines which normal vectors are facing inward and inverts them " - "so that they are facing outward.")); - -ConfigVariableBool assimp_optimize_meshes -("assimp-optimize-meshes", true, - PRC_DESC("Reduces the number of draw calls by unifying geometry with the same " - "materials. Especially effective in conjunction with " - "assimp-optimize-graph and assimp-remove-redundant-materials.")); - -ConfigVariableBool assimp_optimize_graph -("assimp-optimize-graph", false, - PRC_DESC("Optimizes the scene geometry by flattening the scene hierarchy. " - "This is very efficient (combined with assimp-optimize-meshes), but " - "it may result the hierarchy to become lost, so it is disabled by " - "default.")); - -ConfigVariableBool assimp_flip_winding_order -("assimp-flip-winding-order", false, - PRC_DESC("Set this true to flip the winding order of all models loaded via " - "the Assimp loader. Note that you may need to clear the model-cache " - "after changing this.")); - -ConfigVariableBool assimp_gen_normals -("assimp-gen-normals", false, - PRC_DESC("Set this true to generate normals (if absent from file) on import. " - "See assimp-smooth-normal-angle for more information. " - "Note that you may need to clear the model-cache after " - "changing this.")); - -ConfigVariableDouble assimp_smooth_normal_angle -("assimp-smooth-normal-angle", 0.0, - PRC_DESC("Set this to anything other than 0.0 in degrees (so 180.0 is PI) to " - "specify the maximum angle that may be between two face normals at " - "the same vertex position that are smoothed together. Sometimes " - "referred to as 'crease angle'. Only has effect if " - "assimp-gen-normals is set to true and the file does not contain " - "normals. Note that you may need to clear the model-cache after " - "changing this.")); - -ConfigVariableBool assimp_collapse_dummy_root_node -("assimp-collapse-dummy-root-node", true, - PRC_DESC("If set to true, collapses the root node that Assimp creates, if it " - "appears to be a synthetic dummy root node and contains no meshes. " - "This variable is new as of Panda3D 1.10.13 and will become true by " - "default as of Panda3D 1.11.0.")); - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libassimp() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - LoaderFileTypeAssimp::init_type(); - - LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr(); - reg->register_type(new LoaderFileTypeAssimp); -} diff --git a/pandatool/src/assimp/config_assimp.h b/pandatool/src/assimp/config_assimp.h deleted file mode 100644 index f999a600..00000000 --- a/pandatool/src/assimp/config_assimp.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_assimp.h - * @author rdb - * @date 2011-03-29 - */ - -#ifndef CONFIG_ASSIMP_H -#define CONFIG_ASSIMP_H - -#include "pandatoolbase.h" -#include "notifyCategoryProxy.h" -#include "configVariableBool.h" -#include "configVariableDouble.h" -#include "dconfig.h" - -ConfigureDecl(config_assimp, EXPCL_ASSIMP, EXPTP_ASSIMP); -NotifyCategoryDecl(assimp, EXPCL_ASSIMP, EXPTP_ASSIMP); - -extern ConfigVariableBool assimp_calc_tangent_space; -extern ConfigVariableBool assimp_join_identical_vertices; -extern ConfigVariableBool assimp_improve_cache_locality; -extern ConfigVariableBool assimp_remove_redundant_materials; -extern ConfigVariableBool assimp_fix_infacing_normals; -extern ConfigVariableBool assimp_optimize_meshes; -extern ConfigVariableBool assimp_optimize_graph; -extern ConfigVariableBool assimp_flip_winding_order; -extern ConfigVariableBool assimp_gen_normals; -extern ConfigVariableDouble assimp_smooth_normal_angle; -extern ConfigVariableBool assimp_collapse_dummy_root_node; - -extern EXPCL_ASSIMP void init_libassimp(); - -#endif diff --git a/pandatool/src/assimp/loaderFileTypeAssimp.cxx b/pandatool/src/assimp/loaderFileTypeAssimp.cxx deleted file mode 100644 index bd3061f2..00000000 --- a/pandatool/src/assimp/loaderFileTypeAssimp.cxx +++ /dev/null @@ -1,133 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file loaderFileTypeAssimp.cxx - * @author rdb - * @date 2011-03-29 - */ - -#include "loaderFileTypeAssimp.h" -#include "config_assimp.h" -#include "assimpLoader.h" - -#include - -using std::string; - -TypeHandle LoaderFileTypeAssimp::_type_handle; - -/** - * - */ -LoaderFileTypeAssimp:: -LoaderFileTypeAssimp() { -} - -/** - * - */ -LoaderFileTypeAssimp:: -~LoaderFileTypeAssimp() { -} - -/** - * - */ -string LoaderFileTypeAssimp:: -get_name() const { - return "Assimp Importer"; -} - -/** - * - */ -string LoaderFileTypeAssimp:: -get_extension() const { - return ""; -} - -/** - * Returns a space-separated list of extension, in addition to the one - * returned by get_extension(), that are recognized by this converter. - */ -string LoaderFileTypeAssimp:: -get_additional_extensions() const { - // This may be called at static init time, so ensure it is constructed now. - static ConfigVariableString assimp_disable_extensions - ("assimp-disable-extensions", "gltf glb", - PRC_DESC("A list of extensions (without preceding dot) that should not be " - "loaded via the Assimp loader, even if Assimp supports these " - "formats. It is useful to set this for eg. gltf and glb files " - "to prevent them from being accidentally loaded via the Assimp " - "plug-in instead of via a superior plug-in like panda3d-gltf.")); - - bool has_disabled_exts = !assimp_disable_extensions.empty(); - - aiString aexts; - aiGetExtensionList(&aexts); - - char *buffer = (char *)alloca(aexts.length + 2); - char *p = buffer; - - // The format is like: *.mdc;*.mdl;*.mesh.xml;*.mot - char *sub = strtok(aexts.data, ";"); - while (sub != nullptr) { - bool enabled = true; - if (has_disabled_exts) { - for (size_t i = 0; i < assimp_disable_extensions.get_num_words(); ++i) { - std::string disabled_ext = assimp_disable_extensions.get_word(i); - if (strcmp(sub + 2, disabled_ext.c_str()) == 0) { - enabled = false; - break; - } - } - } - if (enabled) { - *(p++) = ' '; - size_t len = strlen(sub + 2); - memcpy(p, sub + 2, len); - p += len; - } - - sub = strtok(nullptr, ";"); - } - - // Strip first space - ++buffer; - return std::string(buffer, p - buffer); -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz or .gz extension), false otherwise. - */ -bool LoaderFileTypeAssimp:: -supports_compressed() const { - return true; -} - -/** - * - */ -PT(PandaNode) LoaderFileTypeAssimp:: -load_file(const Filename &path, const LoaderOptions &options, - BamCacheRecord *record) const { - - assimp_cat.info() - << "Reading " << path << "\n"; - - AssimpLoader loader; - loader.local_object(); - - if (!loader.read(path)) { - return nullptr; - } - - loader.build_graph(); - return DCAST(PandaNode, loader._root); -} diff --git a/pandatool/src/assimp/loaderFileTypeAssimp.h b/pandatool/src/assimp/loaderFileTypeAssimp.h deleted file mode 100644 index 033ab9af..00000000 --- a/pandatool/src/assimp/loaderFileTypeAssimp.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file loaderFileTypeAssimp.h - * @author rdb - * @date 2011-03-29 - */ - -#ifndef LOADERFILETYPEASSIMP_H -#define LOADERFILETYPEASSIMP_H - -#include "config_assimp.h" -#include "loaderFileType.h" - -class AssimpLoader; - -/** - * This defines the Loader interface that uses the Assimp library to load - * various model formats. - */ -class EXPCL_ASSIMP LoaderFileTypeAssimp : public LoaderFileType { -public: - LoaderFileTypeAssimp(); - virtual ~LoaderFileTypeAssimp(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual std::string get_additional_extensions() const; - virtual bool supports_compressed() const; - - virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &options, - BamCacheRecord *record) const; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LoaderFileType::init_type(); - register_type(_type_handle, "LoaderFileTypeAssimp", - LoaderFileType::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; -}; - -#endif diff --git a/pandatool/src/assimp/p3assimp_composite1.cxx b/pandatool/src/assimp/p3assimp_composite1.cxx deleted file mode 100644 index bc813b11..00000000 --- a/pandatool/src/assimp/p3assimp_composite1.cxx +++ /dev/null @@ -1,7 +0,0 @@ - -#include "config_assimp.cxx" -#include "assimpLoader.cxx" -#include "loaderFileTypeAssimp.cxx" -#include "pandaIOStream.cxx" -#include "pandaIOSystem.cxx" -#include "pandaLogger.cxx" diff --git a/pandatool/src/assimp/pandaIOStream.cxx b/pandatool/src/assimp/pandaIOStream.cxx deleted file mode 100644 index e8d4dc86..00000000 --- a/pandatool/src/assimp/pandaIOStream.cxx +++ /dev/null @@ -1,107 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandaIOStream.cxx - * @author rdb - * @date 2011-03-29 - */ - -#include "pandaIOStream.h" - -using std::ios; - -/** - * - */ -PandaIOStream:: -PandaIOStream(std::istream &stream) : _istream(stream) { -} - -/** - * Returns the size of this file. - */ -size_t PandaIOStream:: -FileSize() const { - _istream.clear(); - std::streampos cur = _istream.tellg(); - _istream.seekg(0, ios::end); - std::streampos end = _istream.tellg(); - _istream.seekg(cur); - return end; -} - -/** - * See fflush. - */ -void PandaIOStream:: -Flush() { - nassertv(false); -} - -/** - * See fread. - */ -size_t PandaIOStream:: -Read(void *buffer, size_t size, size_t count) { - _istream.read((char *)buffer, size * count); - - if (_istream.eof()) { - // Gracefully handle EOF. - _istream.clear(ios::eofbit); - } - - return _istream.gcount() / size; -} - -/** - * See fseek. - */ -aiReturn PandaIOStream:: -Seek(size_t offset, aiOrigin origin) { - switch (origin) { - case aiOrigin_SET: - _istream.seekg(offset, ios::beg); - break; - - case aiOrigin_CUR: - _istream.seekg(offset, ios::cur); - break; - - case aiOrigin_END: - _istream.seekg(offset, ios::end); - break; - - default: - // Keep compiler happy - nassertr(false, AI_FAILURE); - break; - } - - if (_istream.good()) { - return AI_SUCCESS; - } else { - return AI_FAILURE; - } -} - -/** - * See ftell. - */ -size_t PandaIOStream:: -Tell() const { - return _istream.tellg(); -} - -/** - * See fwrite. - */ -size_t PandaIOStream:: -Write(const void *buffer, size_t size, size_t count) { - nassertr(false, 0); - return 0; -} diff --git a/pandatool/src/assimp/pandaIOStream.h b/pandatool/src/assimp/pandaIOStream.h deleted file mode 100644 index 18c24b14..00000000 --- a/pandatool/src/assimp/pandaIOStream.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandaIOStream.h - * @author rdb - * @date 2011-03-29 - */ - -#ifndef PANDAIOSTREAM_H -#define PANDAIOSTREAM_H - -#include "config_assimp.h" - -#include - -class PandaIOSystem; - -/** - * Custom implementation of Assimp::IOStream. It simply wraps around an - * istream object, and is unable to write. - */ -class PandaIOStream : public Assimp::IOStream { -public: - PandaIOStream(std::istream &stream); - virtual ~PandaIOStream() {}; - - size_t FileSize() const; - void Flush(); - size_t Read(void *pvBuffer, size_t pSize, size_t pCount); - aiReturn Seek(size_t pOffset, aiOrigin pOrigin); - size_t Tell() const; - size_t Write(const void *buffer, size_t size, size_t count); - -private: - std::istream &_istream; - - friend class PandaIOSystem; -}; - -#endif diff --git a/pandatool/src/assimp/pandaIOSystem.cxx b/pandatool/src/assimp/pandaIOSystem.cxx deleted file mode 100644 index 241790f6..00000000 --- a/pandatool/src/assimp/pandaIOSystem.cxx +++ /dev/null @@ -1,85 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandaIOSystem.cxx - * @author rdb - * @date 2011-03-29 - */ - -#include "pandaIOSystem.h" -#include "pandaIOStream.h" - -/** - * Initializes the object with the given VFS, or the global one if none was - * specified. - */ -PandaIOSystem:: -PandaIOSystem(VirtualFileSystem *vfs) : _vfs(vfs) { -} - -/** - * Returns true if the file exists, duh. - */ -bool PandaIOSystem:: -Exists(const char *file) const { - Filename fn = Filename::from_os_specific(file); - return _vfs->exists(fn); -} - -/** - * Closes the indicated file stream. - */ -void PandaIOSystem:: -Close(Assimp::IOStream *file) { - PandaIOStream *pstr = (PandaIOStream*) file; - _vfs->close_read_file(&pstr->_istream); -} - -/** - * Returns true if the two paths point to the same file, false if not. - */ -bool PandaIOSystem:: -ComparePaths(const char *p1, const char *p2) const { - Filename fn1 = Filename::from_os_specific(p1); - Filename fn2 = Filename::from_os_specific(p2); - fn1.make_canonical(); - fn2.make_canonical(); - return fn1 == fn2; -} - -/** - * Returns the path separator for this operating system. - */ -char PandaIOSystem:: -getOsSeparator() const { -#ifdef _WIN32 - return '\\'; -#else - return '/'; -#endif -} - -/** - * Opens the indicated file. - */ -Assimp::IOStream *PandaIOSystem:: -Open(const char *file, const char *mode) { - Filename fn = Filename::from_os_specific(file); - - if (mode[0] == 'r') { - std::istream *stream = _vfs->open_read_file(file, true); - if (stream == nullptr) { - return nullptr; - } - return new PandaIOStream(*stream); - - } else { - nassert_raise("write mode not implemented"); - return nullptr; - } -} diff --git a/pandatool/src/assimp/pandaIOSystem.h b/pandatool/src/assimp/pandaIOSystem.h deleted file mode 100644 index be8ad2dd..00000000 --- a/pandatool/src/assimp/pandaIOSystem.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandaIOSystem.h - * @author rdb - * @date 2011-03-29 - */ - -#ifndef PANDAIOSYSTEM_H -#define PANDAIOSYSTEM_H - -#include "config_assimp.h" -#include "virtualFileSystem.h" - -#include - -/** - * Custom implementation of Assimp::IOSystem. - */ -class PandaIOSystem : public Assimp::IOSystem { -public: - PandaIOSystem(VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr()); - virtual ~PandaIOSystem() {}; - - void Close(Assimp::IOStream *file); - bool ComparePaths(const char *p1, const char *p2) const; - bool Exists(const char *file) const; - char getOsSeparator() const; - Assimp::IOStream *Open(const char *file, const char *mode); - -private: - VirtualFileSystem *_vfs; -}; - -#endif diff --git a/pandatool/src/assimp/pandaLogger.cxx b/pandatool/src/assimp/pandaLogger.cxx deleted file mode 100644 index ee0a4132..00000000 --- a/pandatool/src/assimp/pandaLogger.cxx +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandaLogger.cxx - * @author rdb - * @date 2011-05-05 - */ - -#include "pandaLogger.h" - -#include - -PandaLogger *PandaLogger::_ptr = nullptr; - -/** - * Makes sure there's a global PandaLogger object and makes sure that it is - * Assimp's default logger. - */ -void PandaLogger:: -set_default() { - if (_ptr == nullptr) { - _ptr = new PandaLogger; - } - if (_ptr != Assimp::DefaultLogger::get()) { - Assimp::DefaultLogger::set(_ptr); - } -} - -/** - * - */ -void PandaLogger::OnDebug(const char *message) { - if (assimp_cat.is_debug()) { - assimp_cat.debug() << message << "\n"; - } -} - -/** - * - */ -void PandaLogger::OnVerboseDebug(const char *message) { - if (assimp_cat.is_spam()) { - assimp_cat.spam() << message << "\n"; - } -} - -/** - * - */ -void PandaLogger::OnError(const char *message) { - assimp_cat.error() << message << "\n"; -} - -/** - * - */ -void PandaLogger::OnInfo(const char *message) { - assimp_cat.info() << message << "\n"; -} - -/** - * - */ -void PandaLogger::OnWarn(const char *message) { - assimp_cat.warning() << message << "\n"; -} diff --git a/pandatool/src/assimp/pandaLogger.h b/pandatool/src/assimp/pandaLogger.h deleted file mode 100644 index 2fdbd446..00000000 --- a/pandatool/src/assimp/pandaLogger.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandaLogger.h - * @author rdb - * @date 2011-05-05 - */ - -#ifndef PANDALOGGER_H -#define PANDALOGGER_H - -#include "config_assimp.h" - -#include - -/** - * Custom implementation of Assimp::Logger. It simply wraps around the - * assimp_cat methods. - */ -class PandaLogger : public Assimp::Logger { -public: - static void set_default(); - -protected: - INLINE bool attachStream(Assimp::LogStream*, unsigned int) { - return false; - }; - INLINE bool detachStream(Assimp::LogStream*, unsigned int) { - return false; - }; - - // Kept for compatibility with Assimp 4.x - INLINE bool detatchStream(Assimp::LogStream*, unsigned int) { - return false; - }; - - void OnDebug(const char *message); - void OnVerboseDebug(const char *message); - void OnError(const char *message); - void OnInfo(const char *message); - void OnWarn(const char *message); - -private: - static PandaLogger *_ptr; -}; - -#endif diff --git a/pandatool/src/bam/CMakeLists.txt b/pandatool/src/bam/CMakeLists.txt deleted file mode 100644 index 32f5a6f5..00000000 --- a/pandatool/src/bam/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(bam-info bamInfo.cxx bamInfo.h) -target_link_libraries(bam-info p3progbase panda) -install(TARGETS bam-info EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -if(HAVE_EGG) - - add_executable(egg2bam eggToBam.cxx eggToBam.h) - target_link_libraries(egg2bam p3eggbase p3progbase panda) - install(TARGETS egg2bam EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - - if(HAVE_SQUISH) - target_compile_definitions(egg2bam PRIVATE HAVE_SQUISH) - endif() - - add_executable(bam2egg bamToEgg.cxx bamToEgg.h) - target_link_libraries(bam2egg p3converter p3eggbase p3progbase panda) - install(TARGETS bam2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - - add_executable(pts2bam ptsToBam.cxx ptsToBam.h) - target_link_libraries(pts2bam p3progbase pandaegg panda) - install(TARGETS pts2bam EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -endif() diff --git a/pandatool/src/bam/bamInfo.cxx b/pandatool/src/bam/bamInfo.cxx deleted file mode 100644 index 291d3379..00000000 --- a/pandatool/src/bam/bamInfo.cxx +++ /dev/null @@ -1,328 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file bamInfo.cxx - * @author drose - * @date 2000-07-02 - */ - -#include "bamInfo.h" - -#include "bamFile.h" -#include "pandaNode.h" -#include "geomNode.h" -#include "texture.h" -#include "recorderHeader.h" -#include "recorderFrame.h" -#include "recorderTable.h" -#include "dcast.h" -#include "pvector.h" -#include "bamCacheRecord.h" -#include "bamCacheIndex.h" - -/** - * - */ -BamInfo:: -BamInfo() { - set_program_brief("describe the contents of .bam files"); - set_program_description - ("This program scans one or more Bam files--Panda's Binary Animation " - "and Models native binary format--and describes their contents."); - - clear_runlines(); - add_runline("[opts] input.bam [input.bam ... ]"); - - add_option - ("ls", "", 0, - "List the scene graph hierarchy in the bam file.", - &BamInfo::dispatch_none, &_ls); - - add_option - ("t", "", 0, - "List explicitly each transition in the hierarchy.", - &BamInfo::dispatch_none, &_verbose_transitions); - - add_option - ("g", "", 0, - "Output verbose information about each Geom in the Bam file.", - &BamInfo::dispatch_none, &_verbose_geoms); - - _num_scene_graphs = 0; -} - - -/** - * - */ -void BamInfo:: -run() { - bool okflag = true; - - Filenames::const_iterator fi; - for (fi = _filenames.begin(); fi != _filenames.end(); ++fi) { - if (!get_info(*fi)) { - okflag = false; - } - } - - if (_num_scene_graphs > 0) { - nout << "\nScene graph statistics:\n"; - _analyzer.write(nout, 2); - } - nout << "\n"; - - if (!okflag) { - // Exit with an error if any of the files was unreadable. - exit(1); - } -} - - -/** - * - */ -bool BamInfo:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the Bam file(s) to read on the command line.\n"; - return false; - } - - ProgramBase::Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - _filenames.push_back(*ai); - } - - return true; -} - - -/** - * Reads a single Bam file and displays its contents. Returns true if - * successful, false on error. - */ -bool BamInfo:: -get_info(const Filename &filename) { - BamFile bam_file; - - if (!bam_file.open_read(filename)) { - nout << "Unable to read.\n"; - return false; - } - - const char *endian = "little-endian"; - if (bam_file.get_file_endian() == BamEnums::BE_bigendian) { - endian = "big-endian"; - } - int float_width = 32; - if (bam_file.get_file_stdfloat_double()) { - float_width = 64; - } - - nout << filename << " : Bam version " << bam_file.get_file_major_ver() - << "." << bam_file.get_file_minor_ver() - << ", " << endian << ", " << float_width << "-bit floats.\n"; - - Objects objects; - TypedWritable *object = bam_file.read_object(); - - if (object != nullptr && - object->is_exact_type(BamCacheRecord::get_class_type())) { - // Here's a special case: if the first object in the file is a - // BamCacheRecord, it's a cache data file; in this case, we output the - // cache record, and then pretend it doesn't exist. - DCAST(BamCacheRecord, object)->write(nout, 2); - nout << "\n"; - object = bam_file.read_object(); - } - - while (object != nullptr || !bam_file.is_eof()) { - if (object != nullptr) { - objects.push_back(object); - } - object = bam_file.read_object(); - } - if (!bam_file.resolve()) { - nout << "Unable to fully resolve file.\n"; - return false; - } - - // We can't close the bam file until we have examined the objects, since - // closing it will decrement reference counts. - - if (objects.size() == 1 && - objects[0]->is_of_type(PandaNode::get_class_type())) { - describe_scene_graph(DCAST(PandaNode, objects[0])); - - } else if (objects.size() == 1 && - objects[0]->is_of_type(Texture::get_class_type())) { - describe_texture(DCAST(Texture, objects[0])); - - } else if (objects.size() == 1 && - objects[0]->is_of_type(BamCacheIndex::get_class_type())) { - describe_cache_index(DCAST(BamCacheIndex, objects[0])); - - } else if (!objects.empty() && objects[0]->is_of_type(RecorderHeader::get_class_type())) { - describe_session(DCAST(RecorderHeader, objects[0]), objects); - - } else { - nout << "file contains " << objects.size() << " objects:\n"; - for (int i = 0; i < (int)objects.size(); i++) { - describe_general_object(objects[i]); - } - } - - return true; -} - - -/** - * Called for Bam files that contain a single scene graph and no other - * objects. This should describe that scene graph in some meaningful way. - */ -void BamInfo:: -describe_scene_graph(PandaNode *node) { - // Parent the node to our own scene graph root, so we can (a) guarantee it - // won't accidentally be deleted before we're done, (b) easily determine the - // bounding volume of the scene, and (c) report statistics on all the bam - // file's scene graphs together when we've finished. - - PT(PandaNode) root = new PandaNode("root"); - root->add_child(node); - _num_scene_graphs++; - - int num_nodes = _analyzer.get_num_nodes(); - _analyzer.add_node(node); - num_nodes = _analyzer.get_num_nodes() - num_nodes; - - nout << " " << num_nodes << " nodes, bounding volume is " - << *root->get_bounds() << "\n"; - - if (_ls || _verbose_geoms || _verbose_transitions) { - list_hierarchy(node, 0); - } -} - -/** - * Called for Bam files that contain a Texture object. - */ -void BamInfo:: -describe_texture(Texture *tex) { - tex->write(nout, 2); -} - -/** - * Called for Bam files that contain a BamCacheIndex object. - */ -void BamInfo:: -describe_cache_index(BamCacheIndex *index) { - index->write(nout, 2); -} - -/** - * Called for Bam files that contain a recorded session table. - */ -void BamInfo:: -describe_session(RecorderHeader *header, const BamInfo::Objects &objects) { - char time_buffer[1024]; - strftime(time_buffer, 1024, "%c", - localtime(&header->_start_time)); - - pset recorders; - double last_timestamp = 0.0; - - for (size_t i = 1; i < objects.size(); i++) { - if (objects[i]->is_of_type(RecorderFrame::get_class_type())) { - RecorderFrame *frame = DCAST(RecorderFrame, objects[i]); - if (frame->_table_changed) { - RecorderTable::Recorders::const_iterator ri; - for (ri = frame->_table->_recorders.begin(); - ri != frame->_table->_recorders.end(); - ++ri) { - recorders.insert((*ri).first); - } - } - last_timestamp = frame->_timestamp; - } - } - - nout << "Session, " << last_timestamp - << " secs, " << objects.size() - 1 << " frames, " - << time_buffer << ".\n" - << "Recorders:"; - for (pset::iterator ni = recorders.begin(); - ni != recorders.end(); - ++ni) { - nout << " " << (*ni); - } - nout << "\n"; -} - -/** - * Called for Bam files that contain multiple objects which may or may not be - * scene graph nodes. This should describe each object in some meaningful - * way. - */ -void BamInfo:: -describe_general_object(TypedWritable *object) { - nassertv(object != nullptr); - nout << " " << object->get_type() << "\n"; -} - -/** - * Outputs the hierarchy and all of the verbose GeomNode information. - */ -void BamInfo:: -list_hierarchy(PandaNode *node, int indent_level) { - indent(nout, indent_level) << *node; - - if (_verbose_transitions) { - nout << "\n"; - if (!node->get_transform()->is_identity()) { - node->get_transform()->write(nout, indent_level); - } - if (!node->get_state()->is_empty()) { - node->get_state()->write(nout, indent_level); - } - if (!node->get_effects()->is_empty()) { - node->get_effects()->write(nout, indent_level); - } - - } else { - if (!node->get_transform()->is_identity()) { - nout << " " << *node->get_transform(); - } - if (!node->get_state()->is_empty()) { - nout << " " << *node->get_state(); - } - if (!node->get_effects()->is_empty()) { - nout << " " << *node->get_effects(); - } - nout << "\n"; - } - - if (_verbose_geoms && node->is_geom_node()) { - GeomNode *geom_node; - DCAST_INTO_V(geom_node, node); - geom_node->write_verbose(nout, indent_level); - } - - int num_children = node->get_num_children(); - for (int i = 0; i < num_children; i++) { - PandaNode *child = node->get_child(i); - list_hierarchy(child, indent_level + 2); - } -} - -int main(int argc, char *argv[]) { - BamInfo prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/bam/bamInfo.h b/pandatool/src/bam/bamInfo.h deleted file mode 100644 index 766c6986..00000000 --- a/pandatool/src/bam/bamInfo.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file bamInfo.h - * @author drose - * @date 2000-07-02 - */ - -#ifndef BAMINFO_H -#define BAMINFO_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "filename.h" -#include "sceneGraphAnalyzer.h" - -#include "pvector.h" - -class TypedWritable; -class PandaNode; -class Texture; -class BamCacheIndex; -class RecorderHeader; - -/** - * - */ -class BamInfo : public ProgramBase { -public: - BamInfo(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - -private: - typedef pvector Objects; - - bool get_info(const Filename &filename); - void describe_scene_graph(PandaNode *node); - void describe_texture(Texture *tex); - void describe_cache_index(BamCacheIndex *index); - void describe_session(RecorderHeader *header, const Objects &objects); - void describe_general_object(TypedWritable *object); - void list_hierarchy(PandaNode *node, int indent_level); - - typedef pvector Filenames; - Filenames _filenames; - - bool _ls; - bool _verbose_transitions; - bool _verbose_geoms; - - int _num_scene_graphs; - SceneGraphAnalyzer _analyzer; -}; - -#endif diff --git a/pandatool/src/bam/bamToEgg.cxx b/pandatool/src/bam/bamToEgg.cxx deleted file mode 100644 index 96aa14e4..00000000 --- a/pandatool/src/bam/bamToEgg.cxx +++ /dev/null @@ -1,104 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file bamToEgg.cxx - * @author drose - * @date 2001-06-25 - */ - -#include "bamToEgg.h" -#include "save_egg_file.h" -#include "string_utils.h" -#include "bamFile.h" -#include "bamCacheRecord.h" - -/** - * - */ -BamToEgg:: -BamToEgg() : - SomethingToEgg("bam", ".bam") -{ - set_program_brief("convert a native Panda .bam file to an .egg file"); - set_program_description - ("This program converts native Panda bam files to egg. The conversion " - "is somewhat incomplete; running egg2bam followed by bam2egg should not " - "be expected to yield the same egg file you started with."); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. By default, this is taken from the Config.prc file, which " - "is currently " + format_string(get_default_coordinate_system()) + "."); - - _coordinate_system = get_default_coordinate_system(); -} - -/** - * - */ -void BamToEgg:: -run() { - BamFile bam_file; - - if (!bam_file.open_read(_input_filename)) { - nout << "Unable to read " << _input_filename << "\n"; - exit(1); - } - - nout << _input_filename << " : Bam version " - << bam_file.get_file_major_ver() << "." - << bam_file.get_file_minor_ver() << "\n"; - - typedef pvector Objects; - Objects objects; - TypedWritable *object = bam_file.read_object(); - - if (object != nullptr && - object->is_exact_type(BamCacheRecord::get_class_type())) { - // Here's a special case: if the first object in the file is a - // BamCacheRecord, it's really a cache data file and not a true bam file; - // but skip over the cache data record and let the user treat it like an - // ordinary bam file. - object = bam_file.read_object(); - } - - while (object != nullptr || !bam_file.is_eof()) { - if (object != nullptr) { - ReferenceCount *ref_ptr = object->as_reference_count(); - if (ref_ptr != nullptr) { - ref_ptr->ref(); - } - objects.push_back(object); - } - object = bam_file.read_object(); - } - bam_file.resolve(); - bam_file.close(); - - _data->set_coordinate_system(_coordinate_system); - - if (objects.size() == 1 && - objects[0]->is_of_type(PandaNode::get_class_type())) { - PandaNode *node = DCAST(PandaNode, objects[0]); - save_egg_data(_data, node); - - } else { - nout << "File does not contain a scene graph.\n"; - exit(1); - } - - write_egg_file(); -} - -int main(int argc, char *argv[]) { - BamToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/bam/bamToEgg.h b/pandatool/src/bam/bamToEgg.h deleted file mode 100644 index f5a29c3f..00000000 --- a/pandatool/src/bam/bamToEgg.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file bamToEgg.h - * @author drose - * @date 2001-06-25 - */ - -#ifndef BAMTOEGG_H -#define BAMTOEGG_H - -#include "pandatoolbase.h" - -#include "somethingToEgg.h" - -/** - * This program reads a bam file, for instance as written out from a real-time - * interaction session, and generates a corresponding egg file. - */ -class BamToEgg : public SomethingToEgg { -public: - BamToEgg(); - - void run(); - -private: -}; - -#endif diff --git a/pandatool/src/bam/eggToBam.cxx b/pandatool/src/bam/eggToBam.cxx deleted file mode 100644 index a7e760d2..00000000 --- a/pandatool/src/bam/eggToBam.cxx +++ /dev/null @@ -1,491 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToBam.cxx - * @author drose - * @date 2000-06-28 - */ - -#include "eggToBam.h" - -#include "config_putil.h" -#include "bamFile.h" -#include "load_egg_file.h" -#include "config_egg2pg.h" -#include "config_gobj.h" -#include "config_chan.h" -#include "pandaNode.h" -#include "geomNode.h" -#include "renderState.h" -#include "textureAttrib.h" -#include "dcast.h" -#include "graphicsPipeSelection.h" -#include "graphicsEngine.h" -#include "graphicsBuffer.h" -#include "graphicsStateGuardian.h" -#include "load_prc_file.h" -#include "windowProperties.h" -#include "frameBufferProperties.h" - -/** - * - */ -EggToBam:: -EggToBam() : - EggToSomething("Bam", ".bam", true, false) -{ - set_program_brief("convert .egg files to .bam files"); - set_program_description - ("This program reads Egg files and outputs Bam files, the binary format " - "suitable for direct loading of animation and models into Panda. Bam " - "files are tied to a particular version of Panda, so should not be " - "considered replacements for egg files, but they tend to be smaller and " - "load much faster than the equivalent egg files."); - - // -f is always in effect for egg2bam. It doesn't make sense to provide it - // as an option to the user. - remove_option("f"); - - add_path_replace_options(); - add_path_store_options(); - - add_option - ("flatten", "flag", 0, - "Specifies whether to flatten the egg hierarchy after it is loaded. " - "If flag is zero, the egg hierarchy will not be flattened, but will " - "instead be written to the bam file exactly as it is. If flag is " - "non-zero, the hierarchy will be flattened so that unnecessary nodes " - "(usually group nodes with only one child) are eliminated. The default " - "if this is not specified is taken from the egg-flatten Config.prc " - "variable.", - &EggToBam::dispatch_int, &_has_egg_flatten, &_egg_flatten); - - add_option - ("combine-geoms", "flag", 0, - "Specifies whether to combine sibling GeomNodes into a common GeomNode " - "when possible. This flag is only respected if flatten, above, is also " - "enabled (or implicitly true from the Config.prc file). The default if " - "this is not specified is taken from the egg-combine-geoms Config.prc " - "variable.", - &EggToBam::dispatch_int, &_has_egg_combine_geoms, &_egg_combine_geoms); - - add_option - ("suppress-hidden", "flag", 0, - "Specifies whether to suppress hidden geometry. If this is nonzero, " - "egg geometry tagged as \"hidden\" will be removed from the final " - "scene graph; otherwise, it will be preserved (but stashed). The " - "default is nonzero, to remove it.", - &EggToBam::dispatch_int, nullptr, &_egg_suppress_hidden); - - add_option - ("ls", "", 0, - "Writes a scene graph listing to standard output after the egg " - "file has been loaded, showing the nodes that will be written out.", - &EggToBam::dispatch_none, &_ls); - - add_option - ("C", "quality", 0, - "Specify the quality level for lossy channel compression. If this " - "is specified, the animation channels will be compressed at this " - "quality level, which is normally an integer value between 0 and 100, " - "inclusive, where higher numbers produce larger files with greater " - "quality. Generally, 95 is the highest useful quality level. Use " - "-NC (described below) to disable channel compression. If neither " - "option is specified, the default comes from the Config.prc file.", - &EggToBam::dispatch_int, &_has_compression_quality, &_compression_quality); - - add_option - ("NC", "", 0, - "Turn off lossy compression of animation channels. Channels will be " - "written exactly as they are, losslessly.", - &EggToBam::dispatch_none, &_compression_off); - - add_option - ("rawtex", "", 0, - "Record texture data directly in the bam file, instead of storing " - "a reference to the texture elsewhere on disk. The textures are " - "stored uncompressed, unless -ctex is also specified. " - "A particular texture that is encoded into " - "multiple different bam files in this way cannot be unified into " - "the same part of texture memory if the different bam files are loaded " - "together. That being said, this can sometimes be a convenient " - "way to ensure the bam file is completely self-contained.", - &EggToBam::dispatch_none, &_tex_rawdata); - - add_option - ("txo", "", 0, - "Rather than writing texture data directly into the bam file, as in " - "-rawtex, create a texture object for each referenced texture. A " - "texture object is a kind of mini-bam file, with a .txo extension, " - "that contains all of the data needed to recreate a texture, including " - "its image contents, filter and wrap settings, and so on. 3-D textures " - "and cube maps can also be represented in a single .txo file. Texture " - "object files, like bam files, are tied to a particular version of " - "Panda.", - &EggToBam::dispatch_none, &_tex_txo); - -#ifdef HAVE_ZLIB - add_option - ("txopz", "", 0, - "In addition to writing texture object files as above, compress each " - "one using pzip to a .txo.pz file. In many cases, this will yield a " - "disk file size comparable to that achieved by png compression. This " - "is an on-disk compression only, and does not affect the amount of " - "RAM or texture memory consumed by the texture when it is loaded.", - &EggToBam::dispatch_none, &_tex_txopz); -#endif // HAVE_ZLIB - - add_option - ("ctex", "", 0, -#ifdef HAVE_SQUISH - "Pre-compress the texture images using the libsquish library, when " - "using -rawtex or -txo. " -#else - "Asks the graphics card to pre-compress the texture images when using " - "-rawtex or -txo. " -#endif // HAVE_SQUISH -#ifdef HAVE_ZLIB - "This is unrelated to the on-disk compression achieved " - "via -txopz (and it may be used in conjunction with that parameter). " -#endif // HAVE_ZLIB - "This will result in a smaller RAM and texture memory footprint for " - "the texture images. The same " - "effect can be achieved at load time by setting compressed-textures in " - "your Config.prc file; but -ctex pre-compresses the " - "textures so that they do not need to be compressed at load time. " -#ifndef HAVE_SQUISH - "Note that, since your Panda is not compiled with the libsquish " - "library, using -ctex will make .txo files that are only guaranteed " - "to load on the particular graphics card that was used to " - "generate them." -#endif // HAVE_SQUISH - , - &EggToBam::dispatch_none, &_tex_ctex); - - add_option - ("mipmap", "", 0, - "Records the pre-generated mipmap levels in the texture object file " - "when using -rawtex or -txo, regardless of the texture filter mode. This " - "will increase the size of the texture object file by about 33%, but " - "it prevents the need to compute the mipmaps at runtime. The default " - "is to record mipmap levels only when the texture uses a mipmap " - "filter mode.", - &EggToBam::dispatch_none, &_tex_mipmap); - - add_option - ("ctexq", "quality", 0, - "Specifies the compression quality to use when performing the " - "texture compression requested by -ctex. This may be one of " - "'default', 'fastest', 'normal', or 'best'. The default is 'best'. " - "Set it to 'default' to use whatever is specified by the Config.prc " - "file. This is a global setting only; individual texture quality " - "settings appearing within the egg file will override this.", - &EggToBam::dispatch_string, nullptr, &_ctex_quality); - - add_option - ("load-display", "display name", 0, - "Specifies the particular display module to load to perform the texture " - "compression requested by -ctex. If this is omitted, the default is " - "taken from the Config.prc file." -#ifdef HAVE_SQUISH - " Since your Panda has libsquish compiled in, this is not necessary; " - "Panda can compress textures without loading a display module." -#endif // HAVE_SQUISH - , - &EggToBam::dispatch_string, nullptr, &_load_display); - - redescribe_option - ("cs", - "Specify the coordinate system of the resulting " + _format_name + - " file. This may be " - "one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default " - "is z-up."); - - _force_complete = true; - _egg_flatten = 0; - _egg_combine_geoms = 0; - _egg_suppress_hidden = 1; - _tex_txopz = false; - _ctex_quality = "best"; -} - -/** - * - */ -void EggToBam:: -run() { - if (_has_egg_flatten) { - // If the user specified some -flatten, we need to set the corresponding - // Config.prc variable. - egg_flatten = (_egg_flatten != 0); - } - if (_has_egg_combine_geoms) { - // Ditto with -combine_geoms. - egg_combine_geoms = (_egg_combine_geoms != 0); - } - - // We always set egg_suppress_hidden. - egg_suppress_hidden = _egg_suppress_hidden; - - if (_compression_off) { - // If the user specified -NC, turn off channel compression. - compress_channels = false; - - } else if (_has_compression_quality) { - // Otherwise, if the user specified a compression quality with -C, use - // that quality level. - compress_channels = true; - compress_chan_quality = _compression_quality; - } - - if (_ctex_quality != "default") { - // Override the user's config file with the command-line parameter for - // texture compression. - std::string prc = "texture-quality-level " + _ctex_quality; - load_prc_file_data("prc", prc); - } - - if (!_got_coordinate_system) { - // If the user didn't specify otherwise, ensure the coordinate system is - // Z-up. - _data->set_coordinate_system(CS_zup_right); - } - - PT(PandaNode) root = load_egg_data(_data); - if (root == nullptr) { - nout << "Unable to build scene graph from egg file.\n"; - exit(1); - } - - if (_tex_ctex) { -#ifndef HAVE_SQUISH - if (!make_buffer()) { - nout << "Unable to initialize graphics context; cannot compress textures.\n"; - exit(1); - } -#endif // HAVE_SQUISH - } - - if (_tex_txo || _tex_txopz || (_tex_ctex && _tex_rawdata)) { - collect_textures(root); - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - Texture *tex = (*ti); - tex->get_ram_image(); - bool want_mipmaps = (_tex_mipmap || tex->uses_mipmaps()); - if (want_mipmaps) { - // Generate mipmap levels. - tex->generate_ram_mipmap_images(); - } - - if (_tex_ctex) { -#ifdef HAVE_SQUISH - if (!tex->compress_ram_image()) { - nout << " couldn't compress " << tex->get_name() << "\n"; - } - tex->set_compression(Texture::CM_on); -#else // HAVE_SQUISH - tex->set_keep_ram_image(true); - bool has_mipmap_levels = (tex->get_num_ram_mipmap_images() > 1); - if (!_engine->extract_texture_data(tex, _gsg)) { - nout << " couldn't compress " << tex->get_name() << "\n"; - } - if (!has_mipmap_levels && !want_mipmaps) { - // Make sure we didn't accidentally introduce mipmap levels by - // rendezvousing through the graphics card. - tex->clear_ram_mipmap_images(); - } - tex->set_keep_ram_image(false); -#endif // HAVE_SQUISH - } - - if (_tex_txo || _tex_txopz) { - convert_txo(tex); - } - } - } - - if (_ls) { - root->ls(nout, 0); - } - - // This should be guaranteed because we pass false to the constructor, - // above. - nassertv(has_output_filename()); - - Filename filename = get_output_filename(); - filename.make_dir(); - nout << "Writing " << filename << "\n"; - BamFile bam_file; - if (!bam_file.open_write(filename)) { - nout << "Error in writing.\n"; - exit(1); - } - - if (!bam_file.write_object(root)) { - nout << "Error in writing.\n"; - exit(1); - } -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggToBam:: -handle_args(ProgramBase::Args &args) { - // If the user specified a path store option, we need to set the bam- - // texture-mode Config.prc variable directly to support this (otherwise the - // bam code will do what it wants to do anyway). - if (_tex_rawdata) { - bam_texture_mode = BamFile::BTM_rawdata; - - } else if (_got_path_store) { - bam_texture_mode = BamFile::BTM_unchanged; - - } else { - // Otherwise, the default path store is absolute; then the bam-texture- - // mode can do the appropriate thing to it. - _path_replace->_path_store = PS_absolute; - } - - return EggToSomething::handle_args(args); -} - -/** - * Recursively walks the scene graph, looking for Texture references. - */ -void EggToBam:: -collect_textures(PandaNode *node) { - collect_textures(node->get_state()); - if (node->is_geom_node()) { - GeomNode *geom_node = DCAST(GeomNode, node); - int num_geoms = geom_node->get_num_geoms(); - for (int i = 0; i < num_geoms; ++i) { - collect_textures(geom_node->get_geom_state(i)); - } - } - - PandaNode::Children children = node->get_children(); - int num_children = children.get_num_children(); - for (int i = 0; i < num_children; ++i) { - collect_textures(children.get_child(i)); - } -} - -/** - * Recursively walks the scene graph, looking for Texture references. - */ -void EggToBam:: -collect_textures(const RenderState *state) { - const TextureAttrib *tex_attrib = DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_type())); - if (tex_attrib != nullptr) { - int num_on_stages = tex_attrib->get_num_on_stages(); - for (int i = 0; i < num_on_stages; ++i) { - _textures.insert(tex_attrib->get_on_texture(tex_attrib->get_on_stage(i))); - } - } -} - -/** - * If the indicated Texture was not already loaded from a txo file, writes it - * to a txo file and updates the Texture object to reference the new file. - */ -void EggToBam:: -convert_txo(Texture *tex) { - if (!tex->get_loaded_from_txo()) { - Filename fullpath = tex->get_fullpath().get_filename_index(0); - if (_tex_txopz) { - fullpath.set_extension("txo.pz"); - // We use this clumsy syntax so that the new extension appears to be two - // separate extensions, .txo followed by .pz, which is what - // Texture::write() expects to find. - fullpath = Filename(fullpath.get_fullpath()); - } else { - fullpath.set_extension("txo"); - } - - if (tex->write(fullpath)) { - nout << " Writing " << fullpath; - if (tex->get_ram_image_compression() != Texture::CM_off) { - nout << " (compressed " << tex->get_ram_image_compression() << ")"; - } - nout << "\n"; - tex->set_loaded_from_txo(); - tex->set_fullpath(fullpath); - tex->clear_alpha_fullpath(); - - Filename filename = tex->get_filename().get_filename_index(0); - if (_tex_txopz) { - filename.set_extension("txo.pz"); - filename = Filename(filename.get_fullpath()); - } else { - filename.set_extension("txo"); - } - - tex->set_filename(filename); - tex->clear_alpha_filename(); - } - } -} - -/** - * Creates a GraphicsBuffer for communicating with the graphics card. - */ -bool EggToBam:: -make_buffer() { - if (!_load_display.empty()) { - // Override the user's config file with the command-line parameter. - std::string prc = "load-display " + _load_display; - load_prc_file_data("prc", prc); - } - - GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); - _pipe = selection->make_default_pipe(); - if (_pipe == nullptr) { - nout << "Unable to create graphics pipe.\n"; - return false; - } - - _engine = new GraphicsEngine; - - FrameBufferProperties fbprops = FrameBufferProperties::get_default(); - - // Some graphics drivers can only create single-buffered offscreen buffers. - // So request that. - fbprops.set_back_buffers(0); - - WindowProperties winprops; - winprops.set_size(1, 1); - winprops.set_origin(0, 0); - winprops.set_undecorated(true); - winprops.set_open(true); - winprops.set_z_order(WindowProperties::Z_bottom); - - // We don't care how big the buffer is; we just need it to manifest the GSG. - _buffer = _engine->make_output(_pipe, "buffer", 0, - fbprops, winprops, - GraphicsPipe::BF_fb_props_optional); - _engine->open_windows(); - if (_buffer == nullptr || !_buffer->is_valid()) { - nout << "Unable to create graphics window.\n"; - return false; - } - _gsg = _buffer->get_gsg(); - - return true; -} - - -int main(int argc, char *argv[]) { - EggToBam prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/bam/eggToBam.h b/pandatool/src/bam/eggToBam.h deleted file mode 100644 index 1ab262a5..00000000 --- a/pandatool/src/bam/eggToBam.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToBam.h - * @author drose - * @date 2000-06-28 - */ - -#ifndef EGGTOBAM_H -#define EGGTOBAM_H - -#include "pandatoolbase.h" - -#include "eggToSomething.h" -#include "pset.h" -#include "graphicsPipe.h" - -class PandaNode; -class RenderState; -class Texture; -class GraphicsEngine; -class GraphicsStateGuardian; -class GraphicsOutput; - -/** - * - */ -class EggToBam : public EggToSomething { -public: - EggToBam(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - -private: - void collect_textures(PandaNode *node); - void collect_textures(const RenderState *state); - void convert_txo(Texture *tex); - - bool make_buffer(); - -private: - typedef pset Textures; - Textures _textures; - - bool _has_egg_flatten; - int _egg_flatten; - bool _has_egg_combine_geoms; - int _egg_combine_geoms; - bool _egg_suppress_hidden; - bool _ls; - bool _has_compression_quality; - int _compression_quality; - bool _compression_off; - bool _tex_rawdata; - bool _tex_txo; - bool _tex_txopz; - bool _tex_ctex; - bool _tex_mipmap; - std::string _ctex_quality; - std::string _load_display; - - // The rest of this is required to support -ctex. - PT(GraphicsPipe) _pipe; - GraphicsStateGuardian *_gsg; - GraphicsEngine *_engine; - GraphicsOutput *_buffer; -}; - -#endif diff --git a/pandatool/src/bam/ptsToBam.cxx b/pandatool/src/bam/ptsToBam.cxx deleted file mode 100644 index 0059df86..00000000 --- a/pandatool/src/bam/ptsToBam.cxx +++ /dev/null @@ -1,238 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file ptsToBam.cxx - * @author drose - * @date 2000-06-28 - */ - -#include "ptsToBam.h" - -#include "config_putil.h" -#include "geomPoints.h" -#include "bamFile.h" -#include "pandaNode.h" -#include "geomNode.h" -#include "dcast.h" -#include "string_utils.h" -#include "config_egg2pg.h" - -using std::string; - -/** - * - */ -PtsToBam:: -PtsToBam() : WithOutputFile(true, false, true) -{ - set_program_brief("convert point cloud data into a .bam file"); - set_program_description - ("This program reads a point clound in a pts file and outputs a bam files, " - "suitable for viewing in Panda."); - - clear_runlines(); - add_runline("[opts] input.pts output.bam"); - add_runline("[opts] -o output.bam input.pts"); - - add_option - ("o", "filename", 0, - "Specify the filename to which the resulting .bam file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file.", - &PtsToBam::dispatch_filename, &_got_output_filename, &_output_filename); - - add_option - ("d", "divisor", 0, - "Decimates the point cloud by the indicated divisor. The number of points\n" - "added is 1/divisor; numbers larger than 1.0 mean correspondingly fewer\n" - "points.", - &PtsToBam::dispatch_double, nullptr, &_decimate_divisor); - - _decimate_divisor = 1.0; -} - -/** - * - */ -void PtsToBam:: -run() { - pifstream pts; - _pts_filename.set_text(); - if (!_pts_filename.open_read(pts)) { - nout << "Cannot open " << _pts_filename << "\n"; - exit(1); - } - - _gnode = new GeomNode(_pts_filename.get_basename()); - - _num_points_expected = 0; - _num_points_found = 0; - _num_points_added = 0; - _decimate_factor = 1.0 / std::max(1.0, _decimate_divisor); - _line_number = 0; - _point_number = 0; - _decimated_point_number = 0.0; - _num_vdatas = 0; - string line; - while (std::getline(pts, line)) { - process_line(line); - } - close_vertex_data(); - - nout << "\nFound " << _num_points_found << " points of " << _num_points_expected << " expected.\n"; - nout << "Generated " << _num_points_added << " points to bam file.\n"; - - // This should be guaranteed because we pass false to the constructor, - // above. - nassertv(has_output_filename()); - - Filename filename = get_output_filename(); - filename.make_dir(); - nout << "Writing " << filename << "\n"; - BamFile bam_file; - if (!bam_file.open_write(filename)) { - nout << "Error in writing.\n"; - exit(1); - } - - if (!bam_file.write_object(_gnode.p())) { - nout << "Error in writing.\n"; - exit(1); - } -} - -/** - * - */ -bool PtsToBam:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the pts file to read on the command line.\n"; - return false; - } - - if (args.size() > 1) { - nout << "Specify only one pts on the command line.\n"; - return false; - } - - _pts_filename = Filename::from_os_specific(args[0]); - - return true; -} - -/** - * Reads a single line from the pts file. - */ -void PtsToBam:: -process_line(const string &line) { - _line_number++; - - if (_line_number % 1000000 == 0) { - std::cerr << "." << std::flush; - } - - if (line.empty() || !isdigit(line[0])) { - return; - } - - if (_line_number == 1) { - // The first line might be just the number of points. - vector_string words; - tokenize(trim(line), words, " \t", true); - if (words.size() == 1) { - string tail; - _num_points_expected = string_to_int(words[0], tail); - nout << "Expecting " << _num_points_expected << " points, will generate " - << (int)(_num_points_expected * _decimate_factor) << "\n"; - return; - } - } - - // Here we might have a point. - _num_points_found++; - _decimated_point_number += _decimate_factor; - int point_number = int(_decimated_point_number); - if (point_number > _point_number) { - _point_number = point_number; - - vector_string words; - tokenize(trim(line), words, " \t", true); - if (words.size() >= 3) { - add_point(words); - } - } -} - -/** - * Adds a point from the pts file. - */ -void PtsToBam:: -add_point(const vector_string &words) { - if (_data == nullptr || _data->get_num_rows() >= egg_max_vertices) { - open_vertex_data(); - } - - string tail; - double x, y, z; - x = string_to_double(words[0], tail); - y = string_to_double(words[1], tail); - z = string_to_double(words[2], tail); - _vertex.add_data3d(x, y, z); - _num_points_added++; -} - -/** - * Creates a new GeomVertexData. - */ -void PtsToBam:: -open_vertex_data() { - if (_data != nullptr) { - close_vertex_data(); - } - CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3(); - _data = new GeomVertexData("pts", format, GeomEnums::UH_static); - _vertex = GeomVertexWriter(_data, "vertex"); -} - -/** - * Closes a previous GeomVertexData and adds it to the scene graph. - */ -void PtsToBam:: -close_vertex_data() { - if (_data == nullptr) { - return; - } - - _num_vdatas++; - nout << "\nGenerating " << _num_points_added << " points in " << _num_vdatas << " GeomVertexDatas\n"; - - PT(Geom) geom = new Geom(_data); - - int num_vertices = _data->get_num_rows(); - int vertices_so_far = 0; - while (num_vertices > 0) { - int this_num_vertices = std::min(num_vertices, (int)egg_max_indices); - PT(GeomPrimitive) points = new GeomPoints(GeomEnums::UH_static); - points->add_consecutive_vertices(vertices_so_far, this_num_vertices); - geom->add_primitive(points); - vertices_so_far += this_num_vertices; - num_vertices -= this_num_vertices; - } - - _gnode->add_geom(geom); - - _data = nullptr; -} - -int main(int argc, char *argv[]) { - PtsToBam prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/bam/ptsToBam.h b/pandatool/src/bam/ptsToBam.h deleted file mode 100644 index 20fa76e7..00000000 --- a/pandatool/src/bam/ptsToBam.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file ptsToBam.h - * @author drose - * @date 2000-06-28 - */ - -#ifndef PTSTOBAM_H -#define PTSTOBAM_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "withOutputFile.h" -#include "filename.h" -#include "vector_string.h" -#include "geomVertexData.h" -#include "geomVertexWriter.h" -#include "geomNode.h" - -/** - * - */ -class PtsToBam : public ProgramBase, public WithOutputFile { -public: - PtsToBam(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - -private: - void process_line(const std::string &line); - void add_point(const vector_string &words); - - void open_vertex_data(); - void close_vertex_data(); - -private: - Filename _pts_filename; - double _decimate_divisor; - double _decimate_factor; - - int _line_number; - int _point_number; - int _num_points_expected; - int _num_points_found; - int _num_points_added; - int _num_vdatas; - - double _decimated_point_number; - PT(GeomNode) _gnode; - PT(GeomVertexData) _data; - GeomVertexWriter _vertex; -}; - -#endif diff --git a/pandatool/src/converter/CMakeLists.txt b/pandatool/src/converter/CMakeLists.txt deleted file mode 100644 index a793b718..00000000 --- a/pandatool/src/converter/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3CONVERTER_HEADERS - somethingToEggConverter.h somethingToEggConverter.I - eggToSomethingConverter.h eggToSomethingConverter.I -) - -set(P3CONVERTER_SOURCES - somethingToEggConverter.cxx eggToSomethingConverter.cxx -) - -add_library(p3converter STATIC ${P3CONVERTER_HEADERS} ${P3CONVERTER_SOURCES}) -target_link_libraries(p3converter p3pandatoolbase pandaegg) - -install(TARGETS p3converter - EXPORT ToolsDevel COMPONENT ToolsDevel - DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d - ARCHIVE COMPONENT ToolsDevel) -install(FILES ${P3CONVERTER_HEADERS} COMPONENT ToolsDevel DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d) diff --git a/pandatool/src/converter/eggToSomethingConverter.I b/pandatool/src/converter/eggToSomethingConverter.I deleted file mode 100644 index 54320824..00000000 --- a/pandatool/src/converter/eggToSomethingConverter.I +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToSomethingConverter.I - * @author drose - * @date 2012-09-26 - */ - -/** - * Resets the error flag to the no-error state. had_error() will return false - * until a new error is generated. - */ -INLINE void EggToSomethingConverter:: -clear_error() { - _error = false; -} - -/** - * Returns true if an error was detected during the conversion process, false - * otherwise. - */ -INLINE bool EggToSomethingConverter:: -had_error() const { - return _error; -} - -/** - * Sets the EggData to NULL and makes the converter invalid. - */ -INLINE void EggToSomethingConverter:: -clear_egg_data() { - set_egg_data(nullptr); -} - -/** - * Returns the EggData structure. - */ -INLINE EggData *EggToSomethingConverter:: -get_egg_data() { - return _egg_data; -} - -/** - * Specifies the units that the EggData has already been scaled to. This is - * informational only; if the target file format supports it, this information - * will be written to the header. - */ -void EggToSomethingConverter:: -set_output_units(DistanceUnit output_units) { - _output_units = output_units; -} - -/** - * Returns the value supplied to set_output_units(). - */ -DistanceUnit EggToSomethingConverter:: -get_output_units() const { - return _output_units; -} diff --git a/pandatool/src/converter/eggToSomethingConverter.cxx b/pandatool/src/converter/eggToSomethingConverter.cxx deleted file mode 100644 index 0f357883..00000000 --- a/pandatool/src/converter/eggToSomethingConverter.cxx +++ /dev/null @@ -1,69 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToSomethingConverter.cxx - * @author drose - * @date 2001-04-26 - */ - -#include "eggToSomethingConverter.h" - -#include "eggData.h" - -/** - * - */ -EggToSomethingConverter:: -EggToSomethingConverter() { - _egg_data = nullptr; - _error = false; -} - -/** - * - */ -EggToSomethingConverter:: -EggToSomethingConverter(const EggToSomethingConverter ©) { - _egg_data = nullptr; - _error = false; -} - -/** - * - */ -EggToSomethingConverter:: -~EggToSomethingConverter() { - clear_egg_data(); -} - -/** - * Sets the egg data that will be filled in when convert_file() is called. - * This must be called before convert_file(). - */ -void EggToSomethingConverter:: -set_egg_data(EggData *egg_data) { - _egg_data = egg_data; -} - -/** - * Returns a space-separated list of extension, in addition to the one - * returned by get_extension(), that are recognized by this converter. - */ -std::string EggToSomethingConverter:: -get_additional_extensions() const { - return std::string(); -} - -/** - * Returns true if this file type can transparently save compressed files - * (with a .pz extension), false otherwise. - */ -bool EggToSomethingConverter:: -supports_compressed() const { - return false; -} diff --git a/pandatool/src/converter/eggToSomethingConverter.h b/pandatool/src/converter/eggToSomethingConverter.h deleted file mode 100644 index 0e95958c..00000000 --- a/pandatool/src/converter/eggToSomethingConverter.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToSomethingConverter.h - * @author drose - * @date 2012-09-26 - */ - -#ifndef EGGTOSOMETHINGCONVERTER_H -#define EGGTOSOMETHINGCONVERTER_H - -#include "pandatoolbase.h" - -#include "filename.h" -#include "pointerTo.h" -#include "distanceUnit.h" -#include "coordinateSystem.h" - -class EggData; -class EggGroupNode; - -/** - * This is a base class for a family of converter classes that manage a - * conversion from egg format to some other file type. - * - * Classes of this type can be used to implement egg2xxx converter programs, - * as well as LoaderFileTypeXXX run-time savers. - */ -class EggToSomethingConverter { -public: - EggToSomethingConverter(); - EggToSomethingConverter(const EggToSomethingConverter ©); - virtual ~EggToSomethingConverter(); - - virtual EggToSomethingConverter *make_copy()=0; - - INLINE void clear_error(); - INLINE bool had_error() const; - - void set_egg_data(EggData *egg_data); - INLINE void clear_egg_data(); - INLINE EggData *get_egg_data(); - - INLINE void set_output_units(DistanceUnit output_units); - INLINE DistanceUnit get_output_units() const; - INLINE void set_output_coordinate_system(CoordinateSystem output_coordinate_system) const; - INLINE CoordinateSystem get_output_coordinate_system() const; - - virtual std::string get_name() const=0; - virtual std::string get_extension() const=0; - virtual std::string get_additional_extensions() const; - virtual bool supports_compressed() const; - - virtual bool write_file(const Filename &filename)=0; - -protected: - PT(EggData) _egg_data; - DistanceUnit _output_units; - CoordinateSystem _output_coordinate_system; - - bool _error; -}; - -#include "eggToSomethingConverter.I" - -#endif diff --git a/pandatool/src/converter/somethingToEggConverter.I b/pandatool/src/converter/somethingToEggConverter.I deleted file mode 100644 index b3fed0cb..00000000 --- a/pandatool/src/converter/somethingToEggConverter.I +++ /dev/null @@ -1,391 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file somethingToEggConverter.I - * @author drose - * @date 2001-04-26 - */ - -/** - * Resets the error flag to the no-error state. had_error() will return false - * until a new error is generated. - */ -INLINE void SomethingToEggConverter:: -clear_error() { - _error = false; -} - -/** - * Returns true if an error was detected during the conversion process (unless - * _allow_errors is true), false otherwise. - */ -INLINE bool SomethingToEggConverter:: -had_error() const { - return !_allow_errors && (_error || _path_replace->had_error()); -} - -/** - * Replaces the PathReplace object (which specifies how to mangle paths from - * the source to the destination egg file) with a new one. - */ -INLINE void SomethingToEggConverter:: -set_path_replace(PathReplace *path_replace) { - _path_replace = path_replace; -} - -/** - * Returns a pointer to the PathReplace object associated with this converter. - * If the converter is non-const, this returns a non-const pointer, which can - * be adjusted. - */ -INLINE PathReplace *SomethingToEggConverter:: -get_path_replace() { - return _path_replace; -} - -/** - * Returns a pointer to the PathReplace object associated with this converter. - * If the converter is non-const, this returns a non-const pointer, which can - * be adjusted. - */ -INLINE const PathReplace *SomethingToEggConverter:: -get_path_replace() const { - return _path_replace; -} - -/** - * Specifies how source animation will be converted into egg structures. The - * default is AC_none, which means animation tables will be ignored. This is - * only meaningful for converters that understand animation. - */ -INLINE void SomethingToEggConverter:: -set_animation_convert(AnimationConvert animation_convert) { - _animation_convert = animation_convert; -} - -/** - * Returns how source animation will be converted into egg structures. - */ -INLINE AnimationConvert SomethingToEggConverter:: -get_animation_convert() const { - return _animation_convert; -} - -/** - * Specifies the name of the character generated. This name should match - * between all the model and channel egg files for a particular character and - * its associated animations. - */ -INLINE void SomethingToEggConverter:: -set_character_name(const std::string &character_name) { - _character_name = character_name; -} - -/** - * Returns the name of the character generated. See set_character_name(). - */ -INLINE const std::string &SomethingToEggConverter:: -get_character_name() const { - return _character_name; -} - -/** - * Specifies the starting frame of the animation to convert, in the units - * specified by set_input_frame_rate(). If this is unspecified, the starting - * frame is taken from the source, for instance from the first frame of the - * animation slider. - */ -INLINE void SomethingToEggConverter:: -set_start_frame(double start_frame) { - _start_frame = start_frame; - _control_flags |= CF_start_frame; -} - -/** - * Returns true if the starting frame has been explicitly specified via - * set_start_frame(), or false if the starting frame should be implicit based - * on the source. - */ -INLINE bool SomethingToEggConverter:: -has_start_frame() const { - return (_control_flags & CF_start_frame) != 0; -} - -/** - * Returns the value set by a previous call to set_start_frame(). It is an - * error to call this if has_start_frame() returns false. - */ -INLINE double SomethingToEggConverter:: -get_start_frame() const { - nassertr(has_start_frame(), 0.0); - return _start_frame; -} - -/** - * Removes the value previously set by set_start_frame(). - */ -INLINE void SomethingToEggConverter:: -clear_start_frame() { - _start_frame = 0.0; - _control_flags &= ~CF_start_frame; -} - -/** - * Specifies the ending frame of the animation to convert, in the units - * specified by set_input_frame_rate(). If this is unspecified, the ending - * frame is taken from the source, for instance from the last frame of the - * animation slider. - */ -INLINE void SomethingToEggConverter:: -set_end_frame(double end_frame) { - _end_frame = end_frame; - _control_flags |= CF_end_frame; -} - -/** - * Returns true if the ending frame has been explicitly specified via - * set_end_frame(), or false if the ending frame should be implicit based on - * the source. - */ -INLINE bool SomethingToEggConverter:: -has_end_frame() const { - return (_control_flags & CF_end_frame) != 0; -} - -/** - * Returns the value set by a previous call to set_end_frame(). It is an - * error to call this if has_end_frame() returns false. - */ -INLINE double SomethingToEggConverter:: -get_end_frame() const { - nassertr(has_end_frame(), 0.0); - return _end_frame; -} - -/** - * Removes the value previously set by set_end_frame(). - */ -INLINE void SomethingToEggConverter:: -clear_end_frame() { - _end_frame = 0.0; - _control_flags &= ~CF_end_frame; -} - -/** - * Specifies the increment between frames to extract. This is the amount to - * increment the time slider (in units of internal_frame_rate) between - * extracting each frame. If this is not specified, the default is taken from - * the animation package, or 1.0 if the animation package does not specified a - * frame increment. - */ -INLINE void SomethingToEggConverter:: -set_frame_inc(double frame_inc) { - _frame_inc = frame_inc; - _control_flags |= CF_frame_inc; -} - -/** - * Returns true if the frame increment has been explicitly specified via - * set_frame_inc(), or false if the ending frame should be implicit based on - * the source. - */ -INLINE bool SomethingToEggConverter:: -has_frame_inc() const { - return (_control_flags & CF_frame_inc) != 0; -} - -/** - * Returns the value set by a previous call to set_frame_inc(). It is an - * error to call this if has_frame_inc() returns false. - */ -INLINE double SomethingToEggConverter:: -get_frame_inc() const { - nassertr(has_frame_inc(), 0.0); - return _frame_inc; -} - -/** - * Removes the value previously set by set_frame_inc(). - */ -INLINE void SomethingToEggConverter:: -clear_frame_inc() { - _frame_inc = 0.0; - _control_flags &= ~CF_frame_inc; -} - -/** - * Specifies the frame of animation to represent the neutral pose of the - * model. - */ -INLINE void SomethingToEggConverter:: -set_neutral_frame(double neutral_frame) { - _neutral_frame = neutral_frame; - _control_flags |= CF_neutral_frame; -} - -/** - * Returns true if the neutral frame has been explicitly specified via - * set_neutral_frame(), or false otherwise. - */ -INLINE bool SomethingToEggConverter:: -has_neutral_frame() const { - return (_control_flags & CF_neutral_frame) != 0; -} - -/** - * Returns the value set by a previous call to set_neutral_frame(). It is an - * error to call this if has_neutral_frame() returns false. - */ -INLINE double SomethingToEggConverter:: -get_neutral_frame() const { - nassertr(has_neutral_frame(), 0.0); - return _neutral_frame; -} - -/** - * Removes the value previously set by set_neutral_frame(). - */ -INLINE void SomethingToEggConverter:: -clear_neutral_frame() { - _neutral_frame = 0.0; - _control_flags &= ~CF_neutral_frame; -} - -/** - * Specifies the number of frames per second that is represented by the - * "frame" unit in the animation package. If this is omitted, it is taken - * from whatever the file header indicates. Some animation packages do not - * encode a frame rate, in which case the default if this is omitted is the - * same as the output frame rate. - */ -INLINE void SomethingToEggConverter:: -set_input_frame_rate(double input_frame_rate) { - _input_frame_rate = input_frame_rate; - _control_flags |= CF_input_frame_rate; -} - -/** - * Returns true if the frame rate has been explicitly specified via - * set_input_frame_rate(), or false otherwise. - */ -INLINE bool SomethingToEggConverter:: -has_input_frame_rate() const { - return (_control_flags & CF_input_frame_rate) != 0; -} - -/** - * Returns the value set by a previous call to set_input_frame_rate(). It is - * an error to call this if has_input_frame_rate() returns false. - */ -INLINE double SomethingToEggConverter:: -get_input_frame_rate() const { - nassertr(has_input_frame_rate(), 0.0); - return _input_frame_rate; -} - -/** - * Removes the value previously set by set_input_frame_rate(). - */ -INLINE void SomethingToEggConverter:: -clear_input_frame_rate() { - _input_frame_rate = 0.0; - _control_flags &= ~CF_input_frame_rate; -} - -/** - * Specifies the number of frames per second that the resulting animation - * should be played at. If this is omitted, it is taken to be the same as the - * input frame rate. - */ -INLINE void SomethingToEggConverter:: -set_output_frame_rate(double output_frame_rate) { - _output_frame_rate = output_frame_rate; - _control_flags |= CF_output_frame_rate; -} - -/** - * Returns true if the frame rate has been explicitly specified via - * set_output_frame_rate(), or false otherwise. - */ -INLINE bool SomethingToEggConverter:: -has_output_frame_rate() const { - return (_control_flags & CF_output_frame_rate) != 0; -} - -/** - * Returns the value set by a previous call to set_output_frame_rate(). It is - * an error to call this if has_output_frame_rate() returns false. - */ -INLINE double SomethingToEggConverter:: -get_output_frame_rate() const { - nassertr(has_output_frame_rate(), 0.0); - return _output_frame_rate; -} - -/** - * Removes the value previously set by set_output_frame_rate(). - */ -INLINE void SomethingToEggConverter:: -clear_output_frame_rate() { - _output_frame_rate = 0.0; - _control_flags &= ~CF_output_frame_rate; -} - -/** - * Returns the default frame rate if nothing is specified for input_frame_rate - * or output_frame_rate, and the animation package does not have an implicit - * frame rate. - */ -INLINE double SomethingToEggConverter:: -get_default_frame_rate() { - return 24.0; -} - -/** - * Sets the merge_externals flag. When this is true, external references - * within the source file are read in and merged directly; otherwise, only a - * reference to a similarly-named egg file is inserted. - */ -INLINE void SomethingToEggConverter:: -set_merge_externals(bool merge_externals) { - _merge_externals = merge_externals; -} - -/** - * Returns the current state of the merge_externals flag. See - * set_merge_externals(). - */ -INLINE bool SomethingToEggConverter:: -get_merge_externals() const { - return _merge_externals; -} - -/** - * Sets the EggData to NULL and makes the converter invalid. - */ -INLINE void SomethingToEggConverter:: -clear_egg_data() { - set_egg_data(nullptr); -} - -/** - * Returns the EggData structure. - */ -INLINE EggData *SomethingToEggConverter:: -get_egg_data() { - return _egg_data; -} - -/** - * Converts the indicated model filename to a relative or absolute or whatever - * filename, according to _path_replace. - */ -INLINE Filename SomethingToEggConverter:: -convert_model_path(const Filename &orig_filename) { - return _path_replace->convert_path(orig_filename); -} diff --git a/pandatool/src/converter/somethingToEggConverter.cxx b/pandatool/src/converter/somethingToEggConverter.cxx deleted file mode 100644 index 8911021a..00000000 --- a/pandatool/src/converter/somethingToEggConverter.cxx +++ /dev/null @@ -1,165 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file somethingToEggConverter.cxx - * @author drose - * @date 2001-04-26 - */ - -#include "somethingToEggConverter.h" - -#include "eggData.h" -#include "eggExternalReference.h" - -/** - * - */ -SomethingToEggConverter:: -SomethingToEggConverter() { - _allow_errors = false; - _path_replace = new PathReplace; - _path_replace->_path_store = PS_absolute; - _animation_convert = AC_none; - _start_frame = 0.0; - _end_frame = 0.0; - _frame_inc = 0.0; - _neutral_frame = 0.0; - _input_frame_rate = 0.0; - _output_frame_rate = 0.0; - _control_flags = 0; - _merge_externals = false; - _egg_data = nullptr; - _error = false; -} - -/** - * - */ -SomethingToEggConverter:: -SomethingToEggConverter(const SomethingToEggConverter ©) : - _allow_errors(copy._allow_errors), - _path_replace(copy._path_replace), - _merge_externals(copy._merge_externals) -{ - _egg_data = nullptr; - _error = false; -} - -/** - * - */ -SomethingToEggConverter:: -~SomethingToEggConverter() { - clear_egg_data(); -} - -/** - * Sets the egg data that will be filled in when convert_file() is called. - * This must be called before convert_file(). - */ -void SomethingToEggConverter:: -set_egg_data(EggData *egg_data) { - _egg_data = egg_data; -} - -/** - * Returns a space-separated list of extension, in addition to the one - * returned by get_extension(), that are recognized by this converter. - */ -std::string SomethingToEggConverter:: -get_additional_extensions() const { - return std::string(); -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. - */ -bool SomethingToEggConverter:: -supports_compressed() const { - return false; -} - -/** - * Returns true if this converter can directly convert the model type to - * internal Panda memory structures, given the indicated options, or false - * otherwise. If this returns true, then convert_to_node() may be called to - * perform the conversion, which may be faster than calling convert_file() if - * the ultimate goal is a PandaNode anyway. - */ -bool SomethingToEggConverter:: -supports_convert_to_node(const LoaderOptions &options) const { - return false; -} - -/** - * This may be called after convert_file() has been called and returned true, - * indicating a successful conversion. It will return the distance units - * represented by the converted egg file, if known, or DU_invalid if not - * known. - */ -DistanceUnit SomethingToEggConverter:: -get_input_units() { - return DU_invalid; -} - -/** - * Reads the input file and directly produces a ready-to-render model file as - * a PandaNode. Returns NULL on failure, or if it is not supported. (This - * functionality is not supported by all converter types; see - * supports_convert_to_node()). - */ -PT(PandaNode) SomethingToEggConverter:: -convert_to_node(const LoaderOptions &options, const Filename &filename) { - return nullptr; -} - -/** - * Handles an external reference in the source file. If the merge_externals - * flag is true (see set_merge_externals()), this causes the named file to be - * read in and converted, and the converted egg geometry is parented to - * egg_parent. Otherwise, only a reference to a similarly named egg file is - * parented to egg_parent. - * - * The parameters orig_filename and searchpath are as those passed to - * convert_model_path(). - * - * Returns true on success, false on failure. - */ -bool SomethingToEggConverter:: -handle_external_reference(EggGroupNode *egg_parent, - const Filename &ref_filename) { - if (_merge_externals) { - SomethingToEggConverter *ext = make_copy(); - PT(EggData) egg_data = new EggData; - egg_data->set_coordinate_system(get_egg_data()->get_coordinate_system()); - ext->set_egg_data(egg_data); - - if (!ext->convert_file(ref_filename)) { - delete ext; - nout << "Unable to read external reference: " << ref_filename << "\n"; - _error = true; - return false; - } - - egg_parent->steal_children(*egg_data); - delete ext; - return true; - - } else { - // If we're installing external references instead of reading them, we - // should make it into an egg filename. - Filename filename = ref_filename; - filename.set_extension("egg"); - - EggExternalReference *egg_ref = new EggExternalReference("", filename); - egg_parent->add_child(egg_ref); - } - - return true; -} diff --git a/pandatool/src/converter/somethingToEggConverter.h b/pandatool/src/converter/somethingToEggConverter.h deleted file mode 100644 index 16d16df5..00000000 --- a/pandatool/src/converter/somethingToEggConverter.h +++ /dev/null @@ -1,148 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file somethingToEggConverter.h - * @author drose - * @date 2001-04-17 - */ - -#ifndef SOMETHINGTOEGGCONVERTER_H -#define SOMETHINGTOEGGCONVERTER_H - -#include "pandatoolbase.h" - -#include "filename.h" -#include "config_putil.h" // for get_model_path() -#include "animationConvert.h" -#include "pathReplace.h" -#include "pointerTo.h" -#include "distanceUnit.h" -#include "pandaNode.h" - -class EggData; -class EggGroupNode; -class LoaderOptions; - -/** - * This is a base class for a family of converter classes that manage a - * conversion from some file type to egg format. - * - * Classes of this type can be used to implement xxx2egg converter programs, - * as well as LoaderFileTypeXXX run-time loaders. - */ -class SomethingToEggConverter { -public: - SomethingToEggConverter(); - SomethingToEggConverter(const SomethingToEggConverter ©); - virtual ~SomethingToEggConverter(); - - virtual SomethingToEggConverter *make_copy()=0; - - INLINE void clear_error(); - INLINE bool had_error() const; - - INLINE void set_path_replace(PathReplace *path_replace); - INLINE PathReplace *get_path_replace(); - INLINE const PathReplace *get_path_replace() const; - - // These methods dealing with animation and frame rate are only relevant to - // converter types that understand animation. - INLINE void set_animation_convert(AnimationConvert animation_convert); - INLINE AnimationConvert get_animation_convert() const; - - INLINE void set_character_name(const std::string &character_name); - INLINE const std::string &get_character_name() const; - - INLINE void set_start_frame(double start_frame); - INLINE bool has_start_frame() const; - INLINE double get_start_frame() const; - INLINE void clear_start_frame(); - - INLINE void set_end_frame(double end_frame); - INLINE bool has_end_frame() const; - INLINE double get_end_frame() const; - INLINE void clear_end_frame(); - - INLINE void set_frame_inc(double frame_inc); - INLINE bool has_frame_inc() const; - INLINE double get_frame_inc() const; - INLINE void clear_frame_inc(); - - INLINE void set_neutral_frame(double neutral_frame); - INLINE bool has_neutral_frame() const; - INLINE double get_neutral_frame() const; - INLINE void clear_neutral_frame(); - - INLINE void set_input_frame_rate(double input_frame_rate); - INLINE bool has_input_frame_rate() const; - INLINE double get_input_frame_rate() const; - INLINE void clear_input_frame_rate(); - - INLINE void set_output_frame_rate(double output_frame_rate); - INLINE bool has_output_frame_rate() const; - INLINE double get_output_frame_rate() const; - INLINE void clear_output_frame_rate(); - - INLINE static double get_default_frame_rate(); - - INLINE void set_merge_externals(bool merge_externals); - INLINE bool get_merge_externals() const; - - void set_egg_data(EggData *egg_data); - INLINE void clear_egg_data(); - INLINE EggData *get_egg_data(); - - virtual std::string get_name() const=0; - virtual std::string get_extension() const=0; - virtual std::string get_additional_extensions() const; - virtual bool supports_compressed() const; - virtual bool supports_convert_to_node(const LoaderOptions &options) const; - - virtual bool convert_file(const Filename &filename)=0; - virtual PT(PandaNode) convert_to_node(const LoaderOptions &options, const Filename &filename); - virtual DistanceUnit get_input_units(); - - bool handle_external_reference(EggGroupNode *egg_parent, - const Filename &ref_filename); - - INLINE Filename convert_model_path(const Filename &orig_filename); - - // Set this true to treat errors as warnings and generate output anyway. - bool _allow_errors; - -protected: - PT(PathReplace) _path_replace; - - AnimationConvert _animation_convert; - std::string _character_name; - double _start_frame; - double _end_frame; - double _frame_inc; - double _neutral_frame; - double _input_frame_rate; // frames per second - double _output_frame_rate; // frames per second - enum ControlFlags { - CF_start_frame = 0x0001, - CF_end_frame = 0x0002, - CF_frame_inc = 0x0004, - CF_neutral_frame = 0x0008, - CF_input_frame_rate = 0x0010, - CF_output_frame_rate = 0x0020, - }; - int _control_flags; - - bool _merge_externals; - - PT(EggData) _egg_data; - - bool _error; -}; - -#include "somethingToEggConverter.I" - -#endif diff --git a/pandatool/src/daeegg/CMakeLists.txt b/pandatool/src/daeegg/CMakeLists.txt deleted file mode 100644 index 07b6320d..00000000 --- a/pandatool/src/daeegg/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -if(NOT HAVE_EGG OR NOT HAVE_FCOLLADA) - return() -endif() - -set(P3DAEEGG_HEADERS - config_daeegg.h - daeCharacter.h - daeMaterials.h - daeToEggConverter.h - fcollada_utils.h - pre_fcollada_include.h -) - -set(P3DAEEGG_SOURCES - config_daeegg.cxx - daeCharacter.cxx - daeMaterials.cxx - daeToEggConverter.cxx -) - -add_library(p3daeegg STATIC ${P3DAEEGG_HEADERS} ${P3DAEEGG_SOURCES}) -target_link_libraries(p3daeegg p3eggbase - PKG::FCOLLADA) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/daeegg/config_daeegg.cxx b/pandatool/src/daeegg/config_daeegg.cxx deleted file mode 100644 index 2b363155..00000000 --- a/pandatool/src/daeegg/config_daeegg.cxx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_daeegg.cxx - * @author rdb - * @date 2008-10-30 - */ - -#include "config_daeegg.h" -#include "daeCharacter.h" -#include "daeMaterials.h" - -#include "dconfig.h" - -Configure(config_daeegg); -NotifyCategoryDef(daeegg, ""); - -ConfigureFn(config_daeegg) { - init_libdaeegg(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libdaeegg() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - DaeCharacter::init_type(); - DaeMaterials::init_type(); -} diff --git a/pandatool/src/daeegg/config_daeegg.h b/pandatool/src/daeegg/config_daeegg.h deleted file mode 100644 index 8f60ed73..00000000 --- a/pandatool/src/daeegg/config_daeegg.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_daeegg.h - * @author rdb - * @date 2008-10-30 - */ - -#ifndef CONFIG_DAEEGG_H -#define CONFIG_DAEEGG_H - -#include "pandatoolbase.h" -#include "notifyCategoryProxy.h" - -NotifyCategoryDeclNoExport(daeegg); - -extern void init_libdaeegg(); - -#endif diff --git a/pandatool/src/daeegg/daeCharacter.cxx b/pandatool/src/daeegg/daeCharacter.cxx deleted file mode 100644 index 57c048fc..00000000 --- a/pandatool/src/daeegg/daeCharacter.cxx +++ /dev/null @@ -1,312 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeCharacter.cxx - * @author rdb - * @date 2008-11-24 - */ - -#include "daeCharacter.h" -#include "config_daeegg.h" -#include "fcollada_utils.h" -#include "pt_EggVertex.h" -#include "eggXfmSAnim.h" -#include "daeToEggConverter.h" -#include "daeMaterials.h" - -#include "eggExternalReference.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -TypeHandle DaeCharacter::_type_handle; - -/** - * - */ -DaeCharacter:: -DaeCharacter(EggGroup *node_group, const FCDControllerInstance *instance) : - _node_group(node_group), - _skin_mesh(nullptr), - _instance(instance), - _bind_shape_mat(LMatrix4d::ident_mat()), - _name(node_group->get_name()), - _skin_controller(nullptr) { - - // If it's a skin controller, add the controller joints. - const FCDController *controller = (const FCDController *)instance->GetEntity(); - if (controller == nullptr) { - return; - } - _skin_mesh = controller->GetBaseGeometry()->GetMesh(); - - if (controller->IsSkin()) { - _skin_controller = controller->GetSkinController(); - _bind_shape_mat = DAEToEggConverter::convert_matrix(_skin_controller->GetBindShapeTransform()); - } -} - -/** - * Binds the joints to the character. This means changing them to the bind - * pose. It is necessary to call this before process_skin_geometry. - * - * Returns the root group. - */ -void DaeCharacter:: -bind_joints(JointMap &joint_map) { - _joints.clear(); - - size_t num_joints = _skin_controller->GetJointCount(); - _joints.reserve(num_joints); - - // Record the bind pose for each joint. - for (size_t j = 0; j < num_joints; ++j) { - const FCDSkinControllerJoint *skin_joint = _skin_controller->GetJoint(j); - std::string sid = FROM_FSTRING(skin_joint->GetId()); - LMatrix4d bind_pose; - bind_pose.invert_from(DAEToEggConverter::convert_matrix( - skin_joint->GetBindPoseInverse())); - - // Check that we already encountered this joint during traversal. - JointMap::iterator ji = joint_map.find(sid); - if (ji != joint_map.end()) { - Joint &joint = ji->second; - - if (joint._character != nullptr) { - // In some cases, though, multiple controllers share the same joints. - // We can't support this without duplicating the joint structure, so - // we check if the bind poses are the same. - if (!joint._bind_pose.almost_equal(bind_pose, 0.0001)) { - // Ugh. What else could we do? - daeegg_cat.error() - << "Multiple controllers share joint with sid " << sid - << ", with different bind poses.\n"; - } - } else { - // Mark the joint as being controlled by this character. - joint._bind_pose = bind_pose; - joint._character = this; - } - - _joints.push_back(joint); - } else { - daeegg_cat.warning() - << "Unknown joint sid being referenced: '" << sid << "'\n"; - - // We still have to add a dummy joint or the index will be off. - _joints.push_back(Joint(nullptr, nullptr)); - } - } -} - -/** - * Traverses through the character hierarchy in order to bind the mesh to the - * character. This involves reorienting the joints to match the bind pose. - * - * It is important that this is called only once. - */ -void DaeCharacter:: -adjust_joints(FCDSceneNode *node, const JointMap &joint_map, - const LMatrix4d &transform) { - - LMatrix4d this_transform = transform; - - if (node->IsJoint()) { - std::string sid = FROM_FSTRING(node->GetSubId()); - - JointMap::const_iterator ji = joint_map.find(sid); - if (ji != joint_map.end()) { - const Joint &joint = ji->second; - - // Panda needs the joints to be in bind pose. Not fun! We copy the - // joint transform to the default pose, though, so that Panda will - // restore the joint transformation after binding. - - if (joint._character == this) { - LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat * - invert(transform); - // LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat * - // joint._group->get_parent()->get_node_frame_inv(); - - this_transform = bind_pose * this_transform; - joint._group->set_default_pose(*joint._group); - joint._group->set_transform3d(bind_pose); - - /* - PT(EggGroup) sphere = new EggGroup; - sphere->add_uniform_scale(0.1); - sphere->set_group_type(EggGroup::GT_instance); - sphere->add_child(new EggExternalReference("", "jack.egg")); - joint._group->add_child(sphere); - */ - } - } - } else { - // this_transform = DAEToEggConverter::convert_matrix(node->ToMatrix()); - } - - // Loop through the children joints - for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) { - // if (node->GetChild(ch)->IsJoint()) { - adjust_joints(node->GetChild(ch), joint_map, this_transform); - // } - } -} - -/** - * Adds the influences for the given vertex. - */ -void DaeCharacter:: -influence_vertex(int index, EggVertex *vertex) { - const FCDSkinControllerVertex *influence = _skin_controller->GetVertexInfluence(index); - - for (size_t pa = 0; pa < influence->GetPairCount(); ++pa) { - const FCDJointWeightPair* jwpair = influence->GetPair(pa); - - if (jwpair->jointIndex >= 0 && jwpair->jointIndex < (int)_joints.size()) { - EggGroup *joint = _joints[jwpair->jointIndex]._group.p(); - if (joint != nullptr) { - joint->ref_vertex(vertex, jwpair->weight); - } - } else { - daeegg_cat.error() - << "Invalid joint index: " << jwpair->jointIndex << "\n"; - } - } -} - -/** - * Collects all animation keys of animations applied to this character. - */ -void DaeCharacter:: -collect_keys(pset &keys) { -#if FCOLLADA_VERSION < 0x00030005 - FCDSceneNodeList roots = _instance->FindSkeletonNodes(); -#else - FCDSceneNodeList roots; - _instance->FindSkeletonNodes(roots); -#endif - - for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) { - r_collect_keys(*it, keys); - } -} - -/** - * Collects all animation keys found for the given node tree. - */ -void DaeCharacter:: -r_collect_keys(FCDSceneNode* node, pset &keys) { - FCDAnimatedList animateds; - - // Collect all the animation curves - for (size_t t = 0; t < node->GetTransformCount(); ++t) { - FCDTransform *transform = node->GetTransform(t); - FCDAnimated *animated = transform->GetAnimated(); - - if (animated != nullptr) { - const FCDAnimationCurveListList &all_curves = animated->GetCurves(); - - for (size_t ci = 0; ci < all_curves.size(); ++ci) { - const FCDAnimationCurveTrackList &curves = all_curves[ci]; - if (curves.empty()) { - continue; - } - - size_t num_keys = curves.front()->GetKeyCount(); - const FCDAnimationKey **curve_keys = curves.front()->GetKeys(); - - for (size_t c = 0; c < num_keys; ++c) { - keys.insert(curve_keys[c]->input); - } - } - } - } -} - -/** - * Processes a joint node and its transforms. - */ -void DaeCharacter:: -build_table(EggTable *parent, FCDSceneNode* node, const pset &keys) { - nassertv(node != nullptr); - - if (!node->IsJoint()) { - for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) { - build_table(parent, node->GetChild(ch), keys); - } - return; - } - - std::string node_id = FROM_FSTRING(node->GetDaeId()); - PT(EggTable) table = new EggTable(node_id); - table->set_table_type(EggTable::TT_table); - parent->add_child(table); - - PT(EggXfmSAnim) xform = new EggXfmSAnim("xform"); - table->add_child(xform); - - // Generate the sampled animation and loop through the matrices - FCDAnimatedList animateds; - - // Collect all the animation curves - for (size_t t = 0; t < node->GetTransformCount(); ++t) { - FCDTransform *transform = node->GetTransform(t); - FCDAnimated *animated = transform->GetAnimated(); - if (animated != nullptr) { - if (animated->HasCurve()) { - animateds.push_back(animated); - } - } - } - - // Sample the scene node transform - float last_key; - float timing_total = 0; - pset::const_iterator ki; - for (ki = keys.begin(); ki != keys.end(); ++ki) { - for (FCDAnimatedList::iterator it = animateds.begin(); it != animateds.end(); ++it) { - // Sample each animated, which changes the transform values directly - (*it)->Evaluate(*ki); - } - - if (ki != keys.begin()) { - timing_total += (*ki - last_key); - } - last_key = *ki; - - // Retrieve the new transform matrix for the COLLADA scene node - FMMatrix44 fmat = node->ToMatrix(); - - // Work around issue in buggy exporters (like ColladaMax) - if (IS_NEARLY_ZERO(fmat[3][3])) { - fmat[3][3] = 1; - } - - xform->add_data(DAEToEggConverter::convert_matrix(fmat)); - } - - // Quantize the FPS, otherwise Panda complains about FPS mismatches. - float fps = cfloor(((keys.size() - 1) / timing_total) * 100 + 0.5f) * 0.01f; - xform->set_fps(fps); - - // Loop through the children joints - for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) { - // if (node->GetChild(ch)->IsJoint()) { - build_table(table, node->GetChild(ch), keys); - // } - } -} diff --git a/pandatool/src/daeegg/daeCharacter.h b/pandatool/src/daeegg/daeCharacter.h deleted file mode 100644 index e384c221..00000000 --- a/pandatool/src/daeegg/daeCharacter.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeCharacter.h - * @author rdb - * @date 2008-11-24 - */ - -#ifndef DAECHARACTER_H -#define DAECHARACTER_H - -#include "pandatoolbase.h" -#include "typedReferenceCount.h" -#include "typeHandle.h" -#include "eggTable.h" -#include "epvector.h" - -#include "pre_fcollada_include.h" -#include -#include -#include -#include -#include - -class DAEToEggConverter; - -/** - * Class representing an animated character. - */ -class DaeCharacter : public TypedReferenceCount { -public: - DaeCharacter(EggGroup *node_group, const FCDControllerInstance* controller_instance); - - struct Joint { - INLINE Joint(EggGroup *group, const FCDSceneNode *scene_node) : - _bind_pose(LMatrix4d::ident_mat()), - _group(group), - _scene_node(scene_node), - _character(nullptr) {} - - LMatrix4d _bind_pose; - PT(EggGroup) _group; - const FCDSceneNode *_scene_node; - DaeCharacter *_character; - }; - typedef epvector Joints; - typedef pmap JointMap; - - void bind_joints(JointMap &joint_map); - void adjust_joints(FCDSceneNode *node, const JointMap &joint_map, - const LMatrix4d &transform = LMatrix4d::ident_mat()); - - void influence_vertex(int index, EggVertex *vertex); - - void collect_keys(pset &keys); - void r_collect_keys(FCDSceneNode *node, pset &keys); - - void build_table(EggTable *parent, FCDSceneNode* node, const pset &keys); - -public: - PT(EggGroup) _node_group; - const FCDGeometryMesh *_skin_mesh; - const FCDControllerInstance *_instance; - LMatrix4d _bind_shape_mat; - -private: - std::string _name; - const FCDSkinController *_skin_controller; - Joints _joints; - JointMap _bound_joints; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedReferenceCount::init_type(); - register_type(_type_handle, "DaeCharacter", - TypedReferenceCount::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/daeegg/daeMaterials.cxx b/pandatool/src/daeegg/daeMaterials.cxx deleted file mode 100644 index ac221344..00000000 --- a/pandatool/src/daeegg/daeMaterials.cxx +++ /dev/null @@ -1,451 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeMaterials.cxx - * @author rdb - * @date 2008-10-03 - */ - -#include "daeMaterials.h" -#include "config_daeegg.h" -#include "fcollada_utils.h" - -#include -#include -#include -#include -#include -#include - -#include "filename.h" -#include "string_utils.h" - -using std::endl; -using std::string; - -TypeHandle DaeMaterials::_type_handle; - -// luminance function, based on the ISOCIE color standards see ITU-R -// Recommendation BT.709-4 -#define luminance(c) ((c[0] * 0.212671 + c[1] * 0.715160 + c[2] * 0.072169)) - -/** - * - */ -DaeMaterials:: -DaeMaterials(const FCDGeometryInstance* geometry_instance) { - for (size_t mi = 0; mi < geometry_instance->GetMaterialInstanceCount(); ++mi) { - add_material_instance(geometry_instance->GetMaterialInstance(mi)); - } -} - -/** - * Adds a material instance. Normally automatically done by constructor. - */ -void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) { - nassertv(instance != nullptr); - const string semantic (FROM_FSTRING(instance->GetSemantic())); - if (_materials.count(semantic) > 0) { - daeegg_cat.warning() << "Ignoring duplicate material with semantic " << semantic << endl; - return; - } - _materials[semantic] = new DaeMaterial(); - - // Load in the uvsets - for (size_t vib = 0; vib < instance->GetVertexInputBindingCount(); ++vib) { - const FCDMaterialInstanceBindVertexInput* mivib = instance->GetVertexInputBinding(vib); - assert(mivib != nullptr); - PT(DaeVertexInputBinding) bvi = new DaeVertexInputBinding(); - bvi->_input_set = mivib->inputSet; -#if FCOLLADA_VERSION >= 0x00030005 - bvi->_input_semantic = mivib->GetInputSemantic(); - bvi->_semantic = *mivib->semantic; -#else - bvi->_input_semantic = mivib->inputSemantic; - bvi->_semantic = FROM_FSTRING(mivib->semantic); -#endif - _materials[semantic]->_uvsets.push_back(bvi); - } - - // Handle the material stuff - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Trying to process material with semantic " << semantic << endl; - } - PT_EggMaterial egg_material = new EggMaterial(semantic); - pvector egg_textures; - const FCDEffect* effect = instance->GetMaterial()->GetEffect(); - if (effect == nullptr) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "Ignoring material (semantic: " << semantic << ") without assigned effect" << endl; - } - } else { - // Grab the common profile effect - const FCDEffectStandard* effect_common = (FCDEffectStandard *)effect->FindProfile(FUDaeProfileType::COMMON); - if (effect_common == nullptr) { - daeegg_cat.info() << "Ignoring effect referenced by material with semantic " << semantic - << " because it has no common profile" << endl; - } else { - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Processing effect, material semantic is " << semantic << endl; - } - // Set the material parameters - egg_material->set_amb(TO_COLOR(effect_common->GetAmbientColor())); - // We already process transparency using blend modes LVecBase4 diffuse = - // TO_COLOR(effect_common->GetDiffuseColor()); - // diffuse.set_w(diffuse.get_w() * (1.0f - - // effect_common->GetOpacity())); egg_material->set_diff(diffuse); - egg_material->set_diff(TO_COLOR(effect_common->GetDiffuseColor())); - egg_material->set_emit(TO_COLOR(effect_common->GetEmissionColor()) * effect_common->GetEmissionFactor()); - egg_material->set_shininess(effect_common->GetShininess()); - egg_material->set_spec(TO_COLOR(effect_common->GetSpecularColor())); - // Now try to load in the textures - process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::DIFFUSE, EggTexture::ET_modulate); - process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::BUMP, EggTexture::ET_normal); - process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::SPECULAR, EggTexture::ET_modulate_gloss); - process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::SPECULAR_LEVEL, EggTexture::ET_gloss); - process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::TRANSPARENT, EggTexture::ET_unspecified, EggTexture::F_alpha); - process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::EMISSION, EggTexture::ET_add); -#if FCOLLADA_VERSION < 0x00030005 - process_texture_bucket(semantic, effect_common, FUDaeTextureChannel::OPACITY, EggTexture::ET_unspecified, EggTexture::F_alpha); -#endif - // Now, calculate the color blend stuff. - _materials[semantic]->_blend = convert_blend(effect_common->GetTransparencyMode(), - TO_COLOR(effect_common->GetTranslucencyColor()), - effect_common->GetTranslucencyFactor()); - } - // Find an tag to support some extra stuff from extensions - process_extra(semantic, effect->GetExtra()); - } - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Found " << egg_textures.size() << " textures in material" << endl; - } - _materials[semantic]->_egg_material = egg_material; -} - -/** - * Processes the given texture bucket and gives the textures in it the given - * envtype and format. - */ -void DaeMaterials:: -process_texture_bucket(const string semantic, const FCDEffectStandard* effect_common, FUDaeTextureChannel::Channel bucket, EggTexture::EnvType envtype, EggTexture::Format format) { - for (size_t tx = 0; tx < effect_common->GetTextureCount(bucket); ++tx) { - const FCDImage* image = effect_common->GetTexture(bucket, tx)->GetImage(); - if (image == nullptr) { - daeegg_cat.warning() << "Texture references a nonexisting image!" << endl; - } else { - const FCDEffectParameterSampler* sampler = effect_common->GetTexture(bucket, tx)->GetSampler(); - // FCollada only supplies absolute paths. We need to grab the document - // location ourselves and make the image path absolute. - Filename texpath; - if (image->GetDocument()) { - Filename docpath = Filename::from_os_specific(FROM_FSTRING(image->GetDocument()->GetFileUrl())); - docpath.make_canonical(); - texpath = Filename::from_os_specific(FROM_FSTRING(image->GetFilename())); - texpath.make_canonical(); - texpath.make_relative_to(docpath.get_dirname(), true); - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "Found texture with path " << texpath << endl; - } - } else { - // Never mind. - texpath = Filename::from_os_specific(FROM_FSTRING(image->GetFilename())); - } - PT_EggTexture egg_texture = new EggTexture(FROM_FSTRING(image->GetDaeId()), texpath.to_os_generic()); - // Find a set of UV coordinates - const FCDEffectParameterInt* uvset = effect_common->GetTexture(bucket, tx)->GetSet(); - if (uvset != nullptr) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "Texture has uv name '" << FROM_FSTRING(uvset->GetSemantic()) << "'\n"; - } - string uvset_semantic (FROM_FSTRING(uvset->GetSemantic())); - - // Only set the UV name if this UV set actually exists. - for (size_t i = 0; i < _materials[semantic]->_uvsets.size(); ++i) { - if (_materials[semantic]->_uvsets[i]->_semantic == uvset_semantic) { - egg_texture->set_uv_name(uvset_semantic); - break; - } - } - } - // Apply sampler stuff - if (sampler != nullptr) { - egg_texture->set_texture_type(convert_texture_type(sampler->GetSamplerType())); - egg_texture->set_wrap_u(convert_wrap_mode(sampler->GetWrapS())); - if (sampler->GetSamplerType() != FCDEffectParameterSampler::SAMPLER1D) { - egg_texture->set_wrap_v(convert_wrap_mode(sampler->GetWrapT())); - } - if (sampler->GetSamplerType() == FCDEffectParameterSampler::SAMPLER3D) { - egg_texture->set_wrap_w(convert_wrap_mode(sampler->GetWrapP())); - } - egg_texture->set_minfilter(convert_filter_type(sampler->GetMinFilter())); - egg_texture->set_magfilter(convert_filter_type(sampler->GetMagFilter())); - if (envtype != EggTexture::ET_unspecified) { - egg_texture->set_env_type(envtype); - } - if (format != EggTexture::F_unspecified) { - egg_texture->set_format(format); - } - } - _materials[semantic]->_egg_textures.push_back(egg_texture); - } - } -} - -/** - * Processes the extra data in the given tag. If the given element is - * NULL, it just silently returns. - */ -void DaeMaterials:: -process_extra(const string semantic, const FCDExtra* extra) { - if (extra == nullptr) return; - const FCDEType* etype = extra->GetDefaultType(); - if (etype == nullptr) return; - for (size_t et = 0; et < etype->GetTechniqueCount(); ++et) { - const FCDENode* enode = ((const FCDENode*)(etype->GetTechnique(et)))->FindChildNode("double_sided"); - if (enode != nullptr) { - string content = trim(enode->GetContent()); - if (content == "1" || content == "true") { - _materials[semantic]->_double_sided = true; - } else if (content == "0" || content == "false") { - _materials[semantic]->_double_sided = false; - } else { - daeegg_cat.warning() << "Expected tag to be either 1 or 0, found '" << content << "' instead" << endl; - } - } - } -} - -/** - * Applies the stuff to the given EggPrimitive. - */ -void DaeMaterials:: -apply_to_primitive(const string semantic, const PT(EggPrimitive) to) { - if (_materials.count(semantic) > 0) { - to->set_material(_materials[semantic]->_egg_material); - for (pvector::iterator it = _materials[semantic]->_egg_textures.begin(); it != _materials[semantic]->_egg_textures.end(); ++it) { - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Applying texture " << (*it)->get_name() << " from material with semantic " << semantic << endl; - } - to->add_texture(*it); - } - to->set_bface_flag(_materials[semantic]->_double_sided); - } -} - -/** - * Applies the colorblend stuff to the given EggGroup. - */ -void DaeMaterials:: -apply_to_group(const string semantic, const PT(EggGroup) to, bool invert_transparency) { - if (_materials.count(semantic) > 0) { - PT(DaeBlendSettings) blend = _materials[semantic]->_blend; - if (blend && blend->_enabled) { - to->set_blend_mode(EggGroup::BM_add); - to->set_blend_color(blend->_color); - if (invert_transparency) { - to->set_blend_operand_a(blend->_operand_b); - to->set_blend_operand_b(blend->_operand_a); - } else { - to->set_blend_operand_a(blend->_operand_a); - to->set_blend_operand_b(blend->_operand_b); - } - } else if (blend && invert_transparency) { - to->set_blend_mode(EggGroup::BM_add); - to->set_blend_color(blend->_color); - to->set_blend_operand_a(blend->_operand_b); - to->set_blend_operand_b(blend->_operand_a); - } - } -} - -/** - * Returns the semantic of the uvset with the specified input set, or an empty - * string if the given material has no input set. - */ -const string DaeMaterials:: -get_uvset_name(const string semantic, FUDaeGeometryInput::Semantic input_semantic, int32 input_set) { - if (_materials.count(semantic) > 0) { - if (input_set == -1 && _materials[semantic]->_uvsets.size() == 1) { - return _materials[semantic]->_uvsets[0]->_semantic; - } else { - for (size_t i = 0; i < _materials[semantic]->_uvsets.size(); ++i) { - if (_materials[semantic]->_uvsets[i]->_input_set == input_set && - _materials[semantic]->_uvsets[i]->_input_semantic == input_semantic) { - return _materials[semantic]->_uvsets[i]->_semantic; - } - } - // If we can't find it, let's look again, but don't care for the - // input_semantic this time. The reason for this is that some tools - // export textangents and texbinormals bound to a uvset with input - // semantic TEXCOORD. - for (size_t i = 0; i < _materials[semantic]->_uvsets.size(); ++i) { - if (_materials[semantic]->_uvsets[i]->_input_set == input_set) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "Using uv set with non-matching input semantic " << _materials[semantic]->_uvsets[i]->_semantic << "\n"; - } - return _materials[semantic]->_uvsets[i]->_semantic; - } - } - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "No uv set binding found for input set " << input_set << "\n"; - } - } - } - return ""; -} - -/** - * Converts an FCollada sampler type to the EggTexture texture type - * equivalent. - */ -EggTexture::TextureType DaeMaterials:: -convert_texture_type(const FCDEffectParameterSampler::SamplerType orig_type) { - switch (orig_type) { - case FCDEffectParameterSampler::SAMPLER1D: - return EggTexture::TT_1d_texture; - case FCDEffectParameterSampler::SAMPLER2D: - return EggTexture::TT_2d_texture; - case FCDEffectParameterSampler::SAMPLER3D: - return EggTexture::TT_3d_texture; - case FCDEffectParameterSampler::SAMPLERCUBE: - return EggTexture::TT_cube_map; - default: - daeegg_cat.warning() << "Invalid sampler type found" << endl; - } - return EggTexture::TT_unspecified; -} - -/** - * Converts an FCollada wrap mode to the EggTexture wrap mode equivalent. - */ -EggTexture::WrapMode DaeMaterials:: -convert_wrap_mode(const FUDaeTextureWrapMode::WrapMode orig_mode) { - switch (orig_mode) { - case FUDaeTextureWrapMode::NONE: - // FIXME: this shouldnt be unspecified - return EggTexture::WM_unspecified; - case FUDaeTextureWrapMode::WRAP: - return EggTexture::WM_repeat; - case FUDaeTextureWrapMode::MIRROR: - return EggTexture::WM_mirror; - case FUDaeTextureWrapMode::CLAMP: - return EggTexture::WM_clamp; - case FUDaeTextureWrapMode::BORDER: - return EggTexture::WM_border_color; - case FUDaeTextureWrapMode::UNKNOWN: - return EggTexture::WM_unspecified; - default: - daeegg_cat.warning() << "Invalid wrap mode found: " << FUDaeTextureWrapMode::ToString(orig_mode) << endl; - } - return EggTexture::WM_unspecified; -} - -/** - * Converts an FCollada filter function to the EggTexture wrap type - * equivalent. - */ -EggTexture::FilterType DaeMaterials:: -convert_filter_type(const FUDaeTextureFilterFunction::FilterFunction orig_type) { - switch (orig_type) { - case FUDaeTextureFilterFunction::NONE: - // FIXME: this shouldnt be unspecified - return EggTexture::FT_unspecified; - case FUDaeTextureFilterFunction::NEAREST: - return EggTexture::FT_nearest; - case FUDaeTextureFilterFunction::LINEAR: - return EggTexture::FT_linear; - case FUDaeTextureFilterFunction::NEAREST_MIPMAP_NEAREST: - return EggTexture::FT_nearest_mipmap_nearest; - case FUDaeTextureFilterFunction::LINEAR_MIPMAP_NEAREST: - return EggTexture::FT_linear_mipmap_nearest; - case FUDaeTextureFilterFunction::NEAREST_MIPMAP_LINEAR: - return EggTexture::FT_nearest_mipmap_linear; - case FUDaeTextureFilterFunction::LINEAR_MIPMAP_LINEAR: - return EggTexture::FT_linear_mipmap_linear; - case FUDaeTextureFilterFunction::UNKNOWN: - return EggTexture::FT_unspecified; - default: - daeegg_cat.warning() << "Unknown filter type found: " << FUDaeTextureFilterFunction::ToString(orig_type) << endl; - } - return EggTexture::FT_unspecified; -} - -/** - * Converts collada blend attribs to Panda's equivalents. - */ -PT(DaeMaterials::DaeBlendSettings) DaeMaterials:: -convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparent, double transparency) { - // Create the DaeBlendSettings and fill it with some defaults. - PT(DaeBlendSettings) blend = new DaeBlendSettings(); - blend->_enabled = true; - blend->_color = LColor::zero(); - blend->_operand_a = EggGroup::BO_unspecified; - blend->_operand_b = EggGroup::BO_unspecified; - - // First fill in the color value. - if (mode == FCDEffectStandard::A_ONE) {// || mode == FCDEffectStandard::A_ZERO) { - double value = transparent[3] * transparency; - blend->_color = LColor(value, value, value, value); - } else if (mode == FCDEffectStandard::RGB_ZERO) {//|| mode == FCDEffectStandard::RGB_ONE) { - blend->_color = transparent * transparency; - blend->_color[3] = luminance(blend->_color); - } else { - daeegg_cat.error() << "Unknown opaque type found!" << endl; - blend->_enabled = false; - return blend; - } - - // Now figure out the operands. - if (mode == FCDEffectStandard::RGB_ZERO) {// || mode == FCDEffectStandard::A_ZERO) { - blend->_operand_a = EggGroup::BO_one_minus_constant_color; - blend->_operand_b = EggGroup::BO_constant_color; - } else if (mode == FCDEffectStandard::A_ONE) {// || mode == FCDEffectStandard::RGB_ONE) { - blend->_operand_a = EggGroup::BO_constant_color; - blend->_operand_b = EggGroup::BO_one_minus_constant_color; - } else { - daeegg_cat.error() << "Unknown opaque type found!" << endl; - blend->_enabled = false; - return blend; - } - - // See if we can optimize out the color. - if (blend->_operand_a == EggGroup::BO_constant_color) { - if (blend->_color == LColor::zero()) { - blend->_operand_a = EggGroup::BO_zero; - } else if (blend->_color == LColor(1, 1, 1, 1)) { - blend->_operand_a = EggGroup::BO_one; - } - } - if (blend->_operand_b == EggGroup::BO_constant_color) { - if (blend->_color == LColor::zero()) { - blend->_operand_b = EggGroup::BO_zero; - } else if (blend->_color == LColor(1, 1, 1, 1)) { - blend->_operand_b = EggGroup::BO_one; - } - } - if (blend->_operand_a == EggGroup::BO_one_minus_constant_color) { - if (blend->_color == LColor::zero()) { - blend->_operand_a = EggGroup::BO_one; - } else if (blend->_color == LColor(1, 1, 1, 1)) { - blend->_operand_a = EggGroup::BO_zero; - } - } - if (blend->_operand_b == EggGroup::BO_one_minus_constant_color) { - if (blend->_color == LColor::zero()) { - blend->_operand_b = EggGroup::BO_one; - } else if (blend->_color == LColor(1, 1, 1, 1)) { - blend->_operand_b = EggGroup::BO_zero; - } - } - - // See if we can entirely disable the blend. - if (blend->_operand_a == EggGroup::BO_one && blend->_operand_b == EggGroup::BO_zero) { - blend->_enabled = false; - } - return blend; -} diff --git a/pandatool/src/daeegg/daeMaterials.h b/pandatool/src/daeegg/daeMaterials.h deleted file mode 100644 index 08cfed03..00000000 --- a/pandatool/src/daeegg/daeMaterials.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeMaterials.h - * @author rdb - * @date 2008-10-03 - */ - -#ifndef DAEMATERIALS_H -#define DAEMATERIALS_H - -#include "pandatoolbase.h" -#include "eggMaterial.h" -#include "eggTexture.h" -#include "eggPrimitive.h" -#include "eggGroup.h" -#include "pointerTo.h" -#include "pt_EggTexture.h" -#include "pt_EggMaterial.h" - -#include "pre_fcollada_include.h" -#include -#include -#include -#include -#include -#include - -/** - * This class is seperated from the converter file because otherwise it would - * get too big and needlessly complicated. - */ -class DaeMaterials : public TypedReferenceCount { -public: - DaeMaterials(const FCDGeometryInstance* geometry_instance); - virtual ~DaeMaterials() {}; - - void add_material_instance(const FCDMaterialInstance* instance); - void apply_to_primitive(const std::string semantic, const PT(EggPrimitive) to); - void apply_to_group(const std::string semantic, const PT(EggGroup) to, bool invert_transparency=false); - const std::string get_uvset_name(const std::string semantic, FUDaeGeometryInput::Semantic input_semantic, int32 input_set); - - static EggTexture::TextureType convert_texture_type(const FCDEffectParameterSampler::SamplerType orig_type); - static EggTexture::WrapMode convert_wrap_mode(const FUDaeTextureWrapMode::WrapMode orig_mode); - static EggTexture::FilterType convert_filter_type(const FUDaeTextureFilterFunction::FilterFunction orig_type); - -private: - // Holds stuff for color blend attribs. - struct DaeBlendSettings : public ReferenceCount { - bool _enabled; - LColor _color; - EggGroup::BlendOperand _operand_a; - EggGroup::BlendOperand _operand_b; - }; - - // Holds information to bind texcoord inputs to textures. - struct DaeVertexInputBinding : public ReferenceCount { - int32 _input_set; - FUDaeGeometryInput::Semantic _input_semantic; - std::string _semantic; - }; - - // Holds stuff for an individual material. - struct DaeMaterial : public ReferenceCount { - pvector _egg_textures; - PT_EggMaterial _egg_material; - bool _double_sided; - pvector _uvsets; - PT(DaeBlendSettings) _blend; - }; - - void process_texture_bucket(const std::string semantic, const FCDEffectStandard* effect_common, FUDaeTextureChannel::Channel bucket, EggTexture::EnvType envtype = EggTexture::ET_unspecified, EggTexture::Format format = EggTexture::F_unspecified); - void process_extra(const std::string semantic, const FCDExtra* extra); - static PT(DaeBlendSettings) convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparent, double transparency); - - pmap _materials; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedReferenceCount::init_type(); - register_type(_type_handle, "DaeMaterials", - TypedReferenceCount::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/daeegg/daeToEggConverter.cxx b/pandatool/src/daeegg/daeToEggConverter.cxx deleted file mode 100644 index 95b146de..00000000 --- a/pandatool/src/daeegg/daeToEggConverter.cxx +++ /dev/null @@ -1,851 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeToEggConverter.cxx - * @author rdb - * @date 2008-05-08 - */ - -#include "daeToEggConverter.h" -#include "fcollada_utils.h" -#include "config_daeegg.h" -#include "daeCharacter.h" -#include "dcast.h" -#include "string_utils.h" -#include "eggData.h" -#include "eggPrimitive.h" -#include "eggLine.h" -#include "eggPolygon.h" -#include "eggTriangleFan.h" -#include "eggTriangleStrip.h" -#include "eggPoint.h" -#include "eggXfmSAnim.h" -#include "eggSAnimData.h" -#include "pt_EggVertex.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if FCOLLADA_VERSION >= 0x00030005 - #include -#endif - -using std::endl; -using std::string; - -/** - * - */ -DAEToEggConverter:: -DAEToEggConverter() { - _unit_name = "meter"; - _unit_meters = 1.0; - _document = nullptr; - _table = nullptr; - _error_handler = nullptr; - _invert_transparency = false; -} - -/** - * - */ -DAEToEggConverter:: -DAEToEggConverter(const DAEToEggConverter ©) : - SomethingToEggConverter(copy) -{ -} - -/** - * - */ -DAEToEggConverter:: -~DAEToEggConverter() { - delete _error_handler; -} - -/** - * Allocates and returns a new copy of the converter. - */ -SomethingToEggConverter *DAEToEggConverter:: -make_copy() { - return new DAEToEggConverter(*this); -} - - -/** - * Returns the English name of the file type this converter supports. - */ -string DAEToEggConverter:: -get_name() const { - return "COLLADA"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -string DAEToEggConverter:: -get_extension() const { - return "dae"; -} - -/** - * Handles the reading of the input file and converting it to egg. Returns - * true if successful, false otherwise. - */ -bool DAEToEggConverter:: -convert_file(const Filename &filename) { - // Reset stuff - clear_error(); - _joints.clear(); - if (_error_handler == nullptr) { - _error_handler = new FUErrorSimpleHandler; - } - - // The default coordinate system is Y-up - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_yup_right); - } - - // Read the file - FCollada::Initialize(); - _document = FCollada::LoadDocument(filename.to_os_specific().c_str()); - if (_document == nullptr) { - daeegg_cat.error() << "Failed to load document: " << _error_handler->GetErrorString() << endl; - FCollada::Release(); - return false; - } - // Make sure the file uses consistent coordinate system and length - if (_document->GetAsset() != nullptr) { - FCDocumentTools::StandardizeUpAxisAndLength(_document); - } - - // Process the scene - process_asset(); - PT(EggGroup) scene_group; - string model_name = _character_name; - - FCDSceneNode* visual_scene = _document->GetVisualSceneInstance(); - if (visual_scene != nullptr) { - if (model_name.empty()) { - // By lack of anything better... - model_name = FROM_FSTRING(visual_scene->GetName()); - } - scene_group = new EggGroup(model_name); - _egg_data->add_child(scene_group); - - for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) { - process_node(scene_group, visual_scene->GetChild(ch)); - } - } else { - daeegg_cat.warning() - << "No visual scene instance found in COLLADA document.\n"; - } - - // Now process the characters. This depends on information from collected - // joints, which is why it's done in a second step. - if (get_animation_convert() != AC_none) { - Characters::iterator it; - DaeCharacter *character; - for (it = _characters.begin(); it != _characters.end(); ++it) { - character = *it; - if (get_animation_convert() != AC_chan) { - character->bind_joints(_joints); - - const FCDGeometryMesh *mesh = character->_skin_mesh; - - if (mesh != nullptr) { - PT(DaeMaterials) materials = new DaeMaterials(character->_instance); - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Processing mesh for controller\n"; - } - process_mesh(character->_node_group, mesh, materials, character); - } - } - } - - // Put the joints in bind pose. - for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) { - character->adjust_joints(visual_scene->GetChild(ch), _joints, LMatrix4d::ident_mat()); - } - - if (scene_group != nullptr) { - // Mark the scene as character. - if (get_animation_convert() == AC_chan) { - _egg_data->remove_child(scene_group); - } else { - scene_group->set_dart_type(EggGroup::DT_default); - } - } - - if (get_animation_convert() != AC_model) { - _table = new EggTable(); - _table->set_table_type(EggTable::TT_table); - _egg_data->add_child(_table); - - PT(EggTable) bundle = new EggTable(model_name); - bundle->set_table_type(EggTable::TT_bundle); - _table->add_child(bundle); - - PT(EggTable) skeleton = new EggTable(""); - skeleton->set_table_type(EggTable::TT_table); - bundle->add_child(skeleton); - - pset keys; - - Characters::iterator it; - DaeCharacter *character; - for (it = _characters.begin(); it != _characters.end(); ++it) { - character = *it; - - // Collect key frame timings. - if (get_animation_convert() == AC_both || - get_animation_convert() == AC_chan) { - character->collect_keys(keys); - } - } - - if (_frame_inc != 0.0) { - // A frame increment was given, this means that we have to sample the - // animation. - float start, end; - if (_end_frame != _start_frame) { - start = _start_frame; - end = _end_frame; - } else { - // No range was given. Infer the frame range from the keys. - start = *keys.begin(); - end = *keys.rbegin(); - } - keys.clear(); - - for (float t = start; t <= end; t += _frame_inc) { - keys.insert(t); - } - } else { - // No sampling parameters given; not necessarily a failure, since the - // animation may already be sampled. We use the key frames as - // animation frames. - if (_end_frame != 0.0) { - // An end frame was given, chop off all keys after that. - float end = _end_frame; - pset::iterator ki; - for (ki = keys.begin(); ki != keys.end(); ++ki) { - if (*ki > end && !IS_THRESHOLD_EQUAL(*ki, end, 0.001)) { - keys.erase(ki, keys.end()); - break; - } - } - } - if (_start_frame != 0.0) { - // A start frame was given, chop off all keys before that. - float start = _start_frame; - pset::iterator ki; - for (ki = keys.begin(); ki != keys.end(); ++ki) { - if (*ki > start && !IS_THRESHOLD_EQUAL(*ki, start, 0.001)) { - keys.erase(keys.begin(), ki); - break; - } - } - } - - // Check that this does indeed look like a sampled animation; if not, - // issue an appropriate warning. - pset::const_iterator ki = keys.begin(); - if (ki != keys.end()) { - float last = *ki; - float diff = 0; - - for (++ki; ki != keys.end(); ++ki) { - if (diff != 0 && !IS_THRESHOLD_EQUAL((*ki - last), diff, 0.001)) { - daeegg_cat.error() - << "This does not appear to be a sampled animation.\n" - << "Specify the -sf, -ef and -if options to indicate how the " - << "animations should be sampled.\n"; - break; - } - diff = (*ki - last); - last = *ki; - } - } - } - - // It doesn't really matter which character we grab for this as it'll - // iterate over the whole graph right now anyway. - for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) { - character->build_table(skeleton, visual_scene->GetChild(ch), keys); - } - } - } - - // Clean up and return - SAFE_DELETE(visual_scene); - SAFE_DELETE(_document); - FCollada::Release(); - return true; -} - -/** - * This may be called after convert_file() has been called and returned true, - * indicating a successful conversion. It will return the distance units - * represented by the converted egg file, if known, or DU_invalid if not - * known. - */ -DistanceUnit DAEToEggConverter:: -get_input_units() { - if (IS_NEARLY_EQUAL(_unit_meters, 0.001)) { - return DU_millimeters; - } - if (IS_NEARLY_EQUAL(_unit_meters, 0.01)) { - return DU_centimeters; - } - if (IS_NEARLY_EQUAL(_unit_meters, 1.0)) { - return DU_meters; - } - if (IS_NEARLY_EQUAL(_unit_meters, 1000.0)) { - return DU_kilometers; - } - if (IS_NEARLY_EQUAL(_unit_meters, 3.0 * 12.0 * 0.0254)) { - return DU_yards; - } - if (IS_NEARLY_EQUAL(_unit_meters, 12.0 * 0.0254)) { - return DU_feet; - } - if (IS_NEARLY_EQUAL(_unit_meters, 0.0254)) { - return DU_inches; - } - if (IS_NEARLY_EQUAL(_unit_meters, 1852.0)) { - return DU_nautical_miles; - } - if (IS_NEARLY_EQUAL(_unit_meters, 5280.0 * 12.0 * 0.0254)) { - return DU_statute_miles; - } - - // Whatever. - return DU_invalid; -} - -void DAEToEggConverter:: -process_asset() { - const FCDAsset *asset = _document->GetAsset(); - if (_document->GetAsset() == nullptr) { - return; - } - - _unit_name = FROM_FSTRING(asset->GetUnitName()); - _unit_meters = asset->GetUnitConversionFactor(); - - // Read out the coordinate system - FMVector3 up_axis = asset->GetUpAxis(); - - if (up_axis == FMVector3(0, 1, 0)) { - _egg_data->set_coordinate_system(CS_yup_right); - - } else if (up_axis == FMVector3(0, 0, 1)) { - _egg_data->set_coordinate_system(CS_zup_right); - - } else { - _egg_data->set_coordinate_system(CS_invalid); - daeegg_cat.warning() << "Unrecognized coordinate system!\n"; - } -} - -// Process the node. If forced is true, it will even process it if its known -// to be a skeleton root. -void DAEToEggConverter:: -process_node(EggGroupNode *parent, const FCDSceneNode* node, bool forced) { - nassertv(node != nullptr); - string node_id = FROM_FSTRING(node->GetDaeId()); - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Processing node with ID '" << node_id << "'" << endl; - } - - // Create an egg group for this node - PT(EggGroup) node_group = new EggGroup(FROM_FSTRING(node->GetDaeId())); - process_extra(node_group, node->GetExtra()); - parent->add_child(node_group); - - // Check if its a joint - if (node->IsJoint()) { - string sid = FROM_FSTRING(node->GetSubId()); - node_group->set_group_type(EggGroup::GT_joint); - - if (!_joints.insert(DaeCharacter::JointMap::value_type(sid, - DaeCharacter::Joint(node_group, node))).second) { - daeegg_cat.error() - << "Joint with sid " << sid << " occurs more than once!\n"; - } - } - - // Loop through the transforms and apply them (in reverse order) - for (size_t tr = node->GetTransformCount(); tr > 0; --tr) { - apply_transform(node_group, node->GetTransform(tr - 1)); - } - // node_group->set_transform3d(convert_matrix(node->ToMatrix())); - - // Loop through the instances and process them - for (size_t in = 0; in < node->GetInstanceCount(); ++in) { - process_instance(node_group, node->GetInstance(in)); - } - - // Loop through the children and recursively process them - for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) { - process_node(DCAST(EggGroupNode, node_group), node->GetChild(ch)); - } - - // Loop through any possible scene node instances and process those, too. - for (size_t in = 0; in < node->GetInstanceCount(); ++in) { - const FCDEntity *entity = node->GetInstance(in)->GetEntity(); - if (entity && entity->GetType() == FCDEntity::SCENE_NODE) { - process_node(node_group, (const FCDSceneNode*) entity); - } - } -} - -void DAEToEggConverter:: -process_instance(EggGroup *parent, const FCDEntityInstance* instance) { - nassertv(instance != nullptr); - nassertv(instance->GetEntity() != nullptr); - // Check what kind of instance this is - switch (instance->GetType()) { - case FCDEntityInstance::GEOMETRY: - { - if (get_animation_convert() != AC_chan) { - const FCDGeometry* geometry = (const FCDGeometry*) instance->GetEntity(); - assert(geometry != nullptr); - if (geometry->IsMesh()) { - // Now, handle the mesh. - process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance)); - } - if (geometry->IsSpline()) { - process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast (geometry->GetSpline())); - } - } - } - break; - - case FCDEntityInstance::CONTROLLER: - // Add the dart tag and process the controller instance - // parent->set_dart_type(EggGroup::DT_default); - process_controller(parent, (const FCDControllerInstance*) instance); - break; - - case FCDEntityInstance::MATERIAL: - // We don't process this directly, handled per-geometry instead. - break; - - case FCDEntityInstance::SIMPLE: - { - // Grab the entity and check its type. - const FCDEntity* entity = instance->GetEntity(); - if (entity->GetType() != FCDEntity::SCENE_NODE) { - daeegg_cat.warning() << "Unsupported entity type found" << endl; - } - } - break; - - default: - daeegg_cat.warning() << "Unsupported instance type found" << endl; - } -} - -// Processes the given mesh. -void DAEToEggConverter:: -process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh, - DaeMaterials *materials, DaeCharacter *character) { - - nassertv(mesh != nullptr); - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "Processing mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << endl; - } - - // Create the egg stuff to hold this mesh - PT(EggGroup) mesh_group = new EggGroup(FROM_FSTRING(mesh->GetDaeId())); - parent->add_child(mesh_group); - PT(EggVertexPool) mesh_pool = new EggVertexPool(FROM_FSTRING(mesh->GetDaeId())); - mesh_group->add_child(mesh_pool); - - // First retrieve the vertex source - if (mesh->GetSourceCount() == 0) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has no sources" << endl; - } - return; - } - const FCDGeometrySource* vsource = mesh->FindSourceByType(FUDaeGeometryInput::POSITION); - if (vsource == nullptr) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has no source for POSITION data" << endl; - } - return; - } - - // Loop through the polygon groups and add them - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has " << mesh->GetPolygonsCount() << " polygon groups" << endl; - } - if (mesh->GetPolygonsCount() == 0) return; - - // This is an array of pointers, I know. But since they are refcounted, I - // don't have a better idea. - PT(EggGroup) *primitive_holders = new PT(EggGroup) [mesh->GetPolygonsCount()]; - for (size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) { - const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr); - string material_semantic = FROM_FSTRING(polygons->GetMaterialSemantic()); - - // Stores which group holds the primitives. - PT(EggGroup) primitiveholder; - // If we have materials, make a group for each material. Then, apply the - // material's per-group stuff. - if (materials != nullptr && (!polygons->GetMaterialSemantic().empty()) && mesh->GetPolygonsCount() > 1) { - // primitiveholder = new EggGroup(FROM_FSTRING(mesh->GetDaeId()) + "." + - // material_semantic); - primitiveholder = new EggGroup; - mesh_group->add_child(primitiveholder); - } else { - primitiveholder = mesh_group; - } - primitive_holders[gr] = primitiveholder; - // Apply the per-group data of the materials, if we have it. - if (materials != nullptr) { - materials->apply_to_group(material_semantic, primitiveholder, _invert_transparency); - } - // Find the position sources - const FCDGeometryPolygonsInput* pinput = polygons->FindInput(FUDaeGeometryInput::POSITION); - assert(pinput != nullptr); - const uint32* indices = pinput->GetIndices(); - // Find the normal sources - const FCDGeometrySource* nsource = mesh->FindSourceByType(FUDaeGeometryInput::NORMAL); - const FCDGeometryPolygonsInput* ninput = polygons->FindInput(FUDaeGeometryInput::NORMAL); - const uint32* nindices; - if (ninput != nullptr) nindices = ninput->GetIndices(); - // Find texcoord sources - const FCDGeometrySource* tcsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXCOORD); - const FCDGeometryPolygonsInput* tcinput = polygons->FindInput(FUDaeGeometryInput::TEXCOORD); - const uint32* tcindices; - if (tcinput != nullptr) tcindices = tcinput->GetIndices(); - // Find vcolor sources - const FCDGeometrySource* csource = mesh->FindSourceByType(FUDaeGeometryInput::COLOR); - const FCDGeometryPolygonsInput* cinput = polygons->FindInput(FUDaeGeometryInput::COLOR); - const uint32* cindices; - if (cinput != nullptr) cindices = cinput->GetIndices(); - // Find binormal sources - const FCDGeometrySource* bsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXBINORMAL); - const FCDGeometryPolygonsInput* binput = polygons->FindInput(FUDaeGeometryInput::TEXBINORMAL); - const uint32* bindices; - if (binput != nullptr) bindices = binput->GetIndices(); - // Find tangent sources - const FCDGeometrySource* tsource = mesh->FindSourceByType(FUDaeGeometryInput::TEXTANGENT); - const FCDGeometryPolygonsInput* tinput = polygons->FindInput(FUDaeGeometryInput::TEXTANGENT); - const uint32* tindices; - if (tinput != nullptr) tindices = tinput->GetIndices(); - // Get a name for potential coordinate sets - string tcsetname; - if (materials != nullptr && tcinput != nullptr) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() - << "Assigning texcoord set " << tcinput->GetSet() - << " to semantic '" << material_semantic << "'\n"; - } - tcsetname = materials->get_uvset_name(material_semantic, - FUDaeGeometryInput::TEXCOORD, tcinput->GetSet()); - } - string tbsetname; - if (materials != nullptr && binput != nullptr) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() - << "Assigning texbinormal set " << binput->GetSet() - << " to semantic '" << material_semantic << "'\n"; - } - tbsetname = materials->get_uvset_name(material_semantic, - FUDaeGeometryInput::TEXBINORMAL, binput->GetSet()); - } - string ttsetname; - if (materials != nullptr && tinput != nullptr) { - if (daeegg_cat.is_debug()) { - daeegg_cat.debug() - << "Assigning textangent set " << tinput->GetSet() - << " to semantic '" << material_semantic << "'\n"; - } - ttsetname = materials->get_uvset_name(material_semantic, - FUDaeGeometryInput::TEXTANGENT, tinput->GetSet()); - } - // Loop through the indices and add the vertices. - for (size_t ix = 0; ix < pinput->GetIndexCount(); ++ix) { - PT_EggVertex vertex = mesh_pool->make_new_vertex(); - const float* data = &vsource->GetData()[indices[ix]*3]; - vertex->set_pos(LPoint3d(data[0], data[1], data[2])); - - if (character != nullptr) { - // If this is skinned geometry, add the vertex influences. - character->influence_vertex(indices[ix], vertex); - } - - // Process the normal - if (nsource != nullptr && ninput != nullptr) { - assert(nsource->GetStride() == 3); - data = &nsource->GetData()[nindices[ix]*3]; - vertex->set_normal(LVecBase3d(data[0], data[1], data[2])); - } - // Process the texcoords - if (tcsource != nullptr && tcinput != nullptr) { - assert(tcsource->GetStride() == 2 || tcsource->GetStride() == 3); - data = &tcsource->GetData()[tcindices[ix]*tcsource->GetStride()]; - if (tcsource->GetStride() == 2) { - vertex->set_uv(tcsetname, LPoint2d(data[0], data[1])); - } else { - vertex->set_uvw(tcsetname, LPoint3d(data[0], data[1], data[2])); - } - } - // Process the color - if (csource != nullptr && cinput != nullptr) { - assert(csource->GetStride() == 3 || csource->GetStride() == 4); - if (csource->GetStride() == 3) { - data = &csource->GetData()[cindices[ix]*3]; - vertex->set_color(LColor(data[0], data[1], data[2], 1.0f)); - } else { - data = &csource->GetData()[cindices[ix]*4]; - vertex->set_color(LColor(data[0], data[1], data[2], data[3])); - } - } - // Possibly add a UV object - if ((bsource != nullptr && binput != nullptr) || (tsource != nullptr && tinput != nullptr)) { - if (bsource != nullptr && binput != nullptr) { - assert(bsource->GetStride() == 3); - data = &bsource->GetData()[bindices[ix]*3]; - PT(EggVertexUV) uv_obj = vertex->modify_uv_obj(tbsetname); - if (uv_obj == nullptr) { - uv_obj = new EggVertexUV(tbsetname, LTexCoordd()); - } - uv_obj->set_binormal(LVecBase3d(data[0], data[1], data[2])); - } - if (tsource != nullptr && tinput != nullptr) { - assert(tsource->GetStride() == 3); - data = &tsource->GetData()[tindices[ix]*3]; - PT(EggVertexUV) uv_obj = vertex->modify_uv_obj(ttsetname); - if (uv_obj == nullptr) { - uv_obj = new EggVertexUV(ttsetname, LTexCoordd()); - } - uv_obj->set_tangent(LVecBase3d(data[0], data[1], data[2])); - } - } - vertex->transform(parent->get_node_to_vertex()); - } - } - // Loop again for the polygons - for (size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) { - const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr); - // Now loop through the faces - uint32 offset = 0; - for (size_t fa = 0; fa < polygons->GetFaceVertexCountCount(); ++fa) { - PT(EggPrimitive) primitive = nullptr; - // Create a primitive that matches the fcollada type - switch (polygons->GetPrimitiveType()) { - case FCDGeometryPolygons::LINES: - primitive = new EggLine(); - break; - case FCDGeometryPolygons::POLYGONS: - primitive = new EggPolygon(); - break; - case FCDGeometryPolygons::TRIANGLE_FANS: - primitive = new EggTriangleFan(); - break; - case FCDGeometryPolygons::TRIANGLE_STRIPS: - primitive = new EggTriangleStrip(); - break; - case FCDGeometryPolygons::POINTS: - primitive = new EggPoint(); - break; - case FCDGeometryPolygons::LINE_STRIPS: - daeegg_cat.warning() << "Linestrips not yet supported!" << endl; - break; - default: - daeegg_cat.warning() << "Unsupported primitive type found!" << endl; - } - if (primitive != nullptr) { - primitive_holders[gr]->add_child(primitive); - if (materials != nullptr) { - materials->apply_to_primitive(FROM_FSTRING(polygons->GetMaterialSemantic()), primitive); - } - for (size_t ve = 0; ve < polygons->GetFaceVertexCount(fa); ++ve) { - assert(mesh_pool->has_vertex(ve + polygons->GetFaceVertexOffset() + offset)); - primitive->add_vertex(mesh_pool->get_vertex(ve + polygons->GetFaceVertexOffset() + offset)); - } - } - offset += polygons->GetFaceVertexCount(fa); - } - } - delete[] primitive_holders; -} - -void DAEToEggConverter:: -process_spline(EggGroup *parent, const string group_name, FCDGeometrySpline* geometry_spline) { - assert(geometry_spline != nullptr); - PT(EggGroup) result = new EggGroup(group_name); - parent->add_child(result); - // TODO: if its not a nurbs, make it convert between the types - if (geometry_spline->GetType() != FUDaeSplineType::NURBS) { - daeegg_cat.warning() << "Only NURBS curves are supported (yet)!" << endl; - } else { - // Loop through the splines - for (size_t sp = 0; sp < geometry_spline->GetSplineCount(); ++sp) { - process_spline(result, geometry_spline->GetSpline(sp)); - } - } -} - -void DAEToEggConverter:: -process_spline(EggGroup *parent, const FCDSpline* spline) { - assert(spline != nullptr); - nassertv(spline->GetSplineType() == FUDaeSplineType::NURBS); - // Now load in the nurbs curve to the egg library - PT(EggNurbsCurve) nurbs_curve = new EggNurbsCurve(FROM_FSTRING(spline->GetName())); - parent->add_child(nurbs_curve); - // TODO: what value is this? - nurbs_curve->setup(0, ((const FCDNURBSSpline*) spline)->GetKnotCount()); - for (size_t kn = 0; kn < ((const FCDNURBSSpline*) spline)->GetKnotCount(); ++kn) { - const float* knot = ((const FCDNURBSSpline*) spline)->GetKnot(kn); - assert(knot != nullptr); - nurbs_curve->set_knot(kn, *knot); - } - for (size_t cv = 0; cv < spline->GetCVCount(); ++cv) { - PT_EggVertex c_vtx = new EggVertex(); - c_vtx->set_pos(TO_VEC3(*spline->GetCV(cv))); - c_vtx->transform(parent->get_node_to_vertex()); - nurbs_curve->add_vertex(c_vtx); - } -} - -void DAEToEggConverter:: -process_controller(EggGroup *parent, const FCDControllerInstance *instance) { - assert(instance != nullptr); - const FCDController* controller = (const FCDController *)instance->GetEntity(); - assert(controller != nullptr); - - if (get_animation_convert() == AC_none) { - // If we're exporting a static mesh, export the base geometry as-is. - const FCDGeometryMesh *mesh = controller->GetBaseGeometry()->GetMesh(); - if (mesh != nullptr) { - PT(DaeMaterials) materials = new DaeMaterials(instance); - if (daeegg_cat.is_spam()) { - daeegg_cat.spam() << "Processing mesh for controller\n"; - } - process_mesh(parent, mesh, materials); - } - } else { - // Add a character for this to the table, the mesh is processed later - PT(DaeCharacter) character = new DaeCharacter(parent, instance); - _characters.push_back(character); - } - - if (controller->IsMorph()) { - assert(controller != nullptr); - const FCDMorphController* morph_controller = controller->GetMorphController(); - assert(morph_controller != nullptr); - PT(EggTable) bundle = new EggTable(parent->get_name()); - bundle->set_table_type(EggTable::TT_bundle); - PT(EggTable) morph = new EggTable("morph"); - morph->set_table_type(EggTable::TT_table); - bundle->add_child(morph); - // Loop through the morph targets. - for (size_t mt = 0; mt < morph_controller->GetTargetCount(); ++mt) { - const FCDMorphTarget* morph_target = morph_controller->GetTarget(mt); - assert(morph_target != nullptr); - PT(EggSAnimData) target = new EggSAnimData(FROM_FSTRING(morph_target->GetGeometry()->GetName())); - if (morph_target->IsAnimated()) { - // TODO - } else { - target->add_data(morph_target->GetWeight()); - } - morph->add_child(target); - } - } -} - -void DAEToEggConverter:: -process_extra(EggGroup *group, const FCDExtra* extra) { - if (extra == nullptr) { - return; - } - nassertv(group != nullptr); - - const FCDEType* etype = extra->GetDefaultType(); - if (etype == nullptr) { - return; - } - - const FCDENode* enode = (const FCDENode*) etype->FindTechnique("PANDA3D"); - if (enode == nullptr) { - return; - } - - FCDENodeList tags; - enode->FindChildrenNodes("param", tags); - for (FCDENodeList::iterator it = tags.begin(); it != tags.end(); ++it) { - const FCDEAttribute* attr = (*it)->FindAttribute("sid"); - if (attr) { - group->set_tag(FROM_FSTRING(attr->GetValue()), (*it)->GetContent()); - } - } -} - -LMatrix4d DAEToEggConverter:: -convert_matrix(const FMMatrix44 &matrix) { - return LMatrix4d( - matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3], - matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3], - matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3], - matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]); -} - -void DAEToEggConverter:: -apply_transform(EggGroup *to, const FCDTransform* from) { - assert(from != nullptr); - assert(to != nullptr); - // to->set_transform3d(convert_matrix(from->ToMatrix()) * - // to->get_transform3d()); - switch (from->GetType()) { - case FCDTransform::TRANSLATION: - { - const FCDTTranslation *trans = (const FCDTTranslation *)from; - to->add_translate3d(TO_VEC3(trans->GetTranslation())); - } - break; - - case FCDTransform::ROTATION: - { - const FCDTRotation *rot = (const FCDTRotation *)from; - to->add_rotate3d(rot->GetAngle(), TO_VEC3(rot->GetAxis())); - } - break; - - case FCDTransform::SCALE: - { - const FCDTScale *scale = (const FCDTScale *)from; - to->add_scale3d(TO_VEC3(scale->GetScale())); - } - break; - - default: - // Either a matrix, or something we can't handle. - to->add_matrix4(convert_matrix(from->ToMatrix())); - break; - } -} diff --git a/pandatool/src/daeegg/daeToEggConverter.h b/pandatool/src/daeegg/daeToEggConverter.h deleted file mode 100644 index bb3b6f55..00000000 --- a/pandatool/src/daeegg/daeToEggConverter.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeToEggConverter.h - * @author rdb - * @date 2008-05-08 - */ - -#ifndef DAETOEGGCONVERTER_H -#define DAETOEGGCONVERTER_H - -#include "pandatoolbase.h" -#include "somethingToEggConverter.h" -#include "eggGroup.h" -#include "eggMaterial.h" -#include "eggTexture.h" -#include "eggTable.h" -#include "eggNurbsCurve.h" - -#include "pre_fcollada_include.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "daeMaterials.h" -#include "daeCharacter.h" -#include "pvector.h" // Include last - -/** - * This class supervises the construction of an EggData structure from a DAE - * file. - */ -class DAEToEggConverter : public SomethingToEggConverter { -public: - DAEToEggConverter(); - DAEToEggConverter(const DAEToEggConverter ©); - ~DAEToEggConverter(); - - virtual SomethingToEggConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - - virtual bool convert_file(const Filename &filename); - virtual DistanceUnit get_input_units(); - - bool _invert_transparency; - -private: - std::string _unit_name; - double _unit_meters; - PT(EggTable) _table; - FCDocument* _document; - FUErrorSimpleHandler* _error_handler; - DaeCharacter::JointMap _joints; - - typedef pvector Characters; - Characters _characters; - - void process_asset(); - void process_node(EggGroupNode *parent, const FCDSceneNode* node, bool forced = false); - void process_instance(EggGroup *parent, const FCDEntityInstance* instance); - void process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh, - DaeMaterials *materials, DaeCharacter *character = nullptr); - void process_spline(EggGroup *parent, const std::string group_name, FCDGeometrySpline* geometry_spline); - void process_spline(EggGroup *parent, const FCDSpline* spline); - void process_controller(EggGroup *parent, const FCDControllerInstance* instance); - void process_extra(EggGroup *group, const FCDExtra* extra); - - static LMatrix4d convert_matrix(const FMMatrix44& matrix); - void apply_transform(EggGroup *to, const FCDTransform* from); - - friend class DaeCharacter; -}; - -#endif diff --git a/pandatool/src/daeegg/fcollada_utils.h b/pandatool/src/daeegg/fcollada_utils.h deleted file mode 100644 index 3a8ae692..00000000 --- a/pandatool/src/daeegg/fcollada_utils.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fcollada_utils.h - * @author rdb - * @date 2008-12-22 - */ - -// This file defines some conversion tools for conversion between FCollada and -// Panda3D - -#ifndef FCOLLADA_UTILS_H -#define FCOLLADA_UTILS_H - -#include "pre_fcollada_include.h" -#include - -// Useful conversion stuff -inline LVecBase3d TO_VEC3(FMVector3 v) { - return LVecBase3d(v.x, v.y, v.z); -} -inline LVecBase4d TO_VEC4(FMVector4 v) { - return LVecBase4d(v.x, v.y, v.z, v.w); -} -inline LColor TO_COLOR(FMVector4 v) { - return LColor(v.x, v.y, v.z, v.w); -} -#define FROM_VEC3(v) (FMVector3(v[0], v[1], v[2])) -#define FROM_VEC4(v) (FMVector4(v[0], v[1], v[2], v[3])) -#define FROM_MAT4(v) (FMMatrix44(v.getData())) -#define FROM_FSTRING(fs) (std::string(fs.c_str())) - -#endif diff --git a/pandatool/src/daeegg/p3daeegg_composite1.cxx b/pandatool/src/daeegg/p3daeegg_composite1.cxx deleted file mode 100644 index be3f927d..00000000 --- a/pandatool/src/daeegg/p3daeegg_composite1.cxx +++ /dev/null @@ -1,5 +0,0 @@ - -#include "config_daeegg.cxx" -#include "daeCharacter.cxx" -#include "daeMaterials.cxx" -#include "daeToEggConverter.cxx" diff --git a/pandatool/src/daeegg/pre_fcollada_include.h b/pandatool/src/daeegg/pre_fcollada_include.h deleted file mode 100644 index 59ad054c..00000000 --- a/pandatool/src/daeegg/pre_fcollada_include.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pre_fcollada_include.h - * @author rdb - * @date 2008-10-04 - */ - -// This file defines some stuff that need to be defined before one includes -// FCollada.h - -#ifndef PRE_FCOLLADA_INCLUDE_H -#define PRE_FCOLLADA_INCLUDE_H - -#ifdef FCOLLADA_VERSION - #error You must include pre_fcollada_include.h before including FCollada.h! -#endif - -#ifdef _WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include -#endif - -// FCollada expects LINUX to be defined on linux -#ifdef IS_LINUX - #ifndef LINUX - #define LINUX - #endif -#endif - -#define NO_LIBXML -#define FCOLLADA_NOMINMAX - -// FCollada does use global min/max. -using std::min; -using std::max; - -#endif diff --git a/pandatool/src/daeprogs/CMakeLists.txt b/pandatool/src/daeprogs/CMakeLists.txt deleted file mode 100644 index 42cd2f48..00000000 --- a/pandatool/src/daeprogs/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(HAVE_EGG AND HAVE_FCOLLADA) - - add_executable(dae2egg daeToEgg.cxx daeToEgg.h) - target_link_libraries(dae2egg p3daeegg p3eggbase p3progbase) - install(TARGETS dae2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -endif() diff --git a/pandatool/src/daeprogs/daeToEgg.cxx b/pandatool/src/daeprogs/daeToEgg.cxx deleted file mode 100644 index e0074734..00000000 --- a/pandatool/src/daeprogs/daeToEgg.cxx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeToEgg.cxx - * @author rdb - * @date 2008-05-08 - */ - -#include "daeToEgg.h" - -#include "daeToEggConverter.h" - -/** - * - */ -DAEToEgg:: -DAEToEgg(): - SomethingToEgg("COLLADA", ".dae") -{ - add_animation_options(); - add_units_options(); - add_normals_options(); - add_transform_options(); - - add_option - ("invtrans", "", false, - "Import the .dae file using inverted transparency. " - "This is useful when importing COLLADA files from some authoring tools " - "that export models with inverted transparency, such as Google SketchUp.", - &SomethingToEgg::dispatch_none, &_invert_transparency); - - set_program_brief("convert COLLADA assets into .egg files"); - set_program_description - ("This program converts .dae files (COLLADA Digital Asset Exchange) to .egg."); - - _coordinate_system = CS_yup_right; - _animation_convert = AC_both; -} - -/** - * - */ -void DAEToEgg:: -run() { - if (_animation_convert != AC_both && _animation_convert != AC_none && - _animation_convert != AC_chan && _animation_convert != AC_model) { - std::cerr << "Unsupported animation convert option.\n"; - exit(1); - } - - nout << "Reading " << _input_filename << "\n"; - - _data->set_coordinate_system(_coordinate_system); - - DAEToEggConverter converter; - converter.set_egg_data(_data); - converter._allow_errors = _allow_errors; - converter._invert_transparency = _invert_transparency; - - apply_parameters(converter); - - if (!converter.convert_file(_input_filename)) { - nout << "Errors in conversion.\n"; - exit(1); - } - - write_egg_file(); - nout << "\n"; -} - - -int main(int argc, char *argv[]) { - DAEToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/daeprogs/daeToEgg.h b/pandatool/src/daeprogs/daeToEgg.h deleted file mode 100644 index 7b7eb3aa..00000000 --- a/pandatool/src/daeprogs/daeToEgg.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file daeToEgg.h - * @author rdb - * @date 2008-05-08 - */ - -#ifndef DAETOEGG_H -#define DAETOEGG_H - -#include "pandatoolbase.h" - -#include "somethingToEgg.h" -#include "daeToEggConverter.h" - -/** - * A program to read a DAE file and generate an egg file. - */ -class DAEToEgg : public SomethingToEgg { -public: - DAEToEgg(); - - void run(); - -private: - bool _invert_transparency; -}; - -#endif diff --git a/pandatool/src/daeprogs/eggToDAE.cxx b/pandatool/src/daeprogs/eggToDAE.cxx deleted file mode 100644 index d3c616c3..00000000 --- a/pandatool/src/daeprogs/eggToDAE.cxx +++ /dev/null @@ -1,173 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToDAE.cxx - * @author rdb - * @date 2008-10-04 - */ - -#include "eggToDAE.h" -#include "dcast.h" -#include "pandaVersion.h" - -#include -#include -#include - -// Useful conversion stuff -#define TO_VEC3(v) (LVecBase3d(v[0], v[1], v[2])) -#define TO_VEC4(v) (LVecBase4d(v[0], v[1], v[2], v[3])) -#define TO_COLOR(v) (LColor(v[0], v[1], v[2], v[3])) -#define FROM_VEC3(v) (FMVector3(v[0], v[1], v[2])) -#define FROM_VEC4(v) (FMVector4(v[0], v[1], v[2], v[3])) -#define FROM_MAT4(v) (FMMatrix44(v.get_data())) -#define FROM_FSTRING(fs) (fs.c_str()) - -using std::cerr; - -/** - * - */ -EggToDAE:: -EggToDAE() : - EggToSomething("COLLADA", ".dae", true, false) -{ - set_binary_output(false); - set_program_brief("convert .egg files into COLLADA asset files"); - set_program_description - ("This program converts files from the egg format to the COLLADA " - ".dae (Digital Asset Exchange) format."); - - _document = nullptr; -} - -/** - * - */ -void EggToDAE:: -run() { - nassertv(has_output_filename()); - nassertv(_data != nullptr); - - FCollada::Initialize(); - _document = FCollada::NewTopDocument(); - - // Add the contributor part to the asset - FCDAssetContributor* contributor = _document->GetAsset()->AddContributor(); - const char* user_name = getenv("USER"); - if (user_name == nullptr) user_name = getenv("USERNAME"); - if (user_name != nullptr) contributor->SetAuthor(TO_FSTRING(user_name)); - // contributor->SetSourceData(); - char authoring_tool[1024]; - snprintf(authoring_tool, 1024, "Panda3D %s eggToDAE converter | FCollada v%d.%02d", PANDA_VERSION_STR, FCOLLADA_VERSION >> 16, FCOLLADA_VERSION & 0xFFFF); - authoring_tool[1023] = 0; - contributor->SetAuthoringTool(TO_FSTRING(authoring_tool)); - - // Set coordinate system - switch (_data->get_coordinate_system()) { - case CS_zup_right: - _document->GetAsset()->SetUpAxis(FMVector3::ZAxis); - break; - case CS_yup_right: - _document->GetAsset()->SetUpAxis(FMVector3::YAxis); - break; - } - - // Now actually start processing the data. - FCDSceneNode* visual_scene = _document->AddVisualScene(); - for (EggGroupNode::iterator it = _data->begin(); it != _data->end(); ++it) { - if ((*it)->is_of_type(EggGroup::get_class_type())) { - process_node(visual_scene, DCAST(EggGroup, *it)); - } - } - - // We're done here. - FCollada::SaveDocument(_document, get_output_filename().to_os_specific().c_str()); - SAFE_DELETE(_document); - FCollada::Release(); - - // if (!out) { nout << "An error occurred while writing.\n"; exit(1); } -} - -void EggToDAE::process_node(FCDSceneNode* parent, const PT(EggGroup) node) { - assert(node != nullptr); - FCDSceneNode* scene_node = parent->AddChildNode(); - // Set the parameters - scene_node->SetDaeId(node->get_name().c_str()); - scene_node->SetJointFlag(node->is_joint()); - // Apply the transforms - apply_transform(scene_node, node); - // Recursively process sub-nodes - for (EggGroupNode::iterator it = node->begin(); it != node->end(); ++it) { - if ((*it)->is_of_type(EggGroup::get_class_type())) { - process_node(scene_node, DCAST(EggGroup, *it)); - } - } -} - -void EggToDAE::apply_transform(FCDSceneNode* to, const PT(EggGroup) from) { - assert(to != nullptr); - assert(from != nullptr); - for (int co = 0; co < from->get_num_components(); ++co) { - switch (from->get_component_type(co)) { - case EggTransform::CT_translate2d: - cerr << "Warning: ignoring non-supported 2d translation\n"; - break; - case EggTransform::CT_rotate2d: - cerr << "Warning: ignoring non-supported 2d rotation\n"; - break; - case EggTransform::CT_scale2d: - cerr << "Warning: ignoring non-supported 2d scaling\n"; - break; - case EggTransform::CT_matrix3: - cerr << "Warning: ignoring non-supported 2d matrix\n"; - break; - case EggTransform::CT_translate3d: { - FCDTTranslation* new_transform = (FCDTTranslation*) to->AddTransform(FCDTransform::TRANSLATION); - new_transform->SetTranslation(FROM_VEC3(from->get_component_vec3(co))); - break; } - case EggTransform::CT_rotate3d: { - FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION); - new_transform->SetRotation(FROM_VEC3(from->get_component_vec3(co)), from->get_component_number(co)); - break; } - case EggTransform::CT_scale3d: { - FCDTScale* new_transform = (FCDTScale*) to->AddTransform(FCDTransform::SCALE); - new_transform->SetScale(FROM_VEC3(from->get_component_vec3(co))); - break; } - case EggTransform::CT_matrix4: { - FCDTMatrix* new_transform = (FCDTMatrix*) to->AddTransform(FCDTransform::MATRIX); - new_transform->SetTransform(FROM_MAT4(from->get_component_mat4(co))); - break; } - case EggTransform::CT_rotx: { - FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION); - new_transform->SetRotation(FMVector3::XAxis, from->get_component_number(co)); - break; } - case EggTransform::CT_roty: { - FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION); - new_transform->SetRotation(FMVector3::YAxis, from->get_component_number(co)); - break; } - case EggTransform::CT_rotz: { - FCDTRotation* new_transform = (FCDTRotation*) to->AddTransform(FCDTransform::ROTATION); - new_transform->SetRotation(FMVector3::ZAxis, from->get_component_number(co)); - break; } - case EggTransform::CT_uniform_scale: { - FCDTScale* new_transform = (FCDTScale*) to->AddTransform(FCDTransform::SCALE); - new_transform->SetScale(from->get_component_number(co), from->get_component_number(co), from->get_component_number(co)); - break; } - default: - cerr << "Warning: ignoring invalid transform\n"; - } - } -} - -int main(int argc, char *argv[]) { - EggToDAE prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/daeprogs/eggToDAE.h b/pandatool/src/daeprogs/eggToDAE.h deleted file mode 100644 index c7782a42..00000000 --- a/pandatool/src/daeprogs/eggToDAE.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToDAE.h - * @author rdb - * @date 2008-10-04 - */ - -#ifndef EGGTODAE_H -#define EGGTODAE_H - -#include "pandatoolbase.h" -#include "eggToSomething.h" -#include "eggGroup.h" -#include "eggTransform.h" - -#include "pre_fcollada_include.h" -#include -#include - -/** - * A program to read an egg file and write a DAE file. - */ -class EggToDAE : public EggToSomething { -public: - EggToDAE(); - - void run(); - -private: - FCDocument* _document; - - void process_node(FCDSceneNode* parent, const PT(EggGroup) node); - void apply_transform(FCDSceneNode* to, const PT(EggGroup) from); - -}; - -#endif diff --git a/pandatool/src/deploy-stub/CMakeLists.txt b/pandatool/src/deploy-stub/CMakeLists.txt deleted file mode 100644 index 066d2925..00000000 --- a/pandatool/src/deploy-stub/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -if(NOT HAVE_PYTHON) - return() -endif() - -add_executable(deploy-stub deploy-stub.c) - -if(IS_OSX) - target_link_options(deploy-stub PRIVATE -sectcreate __PANDA __panda /dev/null) - set_target_properties(deploy-stub PROPERTIES - INSTALL_RPATH "@executable_path" - BUILD_WITH_INSTALL_RPATH ON) - -elseif(WIN32) - target_sources(deploy-stub PRIVATE frozen_dllmain.c) - -elseif(IS_LINUX OR IS_FREEBSD) - set_target_properties(deploy-stub PROPERTIES - INSTALL_RPATH "$ORIGIN" - BUILD_WITH_INSTALL_RPATH ON) - target_link_options(deploy-stub PRIVATE -Wl,--disable-new-dtags -Wl,-z,origin -rdynamic) - target_link_libraries(deploy-stub m) -endif() - -target_link_libraries(deploy-stub Python::Python) -install(TARGETS deploy-stub) - -if(WIN32 OR IS_OSX) - add_executable(deploy-stubw WIN32 deploy-stub.c) - - if(IS_OSX) - target_link_options(deploy-stubw PRIVATE -sectcreate __PANDA __panda /dev/null) - set_target_properties(deploy-stubw PROPERTIES - INSTALL_RPATH "@executable_path/../Frameworks" - BUILD_WITH_INSTALL_RPATH ON) - target_compile_definitions(deploy-stubw PRIVATE MACOS_APP_BUNDLE=1) - elseif(WIN32) - target_sources(deploy-stubw PRIVATE frozen_dllmain.c) - endif() - - target_link_libraries(deploy-stubw Python::Python) - install(TARGETS deploy-stubw) -endif() diff --git a/pandatool/src/deploy-stub/NativeInvocationHandler.java b/pandatool/src/deploy-stub/NativeInvocationHandler.java deleted file mode 100644 index 2a108373..00000000 --- a/pandatool/src/deploy-stub/NativeInvocationHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.jnius; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; - -/** - * Special support for pyjnius. - */ -public class NativeInvocationHandler implements InvocationHandler { - private long _ptr; - - public NativeInvocationHandler(long ptr) { - _ptr = ptr; - } - - public long getPythonObjectPointer() { - return _ptr; - } - - public Object invoke(Object proxy, Method method, Object[] args) { - return invoke0(proxy, method, args); - } - - native Object invoke0(Object proxy, Method method, Object[] args); -} diff --git a/pandatool/src/deploy-stub/android_log.c b/pandatool/src/deploy-stub/android_log.c deleted file mode 100644 index 83b60901..00000000 --- a/pandatool/src/deploy-stub/android_log.c +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file android_log.c - * @author rdb - * @date 2021-12-10 - */ - -#undef _POSIX_C_SOURCE -#undef _XOPEN_SOURCE -#define PY_SSIZE_T_CLEAN 1 - -#include "Python.h" -#include - -/** - * Writes a message to the Android log. - */ -static PyObject * -_py_write(PyObject *self, PyObject *args) { - int prio; - char *tag; - char *text; - if (PyArg_ParseTuple(args, "iss", &prio, &tag, &text)) { - __android_log_write(prio, tag, text); - Py_RETURN_NONE; - } - return NULL; -} - -static PyMethodDef python_simple_funcs[] = { - { "write", &_py_write, METH_VARARGS }, - { NULL, NULL } -}; - -static struct PyModuleDef android_log_module = { - PyModuleDef_HEAD_INIT, - "android_log", - NULL, - -1, - python_simple_funcs, - NULL, NULL, NULL, NULL -}; - -__attribute__((visibility("default"))) -PyObject *PyInit_android_log() { - return PyModule_Create(&android_log_module); -} diff --git a/pandatool/src/deploy-stub/android_main.cxx b/pandatool/src/deploy-stub/android_main.cxx deleted file mode 100644 index d1e140c5..00000000 --- a/pandatool/src/deploy-stub/android_main.cxx +++ /dev/null @@ -1,337 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file android_main.cxx - * @author rdb - * @date 2021-12-06 - */ - -#include "config_android.h" -#include "config_putil.h" -#include "virtualFileMountAndroidAsset.h" -#include "virtualFileSystem.h" -#include "filename.h" -#include "thread.h" -#include "urlSpec.h" - -#include "android_native_app_glue.h" - -#include "Python.h" -#include "structmember.h" - -#include -#include - -#include - -// Leave room for future expansion. -#define MAX_NUM_POINTERS 24 - -// Define an exposed symbol where we store the offset to the module data. -extern "C" { - __attribute__((__visibility__("default"), used)) - volatile struct { - uint64_t blob_offset; - uint64_t blob_size; - uint16_t version; - uint16_t num_pointers; - uint16_t codepage; - uint16_t flags; - uint64_t reserved; - void *pointers[MAX_NUM_POINTERS]; - - // The reason we initialize it to -1 is because otherwise, smart linkers may - // end up putting it in the .bss section for zero-initialized data. - } blobinfo = {(uint64_t)-1}; -} - -// Defined in android_log.c -extern "C" PyObject *PyInit_android_log(); - -/** - * Maps the binary blob at the given memory address to memory, and returns the - * pointer to the beginning of it. - */ -static void *map_blob(const char *path, off_t offset, size_t size) { - FILE *runtime = fopen(path, "rb"); - assert(runtime != NULL); - - void *blob = (void *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(runtime), offset); - assert(blob != MAP_FAILED); - - fclose(runtime); - return blob; -} - -/** - * The inverse of map_blob. - */ -static void unmap_blob(void *blob) { - if (blob) { - munmap(blob, blobinfo.blob_size); - } -} - -/** - * This function is called by native_app_glue to initialize the program. - * - * Note that this does not run in the main thread, but in a thread created - * specifically for this activity by android_native_app_glue. - * - * Unlike the regular deploy-stub, we need to interface directly with the - * Panda3D libraries here, since we can't pass the pointers from Java to Panda - * through the Python interpreter easily. - */ -void android_main(struct android_app *app) { - panda_android_app = app; - - // Attach the app thread to the Java VM. - JNIEnv *env; - ANativeActivity *activity = app->activity; - int attach_status = activity->vm->AttachCurrentThread(&env, nullptr); - if (attach_status < 0 || env == nullptr) { - android_cat.error() << "Failed to attach thread to JVM!\n"; - return; - } - - jclass activity_class = env->GetObjectClass(activity->clazz); - - // Get the current Java thread name. This just helps with debugging. - jmethodID methodID = env->GetStaticMethodID(activity_class, "getCurrentThreadName", "()Ljava/lang/String;"); - jstring jthread_name = (jstring) env->CallStaticObjectMethod(activity_class, methodID); - - std::string thread_name; - if (jthread_name != nullptr) { - const char *c_str = env->GetStringUTFChars(jthread_name, nullptr); - thread_name.assign(c_str); - env->ReleaseStringUTFChars(jthread_name, c_str); - } - - // Before we make any Panda calls, we must make the thread known to Panda. - // This will also cause the JNIEnv pointer to be stored on the thread. - // Note that we must keep a reference to this thread around. - PT(Thread) current_thread = Thread::bind_thread(thread_name, "android_app"); - - android_cat.info() - << "New native activity started on " << *current_thread << "\n"; - - // Fetch the data directory. - jmethodID get_appinfo = env->GetMethodID(activity_class, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;"); - - jobject appinfo = env->CallObjectMethod(activity->clazz, get_appinfo); - jclass appinfo_class = env->GetObjectClass(appinfo); - - // Fetch the path to the data directory. - jfieldID datadir_field = env->GetFieldID(appinfo_class, "dataDir", "Ljava/lang/String;"); - jstring datadir = (jstring) env->GetObjectField(appinfo, datadir_field); - const char *data_path = env->GetStringUTFChars(datadir, nullptr); - - if (data_path != nullptr) { - Filename::_internal_data_dir = data_path; - android_cat.info() << "Path to data: " << data_path << "\n"; - - env->ReleaseStringUTFChars(datadir, data_path); - } - - // Get the cache directory. Set the model-path to this location. - methodID = env->GetMethodID(activity_class, "getCacheDirString", "()Ljava/lang/String;"); - jstring jcache_dir = (jstring) env->CallObjectMethod(activity->clazz, methodID); - - if (jcache_dir != nullptr) { - const char *cache_dir; - cache_dir = env->GetStringUTFChars(jcache_dir, nullptr); - android_cat.info() << "Path to cache: " << cache_dir << "\n"; - - ConfigVariableFilename model_cache_dir("model-cache-dir", Filename()); - model_cache_dir.set_value(cache_dir); - env->ReleaseStringUTFChars(jcache_dir, cache_dir); - } - - // Fetch the path to the library directory. - jfieldID libdir_field = env->GetFieldID(appinfo_class, "nativeLibraryDir", "Ljava/lang/String;"); - jstring libdir_jstr = (jstring) env->GetObjectField(appinfo, libdir_field); - const char *libdir = env->GetStringUTFChars(libdir_jstr, nullptr); - - if (libdir != nullptr) { - std::string dtool_name = std::string(libdir) + "/libp3dtool.so"; - ExecutionEnvironment::set_dtool_name(dtool_name); - android_cat.info() << "Path to dtool: " << dtool_name << "\n"; - } - - // Get the path to the APK. - methodID = env->GetMethodID(activity_class, "getPackageCodePath", "()Ljava/lang/String;"); - jstring code_path = (jstring) env->CallObjectMethod(activity->clazz, methodID); - - const char *apk_path; - apk_path = env->GetStringUTFChars(code_path, nullptr); - android_cat.info() << "Path to APK: " << apk_path << "\n"; - - // Get the path to the native library. - methodID = env->GetMethodID(activity_class, "getNativeLibraryPath", "()Ljava/lang/String;"); - jstring lib_path_jstr = (jstring) env->CallObjectMethod(activity->clazz, methodID); - - const char *lib_path; - lib_path = env->GetStringUTFChars(lib_path_jstr, nullptr); - android_cat.info() << "Path to native library: " << lib_path << "\n"; - ExecutionEnvironment::set_binary_name(lib_path); - - // Map the blob to memory - void *blob = map_blob(lib_path, (off_t)blobinfo.blob_offset, (size_t)blobinfo.blob_size); - env->ReleaseStringUTFChars(lib_path_jstr, lib_path); - assert(blob != NULL); - - assert(blobinfo.num_pointers <= MAX_NUM_POINTERS); - for (uint32_t i = 0; i < blobinfo.num_pointers; ++i) { - // Only offset if the pointer is non-NULL. Except for the first - // pointer, which may never be NULL and usually (but not always) - // points to the beginning of the blob. - if (i == 0 || blobinfo.pointers[i] != nullptr) { - blobinfo.pointers[i] = (void *)((uintptr_t)blobinfo.pointers[i] + (uintptr_t)blob); - } - } - - // Now load the configuration files. - ConfigPage *page = nullptr; - ConfigPageManager *cp_mgr; - const char *prc_data = (char *)blobinfo.pointers[1]; - if (prc_data != nullptr) { - cp_mgr = ConfigPageManager::get_global_ptr(); - std::istringstream in(prc_data); - page = cp_mgr->make_explicit_page("builtin"); - page->read_prc(in); - } - - // Mount the assets directory. - Filename apk_fn(apk_path); - PT(VirtualFileMountAndroidAsset) asset_mount; - asset_mount = new VirtualFileMountAndroidAsset(app->activity->assetManager, apk_fn); - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - - //Filename asset_dir(apk_fn.get_dirname(), "assets"); - Filename asset_dir("/android_asset"); - vfs->mount(asset_mount, asset_dir, 0); - - // Release the apk_path. - env->ReleaseStringUTFChars(code_path, apk_path); - - // Now add the asset directory to the model-path. - //TODO: prevent it from adding the directory multiple times. - get_model_path().append_directory(asset_dir); - - // Offset the pointers in the module table using the base mmap address. - struct _frozen *moddef = (struct _frozen *)blobinfo.pointers[0]; - while (moddef->name) { - moddef->name = (char *)((uintptr_t)moddef->name + (uintptr_t)blob); - if (moddef->code != nullptr) { - moddef->code = (unsigned char *)((uintptr_t)moddef->code + (uintptr_t)blob); - } - //__android_log_print(ANDROID_LOG_DEBUG, "Panda3D", "MOD: %s %p %d\n", moddef->name, (void*)moddef->code, moddef->size); - moddef++; - } - - PyImport_FrozenModules = (struct _frozen *)blobinfo.pointers[0]; - - PyPreConfig preconfig; - PyPreConfig_InitIsolatedConfig(&preconfig); - preconfig.utf8_mode = 1; - PyStatus status = Py_PreInitialize(&preconfig); - if (PyStatus_Exception(status)) { - env->ReleaseStringUTFChars(libdir_jstr, libdir); - Py_ExitStatusException(status); - return; - } - - // Register the android_log module. - if (PyImport_AppendInittab("android_log", &PyInit_android_log) < 0) { - android_cat.error() - << "Failed to register android_log module.\n"; - env->ReleaseStringUTFChars(libdir_jstr, libdir); - return; - } - - PyConfig config; - PyConfig_InitIsolatedConfig(&config); - config.pathconfig_warnings = 0; /* Suppress errors from getpath.c */ - config.buffered_stdio = 0; - config.configure_c_stdio = 0; - config.write_bytecode = 0; - PyConfig_SetBytesString(&config, &config.platlibdir, libdir); - env->ReleaseStringUTFChars(libdir_jstr, libdir); - - status = Py_InitializeFromConfig(&config); - PyConfig_Clear(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - return; - } - - while (!app->destroyRequested) { - // Call the main module. This will not return until the app is done. - android_cat.info() << "Importing __main__\n"; - - int n = PyImport_ImportFrozenModule("__main__"); - if (n == 0) { - Py_FatalError("__main__ not frozen"); - break; - } - if (n < 0) { - if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { - PyErr_Print(); - } else { - PyErr_Clear(); - } - } - - if (app->destroyRequested) { - // The app closed responding to a destroy request. - break; - } - - // Ask Android to clean up the activity. - android_cat.info() << "Exited from __main__, finishing activity\n"; - ANativeActivity_finish(activity); - - // We still need to keep an event loop going until Android gives us leave - // to end the process. - while (!app->destroyRequested) { - int looper_id; - struct android_poll_source *source; - auto result = ALooper_pollOnce(-1, &looper_id, nullptr, (void **)&source); - if (looper_id == LOOPER_ID_MAIN) { - int8_t cmd = android_app_read_cmd(app); - android_app_pre_exec_cmd(app, cmd); - android_app_post_exec_cmd(app, cmd); - - // I don't think we can get a resume command after we call finish(), - // but let's handle it just in case. - if (cmd == APP_CMD_RESUME || cmd == APP_CMD_DESTROY) { - break; - } - } else if (source != nullptr) { - source->process(app, source); - } - } - } - - Py_Finalize(); - - android_cat.info() << "Destroy requested, exiting from android_main\n"; - - vfs->unmount(asset_mount); - - if (page != nullptr) { - cp_mgr->delete_explicit_page(page); - } - - unmap_blob(blob); - - // Detach the thread before exiting. - activity->vm->DetachCurrentThread(); - - _exit(0); -} diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c deleted file mode 100644 index 6cd2c280..00000000 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ /dev/null @@ -1,767 +0,0 @@ -/* Python interpreter main program for frozen scripts */ - -#include "Python.h" -#ifdef _WIN32 -# include "malloc.h" -# include -#else -# include -# include -#endif - -#ifdef __FreeBSD__ -# include -#endif - -#ifdef __APPLE__ -# include -# include -#endif - -#include -#include -#include - -#include - -#include "structmember.h" - -/* Leave room for future expansion. We only read pointer 0, but there are - other pointers that are being read by configPageManager.cxx. */ -#define MAX_NUM_POINTERS 24 - -/* Stored in the flags field of the blobinfo structure below. */ -enum Flags { - F_log_append = 1, - F_log_filename_strftime = 2, - F_keep_docstrings = 4, -}; - -/* Define an exposed symbol where we store the offset to the module data. */ -#ifdef _MSC_VER -__declspec(dllexport) -#else -__attribute__((__visibility__("default"), used)) -#endif -volatile struct { - uint64_t blob_offset; - uint64_t blob_size; - uint16_t version; - uint16_t num_pointers; - uint16_t codepage; - uint16_t flags; - uint64_t reserved; - void *pointers[MAX_NUM_POINTERS]; - - // The reason we initialize it to -1 is because otherwise, smart linkers may - // end up putting it in the .bss section for zero-initialized data. -} blobinfo = {(uint64_t)-1}; - - -#ifdef _WIN32 -// These placeholders can have their names changed by deploy-stub. -__declspec(dllexport) DWORD SymbolPlaceholder___________________ = 0x00000001; -__declspec(dllexport) DWORD SymbolPlaceholder__ = 0x00000001; -#endif - -#ifdef MS_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include - -extern void PyWinFreeze_ExeInit(void); -extern void PyWinFreeze_ExeTerm(void); - -static struct _inittab extensions[] = { - {0, 0}, -}; - -# define WIN_UNICODE -#endif - -#ifdef _WIN32 -static wchar_t *log_pathw = NULL; -#endif - -#if PY_VERSION_HEX >= 0x030b0000 -typedef struct { - const char *name; - const unsigned char *code; - int size; -} ModuleDef; -#else -typedef struct _frozen ModuleDef; -#endif - -/** - * Sets the main_dir field of the blobinfo structure, but only if it wasn't - * already set. - */ -static void set_main_dir(char *main_dir) { - if (blobinfo.num_pointers >= 10) { - if (blobinfo.num_pointers == 10) { - ++blobinfo.num_pointers; - blobinfo.pointers[10] = NULL; - } - if (blobinfo.pointers[10] == NULL) { - blobinfo.pointers[10] = main_dir; - } - } -} - -/** - * Creates the parent directories of the given path. Returns 1 on success. - */ -#ifdef _WIN32 -static int mkdir_parent(const wchar_t *path) { - // Copy the path to a temporary buffer. - wchar_t buffer[4096]; - size_t buflen = wcslen(path); - if (buflen + 1 >= _countof(buffer)) { - return 0; - } - wcscpy_s(buffer, _countof(buffer), path); - - // Seek back to find the last path separator. - while (buflen-- > 0) { - if (buffer[buflen] == '/' || buffer[buflen] == '\\') { - buffer[buflen] = 0; - break; - } - } - if (buflen == (size_t)-1 || buflen == 0) { - // There was no path separator, or this was the root directory. - return 0; - } - - if (CreateDirectoryW(buffer, NULL) != 0) { - // Success! - return 1; - } - - // Failed. - DWORD last_error = GetLastError(); - if (last_error == ERROR_ALREADY_EXISTS) { - // Not really an error: the directory is already there. - return 1; - } - - if (last_error == ERROR_PATH_NOT_FOUND) { - // We need to make the parent directory first. - if (mkdir_parent(buffer)) { - // Parent successfully created. Try again to make the child. - if (CreateDirectoryW(buffer, NULL) != 0) { - // Got it! - return 1; - } - } - } - return 0; -} -#else -static int mkdir_parent(const char *path) { - // Copy the path to a temporary buffer. - char buffer[4096]; - size_t buflen = strlen(path); - if (buflen + 1 >= sizeof(buffer)) { - return 0; - } - strcpy(buffer, path); - - // Seek back to find the last path separator. - while (buflen-- > 0) { - if (buffer[buflen] == '/') { - buffer[buflen] = 0; - break; - } - } - if (buflen == (size_t)-1 || buflen == 0) { - // There was no path separator, or this was the root directory. - return 0; - } - if (mkdir(buffer, 0755) == 0) { - // Success! - return 1; - } - - // Failed. - if (errno == EEXIST) { - // Not really an error: the directory is already there. - return 1; - } - - if (errno == ENOENT || errno == EACCES) { - // We need to make the parent directory first. - if (mkdir_parent(buffer)) { - // Parent successfully created. Try again to make the child. - if (mkdir(buffer, 0755) == 0) { - // Got it! - return 1; - } - } - } - return 0; -} -#endif - -/** - * Redirects the output streams to point to the log file with the given path. - * - * @param path specifies the location of log file, may start with ~ - * @param append should be nonzero if it should not truncate the log file. - */ -static int setup_logging(const char *path, int append) { -#ifdef _WIN32 - // Does it start with a tilde? Perform tilde expansion if so. - wchar_t *pathw = (wchar_t *)malloc(sizeof(wchar_t) * MAX_PATH); - pathw[0] = 0; - size_t offset = 0; - if (path[0] == '~' && (path[1] == 0 || path[1] == '/' || path[1] == '\\')) { - // Strip off the tilde. - ++path; - - // Get the home directory path for the current user. - if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, pathw))) { - free(pathw); - return 0; - } - offset = wcslen(pathw); - } - - // We need to convert the rest of the path from UTF-8 to UTF-16. - if (MultiByteToWideChar(CP_UTF8, 0, path, -1, pathw + offset, - (int)(MAX_PATH - offset)) == 0) { - free(pathw); - return 0; - } - - DWORD access = append ? FILE_APPEND_DATA : (GENERIC_READ | GENERIC_WRITE); - int creation = append ? OPEN_ALWAYS : CREATE_ALWAYS; - HANDLE handle = CreateFileW(pathw, access, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); - - if (handle == INVALID_HANDLE_VALUE) { - // Make the parent directories first. - mkdir_parent(pathw); - handle = CreateFileW(pathw, access, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); - } - - if (handle == INVALID_HANDLE_VALUE) { - free(pathw); - return 0; - } - - log_pathw = pathw; - - if (append) { - SetFilePointer(handle, 0, NULL, FILE_END); - } - - SetStdHandle(STD_OUTPUT_HANDLE, handle); - SetStdHandle(STD_ERROR_HANDLE, handle); - - // If we are running under the UCRT in a GUI application, we can't be sure - // that we have valid fds for stdout and stderr, so we have to set them up. - // One way to do this is to reopen them to something silly (like NUL). - if (_fileno(stdout) < 0) { - _close(1); - _wfreopen(L"\\\\.\\NUL", L"w", stdout); - } - - if (_fileno(stderr) < 0) { - _close(2); - _wfreopen(L"\\\\.\\NUL", L"w", stderr); - } - - // Now replace the stdout and stderr file descriptors with one pointing to - // our desired handle. - int fd = _open_osfhandle((intptr_t)handle, _O_WRONLY | _O_TEXT | _O_APPEND); - _dup2(fd, _fileno(stdout)); - _dup2(fd, _fileno(stderr)); - _close(fd); - - return 1; -#else - // Does it start with a tilde? Perform tilde expansion if so. - char buffer[PATH_MAX * 2]; - size_t offset = 0; - if (path[0] == '~' && (path[1] == 0 || path[1] == '/')) { - // Strip off the tilde. - ++path; - - // Get the home directory path for the current user. - const char *home_dir = getenv("HOME"); - if (home_dir == NULL) { - home_dir = getpwuid(getuid())->pw_dir; - } - offset = strlen(home_dir); - assert(offset < sizeof(buffer)); - strncpy(buffer, home_dir, sizeof(buffer)); - } - - // Copy over the rest of the path. - strcpy(buffer + offset, path); - - mode_t mode = O_CREAT | O_WRONLY | (append ? O_APPEND : O_TRUNC); - int fd = open(buffer, mode, 0644); - if (fd == -1) { - // Make the parent directories first. - mkdir_parent(buffer); - fd = open(buffer, mode, 0644); - } - - if (fd == -1) { - perror(buffer); - return 0; - } - - fflush(stdout); - fflush(stderr); - - dup2(fd, 1); - dup2(fd, 2); - - if (close(fd) < 0) { - perror("setup_logging: close"); - } - return 1; -#endif -} - -/** - * Sets the line_buffering property on a TextIOWrapper object. - */ -static int enable_line_buffering(PyObject *file) { -#if PY_VERSION_HEX >= 0x03070000 - /* Python 3.7 has a useful reconfigure() method. */ - PyObject *kwargs = _PyDict_NewPresized(1); - PyDict_SetItemString(kwargs, "line_buffering", Py_True); - PyObject *args = PyTuple_New(0); - - PyObject *method = PyObject_GetAttrString(file, "reconfigure"); - if (method != NULL) { - PyObject *result = PyObject_Call(method, args, kwargs); - Py_DECREF(method); - Py_DECREF(kwargs); - Py_DECREF(args); - if (result != NULL) { - Py_DECREF(result); - } else { - PyErr_Clear(); - return 0; - } - } else { - Py_DECREF(kwargs); - Py_DECREF(args); - PyErr_Clear(); - return 0; - } -#else - /* Older versions just don't expose a way to reconfigure(), but it's still - safe to override the property; we just have to use a hack to do it, - because it's officially marked "readonly". */ - - PyTypeObject *type = Py_TYPE(file); - PyMemberDef *member = type->tp_members; - - while (member != NULL && member->name != NULL) { - if (strcmp(member->name, "line_buffering") == 0) { - *((char *)file + member->offset) = 1; - return 1; - } - ++member; - } - fflush(stdout); -#endif - return 1; -} - -/* Main program */ - -#ifdef WIN_UNICODE -int Py_FrozenMain(int argc, wchar_t **argv) -#else -int Py_FrozenMain(int argc, char **argv) -#endif -{ - char *p; - int n, sts = 1; - int unbuffered = 0; -#ifndef NDEBUG - int inspect = 0; -#endif - -#ifndef WIN_UNICODE - int i; - char *oldloc; - wchar_t **argv_copy = NULL; - /* We need a second copies, as Python might modify the first one. */ - wchar_t **argv_copy2 = NULL; - - if (argc > 0) { - argv_copy = (wchar_t **)alloca(sizeof(wchar_t *) * argc); - argv_copy2 = (wchar_t **)alloca(sizeof(wchar_t *) * argc); - } -#endif - - Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ - Py_NoSiteFlag = 0; - Py_NoUserSiteDirectory = 1; - -#if PY_VERSION_HEX >= 0x03020000 - if (blobinfo.flags & F_keep_docstrings) { - Py_OptimizeFlag = 1; - } else { - Py_OptimizeFlag = 2; - } -#endif - -#ifndef NDEBUG - if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') - inspect = 1; -#endif - if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') - unbuffered = 1; - - if (unbuffered) { - setbuf(stdin, (char *)NULL); - setbuf(stdout, (char *)NULL); - setbuf(stderr, (char *)NULL); - } - -#ifndef WIN_UNICODE - oldloc = setlocale(LC_ALL, NULL); - setlocale(LC_ALL, ""); - for (i = 0; i < argc; i++) { - argv_copy[i] = Py_DecodeLocale(argv[i], NULL); - argv_copy2[i] = argv_copy[i]; - if (!argv_copy[i]) { - fprintf(stderr, "Unable to decode the command line argument #%i\n", - i + 1); - argc = i; - goto error; - } - } - setlocale(LC_ALL, oldloc); -#endif - -#ifdef MS_WINDOWS - PyImport_ExtendInittab(extensions); -#endif /* MS_WINDOWS */ - - if (argc >= 1) { -#ifndef WIN_UNICODE - Py_SetProgramName(argv_copy[0]); -#else - Py_SetProgramName(argv[0]); -#endif - } - - Py_Initialize(); -#ifdef MS_WINDOWS - PyWinFreeze_ExeInit(); -#endif - -#ifdef MS_WINDOWS - /* Ensure that line buffering is enabled on the output streams. */ - if (!unbuffered) { - PyObject *sys_stream; - sys_stream = PySys_GetObject("__stdout__"); - if (sys_stream && !enable_line_buffering(sys_stream)) { - fprintf(stderr, "Failed to enable line buffering on sys.stdout\n"); - fflush(stderr); - } - sys_stream = PySys_GetObject("__stderr__"); - if (sys_stream && !enable_line_buffering(sys_stream)) { - fprintf(stderr, "Failed to enable line buffering on sys.stderr\n"); - fflush(stderr); - } - } -#endif - - if (Py_VerboseFlag) - fprintf(stderr, "Python %s\n%s\n", - Py_GetVersion(), Py_GetCopyright()); - -#ifndef WIN_UNICODE - PySys_SetArgv(argc, argv_copy); -#else - PySys_SetArgv(argc, argv); -#endif - -#ifdef MACOS_APP_BUNDLE - // Add the Frameworks directory to sys.path. - char buffer[PATH_MAX]; - uint32_t bufsize = sizeof(buffer); - if (_NSGetExecutablePath(buffer, &bufsize) != 0) { - assert(false); - return 1; - } - char resolved[PATH_MAX]; - if (!realpath(buffer, resolved)) { - perror("realpath"); - return 1; - } - const char *dir = dirname(resolved); - sprintf(buffer, "%s/../Frameworks", dir); - - PyObject *sys_path = PyList_New(1); - PyList_SET_ITEM(sys_path, 0, PyUnicode_FromString(buffer)); - PySys_SetObject("path", sys_path); - Py_DECREF(sys_path); - - // Now, store a path to the Resources directory into the main_dir pointer, - // for ConfigPageManager to read out and assign to MAIN_DIR. - sprintf(buffer, "%s/../Resources", dir); - set_main_dir(buffer); - - // Finally, chdir to it, so that regular Python files are read from the - // right location. - chdir(buffer); -#endif - - n = PyImport_ImportFrozenModule("__main__"); - if (n == 0) - Py_FatalError("__main__ not frozen"); - if (n < 0) { - PyErr_Print(); - sts = 1; - } - else - sts = 0; - -#ifndef NDEBUG - if (inspect && isatty((int)fileno(stdin))) - sts = PyRun_AnyFile(stdin, "") != 0; -#endif - -#ifdef MS_WINDOWS - PyWinFreeze_ExeTerm(); -#endif - Py_Finalize(); - -#ifndef WIN_UNICODE -error: - if (argv_copy2) { - for (i = 0; i < argc; i++) { - PyMem_RawFree(argv_copy2[i]); - } - } -#endif - return sts; -} - -/** - * Maps the binary blob at the given memory address to memory, and returns the - * pointer to the beginning of it. - */ -static void *map_blob(off_t offset, size_t size) { - void *blob; - FILE *runtime; - -#ifdef _WIN32 - wchar_t buffer[2048]; - GetModuleFileNameW(NULL, buffer, 2048); - runtime = _wfopen(buffer, L"rb"); -#elif defined(__FreeBSD__) - size_t bufsize = 4096; - char buffer[4096]; - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; - mib[3] = getpid(); - if (sysctl(mib, 4, (void *)buffer, &bufsize, NULL, 0) == -1) { - perror("sysctl"); - return NULL; - } - runtime = fopen(buffer, "rb"); -#elif defined(__APPLE__) - char buffer[4096]; - uint32_t bufsize = sizeof(buffer); - if (_NSGetExecutablePath(buffer, &bufsize) != 0) { - return NULL; - } - runtime = fopen(buffer, "rb"); -#else - char buffer[4096]; - ssize_t pathlen = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); - if (pathlen <= 0) { - perror("readlink(/proc/self/exe)"); - return NULL; - } - buffer[pathlen] = '\0'; - runtime = fopen(buffer, "rb"); -#endif - - // Get offsets. In version 0, we read it from the end of the file. - if (blobinfo.version == 0) { - uint64_t end, begin; - fseek(runtime, -8, SEEK_END); - end = ftell(runtime); - fread(&begin, 8, 1, runtime); - - offset = (off_t)begin; - size = (size_t)(end - begin); - } - - // mmap the section indicated by the offset (or malloc/fread on windows) -#ifdef _WIN32 - blob = (void *)malloc(size); - assert(blob != NULL); - fseek(runtime, (long)offset, SEEK_SET); - fread(blob, size, 1, runtime); -#else - blob = (void *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(runtime), offset); - assert(blob != MAP_FAILED); -#endif - - fclose(runtime); - return blob; -} - -/** - * The inverse of map_blob. - */ -static void unmap_blob(void *blob) { - if (blob) { -#ifdef _WIN32 - free(blob); -#else - munmap(blob, blobinfo.blob_size); -#endif - } -} - -/** - * Main entry point to deploy-stub. - */ -#ifdef _WIN32 -int wmain(int argc, wchar_t *argv[]) { -#else -int main(int argc, char *argv[]) { -#endif - int retval; - ModuleDef *moddef; - const char *log_filename; - void *blob = NULL; - log_filename = NULL; - -#ifdef __APPLE__ - // Strip a -psn_xxx argument passed in by macOS when run from an .app bundle. - if (argc > 1 && strncmp(argv[1], "-psn_", 5) == 0) { - argv[1] = argv[0]; - ++argv; - --argc; - } -#endif - - /* - printf("blob_offset: %d\n", (int)blobinfo.blob_offset); - printf("blob_size: %d\n", (int)blobinfo.blob_size); - printf("version: %d\n", (int)blobinfo.version); - printf("num_pointers: %d\n", (int)blobinfo.num_pointers); - printf("codepage: %d\n", (int)blobinfo.codepage); - printf("flags: %d\n", (int)blobinfo.flags); - printf("reserved: %d\n", (int)blobinfo.reserved); - */ - - // If we have a blob offset, we have to map the blob to memory. - if (blobinfo.version == 0 || blobinfo.blob_offset != 0) { - void *blob = map_blob((off_t)blobinfo.blob_offset, (size_t)blobinfo.blob_size); - assert(blob != NULL); - - // Offset the pointers in the header using the base mmap address. - if (blobinfo.version > 0 && blobinfo.num_pointers > 0) { - uint32_t i; - assert(blobinfo.num_pointers <= MAX_NUM_POINTERS); - for (i = 0; i < blobinfo.num_pointers; ++i) { - // Only offset if the pointer is non-NULL. Except for the first - // pointer, which may never be NULL and usually (but not always) - // points to the beginning of the blob. - if (i == 0 || blobinfo.pointers[i] != 0) { - blobinfo.pointers[i] = (void *)((uintptr_t)blobinfo.pointers[i] + (uintptr_t)blob); - } - } - if (blobinfo.num_pointers >= 12) { - log_filename = blobinfo.pointers[11]; - } - } else { - blobinfo.pointers[0] = blob; - } - - // Offset the pointers in the module table using the base mmap address. - moddef = blobinfo.pointers[0]; -#if PY_VERSION_HEX < 0x030b0000 - PyImport_FrozenModules = moddef; -#endif - while (moddef->name) { - moddef->name = (char *)((uintptr_t)moddef->name + (uintptr_t)blob); - if (moddef->code != 0) { - moddef->code = (unsigned char *)((uintptr_t)moddef->code + (uintptr_t)blob); - } - //printf("MOD: %s %p %d\n", moddef->name, (void*)moddef->code, moddef->size); - moddef++; - } - - // In Python 3.11, we need to convert this to the new structure format. -#if PY_VERSION_HEX >= 0x030b0000 - ModuleDef *moddef_end = moddef; - ptrdiff_t num_modules = moddef - (ModuleDef *)blobinfo.pointers[0]; - struct _frozen *new_moddef = (struct _frozen *)calloc(num_modules + 1, sizeof(struct _frozen)); - PyImport_FrozenModules = new_moddef; - for (moddef = blobinfo.pointers[0]; moddef < moddef_end; ++moddef) { - new_moddef->name = moddef->name; - new_moddef->code = moddef->code; - new_moddef->size = moddef->size < 0 ? -(moddef->size) : moddef->size; - new_moddef->is_package = moddef->size < 0; -#if PY_VERSION_HEX < 0x030d0000 // 3.13 - new_moddef->get_code = NULL; -#endif - new_moddef++; - } -#endif - } else { - PyImport_FrozenModules = blobinfo.pointers[0]; - } - - if (log_filename != NULL) { - char log_filename_buf[4096]; - if (blobinfo.flags & F_log_filename_strftime) { - log_filename_buf[0] = 0; - time_t now = time(NULL); - if (strftime(log_filename_buf, sizeof(log_filename_buf), log_filename, localtime(&now)) > 0) { - log_filename = log_filename_buf; - } - } - setup_logging(log_filename, (blobinfo.flags & F_log_append) != 0); - } - -#ifdef _WIN32 - if (blobinfo.codepage != 0) { - SetConsoleCP(blobinfo.codepage); - SetConsoleOutputCP(blobinfo.codepage); - } -#endif - - // Run frozen application - retval = Py_FrozenMain(argc, argv); - - fflush(stdout); - fflush(stderr); - -#if PY_VERSION_HEX >= 0x030b0000 - free((void *)PyImport_FrozenModules); - PyImport_FrozenModules = NULL; -#endif - - unmap_blob(blob); - return retval; -} - -#ifdef WIN_UNICODE -int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpCmdLine, int nCmdShow) { - return wmain(__argc, __wargv); -} -#elif defined(_WIN32) -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpCmdLine, int nCmdShow) { - return main(__argc, __argv); -} -#endif diff --git a/pandatool/src/deploy-stub/frozen_dllmain.c b/pandatool/src/deploy-stub/frozen_dllmain.c deleted file mode 100644 index 3e374cf5..00000000 --- a/pandatool/src/deploy-stub/frozen_dllmain.c +++ /dev/null @@ -1,134 +0,0 @@ -/* FreezeDLLMain.cpp - -This is a DLLMain suitable for frozen applications/DLLs on -a Windows platform. - -The general problem is that many Python extension modules may define -DLL main functions, but when statically linked together to form -a frozen application, this DLLMain symbol exists multiple times. - -The solution is: -* Each module checks for a frozen build, and if so, defines its DLLMain - function as "__declspec(dllexport) DllMain%module%" - (eg, DllMainpythoncom, or DllMainpywintypes) - -* The frozen .EXE/.DLL links against this module, which provides - the single DllMain. - -* This DllMain attempts to locate and call the DllMain for each - of the extension modules. - -* This code also has hooks to "simulate" DllMain when used from - a frozen .EXE. - -At this stage, there is a static table of "possibly embedded modules". -This should change to something better, but it will work OK for now. - -Note that this scheme does not handle dependencies in the order -of DllMain calls - except it does call pywintypes first :-) - -As an example of how an extension module with a DllMain should be -changed, here is a snippet from the pythoncom extension module. - - // end of example code from pythoncom's DllMain.cpp - #ifndef BUILD_FREEZE - #define DLLMAIN DllMain - #define DLLMAIN_DECL - #else - #define DLLMAIN DllMainpythoncom - #define DLLMAIN_DECL __declspec(dllexport) - #endif - - extern "C" DLLMAIN_DECL - BOOL WINAPI DLLMAIN(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) - // end of example code from pythoncom's DllMain.cpp - -***************************************************************************/ -#include "windows.h" - -static char *possibleModules[] = { - "pywintypes", - "pythoncom", - "win32ui", - NULL, -}; - -BOOL CallModuleDllMain(char *modName, DWORD dwReason); - - -/* - Called by a frozen .EXE only, so that built-in extension - modules are initialized correctly -*/ -void PyWinFreeze_ExeInit(void) -{ - char **modName; - for (modName = possibleModules;*modName;*modName++) { -/* printf("Initialising '%s'\n", *modName); */ - CallModuleDllMain(*modName, DLL_PROCESS_ATTACH); - } -} - -/* - Called by a frozen .EXE only, so that built-in extension - modules are cleaned up -*/ -void PyWinFreeze_ExeTerm(void) -{ - // Must go backwards - char **modName; - for (modName = possibleModules+(sizeof(possibleModules) / sizeof(char *))-2; - modName >= possibleModules; - *modName--) { -/* printf("Terminating '%s'\n", *modName);*/ - CallModuleDllMain(*modName, DLL_PROCESS_DETACH); - } -} - -BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) -{ - BOOL ret = TRUE; - switch (dwReason) { - case DLL_PROCESS_ATTACH: - { - char **modName; - for (modName = possibleModules;*modName;*modName++) { - BOOL ok = CallModuleDllMain(*modName, dwReason); - if (!ok) - ret = FALSE; - } - break; - } - case DLL_PROCESS_DETACH: - { - // Must go backwards - char **modName; - for (modName = possibleModules+(sizeof(possibleModules) / sizeof(char *))-2; - modName >= possibleModules; - *modName--) - CallModuleDllMain(*modName, DLL_PROCESS_DETACH); - break; - } - } - return ret; -} - -BOOL CallModuleDllMain(char *modName, DWORD dwReason) -{ - BOOL (WINAPI * pfndllmain)(HINSTANCE, DWORD, LPVOID); - - char funcName[255]; - HMODULE hmod = GetModuleHandleW(NULL); - strcpy(funcName, "_DllMain"); - strcat(funcName, modName); - strcat(funcName, "@12"); // stdcall convention. - pfndllmain = (BOOL (WINAPI *)(HINSTANCE, DWORD, LPVOID))GetProcAddress(hmod, funcName); - if (pfndllmain==NULL) { - /* No function by that name exported - then that module does - not appear in our frozen program - return OK - */ - return TRUE; - } - return (*pfndllmain)(hmod, dwReason, NULL); -} - diff --git a/pandatool/src/dxf/CMakeLists.txt b/pandatool/src/dxf/CMakeLists.txt deleted file mode 100644 index c8095a32..00000000 --- a/pandatool/src/dxf/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -set(P3DXF_HEADERS - dxfFile.h - dxfLayer.h - dxfLayerMap.h - dxfVertex.h -) - -set(P3DXF_SOURCES - dxfFile.cxx - dxfLayer.cxx - dxfLayerMap.cxx - dxfVertex.cxx -) - -composite_sources(p3dxf P3DXF_SOURCES) -add_library(p3dxf STATIC ${P3DXF_HEADERS} ${P3DXF_SOURCES}) -target_link_libraries(p3dxf p3pandatoolbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/dxf/dxfFile.cxx b/pandatool/src/dxf/dxfFile.cxx deleted file mode 100644 index f5bb6e09..00000000 --- a/pandatool/src/dxf/dxfFile.cxx +++ /dev/null @@ -1,937 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfFile.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfFile.h" -#include "string_utils.h" -#include "virtualFileSystem.h" - -using std::istream; -using std::ostream; -using std::string; - -DXFFile::Color DXFFile::_colors[DXF_num_colors] = { - { 1, 1, 1 }, // Color 0 is not used. - { 1, 0, 0 }, // Color 1 = Red - { 1, 1, 0 }, // Color 2 = Yellow - { 0, 1, 0 }, // Color 3 = Green - { 0, 1, 1 }, // Color 4 = Cyan - { 0, 0, 1 }, // Color 5 = Blue - { 1, 0, 1 }, // Color 6 = Magenta - { 1, 1, 1 }, // Color 7 = Black/White - { 0.3, 0.3, 0.3 }, // Color 8 = Gray - { 0.7, 0.7, 0.7 }, // Color 9 = Gray - { 1, 0, 0 }, // Remaining colors are from the fancy palette. - { 1, 0.5, 0.5 }, - { 0.65, 0, 0 }, - { 0.65, 0.325, 0.325 }, - { 0.5, 0, 0 }, - { 0.5, 0.25, 0.25 }, - { 0.3, 0, 0 }, - { 0.3, 0.15, 0.15 }, - { 0.15, 0, 0 }, - { 0.15, 0.075, 0.075 }, - { 1, 0.25, 0 }, - { 1, 0.625, 0.5 }, - { 0.65, 0.1625, 0 }, - { 0.65, 0.4063, 0.325 }, - { 0.5, 0.125, 0 }, - { 0.5, 0.3125, 0.25 }, - { 0.3, 0.075, 0 }, - { 0.3, 0.1875, 0.15 }, - { 0.15, 0.0375, 0 }, - { 0.15, 0.0938, 0.075 }, - { 1, 0.5, 0 }, - { 1, 0.75, 0.5 }, - { 0.65, 0.325, 0 }, - { 0.65, 0.4875, 0.325 }, - { 0.5, 0.25, 0 }, - { 0.5, 0.375, 0.25 }, - { 0.3, 0.15, 0 }, - { 0.3, 0.225, 0.15 }, - { 0.15, 0.075, 0 }, - { 0.15, 0.1125, 0.075 }, - { 1, 0.75, 0 }, - { 1, 0.875, 0.5 }, - { 0.65, 0.4875, 0 }, - { 0.65, 0.5688, 0.325 }, - { 0.5, 0.375, 0 }, - { 0.5, 0.4375, 0.25 }, - { 0.3, 0.225, 0 }, - { 0.3, 0.2625, 0.15 }, - { 0.15, 0.1125, 0 }, - { 0.15, 0.1313, 0.075 }, - { 1, 1, 0 }, - { 1, 1, 0.5 }, - { 0.65, 0.65, 0 }, - { 0.65, 0.65, 0.325 }, - { 0.5, 0.5, 0 }, - { 0.5, 0.5, 0.25 }, - { 0.3, 0.3, 0 }, - { 0.3, 0.3, 0.15 }, - { 0.15, 0.15, 0 }, - { 0.15, 0.15, 0.075 }, - { 0.75, 1, 0 }, - { 0.875, 1, 0.5 }, - { 0.4875, 0.65, 0 }, - { 0.5688, 0.65, 0.325 }, - { 0.375, 0.5, 0 }, - { 0.4375, 0.5, 0.25 }, - { 0.225, 0.3, 0 }, - { 0.2625, 0.3, 0.15 }, - { 0.1125, 0.15, 0 }, - { 0.1313, 0.15, 0.075 }, - { 0.5, 1, 0 }, - { 0.75, 1, 0.5 }, - { 0.325, 0.65, 0 }, - { 0.4875, 0.65, 0.325 }, - { 0.25, 0.5, 0 }, - { 0.375, 0.5, 0.25 }, - { 0.15, 0.3, 0 }, - { 0.225, 0.3, 0.15 }, - { 0.075, 0.15, 0 }, - { 0.1125, 0.15, 0.075 }, - { 0.25, 1, 0 }, - { 0.625, 1, 0.5 }, - { 0.1625, 0.65, 0 }, - { 0.4063, 0.65, 0.325 }, - { 0.125, 0.5, 0 }, - { 0.3125, 0.5, 0.25 }, - { 0.075, 0.3, 0 }, - { 0.1875, 0.3, 0.15 }, - { 0.0375, 0.15, 0 }, - { 0.0938, 0.15, 0.075 }, - { 0, 1, 0 }, - { 0.5, 1, 0.5 }, - { 0, 0.65, 0 }, - { 0.325, 0.65, 0.325 }, - { 0, 0.5, 0 }, - { 0.25, 0.5, 0.25 }, - { 0, 0.3, 0 }, - { 0.15, 0.3, 0.15 }, - { 0, 0.15, 0 }, - { 0.075, 0.15, 0.075 }, - { 0, 1, 0.25 }, - { 0.5, 1, 0.625 }, - { 0, 0.65, 0.1625 }, - { 0.325, 0.65, 0.4063 }, - { 0, 0.5, 0.125 }, - { 0.25, 0.5, 0.3125 }, - { 0, 0.3, 0.075 }, - { 0.15, 0.3, 0.1875 }, - { 0, 0.15, 0.0375 }, - { 0.075, 0.15, 0.0938 }, - { 0, 1, 0.5 }, - { 0.5, 1, 0.75 }, - { 0, 0.65, 0.325 }, - { 0.325, 0.65, 0.4875 }, - { 0, 0.5, 0.25 }, - { 0.25, 0.5, 0.375 }, - { 0, 0.3, 0.15 }, - { 0.15, 0.3, 0.225 }, - { 0, 0.15, 0.075 }, - { 0.075, 0.15, 0.1125 }, - { 0, 1, 0.75 }, - { 0.5, 1, 0.875 }, - { 0, 0.65, 0.4875 }, - { 0.325, 0.65, 0.5688 }, - { 0, 0.5, 0.375 }, - { 0.25, 0.5, 0.4375 }, - { 0, 0.3, 0.225 }, - { 0.15, 0.3, 0.2625 }, - { 0, 0.15, 0.1125 }, - { 0.075, 0.15, 0.1313 }, - { 0, 1, 1 }, - { 0.5, 1, 1 }, - { 0, 0.65, 0.65 }, - { 0.325, 0.65, 0.65 }, - { 0, 0.5, 0.5 }, - { 0.25, 0.5, 0.5 }, - { 0, 0.3, 0.3 }, - { 0.15, 0.3, 0.3 }, - { 0, 0.15, 0.15 }, - { 0.075, 0.15, 0.15 }, - { 0, 0.75, 1 }, - { 0.5, 0.875, 1 }, - { 0, 0.4875, 0.65 }, - { 0.325, 0.5688, 0.65 }, - { 0, 0.375, 0.5 }, - { 0.25, 0.4375, 0.5 }, - { 0, 0.225, 0.3 }, - { 0.15, 0.2625, 0.3 }, - { 0, 0.1125, 0.15 }, - { 0.075, 0.1313, 0.15 }, - { 0, 0.5, 1 }, - { 0.5, 0.75, 1 }, - { 0, 0.325, 0.65 }, - { 0.325, 0.4875, 0.65 }, - { 0, 0.25, 0.5 }, - { 0.25, 0.375, 0.5 }, - { 0, 0.15, 0.3 }, - { 0.15, 0.225, 0.3 }, - { 0, 0.075, 0.15 }, - { 0.075, 0.1125, 0.15 }, - { 0, 0.25, 1 }, - { 0.5, 0.625, 1 }, - { 0, 0.1625, 0.65 }, - { 0.325, 0.4063, 0.65 }, - { 0, 0.125, 0.5 }, - { 0.25, 0.3125, 0.5 }, - { 0, 0.075, 0.3 }, - { 0.15, 0.1875, 0.3 }, - { 0, 0.0375, 0.15 }, - { 0.075, 0.0938, 0.15 }, - { 0, 0, 1 }, - { 0.5, 0.5, 1 }, - { 0, 0, 0.65 }, - { 0.325, 0.325, 0.65 }, - { 0, 0, 0.5 }, - { 0.25, 0.25, 0.5 }, - { 0, 0, 0.3 }, - { 0.15, 0.15, 0.3 }, - { 0, 0, 0.15 }, - { 0.075, 0.075, 0.15 }, - { 0.25, 0, 1 }, - { 0.625, 0.5, 1 }, - { 0.1625, 0, 0.65 }, - { 0.4063, 0.325, 0.65 }, - { 0.125, 0, 0.5 }, - { 0.3125, 0.25, 0.5 }, - { 0.075, 0, 0.3 }, - { 0.1875, 0.15, 0.3 }, - { 0.0375, 0, 0.15 }, - { 0.0938, 0.075, 0.15 }, - { 0.5, 0, 1 }, - { 0.75, 0.5, 1 }, - { 0.325, 0, 0.65 }, - { 0.4875, 0.325, 0.65 }, - { 0.25, 0, 0.5 }, - { 0.375, 0.25, 0.5 }, - { 0.15, 0, 0.3 }, - { 0.225, 0.15, 0.3 }, - { 0.075, 0, 0.15 }, - { 0.1125, 0.075, 0.15 }, - { 0.75, 0, 1 }, - { 0.875, 0.5, 1 }, - { 0.4875, 0, 0.65 }, - { 0.5688, 0.325, 0.65 }, - { 0.375, 0, 0.5 }, - { 0.4375, 0.25, 0.5 }, - { 0.225, 0, 0.3 }, - { 0.2625, 0.15, 0.3 }, - { 0.1125, 0, 0.15 }, - { 0.1313, 0.075, 0.15 }, - { 1, 0, 1 }, - { 1, 0.5, 1 }, - { 0.65, 0, 0.65 }, - { 0.65, 0.325, 0.65 }, - { 0.5, 0, 0.5 }, - { 0.5, 0.25, 0.5 }, - { 0.3, 0, 0.3 }, - { 0.3, 0.15, 0.3 }, - { 0.15, 0, 0.15 }, - { 0.15, 0.075, 0.15 }, - { 1, 0, 0.75 }, - { 1, 0.5, 0.875 }, - { 0.65, 0, 0.4875 }, - { 0.65, 0.325, 0.5688 }, - { 0.5, 0, 0.375 }, - { 0.5, 0.25, 0.4375 }, - { 0.3, 0, 0.225 }, - { 0.3, 0.15, 0.2625 }, - { 0.15, 0, 0.1125 }, - { 0.15, 0.075, 0.1313 }, - { 1, 0, 0.5 }, - { 1, 0.5, 0.75 }, - { 0.65, 0, 0.325 }, - { 0.65, 0.325, 0.4875 }, - { 0.5, 0, 0.25 }, - { 0.5, 0.25, 0.375 }, - { 0.3, 0, 0.15 }, - { 0.3, 0.15, 0.225 }, - { 0.15, 0, 0.075 }, - { 0.15, 0.075, 0.1125 }, - { 1, 0, 0.25 }, - { 1, 0.5, 0.625 }, - { 0.65, 0, 0.1625 }, - { 0.65, 0.325, 0.4063 }, - { 0.5, 0, 0.125 }, - { 0.5, 0.25, 0.3125 }, - { 0.3, 0, 0.075 }, - { 0.3, 0.15, 0.1875 }, - { 0.15, 0, 0.0375 }, - { 0.15, 0.075, 0.0938 }, - { 0.33, 0.33, 0.33 }, - { 0.464, 0.464, 0.464 }, - { 0.598, 0.598, 0.598 }, - { 0.732, 0.732, 0.732 }, - { 0.866, 0.866, 0.866 }, - { 1, 1, 1 }, -}; - - -/** - * - */ -DXFFile:: -DXFFile() { - _in = nullptr; - _owns_in = false; - _layer = nullptr; - reset_entity(); - _color_index = -1; -} - -/** - * - */ -DXFFile:: -~DXFFile() { - if (_owns_in) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->close_read_file(_in); - } -} - - -/** - * Opens the indicated filename and reads it as a DXF file. - */ -void DXFFile:: -process(Filename filename) { - filename.set_text(); - - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - istream *in = vfs->open_read_file(filename, true); - if (in == nullptr) { - return; - } - process(in, true); -} - - -/** - * Reads the indicated stream as a DXF file. If owns_in is true, then the - * istream will be deleted via vfs->close_read_file() when the DXFFile object - * destructs. - */ -void DXFFile:: -process(istream *in, bool owns_in) { - if (_owns_in) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->close_read_file(_in); - } - _in = in; - _owns_in = owns_in; - _state = ST_top; - - begin_file(); - while (_state != ST_done && _state != ST_error) { - if (get_group()) { - switch (_state) { - case ST_top: - state_top(); - break; - - case ST_section: - state_section(); - break; - - case ST_entity: - state_entity(); - break; - - case ST_verts: - state_verts(); - break; - - default: - break; - } - } - } -} - - - -/** - * A hook for user code, if desired. This function is called whenever - * processing begins on the DXF file. - */ -void DXFFile:: -begin_file() { -} - - -/** - * A hook for user code, if desired. This function is called whenever a new - * section in the DXF file is encountered. - */ -void DXFFile:: -begin_section() { -} - - -/** - * A hook for user code, if desired. This function is called whenever a - * vertex is read from the DXF file. This function has the default behavior - * of adding the vertex to the _verts list, so that when done_entity() is - * called later, it will have the complete list of vertices available to it. - */ -void DXFFile:: -done_vertex() { - DXFVertex v; - v._p = _p; - _verts.push_back(v); -} - - -/** - * This is the primary hook for user code. This function is called when an - * entity is read from the DXF file. This may be something like a polygon, - * point, or a polygon mesh: any geometry. It is up to the user code to - * override this function and do something interesting with each piece of - * geometry that is read. - */ -void DXFFile:: -done_entity() { -} - - -/** - * A hook for user code, if desired. This function is called as each section - * in the DXF file is finished. - */ -void DXFFile:: -end_section() { -} - - -/** - * A hook for user code, if desired. This function is called when the DXF - * processing is complete. - */ -void DXFFile:: -end_file() { -} - - -/** - * A hook for user code, if desired. This function is called when some - * unexpected error occurs while reading the DXF file. - */ -void DXFFile:: -error() { - nout << "Error!\n"; -} - - - -/** - * Returns the index of the closest matching AutoCAD color to the indicated r, - * g, b. - */ -int DXFFile:: -find_color(double r, double g, double b) { - double best_diff = 4.0; // 4 is greater than our expected max, 3. - int best_index = 7; - - for (int i = 0; i < 255; i++) { - double diff = ((r - _colors[i].r) * (r - _colors[i].r) + - (g - _colors[i].g) * (g - _colors[i].g) + - (b - _colors[i].b) * (b - _colors[i].b)); - if (diff < best_diff) { - best_diff = diff; - best_index = i; - } - } - - return best_index; -} - -/** - * This is a convenience function to return the r,g,b color of the current - * entity (at the time of done_entity()). It's based on the _color_index - * value that was read from the DXF file. - */ -const DXFFile::Color &DXFFile:: -get_color() const { - if (_color_index >= 0 && _color_index <= 255) { - return _colors[_color_index]; - } - return _colors[0]; -} - - -/** - * Assuming the current entity is a planar-based entity, for instance, a 2-d - * polygon (as opposed to a 3-d polygon), this converts the coordinates from - * the funny planar coordinate system to the world coordinates. It converts - * the _p value of the entity, as well as all vertices in the _verts list. - */ -void DXFFile:: -ocs_2_wcs() { - compute_ocs(); - - // Convert the entity's position. - _p = _p * _ocs2wcs; - - // Maybe we have these coordinates too. - _q = _q * _ocs2wcs; - _r = _r * _ocs2wcs; - _s = _s * _ocs2wcs; - - // If there are any vertices, convert them too. - DXFVertices::iterator vi; - for (vi = _verts.begin(); vi != _verts.end(); ++vi) { - (*vi)._p = (*vi)._p * _ocs2wcs; - } -} - - -/** - * Computes the matrix used to convert from the planar coordinate system to - * world coordinates. - */ -void DXFFile:: -compute_ocs() { - // A 2-d entity's vertices might be defined in an "Object Coordinate System" - // which has a funny definition. Its Z axis is defined by _z, and its X and - // Y axes are inferred from that. The origin is the same as the world - // coordinate system's origin. - - // The Z axis is _z. Determine the x and y axes. - LVector3d x, y; - - if (fabs(_z[0]) < 1.0/64.0 && fabs(_z[1]) < 1.0/64.0) { - x = cross(LVector3d(0.0, 1.0, 0.0), _z); - } else { - x = cross(LVector3d(0.0, 0.0, 1.0), _z); - } - x.normalize(); - y = cross(x, _z); - y.normalize(); - - // Now build a rotate matrix from these vectors. - LMatrix4d - ocs( x[0], x[1], x[2], 0, - y[0], y[1], y[2], 0, - _z[0], _z[1], _z[2], 0, - 0, 0, 0, 1); - - _ocs2wcs.invert_from(ocs); -} - - -/** - * Reads the next code, string pair from the DXF file. This is the basic unit - * of data in a DXF file. - */ -bool DXFFile:: -get_group() { - istream &in = *_in; - do { - in >> _code; - if (!in) { - change_state(ST_error); - return false; - } - - // Now skip past exactly one newline character and any number of other - // whitespace characters. - while (in && in.peek() != '\n') { - in.get(); - } - in.get(); - while (in && isspace(in.peek()) && in.peek() != '\n') { - in.get(); - } - - std::getline(in, _string); - _string = trim_right(_string); - - if (!in) { - change_state(ST_error); - return false; - } - - // If we just read a comment, go back and get another one. - } while (_code == 999); - - return true; -} - - -/** - * Called as new nodes are read to update the internal state correctly. - */ -void DXFFile:: -change_state(State new_state) { - if (_state == ST_verts) { - done_vertex(); - _p.set(0.0, 0.0, 0.0); - _q.set(0.0, 0.0, 0.0); - _r.set(0.0, 0.0, 0.0); - _s.set(0.0, 0.0, 0.0); - } - if ((_state == ST_entity || _state == ST_verts) && - new_state != ST_verts) { - // We finish an entity when we read a new entity, or when we've read the - // last vertex (if we were scanning the vertices after an entity). - done_entity(); - reset_entity(); - } - switch (new_state) { - case ST_top: - end_section(); - break; - - case ST_done: - end_file(); - break; - - default: - break; - } - _state = new_state; -} - - -/** - * - */ -void DXFFile:: -change_section(Section new_section) { - change_state(ST_section); - _section = new_section; - begin_section(); -} - - -/** - * Given a newly read layer name, sets the _layer pointer to point to the - * associate layer. If the layer name has not been encountered before, - * creates a new layer definition. - */ -void DXFFile:: -change_layer(const string &layer_name) { - if (_layer == nullptr || _layer->get_name() != layer_name) { - _layer = _layers.get_layer(layer_name, this); - } -} - - -/** - * - */ -void DXFFile:: -change_entity(Entity new_entity) { - if (new_entity == EN_vertex && _vertices_follow) { - // If we read a new vertex and we're still scanning the vertices that - // follow an entity, keep scanning it--we haven't finished the entity yet. - change_state(ST_verts); - - } else { - // Otherwise, begin a new entity. - change_state(ST_entity); - _entity = new_entity; - } -} - - -/** - * Resets the current entity to its initial, default state prior to reading a - * new entity. - */ -void DXFFile:: -reset_entity() { - _p.set(0.0, 0.0, 0.0); - _q.set(0.0, 0.0, 0.0); - _r.set(0.0, 0.0, 0.0); - _s.set(0.0, 0.0, 0.0); - _z.set(0.0, 0.0, 1.0); - _vertices_follow = false; - // _color_index = -1; - - _verts.erase(_verts.begin(), _verts.end()); -} - - -/** - * Does the DXF processing when we are at the top of the file, outside of any - * section. - */ -void DXFFile:: -state_top() { - if (_code != 0) { - nout << "Group code 0 not found at top level; found code " << _code - << " instead.\n"; - change_state(ST_error); - } else { - if (_string == "SECTION") { - if (get_group()) { - if (_code != 2) { - nout << "Group code 0 not immediately followed by code 2; found code " - << _code << " instead.\n"; - } else { - if (_string == "HEADER") { - change_section(SE_header); - } else if (_string == "TABLES") { - change_section(SE_tables); - } else if (_string == "BLOCKS") { - change_section(SE_blocks); - } else if (_string == "ENTITIES") { - change_section(SE_entities); - } else if (_string == "OBJECTS") { - change_section(SE_objects); - } else { - change_section(SE_unknown); - } - } - } - } else if (_string == "EOF") { - change_state(ST_done); - } else { - nout << "Unexpected section at top level: '" << _string << "'\n"; - change_state(ST_error); - } - } -} - - - -/** - * Does the DXF processing when we are within some section. - */ -void DXFFile:: -state_section() { - string tail; - - switch (_code) { - case 0: - if (_string == "ENDSEC") { - change_state(ST_top); - } else { - if (_section == SE_entities) { - if (_string == "3DFACE") { - change_entity(EN_3dface); - } else if (_string == "POINT") { - change_entity(EN_point); - } else if (_string == "INSERT") { - change_entity(EN_insert); - } else if (_string == "VERTEX") { - change_entity(EN_vertex); - } else if (_string == "POLYLINE") { - change_entity(EN_polyline); - } else { - change_entity(EN_unknown); - } - } - } - break; - - case 8: - change_layer(_string); - break; - - case 62: // Color. - _color_index = string_to_int(_string, tail); - break; - - default: - break; - } -} - - -/** - * Does the DXF processing when we are reading an entity. - */ -void DXFFile:: -state_entity() { - string tail; - - switch (_code) { - case 0: - state_section(); - break; - - case 8: - change_layer(_string); - break; - - case 10: - _p[0] = string_to_double(_string, tail); - break; - - case 11: - _q[0] = string_to_double(_string, tail); - break; - - case 12: - _r[0] = string_to_double(_string, tail); - break; - - case 13: - _s[0] = string_to_double(_string, tail); - break; - - case 20: - _p[1] = string_to_double(_string, tail); - break; - - case 21: - _q[1] = string_to_double(_string, tail); - break; - - case 22: - _r[1] = string_to_double(_string, tail); - break; - - case 23: - _s[1] = string_to_double(_string, tail); - break; - - case 30: - _p[2] = string_to_double(_string, tail); - break; - - case 31: - _q[2] = string_to_double(_string, tail); - break; - - case 32: - _r[2] = string_to_double(_string, tail); - break; - - case 33: - _s[2] = string_to_double(_string, tail); - break; - - case 62: // Color. - _color_index = string_to_int(_string, tail); - break; - - case 66: // Vertices-follow. - _vertices_follow = (string_to_int(_string, tail) != 0); - break; - - case 70: // Polyline flags. - _flags = string_to_int(_string, tail); - break; - - case 210: - _z[0] = string_to_double(_string, tail); - break; - - case 220: - _z[1] = string_to_double(_string, tail); - break; - - case 230: - _z[2] = string_to_double(_string, tail); - break; - - default: - break; - } -} - - -/** - * Does the DXF processing when we are reading the list of vertices that might - * follow an entity. - */ -void DXFFile:: -state_verts() { - string tail; - - switch (_code) { - case 0: - state_section(); - break; - - case 8: - change_layer(_string); - break; - - case 10: - _p[0] = string_to_double(_string, tail); - break; - - case 20: - _p[1] = string_to_double(_string, tail); - break; - - case 30: - _p[2] = string_to_double(_string, tail); - break; - - default: - break; - } -} - - -ostream &operator << (ostream &out, const DXFFile::State &state) { - switch (state) { - case DXFFile::ST_top: - return out << "ST_top"; - case DXFFile::ST_section: - return out << "ST_section"; - case DXFFile::ST_entity: - return out << "ST_entity"; - case DXFFile::ST_verts: - return out << "ST_verts"; - case DXFFile::ST_error: - return out << "ST_error"; - case DXFFile::ST_done: - return out << "ST_done"; - } - return out << "Unknown state"; -} - -ostream &operator << (ostream &out, const DXFFile::Section §ion) { - switch (section) { - case DXFFile::SE_unknown: - return out << "SE_unknown"; - case DXFFile::SE_header: - return out << "SE_header"; - case DXFFile::SE_tables: - return out << "SE_tables"; - case DXFFile::SE_blocks: - return out << "SE_blocks"; - case DXFFile::SE_entities: - return out << "SE_entities"; - case DXFFile::SE_objects: - return out << "SE_objects"; - } - return out << "Unknown section"; -} - -ostream &operator << (ostream &out, const DXFFile::Entity &entity) { - switch (entity) { - case DXFFile::EN_unknown: - return out << "EN_unknown"; - case DXFFile::EN_3dface: - return out << "EN_3dface"; - case DXFFile::EN_point: - return out << "EN_point"; - case DXFFile::EN_insert: - return out << "EN_insert"; - case DXFFile::EN_vertex: - return out << "EN_vertex"; - case DXFFile::EN_polyline: - return out << "EN_polyline"; - } - return out << "Unknown entity"; -} diff --git a/pandatool/src/dxf/dxfFile.h b/pandatool/src/dxf/dxfFile.h deleted file mode 100644 index e555960e..00000000 --- a/pandatool/src/dxf/dxfFile.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfFile.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFFILE_H -#define DXFFILE_H - -#include "pandatoolbase.h" - -#include "dxfLayer.h" -#include "dxfLayerMap.h" -#include "dxfVertex.h" - -#include "luse.h" -#include "filename.h" - - -static const int DXF_max_line = 256; -static const int DXF_num_colors = 256; - -/** - * A generic DXF-reading class. This class can read a DXF file but doesn't - * actually do anything with the data; it's intended to be inherited from and - * the appropriate functions overridden (particularly DoneEntity()). - */ -class DXFFile : public MemoryBase { -public: - DXFFile(); - virtual ~DXFFile(); - - void process(Filename filename); - void process(std::istream *in, bool owns_in); - - // These functions are called as the file is processed. These are the main - // hooks for redefining how the class should dispense its data. As each - // function is called, the state stored in the DXFFile class reflects the - // data that was most recently read. - - virtual void begin_file(); - virtual void begin_section(); - virtual void done_vertex(); - virtual void done_entity(); - virtual void end_section(); - virtual void end_file(); - virtual void error(); - - // new_layer() is called whenever the DXFFile class encounters a new Layer - // definition, and must allocate a DXFLayer instance. This function is - // provided so that user code may force allocate of a specialized DXFLayer - // instance instead. - virtual DXFLayer *new_layer(const std::string &name) { - return new DXFLayer(name); - } - - enum State { - ST_top, - ST_section, - ST_entity, - ST_verts, - ST_error, - ST_done, - }; - enum Section { - SE_unknown, - SE_header, - SE_tables, - SE_blocks, - SE_entities, - SE_objects, - }; - enum Entity { - EN_unknown, - EN_3dface, - EN_point, - EN_insert, - EN_vertex, - EN_polyline, - }; - enum PolylineFlags { - PF_closed = 0x01, - PF_curve_fit = 0x02, - PF_spline_fit = 0x04, - PF_3d = 0x08, - PF_3d_mesh = 0x10, - PF_closed_n = 0x20, - PF_polyface = 0x40, - PF_continuous_linetype = 0x80, - }; - - // This is a table of standard Autocad colors. DXF files can store only a - // limited range of colors; specifically, the 255 colors defined by Autocad. - struct Color { - double r, g, b; - }; - static Color _colors[DXF_num_colors]; - - // find_color() returns the index of the closest matching AutoCAD color to - // the indicated r, g, b. - static int find_color(double r, double g, double b); - - // get_color() returns the r,g,b of the current entity. It is valid at the - // time done_entity() is called. - const Color &get_color() const; - - // Some entities are defined in world coordinates, in 3-d space; other - // entities are inherently 2-d in nature and are defined in planar - // coordinates and must be converted to 3-d space. Call this function from - // done_entity() to convert a 2-d entity to 3-d world coordinates. - void ocs_2_wcs(); - - // These members indicate the current state and describe properties of the - // current thing being processed. They are valid at done_entity(), and at - // other times. - int _flags; - Section _section; - Entity _entity; - LPoint3d _p, _q, _r, _s; - LVector3d _z; - int _color_index; - DXFLayer *_layer; - - // _verts is the list of vertices associated with the current entity. It is - // valid at the time done_entity() is called. - DXFVertices _verts; - - // This is the set of layers encountered within the DXF file. - DXFLayerMap _layers; - -protected: - State _state; - bool _vertices_follow; - LMatrix4d _ocs2wcs; - - std::istream *_in; - bool _owns_in; - - int _code; - std::string _string; - - void compute_ocs(); - - bool get_group(); - void change_state(State new_state); - void change_section(Section new_section); - void change_layer(const std::string &layer_name); - void change_entity(Entity new_entity); - void reset_entity(); - - void state_top(); - void state_section(); - void state_entity(); - void state_verts(); -}; - -std::ostream &operator << (std::ostream &out, const DXFFile::State &state); -std::ostream &operator << (std::ostream &out, const DXFFile::Section §ion); -std::ostream &operator << (std::ostream &out, const DXFFile::Entity &entity); - -#endif diff --git a/pandatool/src/dxf/dxfLayer.cxx b/pandatool/src/dxf/dxfLayer.cxx deleted file mode 100644 index 6803cc17..00000000 --- a/pandatool/src/dxf/dxfLayer.cxx +++ /dev/null @@ -1,29 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfLayer.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfLayer.h" - - -/** - * - */ -DXFLayer:: -DXFLayer(const std::string &name) : Namable(name) { -} - -/** - * - */ -DXFLayer:: -~DXFLayer() { -} diff --git a/pandatool/src/dxf/dxfLayer.h b/pandatool/src/dxf/dxfLayer.h deleted file mode 100644 index 74519728..00000000 --- a/pandatool/src/dxf/dxfLayer.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfLayer.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFLAYER_H -#define DXFLAYER_H - -#include "pandatoolbase.h" -#include "namable.h" - -/** - * This represents a "layer" as read from the DXF file. A layer may be - * defined by reading the header part of the file, or it may be implicitly - * defined by an entity's having referenced it. - * - * User code may derive from DXFLayer to associate private data with each - * layer, if desired. - */ -class DXFLayer : public Namable { -public: - DXFLayer(const std::string &name); - virtual ~DXFLayer(); -}; - -#endif diff --git a/pandatool/src/dxf/dxfLayerMap.cxx b/pandatool/src/dxf/dxfLayerMap.cxx deleted file mode 100644 index d2049c81..00000000 --- a/pandatool/src/dxf/dxfLayerMap.cxx +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfLayerMap.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfLayerMap.h" -#include "dxfFile.h" - -/** - * Looks up the layer name in the map, and returns a pointer to the associated - * DXFLayer. If this is the first time this layer name has been used, creates - * a new DXFLayer by the given name. In this case, it calls - * dxffile->new_layer() to create the layer, allowing user code to override - * this function to create a specialized time, if desired. - */ -DXFLayer *DXFLayerMap:: -get_layer(const std::string &name, DXFFile *dxffile) { - iterator lmi; - lmi = find(name); - if (lmi != end()) { - // The layer was already here. - return (*lmi).second; - } - - // Need a new layer. - DXFLayer *layer = dxffile->new_layer(name); - (*this)[name] = layer; - - return layer; -} diff --git a/pandatool/src/dxf/dxfLayerMap.h b/pandatool/src/dxf/dxfLayerMap.h deleted file mode 100644 index f2fabe53..00000000 --- a/pandatool/src/dxf/dxfLayerMap.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfLayerMap.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFLAYERMAP_H -#define DXFLAYERMAP_H - -#include "pandatoolbase.h" -#include "pmap.h" - -class DXFLayer; -class DXFFile; - -/** - * A map of string (layer name) to DXFLayer: that is, the layers of a file - * ordered by name. This is used as a lookup within DXFFile to locate the - * layer associated with a particular entity. - */ -class DXFLayerMap : public pmap { -public: - DXFLayer *get_layer(const std::string &name, DXFFile *dxffile); -}; - -#endif diff --git a/pandatool/src/dxf/dxfVertex.cxx b/pandatool/src/dxf/dxfVertex.cxx deleted file mode 100644 index 3802802f..00000000 --- a/pandatool/src/dxf/dxfVertex.cxx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfVertex.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfVertex.h" - -/** - * This defines a unique ordering for vertices so that the DXFVertexMap can - * group identical vertices together. - */ -int DXFVertex:: -operator < (const DXFVertex &other) const { - if (fabs(_p[0] - other._p[0]) > 0.0001) { - return _p[0] < other._p[0]; - } else if (fabs(_p[1] - other._p[1]) > 0.0001) { - return _p[1] < other._p[1]; - } else if (fabs(_p[2] - other._p[2]) > 0.0001) { - return _p[2] < other._p[2]; - } - - return false; -} diff --git a/pandatool/src/dxf/dxfVertex.h b/pandatool/src/dxf/dxfVertex.h deleted file mode 100644 index 32494509..00000000 --- a/pandatool/src/dxf/dxfVertex.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfVertex.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFVERTEX_H -#define DXFVERTEX_H - -#include "pandatoolbase.h" -#include "pvector.h" -#include "luse.h" - -/** - * Stored within DXFFile, this is the basic Vertex data of a DXF file. When - * DXFFile::DoneEntity() is called, if the entity is a type to have vertices, - * then DXFFile::_verts contains a list of all the vertices that belong to the - * entity. - */ -class DXFVertex { -public: - DXFVertex() { } - DXFVertex(const LPoint3d &p) : _p(p) { } - int operator < (const DXFVertex &other) const; - - LPoint3d _p; -}; - -typedef pvector DXFVertices; - -#endif diff --git a/pandatool/src/dxf/p3dxf_composite1.cxx b/pandatool/src/dxf/p3dxf_composite1.cxx deleted file mode 100644 index 6d62c98c..00000000 --- a/pandatool/src/dxf/p3dxf_composite1.cxx +++ /dev/null @@ -1,4 +0,0 @@ -#include "dxfFile.cxx" -#include "dxfLayer.cxx" -#include "dxfLayerMap.cxx" -#include "dxfVertex.cxx" diff --git a/pandatool/src/dxfegg/CMakeLists.txt b/pandatool/src/dxfegg/CMakeLists.txt deleted file mode 100644 index 74684b1c..00000000 --- a/pandatool/src/dxfegg/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3DXFEGG_HEADERS - dxfToEggConverter.h - dxfToEggLayer.h -) - -set(P3DXFEGG_SOURCES - dxfToEggConverter.cxx - dxfToEggLayer.cxx -) - -add_library(p3dxfegg STATIC ${P3DXFEGG_HEADERS} ${P3DXFEGG_SOURCES}) -target_link_libraries(p3dxfegg p3dxf p3eggbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/dxfegg/dxfToEggConverter.cxx b/pandatool/src/dxfegg/dxfToEggConverter.cxx deleted file mode 100644 index 6ba64119..00000000 --- a/pandatool/src/dxfegg/dxfToEggConverter.cxx +++ /dev/null @@ -1,145 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfToEggConverter.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfToEggConverter.h" -#include "dxfToEggLayer.h" -#include "eggData.h" - -/** - * - */ -DXFToEggConverter:: -DXFToEggConverter() { -} - -/** - * - */ -DXFToEggConverter:: -DXFToEggConverter(const DXFToEggConverter ©) : - SomethingToEggConverter(copy) -{ -} - -/** - * - */ -DXFToEggConverter:: -~DXFToEggConverter() { -} - -/** - * Allocates and returns a new copy of the converter. - */ -SomethingToEggConverter *DXFToEggConverter:: -make_copy() { - return new DXFToEggConverter(*this); -} - - -/** - * Returns the English name of the file type this converter supports. - */ -std::string DXFToEggConverter:: -get_name() const { - return "DXF"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -std::string DXFToEggConverter:: -get_extension() const { - return "dxf"; -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. - */ -bool DXFToEggConverter:: -supports_compressed() const { - return true; -} - -/** - * Handles the reading of the input file and converting it to egg. Returns - * true if successful, false otherwise. - */ -bool DXFToEggConverter:: -convert_file(const Filename &filename) { - clear_error(); - - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_zup_right); - } - - process(filename); - return !had_error(); -} - -/** - * - */ -DXFLayer *DXFToEggConverter:: -new_layer(const std::string &name) { - return new DXFToEggLayer(name, get_egg_data()); -} - -/** - * If the entity is a polygon, creates the corresponding egg polygon. - */ -void DXFToEggConverter:: -done_entity() { - if (_entity == EN_polyline) { - // A Polyline is either an unclosed series of connected line segments, or - // a closed polygon of arbitrary complexity. - - if ((_flags & PF_3d) == 0) { - // it's a 2-d polygon; convert it to 3-d coordinates. - ocs_2_wcs(); - } - - if (_flags & PF_closed) { - // it's closed; create a polygon. - nassertv(_layer!=nullptr); - ((DXFToEggLayer *)_layer)->add_polygon(this); - } else { - // It's open; create a series of line segments. - nassertv(_layer!=nullptr); - ((DXFToEggLayer *)_layer)->add_line(this); - } - - } else if (_entity == EN_3dface) { - // DXF can also represent a polygon as a 3DFace. This might be either a - // quad or a triangle (if two of the vertices are the same). We'll add - // the vertices to our list of vertices and then define the polygon. - _verts.clear(); - _verts.push_back(DXFVertex(_s)); - _verts.push_back(DXFVertex(_r)); - _verts.push_back(DXFVertex(_q)); - _verts.push_back(DXFVertex(_p)); - - nassertv(_layer!=nullptr); - ((DXFToEggLayer *)_layer)->add_polygon(this); - } -} - -/** - * A hook for user code, if desired. This function is called when some - * unexpected error occurs while reading the DXF file. - */ -void DXFToEggConverter:: -error() { - _error = true; -} diff --git a/pandatool/src/dxfegg/dxfToEggConverter.h b/pandatool/src/dxfegg/dxfToEggConverter.h deleted file mode 100644 index 56969e74..00000000 --- a/pandatool/src/dxfegg/dxfToEggConverter.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfToEggConverter.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFTOEGGCONVERTER_H -#define DXFTOEGGCONVERTER_H - -#include "pandatoolbase.h" - -#include "somethingToEggConverter.h" -#include "dxfFile.h" - -/** - * This class supervises the construction of an EggData structure from a DXF - * file. - */ -class DXFToEggConverter : public SomethingToEggConverter, public DXFFile { -public: - DXFToEggConverter(); - DXFToEggConverter(const DXFToEggConverter ©); - ~DXFToEggConverter(); - - virtual SomethingToEggConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual bool supports_compressed() const; - - virtual bool convert_file(const Filename &filename); - -protected: - virtual DXFLayer *new_layer(const std::string &name); - virtual void done_entity(); - virtual void error(); - - bool _error; -}; - -#endif diff --git a/pandatool/src/dxfegg/dxfToEggLayer.cxx b/pandatool/src/dxfegg/dxfToEggLayer.cxx deleted file mode 100644 index 3ecb915e..00000000 --- a/pandatool/src/dxfegg/dxfToEggLayer.cxx +++ /dev/null @@ -1,99 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfToEggLayer.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfToEggLayer.h" -#include "dxfToEggConverter.h" - -#include "dxfFile.h" -#include "eggGroup.h" -#include "eggPolygon.h" -#include "eggLine.h" -#include "eggVertex.h" -#include "eggVertexPool.h" - - -/** - * - */ -DXFToEggLayer:: -DXFToEggLayer(const std::string &name, EggGroupNode *parent) : DXFLayer(name) { - _group = new EggGroup(name); - parent->add_child(_group); - _vpool = new EggVertexPool(name); - _group->add_child(_vpool); -} - - -/** - * Given that done_entity() has just been called and that the current entity - * represents a polygon, adds the corresponding polygon to the layer's - * EggGroup and vertex pool. - */ -void DXFToEggLayer:: -add_polygon(const DXFToEggConverter *entity) { - EggPolygon *poly = new EggPolygon; - _group->add_child(poly); - - const DXFFile::Color &color = entity->get_color(); - poly->set_color(LColor(color.r, color.g, color.b, 1.0)); - - // A polyline's vertices are stored in the attached vector by dxf.cxx. They - // were defined in the DXF file using a series of "VERTEX" entries. - - // For a 3dface, the vertices are defined explicitly as part of the entity; - // but in this case, they were added to the vector before add_polygon() was - // called. - - DXFVertices::const_iterator vi; - for (vi = entity->_verts.begin(); - vi != entity->_verts.end(); - ++vi) { - poly->add_vertex(add_vertex(*vi)); - } - - poly->cleanup(); -} - - -/** - * Similar to add_polygon(), but adds a set of point lights instead. - */ -void DXFToEggLayer:: -add_line(const DXFToEggConverter *entity) { - EggLine *line = new EggLine; - _group->add_child(line); - - const DXFFile::Color &color = entity->get_color(); - line->set_color(LColor(color.r, color.g, color.b, 1.0)); - - DXFVertices::const_iterator vi; - for (vi = entity->_verts.begin(); - vi != entity->_verts.end(); - ++vi) { - line->add_vertex(add_vertex(*vi)); - } -} - - -/** - * Adds a unique vertex to the layer's vertex pool and returns it. If the - * vertex was already defined previously, returns the original definition. - * This is designed to share the common vertices within a layer. - */ -EggVertex *DXFToEggLayer:: -add_vertex(const DXFVertex &vert) { - EggVertex egg_vert; - egg_vert.set_pos(vert._p); - - return _vpool->create_unique_vertex(egg_vert); -} diff --git a/pandatool/src/dxfegg/dxfToEggLayer.h b/pandatool/src/dxfegg/dxfToEggLayer.h deleted file mode 100644 index 9067cc70..00000000 --- a/pandatool/src/dxfegg/dxfToEggLayer.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfToEggLayer.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFTOEGGLAYER_H -#define DXFTOEGGLAYER_H - -#include "pandatoolbase.h" - -#include "dxfLayer.h" -#include "eggVertexPool.h" -#include "eggGroup.h" -#include "pointerTo.h" - -class EggGroupNode; -class EggVertex; -class DXFVertex; -class DXFToEggConverter; - -/** - * The specialization of DXFLayer used by DXFToEggConverter. It contains a - * pointer to an EggGroup and a vertex pool; these are used to build up - * polygons grouped by layer in the egg file as each polygon is read from the - * DXF file. - */ -class DXFToEggLayer : public DXFLayer { -public: - DXFToEggLayer(const std::string &name, EggGroupNode *parent); - - void add_polygon(const DXFToEggConverter *entity); - void add_line(const DXFToEggConverter *entity); - EggVertex *add_vertex(const DXFVertex &vertex); - - PT(EggVertexPool) _vpool; - PT(EggGroup) _group; -}; - - -#endif diff --git a/pandatool/src/dxfprogs/CMakeLists.txt b/pandatool/src/dxfprogs/CMakeLists.txt deleted file mode 100644 index 0a2033d1..00000000 --- a/pandatool/src/dxfprogs/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(dxf-points dxfPoints.cxx dxfPoints.h) -target_link_libraries(dxf-points p3progbase p3dxf) -install(TARGETS dxf-points EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -if(HAVE_EGG) - - add_executable(egg2dxf eggToDXF.cxx eggToDXF.h eggToDXFLayer.cxx eggToDXFLayer.h) - target_link_libraries(egg2dxf p3dxfegg p3eggbase p3progbase) - install(TARGETS egg2dxf EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - - add_executable(dxf2egg dxfToEgg.cxx dxfToEgg.h) - target_link_libraries(dxf2egg p3dxfegg p3eggbase p3progbase) - install(TARGETS dxf2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -endif() diff --git a/pandatool/src/dxfprogs/dxfPoints.cxx b/pandatool/src/dxfprogs/dxfPoints.cxx deleted file mode 100644 index c0002b28..00000000 --- a/pandatool/src/dxfprogs/dxfPoints.cxx +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfPoints.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfPoints.h" - -/** - * - */ -DXFPoints:: -DXFPoints() : - WithOutputFile(true, true, false) -{ - // Indicate the extension name we expect the user to supply for output - // files. - _preferred_extension = ".txt"; - - set_program_brief("extract points from AutoCAD .dxf files"); - set_program_description - ("This program reads an AutoCAD .dxf file and generates a simple " - "list of all the points contained within it, one per line, to a " - "text file, or to standard output."); - - clear_runlines(); - add_runline("[opts] input.dxf > output.txt"); - add_runline("[opts] -o output.txt input.dxf"); - add_runline("[opts] input.dxf output.txt"); -} - - -/** - * - */ -void DXFPoints:: -run() { - // Invoke the DXFFile base class to process the input file. - process(_input_filename); -} - -/** - * This is inherited from DXFFile, and gets called as each entity (face, line, - * whatever) has finished processing. - */ -void DXFPoints:: -done_entity() { - if (_entity == EN_point) { - get_output() << _p << "\n"; - - } else if (_entity == EN_insert) { - ocs_2_wcs(); - get_output() << _p << "\n"; - } -} - -/** - * - */ -bool DXFPoints:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the .dxf file to read on the command line.\n"; - return false; - - } else if (args.size() != 1) { - nout << "You must specify only one .dxf file to read on the command line.\n"; - return false; - } - - _input_filename = args[0]; - - return true; -} - - -int main(int argc, char *argv[]) { - DXFPoints prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/dxfprogs/dxfPoints.h b/pandatool/src/dxfprogs/dxfPoints.h deleted file mode 100644 index 9715b5d6..00000000 --- a/pandatool/src/dxfprogs/dxfPoints.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfPoints.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFPOINTS_H -#define DXFPOINTS_H - -#include "pandatoolbase.h" -#include "programBase.h" -#include "withOutputFile.h" - -#include "dxfFile.h" - -/** - * A simple program to read a dxf file and list the points contained within it - * to a text file. - */ -class DXFPoints : public ProgramBase, public WithOutputFile, public DXFFile { -public: - DXFPoints(); - - void run(); - - virtual void done_entity(); - -protected: - virtual bool handle_args(Args &args); - - Filename _input_filename; -}; - -#endif diff --git a/pandatool/src/dxfprogs/dxfToEgg.cxx b/pandatool/src/dxfprogs/dxfToEgg.cxx deleted file mode 100644 index 4ca66f0a..00000000 --- a/pandatool/src/dxfprogs/dxfToEgg.cxx +++ /dev/null @@ -1,74 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfToEgg.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "dxfToEgg.h" - -#include "dxfToEggConverter.h" - -/** - * - */ -DXFToEgg:: -DXFToEgg() : - SomethingToEgg("DXF", ".dxf") -{ - add_units_options(); - add_normals_options(); - add_transform_options(); - - set_program_brief("convert AutoCAD .dxf files to .egg files"); - set_program_description - ("This program converts DXF (AutoCAD interchange format) to egg. It " - "only converts polygon data, with no fancy tricks. DXF does not support " - "hierarchical databases, so dxf2egg creates a single group at the root " - "level for each layer in the DXF file."); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. Normally, this is z-up."); - - _coordinate_system = CS_zup_right; -} - -/** - * - */ -void DXFToEgg:: -run() { - nout << "Reading " << _input_filename << "\n"; - - _data->set_coordinate_system(_coordinate_system); - - DXFToEggConverter converter; - converter.set_egg_data(_data); - converter._allow_errors = _allow_errors; - - apply_parameters(converter); - - if (!converter.convert_file(_input_filename)) { - nout << "Errors in conversion.\n"; - exit(1); - } - - write_egg_file(); - nout << "\n"; -} - - -int main(int argc, char *argv[]) { - DXFToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/dxfprogs/dxfToEgg.h b/pandatool/src/dxfprogs/dxfToEgg.h deleted file mode 100644 index cb8b5b6b..00000000 --- a/pandatool/src/dxfprogs/dxfToEgg.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file dxfToEgg.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef DXFTOEGG_H -#define DXFTOEGG_H - -#include "pandatoolbase.h" - -#include "somethingToEgg.h" -#include "dxfToEggConverter.h" - -/** - * A program to read a DXF file and generate an egg file. - */ -class DXFToEgg : public SomethingToEgg { -public: - DXFToEgg(); - - void run(); -}; - -#endif diff --git a/pandatool/src/dxfprogs/eggToDXF.cxx b/pandatool/src/dxfprogs/eggToDXF.cxx deleted file mode 100644 index 412b8156..00000000 --- a/pandatool/src/dxfprogs/eggToDXF.cxx +++ /dev/null @@ -1,149 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToDXF.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "eggToDXF.h" -#include "eggPolygon.h" -#include "dcast.h" - -/** - * - */ -EggToDXF:: -EggToDXF() : - EggToSomething("DXF", ".dxf", true, false) -{ - set_binary_output(true); - set_program_brief("convert .egg files to AutoCAD .dxf files"); - set_program_description - ("This program converts files from egg format to AutoCAD DXF format. " - "Since DXF does not support nested hierarchies, vertex normals, or any " - "fancy stuff you are probably used to, there is some information lost " - "in the conversion"); - - add_option - ("p", "", 0, - "Use POLYLINE to represent polygons instead of the default, 3DFACE.", - &EggToDXF::dispatch_none, &_use_polyline); - - _coordinate_system = CS_zup_right; - _got_coordinate_system = true; -} - -/** - * - */ -void EggToDXF:: -run() { - get_layers(_data); - if (_layers.empty()) { - nout << "Egg file contains no polygons. Output file not written.\n"; - exit(1); - } - - // uniquify_names("layer", _layers.begin(), _layers.end()); - - std::ostream &out = get_output(); - - // Autodesk says we don't need the header, but some DXF-reading programs - // might get confused if it's missing. We'll write an empty header. - out << "0\nSECTION\n" - << "2\nHEADER\n" - << "0\nENDSEC\n"; - - write_tables(out); - write_entities(out); - out << "0\nEOF\n"; // Mark end of file. - - if (!out) { - nout << "An error occurred while writing.\n"; - exit(1); - } -} - -/** - * Traverses the hierarchy, looking for groups that contain polygons. Any - * such groups are deemed to be layers, and are added to the layers set. - */ -void EggToDXF:: -get_layers(EggGroupNode *group) { - bool has_polys = false; - - EggToDXFLayer layer(this, group); - - EggGroupNode::iterator ci; - for (ci = group->begin(); ci != group->end(); ++ci) { - EggNode *child = (*ci); - if (child->is_of_type(EggPolygon::get_class_type())) { - EggPolygon *poly = DCAST(EggPolygon, child); - has_polys = true; - - layer.add_color(poly->get_color()); - - } else if (child->is_of_type(EggGroupNode::get_class_type())) { - get_layers(DCAST(EggGroupNode, child)); - } - } - - if (has_polys) { - layer.choose_overall_color(); - _layers.push_back(layer); - } -} - - -/** - * Writes out the "layers", e.g. groups. This is just the layers definition - * in the tables section at the beginning of the file; the actual geometry - * gets written later, in write_entities(). - */ -void EggToDXF:: -write_tables(std::ostream &out) { - out << "0\nSECTION\n" - << "2\nTABLES\n" // Begin TABLES section. - << "0\nTABLE\n" - << "2\nLAYER\n" // Define LAYERS. - << "70\n" << _layers.size() << "\n"; - - EggToDXFLayers::iterator li; - for (li = _layers.begin(); li != _layers.end(); ++li) { - (*li).write_layer(out); - } - - out << "0\nENDTAB\n" // End LAYERS definition. - << "0\nENDSEC\n"; // End TABLES section. -} - -/** - * Writes out the "entities", e.g. polygons, defined for all layers. - */ -void EggToDXF:: -write_entities(std::ostream &out) { - out << "0\nSECTION\n" - << "2\nENTITIES\n"; // Begin ENTITIES section. - - EggToDXFLayers::iterator li; - for (li = _layers.begin(); li != _layers.end(); ++li) { - (*li).write_entities(out); - } - - out << "0\nENDSEC\n"; // End ENTITIES section. -} - - - -int main(int argc, char *argv[]) { - EggToDXF prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/dxfprogs/eggToDXF.h b/pandatool/src/dxfprogs/eggToDXF.h deleted file mode 100644 index da7764fb..00000000 --- a/pandatool/src/dxfprogs/eggToDXF.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToDXF.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef EGGTODXF_H -#define EGGTODXF_H - -#include "pandatoolbase.h" - -#include "eggToSomething.h" -#include "eggToDXFLayer.h" - -class EggGroupNode; - -/** - * A program to read an egg file and write a DXF file. - */ -class EggToDXF : public EggToSomething { -public: - EggToDXF(); - - void run(); - - bool _use_polyline; - -private: - void get_layers(EggGroupNode *group); - void write_tables(std::ostream &out); - void write_entities(std::ostream &out); - - EggToDXFLayers _layers; -}; - -#endif diff --git a/pandatool/src/dxfprogs/eggToDXFLayer.cxx b/pandatool/src/dxfprogs/eggToDXFLayer.cxx deleted file mode 100644 index 6922f0b8..00000000 --- a/pandatool/src/dxfprogs/eggToDXFLayer.cxx +++ /dev/null @@ -1,219 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToDXFLayer.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "eggToDXFLayer.h" -#include "eggToDXF.h" -#include "dxfFile.h" -#include "eggGroup.h" -#include "eggGroupNode.h" -#include "eggPolygon.h" -#include "dcast.h" - -using std::ostream; - -/** - * - */ -EggToDXFLayer:: -EggToDXFLayer(EggToDXF *egg2dxf, EggGroupNode *group) : - _egg2dxf(egg2dxf), _group(group) -{ - _layer_color = -1; -} - -/** - * - */ -EggToDXFLayer:: -EggToDXFLayer(const EggToDXFLayer ©) : - _egg2dxf(copy._egg2dxf), - _group(copy._group), - _layer_color(copy._layer_color) -{ - // The copy constructor doesn't bother with the ColorCounts. -} - -/** - * - */ -void EggToDXFLayer:: -operator = (const EggToDXFLayer ©) { - _egg2dxf = copy._egg2dxf; - _group = copy._group; - _layer_color = copy._layer_color; - - // The copy constructor doesn't bother with the ColorCounts. -} - -/** - * Records that one polygon is defined using the indicated color. This will - * get accumulated; the color used by the majority of polygons will become the - * layer color. - */ -void EggToDXFLayer:: -add_color(const LColor &color) { - int autocad_color = get_autocad_color(color); - - ColorCounts::iterator cci; - cci = _color_counts.find(autocad_color); - if (cci == _color_counts.end()) { - // The first time a particular color was used. Count it once. - _color_counts[autocad_color] = 1; - } else { - // This color has been used before. Count it again. - (*cci).second++; - } -} - - -/** - * After all polygons have been accounted for, chooses the polygon color that - * occurred most often as the layer color. - */ -void EggToDXFLayer:: -choose_overall_color() { - int max_count = 0; - - ColorCounts::iterator cci; - for (cci = _color_counts.begin(); cci != _color_counts.end(); ++cci) { - int count = (*cci).second; - if (count > max_count) { - _layer_color = (*cci).first; - max_count = count; - } - } -} - - -/** - * Writes the layer definition into the table at the beginning of the DXF - * file. This does not write the actual geometry; that gets done later by - * write_entities(). - */ -void EggToDXFLayer:: -write_layer(ostream &out) { - out << "0\nLAYER\n" - << "2\n" << _group->get_name() << "\n" - << "70\n0\n" - << "62\n" << _layer_color << "\n" - << "6\nCONTINUOUS\n"; -} - -/** - * Writes a polygon as a POLYLINE entity. - */ -void EggToDXFLayer:: -write_polyline(EggPolygon *poly, ostream &out) { - out << "0\nPOLYLINE\n" - << "8\n" << _group->get_name() << "\n" - << "66\n1\n" - << "70\n1\n" - << "62\n" << get_autocad_color(poly->get_color()) << "\n"; - - // Since DXF uses a clockwise ordering convention, we must reverse the order - // in which we write out the vertices. - EggPolygon::reverse_iterator vi; - for (vi = poly->rbegin(); vi != poly->rend(); ++vi) { - EggVertex *vtx = (*vi); - LVecBase3d pos = vtx->get_pos3() * _group->get_vertex_frame(); - out << "0\nVERTEX\n" - << "10\n" << pos[0] << "\n" - << "20\n" << pos[1] << "\n" - << "30\n" << pos[2] << "\n"; - } - out << "0\nSEQEND\n"; -} - -/** - * Writes a polygon as a 3DFACE entity. - */ -void EggToDXFLayer:: -write_3d_face(EggPolygon *poly, ostream &out) { - if (poly->size() > 4) { - // If we have a big polygon, we have to triangulate it, since 3DFaces can - // only be tris and quads. - PT(EggGroup) group = new EggGroup; - poly->triangulate_into(group, true); - - EggGroupNode::iterator ci; - for (ci = group->begin(); ci != group->end(); ++ci) { - EggNode *child = (*ci); - if (child->is_of_type(EggPolygon::get_class_type())) { - write_3d_face(DCAST(EggPolygon, child), out); - } - } - - } else if (poly->size() > 2) { - // Otherwise, if we have a tri or a quad, just write it out. - out << "0\n3DFACE\n" - << "8\n" << _group->get_name() << "\n"; - - // Since DXF uses a clockwise ordering convention, we must reverse the - // order in which we write out the vertices. - int i; - EggPolygon::reverse_iterator vi; - for (i = 0, vi = poly->rbegin(); vi != poly->rend(); ++i, ++vi) { - EggVertex *vtx = (*vi); - LVecBase3d pos = vtx->get_pos3() * _group->get_vertex_frame(); - out << 10 + i << "\n" << pos[0] << "\n" - << 20 + i << "\n" << pos[1] << "\n" - << 30 + i << "\n" << pos[2] << "\n"; - if (i == 2 && poly->size() == 3) { - // A special case for triangles: repeat the last vertex. - out << 11 + i << "\n" << pos[0] << "\n" - << 21 + i << "\n" << pos[1] << "\n" - << 31 + i << "\n" << pos[2] << "\n"; - } - } - } -} - - -/** - * Writes out the "entities", e.g. polygons, defined for the current layer. - */ -void EggToDXFLayer:: -write_entities(ostream &out) { - EggGroupNode::iterator ci; - for (ci = _group->begin(); ci != _group->end(); ++ci) { - EggNode *child = (*ci); - if (child->is_of_type(EggPolygon::get_class_type())) { - EggPolygon *poly = DCAST(EggPolygon, child); - if (_egg2dxf->_use_polyline) { - write_polyline(poly, out); - } else { - write_3d_face(poly, out); - } - } - } -} - -/** - * Returns the AutoCAD color index that most closely matches the indicated - * EggColor. - */ -int EggToDXFLayer:: -get_autocad_color(const LColor &color) { - typedef pmap ColorMap; - static ColorMap _map; - - ColorMap::iterator cmi; - cmi = _map.find(color); - if (cmi != _map.end()) { - return (*cmi).second; - } - - int result = DXFFile::find_color(color[0], color[1], color[2]); - _map[color] = result; - return result; -} diff --git a/pandatool/src/dxfprogs/eggToDXFLayer.h b/pandatool/src/dxfprogs/eggToDXFLayer.h deleted file mode 100644 index a5fe7b75..00000000 --- a/pandatool/src/dxfprogs/eggToDXFLayer.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToDXFLayer.h - * @author drose - * @date 2004-05-04 - */ - -#ifndef EGGTODXFLAYER_H -#define EGGTODXFLAYER_H - -#include "pandatoolbase.h" -#include "pmap.h" -#include "pvector.h" -#include "luse.h" - -class EggToDXF; -class EggPolygon; -class EggGroupNode; - -/** - * A single layer in the DXF file to be written by EggToDXF. - */ -class EggToDXFLayer { -public: - EggToDXFLayer(EggToDXF *egg2dxf, EggGroupNode *group); - EggToDXFLayer(const EggToDXFLayer ©); - void operator = (const EggToDXFLayer ©); - - void add_color(const LColor &color); - void choose_overall_color(); - - void write_layer(std::ostream &out); - void write_polyline(EggPolygon *poly, std::ostream &out); - void write_3d_face(EggPolygon *poly, std::ostream &out); - void write_entities(std::ostream &out); - -private: - int get_autocad_color(const LColor &color); - - typedef pmap ColorCounts; - ColorCounts _color_counts; - - EggToDXF *_egg2dxf; - EggGroupNode *_group; - int _layer_color; -}; - -typedef pvector EggToDXFLayers; - -#endif diff --git a/pandatool/src/egg-mkfont/CMakeLists.txt b/pandatool/src/egg-mkfont/CMakeLists.txt deleted file mode 100644 index 60f0331e..00000000 --- a/pandatool/src/egg-mkfont/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_EGG OR NOT HAVE_FREETYPE) - return() -endif() - -set(P3EGG_MKFONT_HEADERS - eggMakeFont.h - rangeDescription.h rangeDescription.I - rangeIterator.h rangeIterator.I -) - -set(P3EGG_MKFONT_SOURCES - eggMakeFont.cxx - rangeDescription.cxx - rangeIterator.cxx -) - -composite_sources(egg-mkfont P3EGG_MKFONT_SOURCES) -add_executable(egg-mkfont ${P3EGG_MKFONT_HEADERS} ${P3EGG_MKFONT_SOURCES}) -target_link_libraries(egg-mkfont p3palettizer p3eggbase p3pandatoolbase) - -install(TARGETS egg-mkfont EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/egg-mkfont/egg-mkfont_composite1.cxx b/pandatool/src/egg-mkfont/egg-mkfont_composite1.cxx deleted file mode 100644 index aa44d511..00000000 --- a/pandatool/src/egg-mkfont/egg-mkfont_composite1.cxx +++ /dev/null @@ -1,5 +0,0 @@ - -#include "eggMakeFont.cxx" -#include "rangeDescription.cxx" -#include "rangeIterator.cxx" - diff --git a/pandatool/src/egg-mkfont/eggMakeFont.cxx b/pandatool/src/egg-mkfont/eggMakeFont.cxx deleted file mode 100644 index 4efa4a5a..00000000 --- a/pandatool/src/egg-mkfont/eggMakeFont.cxx +++ /dev/null @@ -1,745 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMakeFont.cxx - * @author drose - * @date 2001-02-16 - */ - -#include "eggMakeFont.h" -#include "rangeIterator.h" -#include "palettizer.h" -#include "filenameUnifier.h" -#include "eggFile.h" -#include "textureImage.h" -#include "sourceTextureImage.h" -#include "pnmTextMaker.h" -#include "pnmTextGlyph.h" -#include "eggData.h" -#include "eggGroup.h" -#include "eggPoint.h" -#include "eggPolygon.h" -#include "eggTexture.h" -#include "eggVertexPool.h" -#include "eggVertex.h" -#include "string_utils.h" -#include "dcast.h" - -#include - -using std::string; - -/** - * - */ -EggMakeFont:: -EggMakeFont() : EggWriter(true, false) { - set_program_brief("generates .egg files with rasterized font glyphs"); - set_program_description - ("egg-mkfont uses the FreeType library to generate an egg file " - "and a series of texture images from a font file " - "input, such as a TTF file. The resulting egg file " - "can be loaded in Panda as a font for rendering text, even " - "if FreeType is not compiled into the executing Panda.\n\n" - - "egg-mkfont will normally run the generated egg file through " - "egg-palettize automatically as part of the generation process. " - "This collects the individual glyph textures into a small number " - "of texture maps. If you intend to run the font through egg-palettize " - "yourself later, you may choose to omit this step."); - - clear_runlines(); - add_runline("[opts] -o output.egg font"); - add_runline("[opts] font output.egg"); - - add_option - ("fg", "r,g,b[,a]", 0, - "Specifies the foreground color of the generated texture map. The " - "default is white: 1,1,1,1, which leads to the most flexibility " - "as the color can be modulated at runtime to any suitable color.", - &EggMakeFont::dispatch_color, nullptr, &_fg[0]); - - add_option - ("bg", "r,g,b[,a]", 0, - "Specifies the background color of the generated texture map. The " - "default is transparent: 1,1,1,0, which allows the text to be " - "visible against any color background by placing a polygon of a " - "suitable color behind it. If the alpha component of either -fg " - "or -bg is not 1, the generated texture images will include an " - "alpha component; if both colors specify an alpha component of 1 " - "(or do not specify an alpha compenent), then the generated images " - "will not include an alpha component.", - &EggMakeFont::dispatch_color, nullptr, &_bg[0]); - - add_option - ("interior", "r,g,b[,a]", 0, - "Specifies the color to render the interior part of a hollow font. " - "This is a special effect that involves analysis of the bitmap after " - "the font has been rendered, and so is more effective when the pixel " - "size is large. It also implies -noaa (but you can use a scale " - "factor with -sf to achieve antialiasing).", - &EggMakeFont::dispatch_color, &_got_interior, &_interior[0]); - - add_option - ("chars", "range", 0, - "Specifies the characters of the font that are used. The range " - "specification may include combinations of decimal or hex unicode " - "values (where hex values are identified with a leading 0x), separated " - "by commas and hyphens to indicate ranges, e.g. '32-126,0xfa0-0xfff'. " - "It also may specify ranges of ASCII characters by enclosing them " - "within square brackets, e.g. '[A-Za-z0-9]'. If this is not specified, " - "the default set has all ASCII characters and an assorted set of " - "latin-1 characters, diacritics and punctuation marks.", - &EggMakeFont::dispatch_range, nullptr, &_range); - - add_option - ("extra", "file.egg", 0, - "Specifies additional externally-painted glyphs to mix into the " - "generated egg file. The named egg file is expected to contain one " - "or more groups, each of which is named with the decimal unicode " - "number of a character and should contain one polygon. These groups " - "are simply copied into the output egg file as if they were generated " - "locally. This option may be repeated.", - &EggMakeFont::dispatch_vector_string, nullptr, &_extra_filenames); - - add_option - ("ppu", "pixels", 0, - "Specify the pixels per unit. This is the number of pixels in the " - "generated texture map that are used for each onscreen unit (or each " - "10 points of font; see -ps). Setting this number larger results in " - "an easier-to-read font, but at the cost of more texture memory. " - "The default is 40.", - &EggMakeFont::dispatch_double, nullptr, &_pixels_per_unit); - - add_option - ("ps", "size", 0, - "Specify the point size of the resulting font. This controls the " - "apparent size of the font when it is rendered onscreen. By convention, " - "a 10 point font is 1 screen unit high, so the default is 10.", - &EggMakeFont::dispatch_double, nullptr, &_point_size); - - add_option - ("sdf", "", 0, - "If this is set, a signed distance field will be generated, which " - "results in crisp text even when the text is enlarged or zoomed in.", - &EggMakeFont::dispatch_true, nullptr, &_generate_distance_field); - - add_option - ("pm", "n", 0, - "The number of extra pixels around a single character in the " - "generated polygon. This may be a floating-point number. The " - "default is 1.", - &EggMakeFont::dispatch_double, nullptr, &_poly_margin); - - add_option - ("tm", "n", 0, - "The number of extra pixels around each character in the texture map. " - "This may only be an integer. The default is 2. This is meaningful " - "when -nopal is also used; in the normal case, use -pm to control " - "both the polygon size and the texture map spacing.", - &EggMakeFont::dispatch_int, nullptr, &_tex_margin); - - add_option - ("rm", "n", 0, - "The amount of padding in screen units to place around the glyph when " - "rendered. This differs from -pm in that it has no effect on the " - "generated texture map, only on the generated egg. Use this in order to " - "space the characters out in case they appear to be too close together " - "when rendered. The default is 0.", - &EggMakeFont::dispatch_double, nullptr, &_render_margin); - - add_option - ("sf", "factor", 0, - "The scale factor of the generated image. This is the factor by which " - "the font image is generated oversized, then reduced to its final size, " - "to improve antialiasing. If the specified font contains one " - "or more fixed-size fonts instead of a scalable font, the scale factor " - "may be automatically adjusted as necessary to scale the closest-" - "matching font to the desired pixel size. The default is 2.", - &EggMakeFont::dispatch_double, &_got_scale_factor, &_scale_factor); - - add_option - ("noaa", "", 0, - "Disable low-level antialiasing by the Freetype library. " - "This is unrelated to the antialiasing that is applied due to the " - "scale factor specified by -sf; you may have either one, neither, or " - "both kinds of antialiasing enabled.", - &EggMakeFont::dispatch_none, &_no_native_aa); - - add_option - ("nopal", "", 0, - "Don't run egg-palettize automatically on the output file, but " - "just output the raw egg file and all of its individual texture " - "images, one for each glyph.", - &EggMakeFont::dispatch_none, &_no_palettize); - - add_option - ("nr", "", 0, - "Don't actually reduce the images after applying the scale factor, but " - "leave them at their inflated sizes. Presumably you will reduce " - "them later, for instance with egg-palettize.", - &EggMakeFont::dispatch_none, &_no_reduce); - - add_option - ("gp", "pattern", 0, - "The pattern to be used to generate the glyph texture images. This " - "string will be passed to sprintf to generate the actual file name; it " - "should contain the string %d or %x (or some variant such as %03d) " - "which will be filled in with the Unicode number of each symbol. " - "If it is omitted, the default is based on the name of the egg file. " - "This is used only if -nopal is specified; in the normal case, " - "without -nopal, use -pp instead.", - &EggMakeFont::dispatch_string, nullptr, &_output_glyph_pattern); - - add_option - ("pp", "pattern", 0, - "The pattern to be used to generate the palette texture images. This " - "string is effectively passed to egg-palettize as the -tn option, and " - "thus should contain %i for the palette index number. This is used " - "if -nopal is not specified.", - &EggMakeFont::dispatch_string, nullptr, &_output_palette_pattern); - - add_option - ("palsize", "xsize,ysize", 0, - "Specify the size of the palette texture images. This is used if " - "-nopal is not specified.", - &EggMakeFont::dispatch_int_pair, nullptr, _palette_size); - - add_option - ("face", "index", 0, - "Specify the face index of the particular face within the font file " - "to use. Some font files contain multiple faces, indexed beginning " - "at 0. The default is face 0.", - &EggMakeFont::dispatch_int, nullptr, &_face_index); - - _fg.set(1.0, 1.0, 1.0, 1.0); - _bg.set(1.0, 1.0, 1.0, 0.0); - _interior.set(1.0, 1.0, 1.0, 1.0); - _pixels_per_unit = 40.0; - _point_size = 10.0; - _poly_margin = 1.0; - _tex_margin = 2; - _render_margin = 0.0; - _palette_size[0] = _palette_size[1] = 512; - _face_index = 0; - _generate_distance_field = false; - - _text_maker = nullptr; - _vpool = nullptr; - _group = nullptr; -} - - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggMakeFont:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "Must specify name of font file on command line.\n"; - return false; - } - - _input_font_filename = args[0]; - args.pop_front(); - return EggWriter::handle_args(args); -} - -/** - * - */ -void EggMakeFont:: -run() { - if (has_output_filename() && !get_output_filename().get_dirname().empty()) { - FilenameUnifier::set_rel_dirname(get_output_filename().get_dirname()); - } else { - FilenameUnifier::set_rel_dirname("."); - } - - _text_maker = new PNMTextMaker(_input_font_filename, _face_index); - if (!_text_maker->is_valid()) { - exit(1); - } - - if (_got_interior) { - _no_native_aa = true; - } - - if (!_got_scale_factor) { - // The default scale factor is 4 if we are not using FreeType's antialias, - // or 2 if we are. - if (_generate_distance_field) { - _scale_factor = 1.0; - } else if (_no_native_aa) { - _scale_factor = 4.0; - } else { - _scale_factor = 2.0; - } - } - - _text_maker->set_point_size(_point_size); - _text_maker->set_native_antialias(!_no_native_aa); - _text_maker->set_interior_flag(_got_interior); - _text_maker->set_pixels_per_unit(_pixels_per_unit); - _text_maker->set_scale_factor(_scale_factor); - - // The text_maker may have had to adjust the pixels per unit and the scale - // factor according to what the font supports. - _pixels_per_unit = _text_maker->get_pixels_per_unit(); - _scale_factor = _text_maker->get_scale_factor(); - - if (_text_maker->get_font_pixel_size() != 0) { - nout << "Using " << _text_maker->get_font_pixel_size() << "-pixel font.\n"; - } - - // Now we may want to tweak the scale factor so that fonts will actually be - // generated big. We have to do this after we have already send the current - // _scale_factor through the _text_maker for validation. - _palettize_scale_factor = _scale_factor; - if (_scale_factor != 1.0 && (_no_reduce || !_no_palettize)) { - // If _no_reduce is true (-nr was specified), we want to keep the glyph - // textures full-sized, because the user asked for that. - - // If _no_palettize is false (-nopal was not specified), we still want to - // keep the glyph textures full-sized, because the palettizer will reduce - // them later. - - _tex_margin = (int)(_tex_margin * _scale_factor); - _poly_margin *= _scale_factor; - _pixels_per_unit *= _scale_factor; - _scale_factor = 1.0; - _text_maker->set_pixels_per_unit(_pixels_per_unit); - _text_maker->set_scale_factor(1.0); - } - - if (_no_reduce) { - // If -nr was specified, but we're still palettizing, we don't even want - // to reduce the palette images. Instead, we'll generate extra-large - // palette images. - _palette_size[0] = (int)(_palette_size[0] * _palettize_scale_factor); - _palette_size[1] = (int)(_palette_size[1] * _palettize_scale_factor); - _palettize_scale_factor = 1.0; - } - - if (_range.is_empty()) { - // If there's no specified range, the default is the entire ASCII set. - _range.add_range(0x20, 0x7e); - - _range.add_singleton(0xa1); // Upside down exclamation mark - _range.add_singleton(0xa9); // Copyright sign - _range.add_singleton(0xab); // Left double angle quote - // _range.add_singleton(0xae); Registered sign - _range.add_singleton(0xb0); // Degree symbol - _range.add_singleton(0xb5); // Mu/micro - _range.add_singleton(0xb8); // Cedilla - _range.add_singleton(0xbb); // Right double angle quote - _range.add_singleton(0xbf); // Upside down question mark - - _range.add_singleton(0xc6); // AE ligature - _range.add_singleton(0xc7); // C cedilla - // _range.add_singleton(0xd0); Upper-case Eth _range.add_singleton(0xd8); - // Upper-case O with line _range.add_singleton(0xde); Upper-case Thorn - _range.add_singleton(0xdf); // German Eszet - _range.add_singleton(0xe6); // ae ligature - _range.add_singleton(0xe7); // c cedilla - _range.add_singleton(0xf0); // Lower-case Eth - _range.add_singleton(0xf8); // Lower-case O with line - _range.add_singleton(0xfe); // Lower-case Thorn - - // _range.add_singleton(0x03c0); pi - - // Dotless i and j, for combining purposes. - _range.add_singleton(0x0131); - _range.add_singleton(0x0237); - - // And general punctuation. These don't take up much space anyway. - _range.add_range(0x2018, 0x201f); - - _range.add_singleton(0x2026); // Ellipses - - // Also add all the combining diacritic marks. - _range.add_range(0x0300, 0x030f); - } - if (_output_glyph_pattern.empty()) { - // Create a default texture filename pattern. - _output_glyph_pattern = get_output_filename().get_fullpath_wo_extension() + "%03d.png"; - } - if (_output_palette_pattern.empty()) { - // Create a default texture filename pattern. - _output_palette_pattern = get_output_filename().get_fullpath_wo_extension() + "_%i"; - } - - // Figure out how many channels we need based on the foreground and - // background colors. - bool needs_alpha = (_fg[3] != 1.0 || _bg[3] != 1.0 || _interior[3] != 1.0); - bool needs_color = (_fg[0] != _fg[1] || _fg[1] != _fg[2] || - _bg[0] != _bg[1] || _bg[1] != _bg[2] || - _interior[0] != _interior[1] || _interior[1] != _interior[2]); - - if (needs_alpha) { - if (needs_color) { - _num_channels = 4; - _format = EggTexture::F_rgba; - } else { - if (_fg[0] == 1.0 && _bg[0] == 1.0 && _interior[0] == 1.0) { - // A special case: we only need an alpha channel. Copy the alpha data - // into the color channels so we can write out a one-channel image. - _fg[0] = _fg[1] = _fg[2] = _fg[3]; - _bg[0] = _bg[1] = _bg[2] = _bg[3]; - _interior[0] = _interior[1] = _interior[2] = _interior[3]; - _num_channels = 1; - _format = EggTexture::F_alpha; - } else { - _num_channels = 2; - _format = EggTexture::F_luminance_alpha; - } - } - } else { - if (needs_color) { - _num_channels = 3; - _format = EggTexture::F_rgb; - } else { - _num_channels = 1; - _format = EggTexture::F_luminance; - } - } - - // Create a global Palettizer object. We'll use this even if the user - // specified -nopal, if nothing else just to hold all of the TextureImage - // pointers. - pal = new Palettizer; - pal->_generated_image_pattern = _output_palette_pattern; - pal->_omit_solitary = false; - pal->_round_uvs = false; - - // Generate a txa script for the palettizer. We have the palettizer reduce - // all of the texture images by the inverse of our scale factor. - char buffer[1024]; - sprintf(buffer, ":margin 0;:coverage 1000;:background %f %f %f %f;:palette %d %d;*: %f%% keep-format", - _bg[0], _bg[1], _bg[2], _bg[3], - _palette_size[0], _palette_size[1], - 100.0 / _palettize_scale_factor); - std::istringstream txa_script(buffer); - pal->read_txa_file(txa_script, "default script"); - - pal->all_params_set(); - - // Now create all the egg structures. We can't use _data, since we want to - // pass this object to the palettizer, which will try to up its reference - // count. - PT(EggData) egg_data = new EggData; - _group = new EggGroup(); - egg_data->add_child(_group); - append_command_comment(egg_data); - - _vpool = new EggVertexPool("vpool"); - _group->add_child(_vpool); - - // Make the group a sequence, as a convenience. If we view the egg file - // directly we can see all the characters one at a time. - _group->set_switch_flag(true); - _group->set_switch_fps(2.0); - - double margin = _poly_margin; - if (_generate_distance_field) { - // Distance fields are always rendered with binary alpha. - _group->set_alpha_mode(EggRenderMode::AM_binary); - - // Fudged to make most fonts fit on 512x256. - if (_poly_margin >= 1) { - margin += 3.5; - _poly_margin -= 0.5; - } - - _text_maker->set_distance_field_radius(4); - } - - // Also create an egg group indicating the font's design size and poly - // margin. - EggGroup *ds_group = new EggGroup("ds"); - _group->add_child(ds_group); - EggVertex *vtx = make_vertex(LPoint2d(margin / _pixels_per_unit, _text_maker->get_line_height())); - EggPoint *point = new EggPoint; - ds_group->add_child(point); - point->add_vertex(vtx); - - // Finally, add the characters, one at a time. - RangeIterator ri(_range); - do { - add_character(ri.get_code()); - } while (ri.next()); - - // If there are extra glyphs, pick them up. - if (!_extra_filenames.empty()) { - vector_string::const_iterator si; - for (si = _extra_filenames.begin(); si != _extra_filenames.end(); ++si) { - add_extra_glyphs(*si); - } - } - - if (_no_palettize) { - // Ok, no palettize step; just write out the egg file and all of the - // textures. - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti); - texture->write(texture->read_source_image()); - } - - egg_data->write_egg(get_output()); - - } else { - // Pass the generated egg structure through egg-palettize, without writing - // it to disk first. - string name = get_output_filename().get_basename(); - EggFile *egg_file = pal->get_egg_file(name); - egg_file->from_command_line(egg_data, "", get_output_filename(), - get_exec_command()); - - pal->add_command_line_egg(egg_file); - pal->process_all(true, ""); - pal->optimal_resize(); - pal->generate_images(true); - if (!pal->write_eggs()) { - exit(1); - } - // pal->report_pi(); - } -} - -/** - * - */ -bool EggMakeFont:: -dispatch_range(const string &, const string &arg, void *var) { - RangeDescription *ip = (RangeDescription *)var; - return ip->parse_parameter(arg); -} - -/** - * Allocates and returns a new vertex from the vertex pool representing the - * indicated 2-d coordinates. - */ -EggVertex *EggMakeFont:: -make_vertex(const LPoint2d &xy) { - return - _vpool->make_new_vertex(LPoint3d::origin(_coordinate_system) + - LVector3d::rfu(xy[0], 0.0, xy[1], _coordinate_system)); -} - -/** - * Generates the indicated character and adds it to the font description. - */ -void EggMakeFont:: -add_character(int code) { - PNMTextGlyph *glyph = _text_maker->get_glyph(code); - if (glyph == nullptr) { - nout << "No definition in font for character " << code << ".\n"; - return; - } - - make_geom(glyph, code); -} - - -/** - * Creates the actual geometry for the glyph. - */ -void EggMakeFont:: -make_geom(PNMTextGlyph *glyph, int character) { - // Create an egg group to hold the polygon. - string group_name = format_string(character); - EggGroup *group = new EggGroup(group_name); - _group->add_child(group); - - if (glyph->get_width() != 0 && glyph->get_height() != 0) { - int bitmap_top = glyph->get_top(); - int bitmap_left = glyph->get_left(); - double tex_x_size = glyph->get_width(); - double tex_y_size = glyph->get_height(); - - double poly_margin = _poly_margin; - double x_origin = _tex_margin; - double y_origin = _tex_margin; - double page_y_size = tex_y_size + _tex_margin * 2; - double page_x_size = tex_x_size + _tex_margin * 2; - - // Determine the corners of the rectangle in geometric units. - double tex_poly_margin = poly_margin / _pixels_per_unit; - double origin_y = bitmap_top / _pixels_per_unit; - double origin_x = bitmap_left / _pixels_per_unit; - double top = origin_y + tex_poly_margin; - double left = origin_x - tex_poly_margin; - double bottom = origin_y - tex_y_size / _pixels_per_unit - tex_poly_margin; - double right = origin_x + tex_x_size / _pixels_per_unit + tex_poly_margin; - - // And the corresponding corners in UV units. - double uv_top = 1.0f - (double)(y_origin - poly_margin) / page_y_size; - double uv_left = (double)(x_origin - poly_margin) / page_x_size; - double uv_bottom = 1.0f - (double)(y_origin + poly_margin + tex_y_size) / page_y_size; - double uv_right = (double)(x_origin + poly_margin + tex_x_size) / page_x_size; - - // Create the vertices for the polygon. - EggVertex *v1 = make_vertex(LPoint2d(left, bottom)); - EggVertex *v2 = make_vertex(LPoint2d(right, bottom)); - EggVertex *v3 = make_vertex(LPoint2d(right, top)); - EggVertex *v4 = make_vertex(LPoint2d(left, top)); - - v1->set_uv(LTexCoordd(uv_left, uv_bottom)); - v2->set_uv(LTexCoordd(uv_right, uv_bottom)); - v3->set_uv(LTexCoordd(uv_right, uv_top)); - v4->set_uv(LTexCoordd(uv_left, uv_top)); - - EggPolygon *poly = new EggPolygon(); - group->add_child(poly); - poly->set_texture(get_tref(glyph, character)); - - poly->add_vertex(v1); - poly->add_vertex(v2); - poly->add_vertex(v3); - poly->add_vertex(v4); - } - - // Now create a single point where the origin of the next character will be. - - EggVertex *v0 = make_vertex(LPoint2d(glyph->get_advance() / _pixels_per_unit + _render_margin, 0.0)); - EggPoint *point = new EggPoint; - group->add_child(point); - point->add_vertex(v0); -} - -/** - * Returns the egg texture reference for a particular glyph, creating it if it - * has not already been created. - */ -EggTexture *EggMakeFont:: -get_tref(PNMTextGlyph *glyph, int character) { - TRefs::iterator ti = _trefs.find(glyph); - if (ti != _trefs.end()) { - return (*ti).second; - } - - EggTexture *tref = make_tref(glyph, character); - _trefs[glyph] = tref; - return tref; -} - -/** - * Generates a texture image for the indicated glyph, and returns its egg - * reference. - */ -EggTexture *EggMakeFont:: -make_tref(PNMTextGlyph *glyph, int character) { - char buffer[1024]; - sprintf(buffer, _output_glyph_pattern.c_str(), character); - - Filename texture_filename = buffer; - PNMImage image(glyph->get_width() + _tex_margin * 2, - glyph->get_height() + _tex_margin * 2, _num_channels); - image.fill(_bg[0], _bg[1], _bg[2]); - if (image.has_alpha()) { - image.alpha_fill(_bg[3]); - } - if (_got_interior) { - glyph->place(image, -glyph->get_left() + _tex_margin, - glyph->get_top() + _tex_margin, _fg, _interior); - } else { - glyph->place(image, -glyph->get_left() + _tex_margin, - glyph->get_top() + _tex_margin, _fg); - } - - // We don't write the image to disk immediately, since it might just get - // palettized. But we do record it in a TextureImage object within the - // global Palettizer, so that it may be written out later. - - string name = texture_filename.get_basename_wo_extension(); - TextureImage *texture = pal->get_texture(name); - _textures.push_back(texture); - texture->set_filename("", texture_filename); - SourceTextureImage *source = texture->get_source(texture_filename, "", 0); - texture->set_source_image(image); - source->set_header(image); - - EggTexture *tref = new EggTexture(name, texture_filename); - tref->set_format(_format); - tref->set_wrap_mode(EggTexture::WM_clamp); - tref->set_minfilter(EggTexture::FT_linear_mipmap_linear); - tref->set_magfilter(EggTexture::FT_linear); - tref->set_quality_level(EggTexture::QL_best); - - return tref; -} - -/** - * Reads the indicated filename and adds any numbered groups into the current - * egg file. - */ -void EggMakeFont:: -add_extra_glyphs(const Filename &extra_filename) { - PT(EggData) extra_data = new EggData; - - if (!extra_data->read(extra_filename)) { - return; - } - - _group->steal_children(*extra_data); -} - -/** - * Recursively searches for numbered groups in the indicated egg file, and - * copies them to the current egg file. - */ -void EggMakeFont:: -r_add_extra_glyphs(EggGroupNode *egg_group) { - if (egg_group->is_of_type(EggGroup::get_class_type())) { - EggGroup *group = DCAST(EggGroup, egg_group); - if (is_numeric(group->get_name())) { - EggGroup *new_group = new EggGroup(group->get_name()); - _group->add_child(new_group); - new_group->steal_children(*group); - return; - } - } - - EggGroupNode::iterator ci; - for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { - EggNode *child = (*ci); - if (child->is_of_type(EggGroupNode::get_class_type())) { - r_add_extra_glyphs(DCAST(EggGroupNode, child)); - } - } -} - -/** - * Returns true if the indicated string is all numeric digits, false - * otherwise. - */ -bool EggMakeFont:: -is_numeric(const string &str) { - if (str.empty()) { - return false; - } - - string::const_iterator si; - for (si = str.begin(); si != str.end(); ++si) { - if (!isdigit(*si)) { - return false; - } - } - - return true; -} - -int main(int argc, char *argv[]) { - EggMakeFont prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/egg-mkfont/eggMakeFont.h b/pandatool/src/egg-mkfont/eggMakeFont.h deleted file mode 100644 index 3df12af6..00000000 --- a/pandatool/src/egg-mkfont/eggMakeFont.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMakeFont.h - * @author drose - * @date 2001-02-16 - */ - -#ifndef EGGMAKEFONT_H -#define EGGMAKEFONT_H - -#include "pandatoolbase.h" -#include "rangeDescription.h" - -#include "eggWriter.h" -#include "eggTexture.h" -#include "pmap.h" -#include "pvector.h" -#include "vector_string.h" - -class PNMTextMaker; -class PNMTextGlyph; -class EggVertexPool; -class EggGroup; -class TextureImage; - -/** - * This program uses FreeType to generate an egg file and a series of texture - * images from a font file input, such as a TTF file. The resulting egg file - * can be loaded in Panda as a StaticTextFont object for rendering text, even - * if FreeType is not compiled into the executing Panda. - */ -class EggMakeFont : public EggWriter { -public: - EggMakeFont(); - -protected: - virtual bool handle_args(Args &args); - -public: - void run(); - -private: - static bool dispatch_range(const std::string &, const std::string &arg, void *var); - EggVertex *make_vertex(const LPoint2d &xy); - - void add_character(int code); - void make_geom(PNMTextGlyph *glyph, int character); - EggTexture *get_tref(PNMTextGlyph *glyph, int character); - EggTexture *make_tref(PNMTextGlyph *glyph, int character); - void add_extra_glyphs(const Filename &extra_filename); - void r_add_extra_glyphs(EggGroupNode *egg_group); - static bool is_numeric(const std::string &str); - - -private: - LColor _fg, _bg, _interior; - bool _got_interior; - RangeDescription _range; - vector_string _extra_filenames; - double _pixels_per_unit; - double _point_size; - double _poly_margin; - int _tex_margin; - double _render_margin; - bool _got_scale_factor; - double _scale_factor; - bool _no_reduce; - bool _no_native_aa; - bool _no_palettize; - int _palette_size[2]; - bool _generate_distance_field; - - double _palettize_scale_factor; - Filename _input_font_filename; - int _face_index; - std::string _output_glyph_pattern; - std::string _output_palette_pattern; - - PNMTextMaker *_text_maker; - - EggTexture::Format _format; - int _num_channels; - EggVertexPool *_vpool; - EggGroup *_group; - - typedef pmap TRefs; - TRefs _trefs; - - typedef pvector Textures; - Textures _textures; -}; - - -#endif diff --git a/pandatool/src/egg-mkfont/rangeDescription.I b/pandatool/src/egg-mkfont/rangeDescription.I deleted file mode 100644 index 39a20162..00000000 --- a/pandatool/src/egg-mkfont/rangeDescription.I +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file rangeDescription.I - * @author drose - * @date 2003-09-07 - */ - -/** - * - */ -INLINE void RangeDescription:: -add_singleton(int code) { - _range_list.push_back(Range(code)); -} - -/** - * - */ -INLINE void RangeDescription:: -add_range(int from_code, int to_code) { - _range_list.push_back(Range(from_code, to_code)); -} - -/** - * Returns true if there are no codes described in the range. - */ -INLINE bool RangeDescription:: -is_empty() const { - return _range_list.empty(); -} - -/** - * - */ -INLINE RangeDescription::Range:: -Range(int code) : - _from_code(code), - _to_code(code) -{ -} - -/** - * - */ -INLINE RangeDescription::Range:: -Range(int from_code, int to_code) : - _from_code(from_code), - _to_code(to_code) -{ -} - -INLINE std::ostream &operator << (std::ostream &out, const RangeDescription &range) { - range.output(out); - return out; -} diff --git a/pandatool/src/egg-mkfont/rangeDescription.cxx b/pandatool/src/egg-mkfont/rangeDescription.cxx deleted file mode 100644 index 2833f533..00000000 --- a/pandatool/src/egg-mkfont/rangeDescription.cxx +++ /dev/null @@ -1,175 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file rangeDescription.cxx - * @author drose - * @date 2003-09-07 - */ - -#include "rangeDescription.h" -#include "string_utils.h" -#include "pnotify.h" - -using std::string; - -/** - * - */ -RangeDescription:: -RangeDescription() { -} - -/** - * Parses a string of comma- and hyphen-delimited unicode values, in decimal - * and/or hex, including possible bracket-delimited ASCII characters, as may - * have been passed on a command line. Returns true if the parameter is - * parsed correctly, false otherwise. - */ -bool RangeDescription:: -parse_parameter(const string ¶m) { - // First, go through and separate the string by commas. We have to do this - // by hand instead of calling tokenize(), because we also have to scan for - // square brackets, which may contain nested commas. - size_t p = 0; - while (p < param.length()) { - size_t q = param.find_first_of("[,", p); - if (q == string::npos) { - return parse_word(trim(param.substr(p))); - } - if (!parse_word(trim(param.substr(p, q - p)))) { - return false; - } - - if (param[q] == '[') { - // A square bracket means we must search for the matching square - // bracket. However, a right bracket immediately after the left bracket - // doesn't count; we start the scan after that. - p = param.find("]", q + 2); - if ( p == string::npos) { - nout << "Unclosed open bracket.\n"; - return false; - } - if (!parse_bracket(param.substr(q + 1, p - q - 1))) { - return false; - } - p = p + 1; - - } else { - // Otherwise, if the separator was just a comma, the next character - // begins the next word. - p = q + 1; - } - } - - return true; -} - -/** - * - */ -void RangeDescription:: -output(std::ostream &out) const { - bool first_time = true; - RangeList::const_iterator ri; - for (ri = _range_list.begin(); ri != _range_list.end(); ++ri) { - const Range &range = (*ri); - if (!first_time) { - out << ","; - } - first_time = false; - if (range._from_code == range._to_code) { - out << range._from_code; - } else { - out << range._from_code << "-" << range._to_code; - } - } -} - -/** - * Parses a single "word", i.e. the text delimited by commas, that might be - * listed on the command line. This is generally either the empty string, a - * single number, or a pair of numbers separated by a hyphen. - */ -bool RangeDescription:: -parse_word(const string &word) { - if (word.empty()) { - return true; - } - - // It's not empty, so see if it includes a hyphen. - size_t hyphen = word.find('-'); - if (hyphen == string::npos) { - // Nope, just one number. - int code; - if (!parse_code(word, code)) { - return false; - } - add_singleton(code); - - } else { - // Two numbers separated by a hyphen. - int from_code, to_code; - if (!parse_code(word.substr(0, hyphen), from_code)) { - return false; - } - if (!parse_code(word.substr(hyphen + 1), to_code)) { - return false; - } - add_range(from_code, to_code); - } - - return true; -} - -/** - * Parses a single numeric value, either decimal or hexadecimal, and stores it - * in the indicated parameter. Returns true if successful, false otherwise. - */ -bool RangeDescription:: -parse_code(const string &word, int &code) { - string str = trim(word); - const char *nptr = str.c_str(); - char *endptr; - code = strtol(nptr, &endptr, 0); - if (*endptr == '\0') { - return true; - } - - nout << "Invalid Unicode value: " << word << "\n"; - return false; -} - -/** - * Parses the text listed between square brackets on the command line. - */ -bool RangeDescription:: -parse_bracket(const string &str) { - string::const_iterator si; - si = str.begin(); - while (si != str.end()) { - int ch = (*si); - ++si; - if (si != str.end() && (*si) == '-') { - // A hyphen indicates a range. - ++si; - if (si == str.end()) { - // Unless the hyphen is the last character. - add_singleton(ch); - add_singleton('-'); - } else { - add_range(ch, (*si)); - ++si; - } - } else { - // Anything other than a hyphen indicates a singleton. - add_singleton(ch); - } - } - - return true; -} diff --git a/pandatool/src/egg-mkfont/rangeDescription.h b/pandatool/src/egg-mkfont/rangeDescription.h deleted file mode 100644 index 25119cb1..00000000 --- a/pandatool/src/egg-mkfont/rangeDescription.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file rangeDescription.h - * @author drose - * @date 2003-09-07 - */ - -#ifndef RANGEDESCRIPTION_H -#define RANGEDESCRIPTION_H - -#include "pandatoolbase.h" -#include "pvector.h" - -/** - * This describes a sparse range of Unicode character codes for conversion - * that may be specified on the command line. - */ -class RangeDescription { -public: - RangeDescription(); - - bool parse_parameter(const std::string ¶m); - INLINE void add_singleton(int code); - INLINE void add_range(int from_code, int to_code); - INLINE bool is_empty() const; - - void output(std::ostream &out) const; - -private: - bool parse_word(const std::string &word); - bool parse_code(const std::string &word, int &code); - bool parse_bracket(const std::string &str); - -private: - class Range { - public: - INLINE Range(int code); - INLINE Range(int from_code, int to_code); - - int _from_code; - int _to_code; - }; - - typedef pvector RangeList; - RangeList _range_list; - - friend class RangeIterator; -}; - -INLINE std::ostream &operator << (std::ostream &out, const RangeDescription &range); - -#include "rangeDescription.I" - -#endif diff --git a/pandatool/src/egg-mkfont/rangeIterator.I b/pandatool/src/egg-mkfont/rangeIterator.I deleted file mode 100644 index 5d34d4ec..00000000 --- a/pandatool/src/egg-mkfont/rangeIterator.I +++ /dev/null @@ -1,29 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file rangeIterator.I - * @author drose - * @date 2003-09-07 - */ - -/** - * Returns the current Unicode value represented by the iterator, or -1 if the - * iterator has reached the end. - */ -INLINE int RangeIterator:: -get_code() const { - return _code; -} - -/** - * Returns true if all the code have been retrieved, false otherwise. - */ -INLINE bool RangeIterator:: -eof() const { - return (_it == _desc._range_list.end()); -} diff --git a/pandatool/src/egg-mkfont/rangeIterator.cxx b/pandatool/src/egg-mkfont/rangeIterator.cxx deleted file mode 100644 index 0050c80b..00000000 --- a/pandatool/src/egg-mkfont/rangeIterator.cxx +++ /dev/null @@ -1,63 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file rangeIterator.cxx - * @author drose - * @date 2003-09-07 - */ - -#include "rangeIterator.h" - -/** - * Constructs an iterator to walk through the codes on the descriptor. It is - * important not to modify the RangeDescription object during the lifetime of - * the iterator. - */ -RangeIterator:: -RangeIterator(const RangeDescription &desc) : - _desc(desc) -{ - _it = _desc._range_list.begin(); - if (_it == _desc._range_list.end()) { - _code = -1; - } else { - _code = (*_it)._from_code; - _codes_generated.insert(_code); - } -} - -/** - * Advances the iterator to the next code. Returns true if there is a next - * code, or false if there are no mode codes. - */ -bool RangeIterator:: -next() { - do { - if (_it == _desc._range_list.end()) { - return false; - } - - if (_code < (*_it)._to_code) { - _code++; - - } else { - _it++; - if (_it == _desc._range_list.end()) { - _code = -1; - return false; - } - - _code = (*_it)._from_code; - } - - // If this code has already been generated, repeat and skip to the next - // one. - } while (!_codes_generated.insert(_code).second); - - return true; -} diff --git a/pandatool/src/egg-mkfont/rangeIterator.h b/pandatool/src/egg-mkfont/rangeIterator.h deleted file mode 100644 index 5a9630d7..00000000 --- a/pandatool/src/egg-mkfont/rangeIterator.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file rangeIterator.h - * @author drose - * @date 2003-09-07 - */ - -#ifndef RANGEITERATOR_H -#define RANGEITERATOR_H - -#include "pandatoolbase.h" -#include "rangeDescription.h" - -#include "pset.h" - -/** - * Walks through all the Unicode characters described by a RangeDescription - * class. - */ -class RangeIterator { -public: - RangeIterator(const RangeDescription &desc); - - INLINE int get_code() const; - bool next(); - INLINE bool eof() const; - -private: - const RangeDescription &_desc; - RangeDescription::RangeList::const_iterator _it; - int _code; - - typedef pset Codes; - Codes _codes_generated; -}; - -#include "rangeIterator.I" - -#endif diff --git a/pandatool/src/egg-optchar/CMakeLists.txt b/pandatool/src/egg-optchar/CMakeLists.txt deleted file mode 100644 index 379fc301..00000000 --- a/pandatool/src/egg-optchar/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_EGG) - return() -endif() - -set(P3EGG_OPTCHAR_HEADERS - config_egg_optchar.h - eggOptchar.h - eggOptcharUserData.h eggOptcharUserData.I - vertexMembership.h vertexMembership.I -) - -set(P3EGG_OPTCHAR_SOURCES - config_egg_optchar.cxx - eggOptchar.cxx - eggOptcharUserData.cxx - vertexMembership.cxx -) - -composite_sources(egg-optchar P3EGG_OPTCHAR_SOURCES) -add_executable(egg-optchar ${P3EGG_OPTCHAR_HEADERS} ${P3EGG_OPTCHAR_SOURCES}) -target_link_libraries(egg-optchar p3eggcharbase) - -install(TARGETS egg-optchar EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/egg-optchar/config_egg_optchar.cxx b/pandatool/src/egg-optchar/config_egg_optchar.cxx deleted file mode 100644 index ef835f1f..00000000 --- a/pandatool/src/egg-optchar/config_egg_optchar.cxx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_egg_optchar.cxx - * @author drose - * @date 2003-07-18 - */ - -#include "config_egg_optchar.h" -#include "eggOptcharUserData.h" - -#include "dconfig.h" - - -Configure(config_egg_optchar); - -ConfigureFn(config_egg_optchar) { - init_egg_optchar(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_egg_optchar() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - EggOptcharUserData::init_type(); -} diff --git a/pandatool/src/egg-optchar/config_egg_optchar.h b/pandatool/src/egg-optchar/config_egg_optchar.h deleted file mode 100644 index 9d01b7fe..00000000 --- a/pandatool/src/egg-optchar/config_egg_optchar.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_egg_optchar.h - * @author drose - * @date 2003-07-18 - */ - -#ifndef CONFIG_EGG_OPTCHAR_H -#define CONFIG_EGG_OPTCHAR_H - -#include "pandatoolbase.h" - -void init_egg_optchar(); - -#endif /* CONFIG_EGG_OPTCHAR_H */ diff --git a/pandatool/src/egg-optchar/eggOptchar.cxx b/pandatool/src/egg-optchar/eggOptchar.cxx deleted file mode 100644 index 182b6579..00000000 --- a/pandatool/src/egg-optchar/eggOptchar.cxx +++ /dev/null @@ -1,1522 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggOptchar.cxx - * @author drose - * @date 2003-07-18 - */ - -#include "eggOptchar.h" -#include "eggOptcharUserData.h" -#include "vertexMembership.h" - -#include "eggJointData.h" -#include "eggSliderData.h" -#include "eggCharacterCollection.h" -#include "eggCharacterData.h" -#include "eggBackPointer.h" -#include "eggGroupNode.h" -#include "eggPrimitive.h" -#include "eggVertexPool.h" -#include "eggTable.h" -#include "eggGroup.h" -#include "eggAnimPreload.h" -#include "string_utils.h" -#include "dcast.h" -#include "pset.h" -#include "compose_matrix.h" -#include "fftCompressor.h" - -#include - -using std::cout; -using std::setw; -using std::string; - -/** - * - */ -EggOptchar:: -EggOptchar() { - add_path_replace_options(); - add_path_store_options(); - add_normals_options(); - add_transform_options(); - add_fixrest_option(); - - set_program_brief("optimizes character models and animations in .egg files"); - set_program_description - ("egg-optchar performs basic optimizations of a character model " - "and its associated animations, primarily by analyzing the " - "animation tables and removing unneeded joints and/or morphs. " - "It can also perform basic restructuring operations on the " - "character hierarchy."); - - add_option - ("ls", "", 0, - "List the joint hierarchy instead of performing any operations.", - &EggOptchar::dispatch_none, &_list_hierarchy); - - add_option - ("lsv", "", 0, - "List the joint hierarchy along with an indication of the properties " - "each joint.", - &EggOptchar::dispatch_none, &_list_hierarchy_v); - - add_option - ("lsp", "", 0, - "List the existing joint hierarchy as a series of -p joint,parent " - "commands, suitable for pasting into an egg-optchar command line.", - &EggOptchar::dispatch_none, &_list_hierarchy_p); - - add_option - ("keep", "joint[,joint...]", 0, - "Keep the named joints (or sliders) in the character, even if they do " - "not appear to be needed by the animation.", - &EggOptchar::dispatch_vector_string_comma, nullptr, &_keep_components); - - add_option - ("drop", "joint[,joint...]", 0, - "Removes the named joints or sliders, even if they appear to be needed.", - &EggOptchar::dispatch_vector_string_comma, nullptr, &_drop_components); - - add_option - ("expose", "joint[,joint...]", 0, - "Expose the named joints by flagging them with a DCS attribute, so " - "each one can be found in the scene graph when the character is loaded, " - "and objects can be parented to it. This implies -keep.", - &EggOptchar::dispatch_vector_string_comma, nullptr, &_expose_components); - - add_option - ("suppress", "joint[,joint...]", 0, - "The opposite of suppress, this prevents the named joints from " - "being created with an implicit DCS attribute, even if they contain " - "rigid geometry. The default is to create an implicit node for any " - "joint that contains rigid geometry, to take advantage of display " - "list and/or vertex buffer caching. This does not imply -keep.", - &EggOptchar::dispatch_vector_string_comma, nullptr, &_suppress_components); - - add_option - ("flag", "node[,node...][=name]", 0, - "Assign the indicated name to the geometry within the given nodes. " - "This will make the geometry visible as a node in the resulting " - "character model when it is loaded in the scene graph (normally, " - "the node hierarchy is suppressed when loading characters). This " - "is different from -expose in that it reveals geometry rather than " - "joints; the revealed node can be hidden or its attributes changed " - "at runtime, but it will be animated by its vertices, not the node, so " - "objects parented to this node will not inherit its animation.", - &EggOptchar::dispatch_flag_groups, nullptr, &_flag_groups); - - add_option - ("defpose", "anim.egg,frame", 0, - "Specify the model's default pose. The pose is taken " - "from the indicated frame of the named animation file (which must " - "also be named separately on the command line). The " - "pose will be held by the model in " - "the absence of any animation, and need not be the same " - "pose in which the model was originally skinned.", - &EggOptchar::dispatch_string, nullptr, &_defpose); - - add_option - ("preload", "", 0, - "Add an entry for each animation to the model file(s). " - "This can be used at runtime to support asynchronous " - "loading and binding of animation channels.", - &EggOptchar::dispatch_none, &_preload); - - add_option - ("zero", "joint[,hprxyzijkabc]", 0, - "Zeroes out the animation channels for the named joint. If " - "a subset of the component letters hprxyzijkabc is included, the " - "operation is restricted to just those components; otherwise the " - "entire transform is cleared.", - &EggOptchar::dispatch_name_components, nullptr, &_zero_channels); - - add_option - ("keepall", "", 0, - "Keep all joints and sliders in the character, except those named " - "explicitly by -drop.", - &EggOptchar::dispatch_none, &_keep_all); - - add_option - ("p", "joint,parent", 0, - "Moves the named joint under the named parent joint. Use " - "\"-p joint,\" to reparent a joint to the root. The joint transform " - "is recomputed appropriately under its new parent so that the animation " - "is not affected (the effect is similar to NodePath::wrt_reparent_to).", - &EggOptchar::dispatch_vector_string_pair, nullptr, &_reparent_joints); - - add_option - ("new", "joint,source", 0, - "Creates a new joint under the named parent joint. The new " - "joint will inherit the same net transform as its parent.", - &EggOptchar::dispatch_vector_string_pair, nullptr, &_new_joints); - - add_option - ("rename", "joint,newjoint", 0, - "Renames the indicated joint, if present, to the given name.", - &EggOptchar::dispatch_vector_string_pair, nullptr, &_rename_joints); - - if (FFTCompressor::is_compression_available()) { - add_option - ("optimal", "", 0, - "Computes the optimal joint hierarchy for the character by analyzing " - "all of the joint animation and reparenting joints to minimize " - "transformations. This can repair skeletons that have been flattened " - "or whose hierarchy was otherwise damaged in conversion; it can also " - "detect joints that are constrained to follow other joints and should " - "therefore be parented to the master joints. The result is a file " - "from which more joints may be successfully removed, that generally " - "compresses better and with fewer artifacts. However, this is a " - "fairly expensive operation.", - &EggOptchar::dispatch_none, &_optimal_hierarchy); - } - - add_option - ("q", "quantum", 0, - "Quantize joint membership values to the given unit. This is " - "the smallest significant change in joint membership. There can " - "be a significant performance (and memory utilization) runtime " - "benefit for eliminating small differences in joint memberships " - "between neighboring vertices. The default is 0.01; specifying " - "0 means to preserve the original values.", - &EggOptchar::dispatch_double, nullptr, &_vref_quantum); - - add_option - ("qa", "quantum[,hprxyzijkabc]", 0, - "Quantizes animation channels to the given unit. This rounds each " - "of the named components of all joints to the nearest multiple of unit. " - "There is no performance benefit, and little compression benefit, " - "for doing this; and this may introduce visible artifacts to the " - "animation. However, sometimes it is a useful tool for animation " - "analysis and comparison. This option may be repeated several times " - "to quantize different channels by a different amount.", - &EggOptchar::dispatch_double_components, nullptr, &_quantize_anims); - - add_option - ("dart", "[default, sync, nosync, or structured]", 0, - "change the dart value in the given eggs", - &EggOptchar::dispatch_string, nullptr, &_dart_type); - - - _optimal_hierarchy = false; - _vref_quantum = 0.01; -} - -/** - * - */ -void EggOptchar:: -run() { - // We have to apply the user-specified reparent requests first, before we - // even analyze the joints. This is because reparenting the joints may - // change their properties. - if (apply_user_reparents()) { - nout << "Reparenting hierarchy.\n"; - // So we'll have to call do_reparent() twice. It seems wasteful, but it - // really is necessary, and it's not that bad. - do_reparent(); - } - - if (!_zero_channels.empty()) { - zero_channels(); - } - - int num_characters = _collection->get_num_characters(); - int ci; - - // Now we can analyze the joints for their properties. - for (ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - analyze_joints(char_data->get_root_joint(), 0); - analyze_sliders(char_data); - } - - if (_list_hierarchy || _list_hierarchy_v) { - for (ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - nout << "Character: " << char_data->get_name() << "\n"; - list_joints(char_data->get_root_joint(), 0, _list_hierarchy_v); - list_scalars(char_data, _list_hierarchy_v); - nout << char_data->get_num_joints() << " joints.\n"; - } - - } else if (_list_hierarchy_p) { - for (ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - nout << "Character: " << char_data->get_name() << "\n"; - int col = 0; - list_joints_p(char_data->get_root_joint(), col); - // A newline to cout is needed after the above call. - cout << "\n"; - nout << char_data->get_num_joints() << " joints.\n"; - } - - } else { - // The meat of the program: determine which joints are to be removed, and - // then actually remove them. - determine_removed_components(); - move_vertices(); - if (process_joints()) { - do_reparent(); - } - - // We currently do not implement optimizing morph sliders. Need to add - // this at some point; it's quite easy. Identity and empty morph sliders - // can simply be removed, while static sliders need to be applied to the - // vertices and then removed. - - rename_joints(); - - // Quantize the vertex memberships. We call this even if _vref_quantum is - // 0, because this also normalizes the vertex memberships. - quantize_vertices(); - - // Also quantize the animation channels, if the user so requested. - quantize_channels(); - - // flag all the groups as the user requested. - if (!_flag_groups.empty()) { - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - do_flag_groups(*ei); - } - } - - // Add the AnimPreload entries. - if (_preload) { - do_preload(); - } - - - // Finally, set the default poses. It's important not to do this until - // after we have adjusted all of the transforms for the various joints. - if (!_defpose.empty()) { - do_defpose(); - } - - if (!_dart_type.empty()) { - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - change_dart_type(*ei, _dart_type); - } - } - - write_eggs(); - } -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggOptchar:: -handle_args(ProgramBase::Args &args) { - if (_list_hierarchy || _list_hierarchy_v || _list_hierarchy_p) { - _read_only = true; - } - - return EggCharacterFilter::handle_args(args); -} - -/** - * Standard dispatch function for an option that takes a pair of string - * parameters. The data pointer is to StringPairs vector; the pair will be - * pushed onto the end of the vector. - */ -bool EggOptchar:: -dispatch_vector_string_pair(const string &opt, const string &arg, void *var) { - StringPairs *ip = (StringPairs *)var; - - vector_string words; - tokenize(arg, words, ","); - - if (words.size() == 2) { - StringPair sp; - sp._a = words[0]; - sp._b = words[1]; - ip->push_back(sp); - - } else { - nout << "-" << opt - << " requires a pair of strings separated by a comma.\n"; - return false; - } - - return true; -} - -/** - * Accepts a name optionally followed by a comma and some of the nine standard - * component letters, - * - * The data pointer is to StringPairs vector; the pair will be pushed onto the - * end of the vector. - */ -bool EggOptchar:: -dispatch_name_components(const string &opt, const string &arg, void *var) { - StringPairs *ip = (StringPairs *)var; - - vector_string words; - tokenize(arg, words, ","); - - StringPair sp; - if (words.size() == 1) { - sp._a = words[0]; - - } else if (words.size() == 2) { - sp._a = words[0]; - sp._b = words[1]; - - } else { - nout << "-" << opt - << " requires a pair of strings separated by a comma.\n"; - return false; - } - - if (sp._b.empty()) { - sp._b = matrix_component_letters; - } else { - for (string::const_iterator si = sp._b.begin(); si != sp._b.end(); ++si) { - if (strchr(matrix_component_letters, *si) == nullptr) { - nout << "Not a standard matrix component: \"" << *si << "\"\n" - << "-" << opt << " requires a joint name followed by a set " - << "of component names. The standard component names are \"" - << matrix_component_letters << "\".\n"; - return false; - } - } - } - - ip->push_back(sp); - - return true; -} - -/** - * Accepts a double value optionally followed by a comma and some of the nine - * standard component letters, - * - * The data pointer is to a DoubleStrings vector; the pair will be pushed onto - * the end of the vector. - */ -bool EggOptchar:: -dispatch_double_components(const string &opt, const string &arg, void *var) { - DoubleStrings *ip = (DoubleStrings *)var; - - vector_string words; - tokenize(arg, words, ","); - - bool valid_double = false; - - DoubleString sp; - if (words.size() == 1) { - valid_double = string_to_double(words[0], sp._a); - - } else if (words.size() == 2) { - valid_double = string_to_double(words[0], sp._a); - sp._b = words[1]; - - } else { - nout << "-" << opt - << " requires a numeric value followed by a string.\n"; - return false; - } - - if (!valid_double) { - nout << "-" << opt - << " requires a numeric value followed by a string.\n"; - return false; - } - - if (sp._b.empty()) { - sp._b = matrix_component_letters; - } else { - for (string::const_iterator si = sp._b.begin(); si != sp._b.end(); ++si) { - if (strchr(matrix_component_letters, *si) == nullptr) { - nout << "Not a standard matrix component: \"" << *si << "\"\n" - << "-" << opt << " requires a joint name followed by a set " - << "of component names. The standard component names are \"" - << matrix_component_letters << "\".\n"; - return false; - } - } - } - - ip->push_back(sp); - - return true; -} - -/** - * Accepts a set of comma-delimited group names followed by an optional name - * separated with an equal sign. - * - * The data pointer is to a FlagGroups object. - */ -bool EggOptchar:: -dispatch_flag_groups(const string &opt, const string &arg, void *var) { - FlagGroups *ip = (FlagGroups *)var; - - vector_string words; - - tokenize(arg, words, ","); - - if (words.empty()) { - nout << "-" << opt - << " requires a series of words separated by a comma.\n"; - return false; - } - - FlagGroupsEntry entry; - - // Check for an equal sign in the last word. This marks the name to assign. - string &last_word = words.back(); - size_t equals = last_word.rfind('='); - if (equals != string::npos) { - entry._name = last_word.substr(equals + 1); - last_word = last_word.substr(0, equals); - - } else { - // If there's no equal sign, the default is to name all groups after the - // group itself. We leave the name empty to indicate that. - } - - // Convert the words to GlobPatterns. - vector_string::const_iterator si; - for (si = words.begin(); si != words.end(); ++si) { - const string &word = (*si); - entry._groups.push_back(GlobPattern(word)); - } - - ip->push_back(entry); - - return true; -} - -/** - * Flag all joints and sliders that should be removed for optimization - * purposes. - */ -void EggOptchar:: -determine_removed_components() { - typedef pset Names; - Names keep_names; - Names drop_names; - Names expose_names; - Names suppress_names; - Names names_used; - - vector_string::const_iterator si; - for (si = _keep_components.begin(); si != _keep_components.end(); ++si) { - keep_names.insert(*si); - } - for (si = _drop_components.begin(); si != _drop_components.end(); ++si) { - drop_names.insert(*si); - } - for (si = _expose_components.begin(); si != _expose_components.end(); ++si) { - keep_names.insert(*si); - expose_names.insert(*si); - } - for (si = _suppress_components.begin(); si != _suppress_components.end(); ++si) { - suppress_names.insert(*si); - } - - // We always keep the root joint, which has no name. - keep_names.insert(""); - - int num_characters = _collection->get_num_characters(); - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - int num_components = char_data->get_num_components(); - nout << char_data->get_name() << " has " << num_components << " components.\n"; - for (int i = 0; i < num_components; i++) { - EggComponentData *comp_data = char_data->get_component(i); - nassertv(comp_data != nullptr); - - EggOptcharUserData *user_data = - DCAST(EggOptcharUserData, comp_data->get_user_data()); - nassertv(user_data != nullptr); - - const string &name = comp_data->get_name(); - if (suppress_names.find(name) != suppress_names.end()) { - // If this component is not dropped, it will not be implicitly - // exposed. - names_used.insert(name); - user_data->_flags |= EggOptcharUserData::F_suppress; - } - - if (drop_names.find(name) != drop_names.end()) { - // Remove this component by user request. - names_used.insert(name); - user_data->_flags |= EggOptcharUserData::F_remove; - - } else if (_keep_all || keep_names.find(name) != keep_names.end()) { - // Keep this component. - names_used.insert(name); - - if (expose_names.find(name) != expose_names.end()) { - // In fact, expose it. - user_data->_flags |= EggOptcharUserData::F_expose; - } - - } else { - // Remove this component if it's unanimated or empty. - if ((user_data->_flags & (EggOptcharUserData::F_static | EggOptcharUserData::F_empty)) != 0) { - if ((user_data->_flags & (EggOptcharUserData::F_top | EggOptcharUserData::F_empty)) == EggOptcharUserData::F_top) { - // Actually, we can't remove it if it's a top joint, unless it's - // also empty. That's because vertices that are partially - // assigned to this joint would then have no joint to represent - // the same partial assignment, and they would then appear to be - // wholly assigned to their other joint, which would be incorrect. - - } else { - // But joints that aren't top joints (or that are empty) are o.k. - // to remove. - user_data->_flags |= EggOptcharUserData::F_remove; - } - } - } - } - } - - // Go back and tell the user about component names we didn't use, just to be - // helpful. - for (si = _keep_components.begin(); si != _keep_components.end(); ++si) { - const string &name = (*si); - if (names_used.find(name) == names_used.end()) { - nout << "No such component: " << name << "\n"; - } - } - for (si = _drop_components.begin(); si != _drop_components.end(); ++si) { - const string &name = (*si); - if (names_used.find(name) == names_used.end()) { - nout << "No such component: " << name << "\n"; - } - } - for (si = _expose_components.begin(); si != _expose_components.end(); ++si) { - const string &name = (*si); - if (names_used.find(name) == names_used.end()) { - nout << "No such component: " << name << "\n"; - } - } - for (si = _suppress_components.begin(); si != _suppress_components.end(); ++si) { - const string &name = (*si); - if (names_used.find(name) == names_used.end()) { - nout << "No such component: " << name << "\n"; - } - } -} - -/** - * Moves the vertices from joints that are about to be removed into the first - * suitable parent. This might result in fewer joints being removed (because - * the parent might suddenly no longer be empty). - */ -void EggOptchar:: -move_vertices() { - int num_characters = _collection->get_num_characters(); - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - int num_joints = char_data->get_num_joints(); - - for (int i = 0; i < num_joints; i++) { - EggJointData *joint_data = char_data->get_joint(i); - EggOptcharUserData *user_data = - DCAST(EggOptcharUserData, joint_data->get_user_data()); - - if ((user_data->_flags & EggOptcharUserData::F_empty) == 0 && - (user_data->_flags & EggOptcharUserData::F_remove) != 0) { - // This joint has vertices, but is scheduled to be removed; find a - // suitable home for its vertices. - EggJointData *best_joint = find_best_vertex_joint(joint_data->get_parent()); - joint_data->move_vertices_to(best_joint); - - // Now we can't remove the joint. - if (best_joint != nullptr) { - EggOptcharUserData *best_user_data = - DCAST(EggOptcharUserData, best_joint->get_user_data()); - best_user_data->_flags &= ~(EggOptcharUserData::F_empty | EggOptcharUserData::F_remove); - } - } - } - } -} - - -/** - * Effects the actual removal of joints flagged for removal by reparenting the - * hierarchy appropriately. Returns true if any joints are removed, false - * otherwise. - */ -bool EggOptchar:: -process_joints() { - bool removed_any = false; - int num_characters = _collection->get_num_characters(); - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - int num_joints = char_data->get_num_joints(); - - int num_static = 0; - int num_empty = 0; - int num_identity = 0; - int num_other = 0; - int num_kept = 0; - - for (int i = 0; i < num_joints; i++) { - EggJointData *joint_data = char_data->get_joint(i); - EggOptcharUserData *user_data = - DCAST(EggOptcharUserData, joint_data->get_user_data()); - - if ((user_data->_flags & EggOptcharUserData::F_remove) != 0) { - // This joint will be removed, so reparent it to nothing. - joint_data->reparent_to(nullptr); - - // Determine what kind of node it is we're removing, for the user's - // information. - if ((user_data->_flags & EggOptcharUserData::F_identity) != 0) { - num_identity++; - } else if ((user_data->_flags & EggOptcharUserData::F_static) != 0) { - num_static++; - } else if ((user_data->_flags & EggOptcharUserData::F_empty) != 0) { - num_empty++; - } else { - num_other++; - } - removed_any = true; - - } else { - // This joint will be preserved, but maybe its parent will change. - EggJointData *best_parent = find_best_parent(joint_data->get_parent()); - joint_data->reparent_to(best_parent); - if ((user_data->_flags & EggOptcharUserData::F_expose) != 0) { - joint_data->expose(); - } else if ((user_data->_flags & EggOptcharUserData::F_suppress) != 0) { - joint_data->expose(EggGroup::DC_none); - } - num_kept++; - } - } - - if (num_joints == num_kept) { - nout << char_data->get_name() << ": keeping " << num_joints - << " joints.\n"; - } else { - nout << setw(5) << num_joints - << " original joints in " << char_data->get_name() - << "\n"; - if (num_identity != 0) { - nout << setw(5) << num_identity << " identity joints\n"; - } - if (num_static != 0) { - nout << setw(5) << num_static << " unanimated joints\n"; - } - if (num_empty != 0) { - nout << setw(5) << num_empty << " empty joints\n"; - } - if (num_other != 0) { - nout << setw(5) << num_other << " other joints\n"; - } - nout << " ----\n" - << setw(5) << num_kept << " joints remaining\n\n"; - } - } - - return removed_any; -} - -/** - * Searches for the first joint at this level or above that is not scheduled - * to be removed. This is the joint that the first child of this joint should - * be reparented to. - */ -EggJointData *EggOptchar:: -find_best_parent(EggJointData *joint_data) const { - EggOptcharUserData *user_data = - DCAST(EggOptcharUserData, joint_data->get_user_data()); - - if ((user_data->_flags & EggOptcharUserData::F_remove) != 0) { - // Keep going. - if (joint_data->get_parent() != nullptr) { - return find_best_parent(joint_data->get_parent()); - } - } - - // This is the one! - return joint_data; -} - -/** - * Searches for the first joint at this level or above that is not static. - * This is the joint that the vertices of this joint should be moved into. - */ -EggJointData *EggOptchar:: -find_best_vertex_joint(EggJointData *joint_data) const { - if (joint_data == nullptr) { - return nullptr; - } - - EggOptcharUserData *user_data = - DCAST(EggOptcharUserData, joint_data->get_user_data()); - - if ((user_data->_flags & EggOptcharUserData::F_static) != 0) { - // Keep going. - return find_best_vertex_joint(joint_data->get_parent()); - } - - // This is the one! - return joint_data; -} - -/** - * Reparents all the joints that the user suggested on the command line. - * Returns true if any operations were performed, false otherwise. - */ -bool EggOptchar:: -apply_user_reparents() { - bool did_anything = false; - - int num_characters = _collection->get_num_characters(); - - // First, get the new joints. - StringPairs::const_iterator spi; - for (spi = _new_joints.begin(); spi != _new_joints.end(); ++spi) { - const StringPair &p = (*spi); - - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - EggJointData *node_a = char_data->find_joint(p._a); - EggJointData *node_b = char_data->get_root_joint(); - if (!p._b.empty()) { - node_b = char_data->find_joint(p._b); - } - - if (node_b == nullptr) { - nout << "No joint named " << p._b << " in " << char_data->get_name() - << ".\n"; - - } else if (node_a != nullptr) { - nout << "Joint " << p._a << " already exists in " - << char_data->get_name() << ".\n"; - - } else { - nout << "Creating new joint " << p._a << " in " - << char_data->get_name() << ".\n"; - node_a = char_data->make_new_joint(p._a, node_b); - did_anything = true; - } - } - } - - // Now get the user reparents. - for (spi = _reparent_joints.begin(); spi != _reparent_joints.end(); ++spi) { - const StringPair &p = (*spi); - - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - EggJointData *node_a = char_data->find_joint(p._a); - EggJointData *node_b = char_data->get_root_joint(); - if (!p._b.empty()) { - node_b = char_data->find_joint(p._b); - } - - if (node_b == nullptr) { - nout << "No joint named " << p._b << " in " << char_data->get_name() - << ".\n"; - } else if (node_a == nullptr) { - nout << "No joint named " << p._a << " in " << char_data->get_name() - << ".\n"; - } else { - node_a->reparent_to(node_b); - did_anything = true; - } - } - } - - if (_optimal_hierarchy) { - did_anything = true; - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - nout << "Computing optimal hierarchy for " - << char_data->get_name() << ".\n"; - char_data->choose_optimal_hierarchy(); - nout << "Done computing optimal hierarchy for " - << char_data->get_name() << ".\n"; - } - } - - return did_anything; -} - -/** - * Zeroes out the channels specified by the user on the command line. - * - * Returns true if any operation was performed, false otherwise. - */ -bool EggOptchar:: -zero_channels() { - bool did_anything = false; - int num_characters = _collection->get_num_characters(); - - StringPairs::const_iterator spi; - for (spi = _zero_channels.begin(); spi != _zero_channels.end(); ++spi) { - const StringPair &p = (*spi); - - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - EggJointData *joint_data = char_data->find_joint(p._a); - - if (joint_data == nullptr) { - nout << "No joint named " << p._a << " in " << char_data->get_name() - << ".\n"; - } else { - joint_data->zero_channels(p._b); - did_anything = true; - } - } - } - - return did_anything; -} - -/** - * Quantizes the channels specified by the user on the command line. - * - * Returns true if any operation was performed, false otherwise. - */ -bool EggOptchar:: -quantize_channels() { - bool did_anything = false; - int num_characters = _collection->get_num_characters(); - - DoubleStrings::const_iterator spi; - for (spi = _quantize_anims.begin(); spi != _quantize_anims.end(); ++spi) { - const DoubleString &p = (*spi); - - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - EggJointData *joint_data = char_data->get_root_joint(); - - if (joint_data != nullptr) { - joint_data->quantize_channels(p._b, p._a); - did_anything = true; - } - } - } - - return did_anything; -} - -/** - * Recursively walks the joint hierarchy for a particular character, - * indentifying properties of each joint. - */ -void EggOptchar:: -analyze_joints(EggJointData *joint_data, int level) { - PT(EggOptcharUserData) user_data = new EggOptcharUserData; - joint_data->set_user_data(user_data); - - if (level == 1) { - // The child joints of the root joint are deemed "top" joints. These may - // not be removed unless they are empty (because their vertices have no - // joint to be moved into). - user_data->_flags |= EggOptcharUserData::F_top; - } - - // Analyze the table of matrices for this joint, checking to see if they're - // all the same across all frames, or if any of them are different; also - // look for empty joints (that control no vertices). - int num_mats = 0; - bool different_mat = false; - bool has_vertices = false; - - int num_models = joint_data->get_num_models(); - int i; - for (i = 0; i < num_models; i++) { - if (joint_data->has_model(i)) { - EggBackPointer *model = joint_data->get_model(i); - if (model->has_vertices()) { - has_vertices = true; - } - - int num_frames = joint_data->get_num_frames(i); - - int f; - for (f = 0; f < num_frames && !different_mat; f++) { - LMatrix4d mat = joint_data->get_frame(i, f); - num_mats++; - if (num_mats == 1) { - // This is the first matrix. - user_data->_static_mat = mat; - - } else { - // This is a second or later matrix. - if (!mat.almost_equal(user_data->_static_mat, 0.0001)) { - // It's different than the first one. - different_mat = true; - } - } - } - } - } - - if (!different_mat) { - // All the mats are the same for this joint. - user_data->_flags |= EggOptcharUserData::F_static; - - if (num_mats == 0 || - user_data->_static_mat.almost_equal(LMatrix4d::ident_mat(), 0.0001)) { - // It's not only static, but it's the identity matrix. - user_data->_flags |= EggOptcharUserData::F_identity; - } - } - - if (!has_vertices) { - // There are no vertices in this joint. - user_data->_flags |= EggOptcharUserData::F_empty; - } - - int num_children = joint_data->get_num_children(); - for (i = 0; i < num_children; i++) { - analyze_joints(joint_data->get_child(i), level + 1); - } -} - -/** - * Linearly walks the slider list for a particular character, indentifying - * properties of each slider. - */ -void EggOptchar:: -analyze_sliders(EggCharacterData *char_data) { - int num_sliders = char_data->get_num_sliders(); - for (int si = 0; si < num_sliders; si++) { - EggSliderData *slider_data = char_data->get_slider(si); - - PT(EggOptcharUserData) user_data = new EggOptcharUserData; - slider_data->set_user_data(user_data); - - // Analyze the table of values for this slider, checking to see if they're - // all the same across all frames, or if any of them are different; also - // look for empty sliders (that control no vertices). - int num_values = 0; - bool different_value = false; - bool has_vertices = false; - - int num_models = slider_data->get_num_models(); - for (int i = 0; i < num_models; i++) { - if (slider_data->has_model(i)) { - EggBackPointer *model = slider_data->get_model(i); - if (model->has_vertices()) { - has_vertices = true; - } - - int num_frames = slider_data->get_num_frames(i); - - int f; - for (f = 0; f < num_frames && !different_value; f++) { - double value = slider_data->get_frame(i, f); - num_values++; - if (num_values == 1) { - // This is the first value. - user_data->_static_value = value; - - } else { - // This is a second or later value. - if (!IS_THRESHOLD_EQUAL(value, user_data->_static_value, 0.0001)) { - // It's different than the first one. - different_value = true; - } - } - } - } - } - - if (!different_value) { - // All the values are the same for this slider. - user_data->_flags |= EggOptcharUserData::F_static; - - if (num_values == 0 || IS_THRESHOLD_ZERO(user_data->_static_value, 0.0001)) { - // It's not only static, but it's the identity value. - user_data->_flags |= EggOptcharUserData::F_identity; - } - } - - if (!has_vertices) { - // There are no vertices in this slider. - user_data->_flags |= EggOptcharUserData::F_empty; - } - } -} - -/** - * Outputs a list of the joint hierarchy. - */ -void EggOptchar:: -list_joints(EggJointData *joint_data, int indent_level, bool verbose) { - // Don't list the root joint, which is artificially created when the - // character is loaded. Instead, list each child as it is encountered. - - int num_children = joint_data->get_num_children(); - for (int i = 0; i < num_children; i++) { - EggJointData *child_data = joint_data->get_child(i); - describe_component(child_data, indent_level, verbose); - - list_joints(child_data, indent_level + 2, verbose); - } -} - -/** - * Outputs a list of the joint hierarchy as a series of -p joint,parent - * commands. - */ -void EggOptchar:: -list_joints_p(EggJointData *joint_data, int &col) { - // As above, don't list the root joint. - - int num_children = joint_data->get_num_children(); - static const int max_col = 72; - - for (int i = 0; i < num_children; i++) { - EggJointData *child_data = joint_data->get_child(i); - // We send output to cout instead of nout to avoid the word-wrapping, and - // also to allow the user to redirect this easily to a file. - - string text = string(" -p ") + child_data->get_name() + - string(",") + joint_data->get_name(); - if (col == 0) { - cout << " " << text; - col = 4 + text.length(); - } else { - col += text.length(); - if (col >= max_col) { - cout << " \\\n " << text; - col = 4 + text.length(); - } else { - cout << text; - } - } - - list_joints_p(child_data, col); - } -} - -/** - * Outputs a list of the scalars. - */ -void EggOptchar:: -list_scalars(EggCharacterData *char_data, bool verbose) { - int num_sliders = char_data->get_num_sliders(); - for (int si = 0; si < num_sliders; si++) { - EggSliderData *slider_data = char_data->get_slider(si); - describe_component(slider_data, 0, verbose); - } -} - -/** - * Describes one particular slider or joint. - */ -void EggOptchar:: -describe_component(EggComponentData *comp_data, int indent_level, - bool verbose) { - // We use cout instead of nout so the user can easily redirect this to a - // file. - indent(cout, indent_level) - << comp_data->get_name(); - - if (verbose) { - EggOptcharUserData *user_data = - DCAST(EggOptcharUserData, comp_data->get_user_data()); - if (user_data->is_identity()) { - cout << " (identity)"; - } else if (user_data->is_static()) { - cout << " (static)"; - } - if (user_data->is_empty()) { - cout << " (empty)"; - } - if (user_data->is_top()) { - cout << " (top)"; - } - } - cout << "\n"; -} - -/** - * Performs all of the queued up reparenting operations. - */ -void EggOptchar:: -do_reparent() { - bool all_ok = true; - - int num_characters = _collection->get_num_characters(); - for (int ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - if (!char_data->do_reparent()) { - all_ok = false; - } - } - - if (!all_ok) { - exit(1); - } -} - -/** - * Walks through all of the loaded egg files, looking for vertices whose joint - * memberships are then quantized according to _vref_quantum. - */ -void EggOptchar:: -quantize_vertices() { - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - quantize_vertices(*ei); - } -} - -/** - * Recursively walks through the indicated egg hierarchy, looking for vertices - * whose joint memberships are then quantized according to _vref_quantum. - */ -void EggOptchar:: -quantize_vertices(EggNode *egg_node) { - if (egg_node->is_of_type(EggVertexPool::get_class_type())) { - EggVertexPool *vpool = DCAST(EggVertexPool, egg_node); - EggVertexPool::iterator vi; - for (vi = vpool->begin(); vi != vpool->end(); ++vi) { - quantize_vertex(*vi); - } - - } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, egg_node); - EggGroupNode::iterator ci; - for (ci = group->begin(); ci != group->end(); ++ci) { - quantize_vertices(*ci); - } - } -} - -/** - * Quantizes the indicated vertex's joint membership. - */ -void EggOptchar:: -quantize_vertex(EggVertex *egg_vertex) { - if (egg_vertex->gref_size() == 0) { - // Never mind on this vertex. - return; - } - - // First, get a copy of the existing membership. - VertexMemberships memberships; - EggVertex::GroupRef::const_iterator gi; - double net_membership = 0.0; - for (gi = egg_vertex->gref_begin(); gi != egg_vertex->gref_end(); ++gi) { - EggGroup *group = (*gi); - double membership = group->get_vertex_membership(egg_vertex); - memberships.push_back(VertexMembership(group, membership)); - net_membership += membership; - } - nassertv(net_membership != 0.0); - - // Now normalize all the memberships so the net membership is 1.0, and then - // quantize the result (if the user so requested). - double factor = 1.0 / net_membership; - net_membership = 0.0; - VertexMemberships::iterator mi; - VertexMemberships::iterator largest = memberships.begin(); - - for (mi = memberships.begin(); mi != memberships.end(); ++mi) { - if ((*largest) < (*mi)) { - // Remember the largest membership value, so we can readjust it at the - // end. - largest = mi; - } - - double value = (*mi)._membership * factor; - if (_vref_quantum != 0.0) { - value = floor(value / _vref_quantum + 0.5) * _vref_quantum; - } - (*mi)._membership = value; - - net_membership += value; - } - - // The the largest membership value gets corrected again by the roundoff - // error. - (*largest)._membership += 1.0 - net_membership; - - // Finally, walk back through and apply these computed values to the vertex. - for (mi = memberships.begin(); mi != memberships.end(); ++mi) { - (*mi)._group->set_vertex_membership(egg_vertex, (*mi)._membership); - } -} - -/** - * Recursively walks the indicated egg hierarchy, looking for groups that - * match one of the group names in _flag_groups, and renaming geometry - * appropriately. - */ -void EggOptchar:: -do_flag_groups(EggGroupNode *egg_group) { - bool matched = false; - string name; - FlagGroups::const_iterator fi; - for (fi = _flag_groups.begin(); - fi != _flag_groups.end() && !matched; - ++fi) { - const FlagGroupsEntry &entry = (*fi); - Globs::const_iterator si; - for (si = entry._groups.begin(); - si != entry._groups.end() && !matched; - ++si) { - if ((*si).matches(egg_group->get_name())) { - matched = true; - if (!entry._name.empty()) { - name = entry._name; - } else { - name = egg_group->get_name(); - } - } - } - } - - if (matched) { - // Ok, this group matched one of the user's command-line renames. Rename - // all the primitives in this group and below to the indicated name; this - // will expose the primitives through the character loader. - rename_primitives(egg_group, name); - } - - // Now recurse on children. - EggGroupNode::iterator gi; - for (gi = egg_group->begin(); gi != egg_group->end(); ++gi) { - EggNode *child = (*gi); - if (child->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, child); - do_flag_groups(group); - } - } -} - -/** - * Rename all the joints named with the -rename command-line option. - */ -void EggOptchar:: -rename_joints() { - for (StringPairs::iterator spi = _rename_joints.begin(); - spi != _rename_joints.end(); - ++spi) { - const StringPair &sp = (*spi); - int num_characters = _collection->get_num_characters(); - int ci; - for (ci = 0; ci < num_characters; ++ci) { - EggCharacterData *char_data = _collection->get_character(ci); - EggJointData *joint = char_data->find_joint(sp._a); - if (joint != nullptr) { - nout << "Renaming joint " << sp._a << " to " << sp._b << "\n"; - joint->set_name(sp._b); - - int num_models = joint->get_num_models(); - for (int mn = 0; mn < num_models; ++mn) { - if (joint->has_model(mn)) { - EggBackPointer *model = joint->get_model(mn); - model->set_name(sp._b); - } - } - - } else { - nout << "Couldn't find joint " << sp._a << "\n"; - } - } - } -} - -/** - * Recursively walks the indicated egg hierarchy, renaming geometry to the - * indicated name. - */ -void EggOptchar:: -change_dart_type(EggGroupNode *egg_group, const string &new_dart_type) { - EggGroupNode::iterator gi; - for (gi = egg_group->begin(); gi != egg_group->end(); ++gi) { - EggNode *child = (*gi); - if (child->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, child); - if (child->is_of_type(EggGroup::get_class_type())) { - EggGroup *gr = DCAST(EggGroup, child); - EggGroup::DartType dt = gr->get_dart_type(); - if(dt != EggGroup::DT_none) { - EggGroup::DartType newDt = gr->string_dart_type(new_dart_type); - gr->set_dart_type(newDt); - } - } - change_dart_type(group, new_dart_type); - } - } -} - - -/** - * Recursively walks the indicated egg hierarchy, renaming geometry to the - * indicated name. - */ -void EggOptchar:: -rename_primitives(EggGroupNode *egg_group, const string &name) { - EggGroupNode::iterator gi; - for (gi = egg_group->begin(); gi != egg_group->end(); ++gi) { - EggNode *child = (*gi); - - if (child->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, child); - rename_primitives(group, name); - - } else if (child->is_of_type(EggPrimitive::get_class_type())) { - child->set_name(name); - } - } -} - -/** - * Generates the preload tables for each model. - */ -void EggOptchar:: -do_preload() { - // First, build up the list of AnimPreload entries, one for each animation - // file. - PT(EggGroup) anim_group = new EggGroup("preload"); - - int num_characters = _collection->get_num_characters(); - int ci; - for (ci = 0; ci < num_characters; ++ci) { - EggCharacterData *char_data = _collection->get_character(ci); - - int num_models = char_data->get_num_models(); - for (int mn = 0; mn < num_models; ++mn) { - EggNode *root = char_data->get_model_root(mn); - if (root->is_of_type(EggTable::get_class_type())) { - // This model represents an animation. - EggData *data = char_data->get_egg_data(mn); - string basename = data->get_egg_filename().get_basename_wo_extension(); - PT(EggAnimPreload) anim_preload = new EggAnimPreload(basename); - - int mi = char_data->get_model_index(mn); - anim_preload->set_num_frames(char_data->get_num_frames(mi)); - double frame_rate = char_data->get_frame_rate(mi); - if (frame_rate != 0.0) { - anim_preload->set_fps(frame_rate); - } - - anim_group->add_child(anim_preload); - } - } - } - - // Now go back through and copy the preload tables into each of the model - // files. - for (ci = 0; ci < num_characters; ++ci) { - EggCharacterData *char_data = _collection->get_character(ci); - - int num_models = char_data->get_num_models(); - for (int mn = 0; mn < num_models; ++mn) { - EggNode *root = char_data->get_model_root(mn); - if (root->is_of_type(EggGroup::get_class_type())) { - // This is a model file. Copy in the table. - EggGroup *model_root = DCAST(EggGroup, root); - EggGroup::const_iterator ci; - for (ci = anim_group->begin(); ci != anim_group->end(); ++ci) { - EggAnimPreload *anim_preload = DCAST(EggAnimPreload, *ci); - PT(EggAnimPreload) new_anim_preload = new EggAnimPreload(*anim_preload); - model_root->add_child(new_anim_preload); - } - } - } - } -} - -/** - * Sets the initial pose for the character(s). - */ -void EggOptchar:: -do_defpose() { - // Split out the defpose parameter. - Filename egg_filename; - size_t comma = _defpose.find(','); - egg_filename = _defpose.substr(0, comma); - - string frame_str; - if (comma != string::npos) { - frame_str = _defpose.substr(comma + 1); - } - frame_str = trim(frame_str); - int frame = 0; - if (!frame_str.empty()) { - if (!string_to_int(frame_str, frame)) { - nout << "Invalid integer in -defpose: " << frame_str << "\n"; - return; - } - } - - // Now find the named animation file in our egg list. - int egg_index = -1; - int num_eggs = _collection->get_num_eggs(); - int i; - - // First, look for an exact match. - for (i = 0; i < num_eggs && egg_index == -1; ++i) { - if (_collection->get_egg(i)->get_egg_filename() == egg_filename) { - egg_index = i; - } - } - - // Then, look for an inexact match. - string egg_basename = egg_filename.get_basename_wo_extension(); - for (i = 0; i < num_eggs && egg_index == -1; ++i) { - if (_collection->get_egg(i)->get_egg_filename().get_basename_wo_extension() == egg_basename) { - egg_index = i; - } - } - - if (egg_index == -1) { - // No joy. - nout << "Egg file " << egg_filename << " named in -defpose, but does not appear on command line.\n"; - return; - } - - EggData *egg_data = _collection->get_egg(egg_index); - - if (_collection->get_num_models(egg_index) == 0) { - nout << "Egg file " << egg_filename << " does not include any model or animation.\n"; - return; - } - - // Now get the first model (or animation) named by this egg file. - int mi = _collection->get_first_model_index(egg_index); - EggCharacterData *ch = _collection->get_character_by_model_index(mi); - EggJointData *root_joint = ch->get_root_joint(); - - int anim_index = -1; - for (i = 0; i < ch->get_num_models() && anim_index == -1; ++i) { - if (ch->get_egg_data(i) == egg_data) { - anim_index = i; - } - } - - // This couldn't possibly fail, since we already checked this above. - nassertv(anim_index != -1); - - // Now we can recursively apply the default pose to the hierarchy. - root_joint->apply_default_pose(anim_index, frame); -} - -int main(int argc, char *argv[]) { - EggOptchar prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/egg-optchar/eggOptchar.h b/pandatool/src/egg-optchar/eggOptchar.h deleted file mode 100644 index 30ea4cdd..00000000 --- a/pandatool/src/egg-optchar/eggOptchar.h +++ /dev/null @@ -1,129 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggOptchar.h - * @author drose - * @date 2003-07-18 - */ - -#ifndef EGGOPTCHAR_H -#define EGGOPTCHAR_H - -#include "pandatoolbase.h" - -#include "eggCharacterFilter.h" -#include "luse.h" - -#include "pvector.h" -#include "vector_string.h" -#include "globPattern.h" - -class EggCharacterData; -class EggComponentData; -class EggJointData; -class EggSliderData; -class EggGroupNode; - -/** - * Performs basic optimizations of a character model and its associated - * animations, by analyzing the animation tables and removing unneeded joints - * and/or morphs. Can also be used to restructure the character hierarchy. - */ -class EggOptchar : public EggCharacterFilter { -public: - EggOptchar(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - -private: - static bool dispatch_vector_string_pair(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_name_components(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_double_components(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_flag_groups(const std::string &opt, const std::string &arg, void *var); - - void determine_removed_components(); - void move_vertices(); - bool process_joints(); - EggJointData *find_best_parent(EggJointData *joint_data) const; - EggJointData *find_best_vertex_joint(EggJointData *joint_data) const; - - bool apply_user_reparents(); - bool zero_channels(); - bool quantize_channels(); - void analyze_joints(EggJointData *joint_data, int level); - void analyze_sliders(EggCharacterData *char_data); - void list_joints(EggJointData *joint_data, int indent_level, bool verbose); - void list_joints_p(EggJointData *joint_data, int &col); - void list_scalars(EggCharacterData *char_data, bool verbose); - void describe_component(EggComponentData *comp_data, int indent_level, - bool verbose); - void do_reparent(); - - void quantize_vertices(); - void quantize_vertices(EggNode *egg_node); - void quantize_vertex(EggVertex *egg_vertex); - - void do_flag_groups(EggGroupNode *egg_group); - void rename_joints(); - void rename_primitives(EggGroupNode *egg_group, const std::string &name); - void change_dart_type(EggGroupNode *egg_group, const std::string &new_dart_type); - void do_preload(); - void do_defpose(); - - bool _list_hierarchy; - bool _list_hierarchy_v; - bool _list_hierarchy_p; - bool _preload; - bool _keep_all; - - class StringPair { - public: - std::string _a; - std::string _b; - }; - typedef pvector StringPairs; - StringPairs _new_joints; - StringPairs _reparent_joints; - StringPairs _zero_channels; - StringPairs _rename_joints; - - vector_string _keep_components; - vector_string _drop_components; - vector_string _expose_components; - vector_string _suppress_components; - - std::string _dart_type; - - class DoubleString { - public: - double _a; - std::string _b; - }; - typedef pvector DoubleStrings; - DoubleStrings _quantize_anims; - - typedef pvector Globs; - - class FlagGroupsEntry { - public: - Globs _groups; - std::string _name; - }; - typedef pvector FlagGroups; - FlagGroups _flag_groups; - - std::string _defpose; - - bool _optimal_hierarchy; - double _vref_quantum; -}; - -#endif diff --git a/pandatool/src/egg-optchar/eggOptcharUserData.I b/pandatool/src/egg-optchar/eggOptcharUserData.I deleted file mode 100644 index 47f71ac4..00000000 --- a/pandatool/src/egg-optchar/eggOptcharUserData.I +++ /dev/null @@ -1,79 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggOptcharUserData.I - * @author drose - * @date 2003-07-18 - */ - -/** - * - */ -INLINE EggOptcharUserData:: -EggOptcharUserData() { - _flags = 0; - _static_mat = LMatrix4d::ident_mat(); - _static_value = 0.0; -} - - -/** - * - */ -INLINE EggOptcharUserData:: -EggOptcharUserData(const EggOptcharUserData ©) : - EggUserData(copy), - _flags(copy._flags), - _static_mat(copy._static_mat), - _static_value(copy._static_value) -{ -} - - -/** - * - */ -INLINE void EggOptcharUserData:: -operator = (const EggOptcharUserData ©) { - EggUserData::operator = (copy); - _flags = copy._flags; - _static_mat = copy._static_mat; - _static_value = copy._static_value; -} - -/** - * - */ -INLINE bool EggOptcharUserData:: -is_static() const { - return (_flags & F_static) != 0; -} - -/** - * - */ -INLINE bool EggOptcharUserData:: -is_identity() const { - return (_flags & F_identity) != 0; -} - -/** - * - */ -INLINE bool EggOptcharUserData:: -is_empty() const { - return (_flags & F_empty) != 0; -} - -/** - * - */ -INLINE bool EggOptcharUserData:: -is_top() const { - return (_flags & F_top) != 0; -} diff --git a/pandatool/src/egg-optchar/eggOptcharUserData.cxx b/pandatool/src/egg-optchar/eggOptcharUserData.cxx deleted file mode 100644 index ecb6b32c..00000000 --- a/pandatool/src/egg-optchar/eggOptcharUserData.cxx +++ /dev/null @@ -1,16 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggOptcharUserData.cxx - * @author drose - * @date 2003-07-18 - */ - -#include "eggOptcharUserData.h" - -TypeHandle EggOptcharUserData::_type_handle; diff --git a/pandatool/src/egg-optchar/eggOptcharUserData.h b/pandatool/src/egg-optchar/eggOptcharUserData.h deleted file mode 100644 index 2f12aae9..00000000 --- a/pandatool/src/egg-optchar/eggOptcharUserData.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggOptcharUserData.h - * @author drose - * @date 2003-07-18 - */ - -#ifndef EGGOPTCHARUSERDATA_H -#define EGGOPTCHARUSERDATA_H - -#include "pandatoolbase.h" -#include "eggUserData.h" -#include "luse.h" - -/** - * This class contains extra user data which is piggybacked onto EggGroup - * objects for the purpose of the maya converter. - */ -class EggOptcharUserData : public EggUserData { -public: - INLINE EggOptcharUserData(); - INLINE EggOptcharUserData(const EggOptcharUserData ©); - INLINE void operator = (const EggOptcharUserData ©); - - INLINE bool is_static() const; - INLINE bool is_identity() const; - INLINE bool is_empty() const; - INLINE bool is_top() const; - - enum Flags { - F_static = 0x0001, - F_identity = 0x0002, - F_empty = 0x0004, - F_top = 0x0008, - F_remove = 0x0010, - F_expose = 0x0020, - F_suppress = 0x0040, - }; - int _flags; - LMatrix4d _static_mat; - double _static_value; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggUserData::init_type(); - register_type(_type_handle, "EggOptcharUserData", - EggUserData::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 "eggOptcharUserData.I" - -#endif diff --git a/pandatool/src/egg-optchar/vertexMembership.I b/pandatool/src/egg-optchar/vertexMembership.I deleted file mode 100644 index f001b1d9..00000000 --- a/pandatool/src/egg-optchar/vertexMembership.I +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vertexMembership.I - * @author drose - * @date 2003-07-21 - */ - -/** - * - */ -INLINE VertexMembership:: -VertexMembership(EggGroup *group, double membership) : - _group(group), - _membership(membership) -{ -} - -/** - * - */ -INLINE VertexMembership:: -VertexMembership(const VertexMembership ©) : - _group(copy._group), - _membership(copy._membership) -{ -} - -/** - * - */ -INLINE void VertexMembership:: -operator = (const VertexMembership ©) { - _group = copy._group; - _membership = copy._membership; -} - -/** - * - */ -INLINE bool VertexMembership:: -operator < (const VertexMembership &other) const { - if (_membership != other._membership) { - return _membership < other._membership; - } - return _group < other._group; -} diff --git a/pandatool/src/egg-optchar/vertexMembership.cxx b/pandatool/src/egg-optchar/vertexMembership.cxx deleted file mode 100644 index d7eab777..00000000 --- a/pandatool/src/egg-optchar/vertexMembership.cxx +++ /dev/null @@ -1,14 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vertexMembership.cxx - * @author drose - * @date 2003-07-21 - */ - -#include "vertexMembership.h" diff --git a/pandatool/src/egg-optchar/vertexMembership.h b/pandatool/src/egg-optchar/vertexMembership.h deleted file mode 100644 index 31cc16ae..00000000 --- a/pandatool/src/egg-optchar/vertexMembership.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vertexMembership.h - * @author drose - * @date 2003-07-21 - */ - -#ifndef VERTEXMEMBERSHIP_H -#define VERTEXMEMBERSHIP_H - -#include "pandatoolbase.h" - -#include "pvector.h" - -class EggGroup; - -/** - * This class is used to help EggOptchar quantize the membership of one vertex - * among its various groups. - */ -class VertexMembership { -public: - INLINE VertexMembership(EggGroup *group, double membership); - INLINE VertexMembership(const VertexMembership ©); - INLINE void operator = (const VertexMembership ©); - - INLINE bool operator < (const VertexMembership &other) const; - - EggGroup *_group; - double _membership; -}; - -typedef pvector VertexMemberships; - -#include "vertexMembership.I" - -#endif diff --git a/pandatool/src/egg-palettize/CMakeLists.txt b/pandatool/src/egg-palettize/CMakeLists.txt deleted file mode 100644 index 9af14457..00000000 --- a/pandatool/src/egg-palettize/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_EGG) - return() -endif() - -add_executable(egg-palettize eggPalettize.cxx eggPalettize.h) -target_link_libraries(egg-palettize p3palettizer p3eggbase p3progbase) -install(TARGETS egg-palettize EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_library(p3txafile txaFileFilter.cxx txaFileFilter.h txaFileFilter.I) -set_target_properties(p3txafile PROPERTIES DEFINE_SYMBOL BUILDING_MISC) -target_link_libraries(p3txafile PRIVATE p3palettizer) -if(BUILD_SHARED_LIBS) - # We can't install this if we're doing a static build, because it depends on - # a static library that isn't installed. - install(TARGETS p3txafile EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -endif() diff --git a/pandatool/src/egg-palettize/eggPalettize.cxx b/pandatool/src/egg-palettize/eggPalettize.cxx deleted file mode 100644 index 385dd789..00000000 --- a/pandatool/src/egg-palettize/eggPalettize.cxx +++ /dev/null @@ -1,878 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggPalettize.cxx - * @author drose - * @date 2000-11-28 - */ - -#include "eggPalettize.h" -#include "palettizer.h" -#include "eggFile.h" -#include "pal_string_utils.h" -#include "filenameUnifier.h" - -#include "dcast.h" -#include "eggData.h" -#include "bamFile.h" -#include "pnotify.h" -#include "notifyCategory.h" -#include "notifySeverity.h" - -#include - -/** - * - */ -EggPalettize:: -EggPalettize() : EggMultiFilter(true) { - set_program_brief("pack textures from various .egg models into palette images"); - set_program_description - ("egg-palettize attempts to pack several texture maps from various models " - "together into one or more palette images, for improved rendering performance " - "and ease of texture management. It can also resize textures and convert " - "them to another image file format, whether or not they are actually " - "placed on a palette, and can manage some " - "simple texture properties, like mipmapping and rendering " - "format.\n\n" - - "egg-palettize reads a texture attributes file, usually named " - "textures.txa, which contains instructions from the user about " - "resizing particular textures. Type egg-palettize -H for an " - "introduction to the syntax of this file.\n\n" - - "The palettization information from previous runs is recorded in a file " - "named textures.boo (assuming the attributes file is named " - "textures.txa); a complete record of every egg file and every texture " - "that has been referenced is kept here. This allows the program " - "to intelligently manage the multiple egg files that may reference " - "the textures in question."); - - - clear_runlines(); - add_runline("[opts] file.egg [file.egg ...]"); - - // We always have EggMultiBase's -f on: force complete load. In fact, we - // use -f for our own purposes, below. - remove_option("f"); - _force_complete = true; - - add_option - ("af", "filename", 0, - "Read the indicated file as the .txa file. The default is textures.txa.", - &EggPalettize::dispatch_filename, &_got_txa_filename, &_txa_filename); - - add_option - ("a", "filename", 0, - "Deprecated option. This is the same as -af.", - &EggPalettize::dispatch_filename, &_got_txa_filename, &_txa_filename); - - add_option - ("as", "script", 0, - "Accept the script specified on the command line as the contents of the " - ".txa file, instead of reading a file on disk. This implies -nodb and " - "-opt.", - &EggPalettize::dispatch_string, &_got_txa_script, &_txa_script); - - add_option - ("nodb", "", 0, - "Don't read or record the state information to a .boo file. By default, " - "the palettization information is recorded so it can be preserved " - "between multiple invocations of egg-palettize. If you specify this " - "parameter, all the egg files to be palettized together must be " - "named at the same time. This also implies -opt, since there's no point " - "in not making an optimal packing if you won't be preserving the " - "state for future adjustments.", - &EggPalettize::dispatch_none, &_nodb); - - add_option - ("tn", "pattern", 0, - "Specify the name to generate for each palette image. The string should " - "contain %g for the group name, %p for the page name, and %i for the " - "index within the page. The extension is inferred from the image " - "type. The default is '%g_palette_%p_%i'.", - &EggPalettize::dispatch_string, &_got_generated_image_pattern, - &_generated_image_pattern); - - add_option - ("pi", "", 0, - "Do not process anything, but instead report the detailed palettization " - "information written in the state file.", - &EggPalettize::dispatch_none, &_report_pi); - - add_option - ("s", "", 0, - "Do not process anything, but report statistics on palette " - "and texture utilization from the state file.", - &EggPalettize::dispatch_none, &_report_statistics); - - add_option - ("R", "", 0, - "Remove the named egg files from the previously-generated state data " - "file.", - &EggPalettize::dispatch_none, &_remove_eggs); - - // We redefine -d using add_option() instead of redescribe_option() so it - // gets listed along with these other options that relate. - add_option - ("d", "dirname", 0, - "The directory in which to write the palettized egg files. This is " - "only necessary if more than one egg file is processed at the same " - "time; if it is included, each egg file will be processed and written " - "into the indicated directory.", - &EggPalettize::dispatch_filename, &_got_output_dirname, &_output_dirname); - add_option - ("dm", "dirname", 0, - "The directory in which to place all maps: generated palettes, " - "as well as images which were not placed on palettes " - "(but may have been resized). If this contains the string %g, " - "this will be replaced with the 'dir' string associated with a " - "palette group; see egg-palettize -H.", - &EggPalettize::dispatch_string, &_got_map_dirname, &_map_dirname); - add_option - ("ds", "dirname", 0, - "The directory to write palette shadow images to. These are working " - "copies of the palette images, useful when the palette image type is " - "a lossy-compression type like JPEG; you can avoid generational loss " - "of quality on the palette images with each pass through the palettes " - "by storing these extra shadow images in a lossless image type. This " - "directory is only used if the :shadowtype keyword appears in the .txa " - "file.", - &EggPalettize::dispatch_filename, &_got_shadow_dirname, &_shadow_dirname); - add_option - ("dr", "dirname", 0, - "The directory to make map filenames relative to when writing egg " - "files. If specified, this should be an initial substring of -dm.", - &EggPalettize::dispatch_filename, &_got_rel_dirname, &_rel_dirname); - add_option - ("g", "group", 0, - "The default palette group that egg files will be assigned to if they " - "are not explicitly assigned to any other group.", - &EggPalettize::dispatch_string, &_got_default_groupname, &_default_groupname); - add_option - ("gdir", "name", 0, - "The \"dir\" string to associate with the default palette group " - "specified with -g, if no other dir name is given in the .txa file.", - &EggPalettize::dispatch_string, &_got_default_groupdir, &_default_groupdir); - - add_option - ("all", "", 0, - "Consider all the textures referenced in all egg files that have " - "ever been palettized, not just the egg files that appear on " - "the command line.", - &EggPalettize::dispatch_none, &_all_textures); - add_option - ("egg", "", 0, - "Regenerate all egg files that need modification, even those that " - "aren't named on the command line.", - &EggPalettize::dispatch_none, &_redo_eggs); - add_option - ("redo", "", 0, - "Force a regeneration of each image from its original source(s). " - "When used in conjunction with -egg, this also forces each egg file to " - "be regenerated.", - &EggPalettize::dispatch_none, &_redo_all); - add_option - ("opt", "", 0, - "Force an optimal packing. By default, textures are added to " - "existing palettes without disturbing them, which can lead to " - "suboptimal packing. Including this switch forces the palettes " - "to be rebuilt if necessary to optimize the packing, but this " - "may invalidate other egg files which share this palette.", - &EggPalettize::dispatch_none, &_optimal); - add_option - ("omitall", "", 0, - "Re-enables the flag to omit all textures. This flag is normally on " - "by default, causing nothing actually to be palettized, until the " - "first time egg-palettize is run with the -opt flag, which turns off " - "the omitall flag and thenceforth allows textures to be combined " - "into palettes. Specifying this flag restores the original behavior " - "of keeping every texture as a separate image (which is convenient for " - "development).", - &EggPalettize::dispatch_none, &_omitall); - - // This isn't even implemented yet. Presently, we never lock anyway. - // Dangerous, but hard to implement reliable file locking across NFSSamba - // and between multiple OS's. - /* - add_option - ("nolock", "", 0, - "Don't attempt to grab a file lock on the .txa file. Use " - "with extreme caution, as multiple processes running on the same " - ".txa file may overwrite each other. Use this only if the lock " - "cannot be achieved for some reason.", - &EggPalettize::dispatch_none, &_dont_lock_txa); - */ - - add_option - ("H", "", 0, - "Describe the syntax of the attributes file.", - &EggPalettize::dispatch_none, &_describe_input_file); - - _txa_filename = "textures.txa"; -} - - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggPalettize:: -handle_args(ProgramBase::Args &args) { - if (_describe_input_file) { - describe_input_file(); - exit(1); - } - - if (_remove_eggs) { - // If we're removing these egg files from the database, we don't want to - // try to load them up. Instead, just save the filenames. - _remove_egg_list = args; - return true; - } - - // Otherwise, load the named egg files up normally. - return EggMultiFilter::handle_args(args); -} - -/** - * - */ -void EggPalettize:: -describe_input_file() { - nout << - "An attributes file consists mostly of lines describing desired sizes of " - "texture maps. The format resembles, but is not identical to, that of " - "the qtess input file. Examples:\n\n" - - " texturename.rgb : 64 64\n" - " texture-a.rgb texture-b.rgb : 32 16 margin 2\n" - " *.rgb : 50% cont\n" - " eyelids.rgb : 16 16 omit\n\n" - - "In general, each line consists of one or more filenames (and can " - "contain shell globbing characters like '*' or '?'), and a colon " - "followed by a size request. For each texture appearing in an egg " - "file, the input list is scanned from the beginning and the first " - "line that matches the filename defines the size of the texture, as " - "well as other properties associated with the texture.\n\n" - - "A size request is most often a pair of numbers, giving a specific x y " - "size of the texture. A third number may also be supplied, giving a " - "specific number of channels to convert to (for instance, to force an " - "image to a 64x64 grayscale image, set its size to 64 64 1). " - "Alternatively, a percentage scaling may be specified, e.g. 30%. The " - "requested size need not be a power of 2.\n\n" - - "Other valid keywords that may be specified on the same line with the " - "texture are:\n\n"; - - show_text(" omit", 10, - "This indicates that the texture should not be placed on any " - "palette image. It may still be resized, and it will in any " - "case be copied into the install directory.\n\n"); - - show_text(" margin i", 10, - "This specifies the number of pixels that should be written " - "around the border of the texture when it is placed in a " - "palette image; i is the integer number of pixels. The " - "use of a margin helps cut down on color bleed " - "from neighboring images. If the texture does " - "not end up placed in a palette image, the " - "margin is not used. If not specified, the default margin is " - "used, which is specified by the :margin command (see below).\n\n"); - - show_text(" coverage f", 10, - "This parameter specifies the maximum coverage to allow for this " - "particular texture before rejecting it " - "from the palette. If not specified, the default is " - "specified by the :coverage command (see below).\n\n"); - - nout << " nearest\n" - << " linear\n"; - show_text(" mipmap", 10, - "One of these options may be used to force the texture to use " - "a particular minfilter/magfilter sampling mode. If this is not " - "specified, the sampling mode specified in the egg file is " - "used. Textures that use different sampling modes cannot " - "be placed together on the same palette images.\n\n"); - - show_text(" rgba", 10, - "This specifies format 'rgba' should be in effect for this " - "particular texture. Any valid egg texture format, such as " - "rgba, rgba12, rgba8, rgb5, luminance, etc. may be specified. " - "If nothing is specified, the format specified in the egg file " - "is used. The format will automatically be downgraded to match " - "the number of channels in the texture image; e.g. rgba will " - "automatically be converted to rgb for a three-channel image. " - "As with the filter modes above, textures that use different " - "formats cannot be placed together on the same palette " - "images.\n\n"); - - show_text(" force-rgba", 10, - "This specifies a particular format, as above, that should be " - "in effect for this texture, but it will not be downgraded to " - "match the number of channels. As above, any valid egg texture " - "format may be used, e.g. force-rgba12, force-rgb5, etc.\n\n"); - - show_text(" srgb", 10, - "This specifies that this texture is in sRGB space and the format " - "should be changed to reflect that. The texture format will be " - "changed to the appropriate sRGB equivalent based on the number " - "of image channels.\n\n"); - - show_text(" keep-format", 10, - "This specifies that the image format requested by an egg file " - "should be exactly preserved, without attempting to optimize " - "it by, for instance, automatically downgrading.\n\n"); - - show_text(" generic", 10, - "Specifies that any image format requested by an egg file " - "that requests a particular bitdepth should be replaced by " - "its generic equivalent, e.g. rgba8 should become rgba.\n\n"); - - show_text(" (alpha mode)", 10, - "A particular alpha mode may be applied to a texture by naming " - "the alpha mode. This may be any valid egg alpha mode, e.g. " - "blend, binary, ms, or dual.\n\n"); - - show_text(" repeat_u, repeat_v, clamp_u, clamp_v", 10, - "Explcitly specify whether the source texture should repeat or " - "clamp in each direction. Although palette images are always " - "clamped, this will affect the pixels that are painted into " - "the palette image.\n\n"); - - show_text(" (image type)", 10, - "A texture may be converted to a particular image type, for " - "instance jpg or rgb, by naming the type. If present, this " - "overrides the :imagetype command, described below. As with " - ":imagetype, you may also specify two type names separated " - "by a comma, to indicate that a different file should be written " - "for the color and alpha components.\n\n"); - - show_text(" (group name)", 10, - "A texture may also be assigned to a specific group by naming " - "the group. The groups are defined using the :group command " - "(see below). Normally, textures are not assigned directly " - "to groups; instead, it is more useful to assign the egg files " - "they are referenced in to groups; see below.\n\n"); - - show_text(" cont", 10, - "Normally, a texture file (or egg file) scans the lines in the " - "attributes file from the top, and stops on the first line that " - "matches its name. If the keyword 'cont' is included on the " - "line, however, the texture will apply the properties given " - "on the line, and then continue scanning. This trick may be " - "used to specify general parameters for all files while still " - "allowing the texture to match a more specific line below.\n\n"); - - nout << - "The attributes file may also assign egg files to various " - "named palette groups. The syntax is similar to the above:\n\n" - - " car-blue.egg : main\n" - " road.egg house.egg : main\n" - " plane.egg : phase_2 main\n" - " *.egg : phase_2\n\n" - - "Any number of egg files may be named on one line, and the set of " - "named egg files may be simultaneously assigned to one or more groups. " - "Each group must have been previously defined using the :group command " - "(see below). Each texture that is referenced by a given " - "egg file will be palettized " - "into at least one of the groups assigned to the egg file.\n\n" - - "Finally, there are a number of special commands that may appear in the " - "attributes file; some of these have been alluded to in the above " - "comments. These commands typically specify global parameters or " - "palettization options. The command names begin with a colon to " - "distinguish them from other kinds of lines. Each command must " - "appear on a line by itself. The commands are:\n\n"; - - show_text(" :palette xsize ysize", 10, - "This specifies the size of the palette images to be " - "created. The default is 512 by 512.\n\n"); - - show_text(" :margin msize", 10, - "This specifies the amount of default margin to apply to all " - "textures that are placed within a palette image. The margin " - "is a number of additional pixels that are written around the " - "texture image to help prevent color bleeding between " - "neighboring images within the same palette. The default " - "is 2.\n\n"); - - show_text(" :background r g b a", 10, - "Specifies the background color of the generated palette " - "images. Normally, this is black, and it doesn't matter much " - "since the background color is, by definition, the color " - "of the palette images where nothing is used.\n\n"); - - show_text(" :coverage area", 10, - "The 'coverage' of a texture refers to the fraction of " - "the area in the texture image that is actually used, according " - "to the UV's that appear in the various egg files. If a texture's " - "coverage is less than 1, only some of the texture image is used " - "(and only this part will be written to the palette). If the " - "coverage is greater than 1, the texture repeats that number of " - "times. A repeating texture may still be palettized by writing " - "the required number of copies into the palette image, according " - "to the coverage area.\n\n" - - "This command specifies the maximum coverage to allow for any " - "texture before rejecting it from the palette. It may be any " - "floating-point number greater than zero. Set this to 1 " - "to avoid palettizing repeating textures altogether. This may " - "also be overridden for a particular texture using the 'coverage' " - "keyword on the texture line.\n\n"); - - show_text(" :powertwo flag", 10, - "Specifies whether textures should be forced to a power of two " - "size when they are not placed within a palette. Use 1 for true, " - "to force textures to a power of two; or 0 to leave them exactly " - "the size they are specified. The default is true.\n\n"); - - show_text(" :round fraction fuzz", 10, - "When the coverage area is computed, it may optionally be " - "rounded up to the next sizeable unit before placing the " - "texture within the palette. This helps reduce constant " - "repalettization caused by slight differences in coverage " - "between egg files. For instance, say file a.egg references a " - "texture with a coverage of 0.91, and then later file b.egg " - "is discovered to reference the same texture with a coverage of " - "0.92. If the texture was already palettized with the original " - "coverage of 0.91, it must now be moved in the palette.\n\n" - - "Rounding the coverage area up to some fixed unit reduces this " - "problem. For instance, if you specified a value 0.5 for " - "fraction in the above command, it would round both of these " - "values up to the next half-unit, or 1.0.\n\n" - - "The second number is a fuzz factor, and should be a small " - "number; if the coverage area is just slightly larger than " - "the last unit (within the fuzz factor), it is rounded down " - "instead of up. This is intended to prevent UV coordinates " - "that are just slightly out of the range [0, 1] (which happens " - "fairly often) from forcing the palettization area all the " - "way up to the next stop.\n\n" - - "The default if this is unspecified is 0.1 0.01. That is, " - "round up to the next tenth, unless within a hundredth of the " - "last tenth. To disable rounding, specify ':round no'. " - "Rounding is implicitly disabled when you run with the -opt " - "command line option.\n\n"); - - show_text(" :remap (never | group | poly)", 10, - "Sometimes two different parts of an egg file may reference " - "different regions of a repeating texture. For instance, " - "group A may reference UV coordinate values ranging from (0,5) " - "to (1,6), for a coverage of 1.0, while group B references " - "values ranging from (0,2) to (1,4), for a coverage of 2.0. " - "The maximum coverage used is only 2.0, and thus the texture " - "only needs to appear in the palette twice, but the total range " - "of UV's is from (0,2) to (1,6), causing an apparent coverage " - "of 4.0.\n\n" - - "It's possible for egg-palettize to reduce this kind of mistake " - "by remapping both groups of UV's so that they overlap. This " - "parameter specifies how this operation should be done. If " - "the option is 'never', remapping will not be performed; if " - "'group', entire groups will be remapped as a unit, if 'poly', " - "individual polygons within a group may be remapped. This last " - "option provides the greatest minimization of UV coverage, " - "but possibly at the expense of triangle strips in the resulting " - "model (since some vertices can no longer be shared).\n\n" - - "Sometimes, it may be necessary to be more restrictive on " - "character geometry than on non-character geometry, because " - "the cost of adding additional vertices on characters is " - "greater. You can specify a different kind of remapping for " - "characters only, by using the keyword 'char' on the same line, " - "e.g. ':remap group char never'.\n\n" - - "The default remap mode for all geometry, character or otherwise, " - "if no remap mode is specified is 'poly'.\n\n"); - - show_text(" :imagetype type[,alpha_type]", 10, - "This specifies the default type of image file that should be " - "generated for each palette image and for each unplaced texture " - "copied into the install directory. This may be overridden for " - "a particular texture by specifying the image type on the " - "texture line.\n\n" - - "If two image type names separate by a comma are given, it means " - "to generate a second file of the second type for the alpha " - "channel, for images that require an alpha channel. This allows " - "support for image file formats that do not support alpha " - "(for instance, JPEG).\n\n"); - - show_text(" :shadowtype type[,alpha_type]", 10, - "When generating palette images, egg-palettize sometimes has to " - "read and write the same palette image repeatedly. If the " - "palette image is stored in a lossy file format (like JPEG, see " - ":imagetype), this can eventually lead to degradation of the " - "palette images. As a workaround, egg-palettize can store " - "its working copies of the palette images in lossless shadow " - "images. Specify this to enable this feature; give it the " - "name of a lossless image file format. The shadow images will " - "be written to the directory specified by -ds on the command " - "line.\n\n"); - - show_text(" :group groupname [dir dirname] [on group1 group2 ...] [includes group1 group2 ...]", 10, - "This defines a palette group, a logical division of textures. " - "Each texture is assigned to one or more palette groups before " - "being placed in any palette image; the palette images are " - "tied to the groups.\n\n" - - "The optional parameter 'dir' specifies a directory name to " - "associate with this group. This name is substituted in for " - "the string '%g' when it appears in the map directory name " - "specified on the command line with -dm; this may be used to " - "install textures and palettes into different directories based " - "on the groups they are assigned to.\n\n" - - "Palette groups can also be hierarchically related. The " - "keyword 'on' specifies any number of groups that this " - "palette group depends on; if a texture has already been " - "assigned to one of this group's dependent groups, it will " - "not need to be assigned to this group. This also implicitly " - "specifies a dir if one has not already been specified.\n\n" - - "The keyword 'includes' names one or more groups that depend " - "on this group.\n\n"); - - show_text(" :textureswap groupname texturename0 texturename1 [texturename2 ...]", 10, - "This option builds a set of matching, interchangeable palette images. " - "All palette images in the set share the same internal texture layout. " - "The intention is to be able to swap palette images out at runtime, " - "to replace entire sets of textures on a model in one operation. " - "The textures named by this option indicate the texture images " - "which are similar to each other, and which all should be assigned " - "to the same placement on the different palette images: " - "texturename0 will be assigned to palette image 0, " - "texturename1 to the same position on palette image 1, " - "texturename2 to the same position on palette image 2, and so on. " - "To define a complete palette image, you must repeat this option " - "several times to associate all of the similar texture images.\n\n"); - - nout << - "Comments may appear freely throughout the file, and are set off by a " - "hash mark (#).\n\n"; -} - - -/** - * - */ -void EggPalettize:: -run() { - // Fiddle with the loader severity, so we don't confuse the user with - // spurious "reading" and "writing" messages about the state file. If the - // severity is currently NS_info (the default), set it to NS_warning - // instead. - Notify *notify = Notify::ptr(); - NotifyCategory *loader_cat = notify->get_category(":loader"); - if (loader_cat != nullptr && - loader_cat->get_severity() == NS_info) { - loader_cat->set_severity(NS_warning); - } - - Filename state_filename; - BamFile state_file; - - if (_got_txa_script) { - // If we got a command-line script instead of a .txa file, we won't be - // encoding a .boo file either. - _nodb = true; - - } else { - // Look for the .txa file. - if (!_txa_filename.exists() && !_got_txa_filename) { - // If we did not specify a filename, and the default filename of - // "textures.txa" doesn't exist, try looking in srcmaps, as another - // likely possibility. - Filename maybe = _txa_filename; - maybe.set_dirname("src/maps"); - if (maybe.exists()) { - _txa_filename = maybe; - } - } - - if (!_txa_filename.exists()) { - nout << FilenameUnifier::make_user_filename(_txa_filename) - << " does not exist; cannot run.\n"; - exit(1); - } - - FilenameUnifier::set_txa_filename(_txa_filename); - - state_filename = _txa_filename; - state_filename.set_extension("boo"); - } - - if (_nodb) { - // -nodb means don't attempt to read textures.boo; in fact, don't even - // bother reporting this absence to the user. - pal = new Palettizer; - - // And -nodb implies -opt. - _optimal = true; - - } else if (!state_filename.exists()) { - nout << FilenameUnifier::make_user_filename(state_filename) - << " does not exist; starting palettization from scratch.\n"; - pal = new Palettizer; - - // By default, the -omitall flag is true from the beginning. - pal->_omit_everything = true; - - } else { - // Read the Palettizer object from the Bam file written previously. This - // will recover all of the state saved from the past session. - nout << "Reading " << FilenameUnifier::make_user_filename(state_filename) - << "\n"; - - if (!state_file.open_read(state_filename)) { - nout << FilenameUnifier::make_user_filename(state_filename) - << " exists, but cannot be read. Perhaps you should " - << "remove it so a new one can be created.\n"; - exit(1); - } - - TypedWritable *obj = state_file.read_object(); - if (obj == nullptr || !state_file.resolve()) { - nout << FilenameUnifier::make_user_filename(state_filename) - << " exists, but appears to be corrupt. Perhaps you " - << "should remove it so a new one can be created.\n"; - exit(1); - } - - if (!obj->is_of_type(Palettizer::get_class_type())) { - nout << FilenameUnifier::make_user_filename(state_filename) - << " exists, but does not appear to be " - << "an egg-palettize output file. Perhaps you " - << "should remove it so a new one can be created.\n"; - exit(1); - } - - state_file.close(); - - pal = DCAST(Palettizer, obj); - - if (pal->_read_pi_version > pal->_pi_version) { - nout << FilenameUnifier::make_user_filename(state_filename) - << " was written by a more recent version of egg-palettize " - << "than this one. You will need to update your egg-palettize.\n"; - exit(1); - } - - if (pal->_read_pi_version < pal->_min_pi_version) { - nout << FilenameUnifier::make_user_filename(state_filename) - << " was written by an old version of egg-palettize.\n\n" - << "You will need to make undo-pal (or simply remove the file " - << FilenameUnifier::make_user_filename(state_filename) - << " and try again).\n\n"; - exit(1); - } - - if (!pal->is_valid()) { - nout << FilenameUnifier::make_user_filename(state_filename) - << " could not be properly read. You will need to remove it.\n"; - exit(1); - } - } - - pal->set_noabs(_noabs); - - if (_report_pi) { - pal->report_pi(); - exit(0); - } - - if (_report_statistics) { - pal->report_statistics(); - exit(0); - } - - bool okflag = true; - - if (_got_txa_script) { - std::istringstream txa_script(_txa_script); - pal->read_txa_file(txa_script, "command line"); - - } else { - _txa_filename.set_text(); - std::ifstream txa_file; - if (!_txa_filename.open_read(txa_file)) { - nout << "Unable to open " << _txa_filename << "\n"; - exit(1); - } - pal->read_txa_file(txa_file, _txa_filename); - } - - if (_got_generated_image_pattern) { - pal->_generated_image_pattern = _generated_image_pattern; - } - - if (_got_default_groupname) { - pal->_default_groupname = _default_groupname; - } else { - pal->_default_groupname = _txa_filename.get_basename_wo_extension(); - } - - if (_got_default_groupdir) { - pal->_default_groupdir = _default_groupdir; - } - - if (_got_map_dirname) { - pal->_map_dirname = _map_dirname; - } - if (_got_shadow_dirname) { - pal->_shadow_dirname = _shadow_dirname; - } - if (_got_rel_dirname) { - pal->_rel_dirname = _rel_dirname; - FilenameUnifier::set_rel_dirname(_rel_dirname); - } - - // We only omit solitary textures from palettes if we're running in optimal - // mode. Otherwise, we're likely to invalidate old egg files by changing a - // texture from solitary to nonsolitary state or vice-versa. - pal->_omit_solitary = _optimal; - - if (_omitall) { - pal->_omit_everything = true; - } else if (_optimal) { - pal->_omit_everything = false; - } - - pal->all_params_set(); - - // Remove any files named for removal. - Args::const_iterator ai; - for (ai = _remove_egg_list.begin(); ai != _remove_egg_list.end(); ++ai) { - Filename filename = (*ai); - pal->remove_egg_file(filename.get_basename()); - } - - // And process the egg files named for addition. - bool all_eggs_valid = true; - - std::string egg_comment = get_exec_command(); - Eggs::const_iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - EggData *egg_data = (*ei); - Filename source_filename = egg_data->get_egg_filename(); - Filename dest_filename = get_output_filename(source_filename); - std::string name = source_filename.get_basename(); - - EggFile *egg_file = pal->get_egg_file(name); - if (!egg_file->from_command_line(egg_data, source_filename, dest_filename, - egg_comment)) { - all_eggs_valid = false; - - } else { - pal->add_command_line_egg(egg_file); - } - } - - if (!all_eggs_valid) { - nout << "Errors reading egg file(s).\n"; - exit(1); - } - - if (_optimal) { - // If we're asking for an optimal packing, throw away the old packing and - // start fresh. - pal->reset_images(); - _all_textures = true; - - /* Asad: I disagree: unless :round is set to no from textures.txa, we - should always leave the _round_uvs to default. - // Also turn off the rounding-up of UV's for this purpose. - pal->_round_uvs = false; - */ - } - - if (_all_textures) { - pal->process_all(_redo_all, state_filename); - } else { - pal->process_command_line_eggs(_redo_all, state_filename); - } - - if (_optimal) { - // If we're asking for optimal packing, this also implies we want to - // resize the big empty palette images down. - pal->optimal_resize(); - } - - if (_redo_eggs) { - if (!pal->read_stale_eggs(_redo_all)) { - okflag = false; - } - } - - if (okflag) { - pal->generate_images(_redo_all); - - if (_redo_eggs) { - // generate_images() might have made a few more stale egg files - // (particularly if a texture palette changed filenames). - if (!pal->read_stale_eggs(false)) { - okflag = false; - } - } - } - - if (okflag) { - if (!pal->write_eggs()) { - okflag = false; - } - } - - if (!_nodb) { - // Make up a temporary filename to write the state file to, then move the - // state file into place. We do this in case the user interrupts us (or - // we core dump) before we're done; that way we won't leave the state file - // incompletely written. - std::string dirname = state_filename.get_dirname(); - if (dirname.empty()) { - dirname = "."; - } - Filename temp_filename = Filename::temporary(dirname, "pi"); - - if (!state_file.open_write(temp_filename) || - !state_file.write_object(pal)) { - nout << "Unable to write palettization information to " - << FilenameUnifier::make_user_filename(temp_filename) - << "\n"; - exit(1); - } - - state_file.close(); - state_filename.unlink(); - if (!temp_filename.rename_to(state_filename)) { - nout << "Unable to rename temporary file " - << FilenameUnifier::make_user_filename(temp_filename) << " to " - << FilenameUnifier::make_user_filename(state_filename) << "\n"; - exit(1); - } - } - - if (!okflag) { - exit(1); - } -} - -int -main(int argc, char *argv[]) { - EggPalettize prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/egg-palettize/eggPalettize.h b/pandatool/src/egg-palettize/eggPalettize.h deleted file mode 100644 index d30a9d4f..00000000 --- a/pandatool/src/egg-palettize/eggPalettize.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggPalettize.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef EGGPALETTIZE_H -#define EGGPALETTIZE_H - -#include "pandatoolbase.h" - -#include "eggMultiFilter.h" - -/** - * This is the program wrapper for egg-palettize, but it mainly serves to read - * in all the command-line parameters and then invoke the Palettizer. - */ -class EggPalettize : public EggMultiFilter { -public: - EggPalettize(); - - virtual bool handle_args(Args &args); - - void describe_input_file(); - - void run(); - - // The following parameter values specifically relate to textures and - // palettes. These values are copied to the Palettizer. - bool _got_txa_filename; - Filename _txa_filename; - bool _got_txa_script; - std::string _txa_script; - bool _nodb; - std::string _generated_image_pattern; - bool _got_generated_image_pattern; - std::string _map_dirname; - bool _got_map_dirname; - Filename _shadow_dirname; - bool _got_shadow_dirname; - Filename _rel_dirname; - bool _got_rel_dirname; - std::string _default_groupname; - bool _got_default_groupname; - std::string _default_groupdir; - bool _got_default_groupdir; - -private: - // The following values control behavior specific to this session. They're - // not saved for future sessions. - bool _report_pi; - bool _report_statistics; - bool _all_textures; - bool _optimal; - bool _omitall; - bool _redo_all; - bool _redo_eggs; - - bool _describe_input_file; - bool _remove_eggs; - Args _remove_egg_list; -}; - -#endif diff --git a/pandatool/src/egg-palettize/txaFileFilter.I b/pandatool/src/egg-palettize/txaFileFilter.I deleted file mode 100644 index 44cde648..00000000 --- a/pandatool/src/egg-palettize/txaFileFilter.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file txaFileFilter.I - * @author drose - * @date 2006-07-27 - */ diff --git a/pandatool/src/egg-palettize/txaFileFilter.cxx b/pandatool/src/egg-palettize/txaFileFilter.cxx deleted file mode 100644 index d45bea3b..00000000 --- a/pandatool/src/egg-palettize/txaFileFilter.cxx +++ /dev/null @@ -1,148 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file txaFileFilter.cxx - * @author drose - * @date 2006-07-27 - */ - -#include "txaFileFilter.h" -#include "palettizer.h" -#include "txaFile.h" -#include "textureImage.h" -#include "sourceTextureImage.h" -#include "texturePool.h" -#include "dconfig.h" -#include "configVariableFilename.h" -#include "virtualFileSystem.h" -#include "config_putil.h" - -NotifyCategoryDeclNoExport(txafile); -NotifyCategoryDef(txafile, ""); - -// A few lines to register this filter type with the TexturePool when the -// shared library is loaded. -Configure(config_txaFileFilter); -ConfigureFn(config_txaFileFilter) { - TxaFileFilter::init_type(); - TexturePool::register_filter(new TxaFileFilter); -} - -TypeHandle TxaFileFilter::_type_handle; -TxaFile *TxaFileFilter::_txa_file; -bool TxaFileFilter::_got_txa_file; - -/** - * This method is called after each texture has been loaded from disk, via the - * TexturePool, for the first time. By the time this method is called, the - * Texture has already been fully read from disk. This method should return - * the Texture pointer that the TexturePool should actually return (usually it - * is the same as the pointer supplied). - */ -PT(Texture) TxaFileFilter:: -post_load(Texture *tex) { - if (!_got_txa_file) { - read_txa_file(); - } - - TextureImage tex_image; - std::string name = tex->get_filename().get_basename_wo_extension(); - tex_image.set_name(name); - - SourceTextureImage *source = tex_image.get_source - (tex->get_fullpath(), tex->get_alpha_fullpath(), 0); - PNMImage pnm_image; - tex->store(pnm_image); - source->set_header(pnm_image); - tex_image.set_source_image(pnm_image); - - tex_image.pre_txa_file(); - - bool matched = _txa_file->match_texture(&tex_image); - if (txafile_cat.is_debug()) { - if (!matched) { - txafile_cat.debug() - << "Not matched: " << name << "\n"; - } else { - txafile_cat.debug() - << "Matched: " << name << "\n"; - } - } - - tex_image.post_txa_file(); - - PNMImage dest(tex_image.get_x_size(), - tex_image.get_y_size(), - tex_image.get_num_channels(), - pnm_image.get_maxval()); - dest.quick_filter_from(pnm_image); - - tex->load(dest); - - // Create an EggTexture to pass back the requested alpha mode to the egg - // loader, if the texture is now being loaded from an egg file. - PT_EggTexture egg_tex = new EggTexture(tex->get_name(), tex->get_fullpath()); - const TextureProperties &props = tex_image.get_properties(); - - egg_tex->set_alpha_mode(tex_image.get_alpha_mode()); - egg_tex->set_format(props._format); - egg_tex->set_minfilter(props._minfilter); - egg_tex->set_magfilter(props._magfilter); - egg_tex->set_anisotropic_degree(props._anisotropic_degree); - - tex->set_aux_data("egg", egg_tex); - - return tex; -} - -/** - * Reads the textures.txa file named by the variable txa-file. Called only - * once, at startup. - */ -void TxaFileFilter:: -read_txa_file() { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - - // We need to create a global Palettizer object to hold some of the global - // properties that may be specified in a txa file. - if (pal == nullptr) { - pal = new Palettizer; - } - - _txa_file = new TxaFile; - _got_txa_file = true; - - ConfigVariableFilename txa_file - ("txa-file", Filename("textures.txa"), - PRC_DESC("Specify the name of the txa file to load when the txafile texture filter" - "is in effect.")); - - Filename filename = txa_file; - vfs->resolve_filename(filename, get_model_path()); - - if (!vfs->exists(filename)) { - txafile_cat.warning() - << "Filename " << filename << " not found.\n"; - } else { - filename.set_text(); - std::istream *ifile = vfs->open_read_file(filename, true); - if (ifile == nullptr) { - txafile_cat.warning() - << "Filename " << filename << " cannot be read.\n"; - } else { - if (!_txa_file->read(*ifile, filename)) { - txafile_cat.warning() - << "Syntax errors in " << filename << "\n"; - } else { - txafile_cat.info() - << "Read " << filename << "\n"; - } - vfs->close_read_file(ifile); - } - } -} diff --git a/pandatool/src/egg-palettize/txaFileFilter.h b/pandatool/src/egg-palettize/txaFileFilter.h deleted file mode 100644 index a2f13a71..00000000 --- a/pandatool/src/egg-palettize/txaFileFilter.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file txaFileFilter.h - * @author drose - * @date 2006-07-27 - */ - -#ifndef TXAFILEFILTER_H -#define TXAFILEFILTER_H - -#include "pandatoolbase.h" -#include "texturePoolFilter.h" -#include "pt_EggTexture.h" - -class TxaFile; - -/** - * This is an abstract base class, a placeholder for any number of different - * classes that may wish to implement an effect on every texture loaded from - * disk via the TexturePool. - * - * In practice, as of the time of this writing, only the TxaFileFilter (in - * pandatool) actually implements this. But other kinds of filters are - * possible. - * - * This filter, once registered, will get a callback and a chance to modify - * each texture as it is loaded from disk the first time. If more than one - * filter is registered, each will be called in sequence, in the order in - * which they were registered. - * - * The filter does not get called again if the texture is subsequently - * reloaded from disk. It is suggested that filters for which this might be a - * problem should call tex->set_keep_ram_image(true). - */ -class EXPCL_MISC TxaFileFilter : public TexturePoolFilter { -public: - virtual PT(Texture) post_load(Texture *tex); - -private: - static void read_txa_file(); - -private: - static TxaFile *_txa_file; - static bool _got_txa_file; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TexturePoolFilter::init_type(); - register_type(_type_handle, "TxaFileFilter", - TexturePoolFilter::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 "txaFileFilter.I" - -#endif diff --git a/pandatool/src/egg-qtess/CMakeLists.txt b/pandatool/src/egg-qtess/CMakeLists.txt deleted file mode 100644 index 83e6ff1f..00000000 --- a/pandatool/src/egg-qtess/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_EGG) - return() -endif() - -set(P3EGG_QTESS_HEADERS - config_egg_qtess.h - eggQtess.h - isoPlacer.h isoPlacer.I - qtessGlobals.h - qtessInputEntry.h qtessInputEntry.I - qtessInputFile.h qtessInputFile.I - qtessSurface.h qtessSurface.I - subdivSegment.h subdivSegment.I -) - -set(P3EGG_QTESS_SOURCES - config_egg_qtess.cxx - eggQtess.cxx - isoPlacer.cxx - qtessGlobals.cxx - qtessInputEntry.cxx - qtessInputFile.cxx - qtessSurface.cxx - subdivSegment.cxx -) - -composite_sources(egg-qtess P3EGG_QTESS_SOURCES) -add_executable(egg-qtess ${P3EGG_QTESS_HEADERS} ${P3EGG_QTESS_SOURCES}) -target_link_libraries(egg-qtess p3eggbase) - -install(TARGETS egg-qtess EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/egg-qtess/config_egg_qtess.cxx b/pandatool/src/egg-qtess/config_egg_qtess.cxx deleted file mode 100644 index de3dbf95..00000000 --- a/pandatool/src/egg-qtess/config_egg_qtess.cxx +++ /dev/null @@ -1,22 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_egg_qtess.cxx - * @author drose - * @date 2003-10-13 - */ - -#include "config_egg_qtess.h" - -#include "dconfig.h" - -Configure(config_egg_qtess); -NotifyCategoryDef(qtess, ""); - -ConfigureFn(config_egg_qtess) { -} diff --git a/pandatool/src/egg-qtess/config_egg_qtess.h b/pandatool/src/egg-qtess/config_egg_qtess.h deleted file mode 100644 index abc9ef39..00000000 --- a/pandatool/src/egg-qtess/config_egg_qtess.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_egg_qtess.h - * @author drose - * @date 2003-10-13 - */ - -#ifndef CONFIG_EGG_QTESS_H -#define CONFIG_EGG_QTESS_H - -#include "pandatoolbase.h" -#include "notifyCategoryProxy.h" - -NotifyCategoryDeclNoExport(qtess); - -// No variables to declare here. - -#endif diff --git a/pandatool/src/egg-qtess/egg-qtess_composite1.cxx b/pandatool/src/egg-qtess/egg-qtess_composite1.cxx deleted file mode 100644 index 01ed99bd..00000000 --- a/pandatool/src/egg-qtess/egg-qtess_composite1.cxx +++ /dev/null @@ -1,8 +0,0 @@ -#include "config_egg_qtess.cxx" -#include "eggQtess.cxx" -#include "isoPlacer.cxx" -#include "qtessGlobals.cxx" -#include "qtessInputEntry.cxx" -#include "qtessInputFile.cxx" -#include "qtessSurface.cxx" -#include "subdivSegment.cxx" diff --git a/pandatool/src/egg-qtess/eggQtess.cxx b/pandatool/src/egg-qtess/eggQtess.cxx deleted file mode 100644 index 37473557..00000000 --- a/pandatool/src/egg-qtess/eggQtess.cxx +++ /dev/null @@ -1,337 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggQtess.cxx - * @author drose - * @date 2003-10-13 - */ - -#include "eggQtess.h" -#include "qtessGlobals.h" -#include "dcast.h" - -/** - * - */ -EggQtess:: -EggQtess() { - add_normals_options(); - - set_program_brief("tesselate NURBS surfaces in .egg files"); - set_program_description - ("egg-qtess reads an egg file, tessellates all of its NURBS surfaces " - "using a simple uniform tessellation, and outputs a polygonal " - "egg file.\n\n" - - "Characters are supported, soft-skinned and otherwise; joint " - "ownership is computed correctly for each new polygon vertex. " - "Primitives other than NURBS surfaces appearing in the egg file " - "are unaffected."); - - add_option - ("f", "filename", 0, - "Read the indicated parameter file. Type egg-qtess -H " - "to print a description of the parameter file format.", - &EggQtess::dispatch_filename, nullptr, &_qtess_filename); - - add_option - ("up", "subdiv", 0, - "Specify a uniform subdivision per patch (isoparam). Each NURBS " - "surface is made up of N x M patches, each of which is divided " - "into subdiv x subdiv quads. A fractional number is allowed.", - &EggQtess::dispatch_double, nullptr, &_uniform_per_isoparam); - - add_option - ("us", "subdiv", 0, - "Specify a uniform subdivision per surface. Each NURBS " - "surface is subdivided into subdiv x subdiv quads, regardless " - "of the number of isoparams it has. A fractional number is " - "meaningless.", - &EggQtess::dispatch_int, nullptr, &_uniform_per_surface); - - add_option - ("t", "tris", 0, - "Specify an approximate number of triangles to produce. This " - "is the total number of triangles for the entire egg file, " - "including those surfaces that have already been given an " - "explicit tessellation by a parameter file.", - &EggQtess::dispatch_int, nullptr, &_total_tris); - - add_option - ("ap", "", 0, - "Attempt to automatically place tessellation lines where they'll " - "do the most good on each surface (once the number of polygons " - "for the surface has already been determined).", - &EggQtess::dispatch_none, &QtessGlobals::_auto_place); - - add_option - ("ad", "", 0, - "Attempt to automatically distribute polygons among the surfaces " - "where they are most needed according to curvature and size, " - "instead of according to the number of isoparams. This only has " - "meaning when used in conjunction with -t.", - &EggQtess::dispatch_none, &QtessGlobals::_auto_distribute); - - add_option - ("ar", "ratio", 0, - "Specify the ratio of dominance of size to curvature for -ap and " - "-ad. A value of 0 forces placement by curvature only; a very " - "large value (like 1000) forces placement by size only. The " - "default is 5.0.", - &EggQtess::dispatch_double, nullptr, &QtessGlobals::_curvature_ratio); - - add_option - ("e", "", 0, - "Respect subdivision parameters given in the egg file. If this " - "is specified, the egg file may define the effective number of " - "patches of each NURBS entry. This can be used alone or in " - "conjunction with -u or -t to fine-tune the uniform tessellation " - "on a per-surface basis. (This is ignored if -ad is in effect.)", - &EggQtess::dispatch_none, &QtessGlobals::_respect_egg); - - add_option - ("q", "", 0, - "Instead of writing an egg file, generate a parameter file " - "for output.", - &EggQtess::dispatch_none, &_qtess_output); - - add_option - ("H", "", 0, - "Describe the format of the parameter file specified with -f.", - &EggQtess::dispatch_none, &_describe_qtess); - - _uniform_per_isoparam = 0.0; - _uniform_per_surface = 0; - _total_tris = 0; -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggQtess:: -handle_args(ProgramBase::Args &args) { - if (_describe_qtess) { - describe_qtess_format(); - exit(0); - } - - return EggFilter::handle_args(args); -} - -/** - * - */ -void EggQtess:: -run() { - bool read_qtess = false; - if (!_qtess_filename.empty()) { - if (!_qtess_file.read(_qtess_filename)) { - exit(1); - } - read_qtess = true; - } - - find_surfaces(_data); - - QtessInputEntry &default_entry = _qtess_file.get_default_entry(); - if (!read_qtess || default_entry.get_num_surfaces() == 0) { - nout << _surfaces.size() << " NURBS surfaces found.\n"; - - } else { - nout << _surfaces.size() << " NURBS surfaces found; " - << default_entry.get_num_surfaces() - << " unaccounted for by input file.\n"; - } - - int num_tris = _qtess_file.count_tris(); - - if (_total_tris != 0) { - // Whatever number of triangles we have unaccounted for, assign to the - // default bucket. - int extra_tris = std::max(0, _total_tris - num_tris); - if (read_qtess && default_entry.get_num_surfaces() != 0) { - std::cerr << extra_tris << " triangles unaccounted for.\n"; - } - - default_entry.set_num_tris(extra_tris); - - } else if (_uniform_per_isoparam!=0.0) { - default_entry.set_per_isoparam(_uniform_per_isoparam); - - } else if (_uniform_per_surface!=0.0) { - default_entry.set_uv(_uniform_per_surface, _uniform_per_surface); - - } else { - default_entry.set_per_isoparam(1.0); - } - - default_entry.count_tris(); - - if (_qtess_output) { - // Sort the names into alphabetical order for aesthetics. - // sort(_surfaces.begin(), _surfaces.end(), compare_surfaces()); - - int tris = 0; - - std::ostream &out = get_output(); - Surfaces::const_iterator si; - for (si = _surfaces.begin(); si != _surfaces.end(); ++si) { - tris += (*si)->write_qtess_parameter(out); - } - - std::cerr << tris << " tris generated.\n"; - - } else { - - int tris = 0; - - Surfaces::const_iterator si; - for (si = _surfaces.begin(); si != _surfaces.end(); ++si) { - tris += (*si)->tesselate(); - } - - std::cerr << tris << " tris generated.\n"; - - // Clear out the surfaces list before removing the vertices, since each - // surface is holding reference counts to the previously-used vertices. - _surfaces.clear(); - - _data->remove_unused_vertices(true); - write_egg_file(); - } -} - -/** - * - */ -void EggQtess:: -describe_qtess_format() { - nout << - "An egg-qtess parameter file consists of lines of the form:\n\n" - - "name [name...] : parameters\n\n" - - "Where name is a string (possibly including wildcard characters " - "such as * and ?) that matches one or more surface " - "names, and parameters is a tesselation specification, described below. " - "The colon must be followed by at least one space to differentiate it " - "from a colon character in the name(s). Multiple names " - "may be combined on one line.\n\n\n" - - - "The parameters may be any of the following. Lowercase letters are " - "literal. NUM is any number.\n\n"; - - show_text(" omit", 10, - "Remove the surface from the output.\n\n"); - - show_text(" NUM", 10, - "Try to achieve the indicated number of triangles over all the " - "surfaces matched by this line.\n\n"); - - show_text(" NUM NUM [[!]u# [!]u# ...] [[!]v# [!]v# ...]", 10, - "Tesselate to NUM x NUM quads. If u# or v# appear, they indicate " - "additional isoparams to insert (or remove if preceded by an " - "exclamation point). The range is [0, 1].\n\n"); - - show_text(" iNUM", 10, - "Subdivision amount per isoparam. Equivalent to the command-line " - "option -u NUM.\n\n"); - - show_text(" NUM%", 10, - "This is a special parameter. This does not request any specific " - "tesselation for the named surfaces, but instead gives a relative " - "importance for them when they appear with other surfaces in a " - "later entry (or are tesselated via -t on the command line). In " - "general, a surface with a weight of 25% will be given a quarter " - "of the share of the polygons it otherwise would have received; " - "a weight of 150% will give the surface 50% more than its fair " - "share.\n\n"); - - show_text(" matchvu", 10, - "This is a special parameter that indicates that two or more " - "surfaces share a common edge, and must be tesselated the " - "same way " - "along that edge. Specifically, matchvu means that the V " - "tesselation of the first named surface will be applied to the U " - "tesselation of the second (and later) named surface(s). Similar " - "definitions exist for matchuv, matchuu, and matchvv.\n\n"); - - show_text(" minu NUM", 10, - "This is another special parameter that specifies a " - "minimum tesselation for all these surfaces in " - "the U direction. This is " - "the number of quads across the dimension the surface will be " - "broken into. The default is 1 for an open surface, and 3 for " - "a closed surface.\n\n"); - - show_text(" minv NUM", 10, - "Similar to minv, in the V direction.\n\n"); - - nout << - "In addition, the following optional parameters may appear. If they appear, " - "they override similar parameters given on the command line; if they do not " - "appear, the defaults are taken from the command line:\n\n"; - - show_text(" ap", 10, - "Automatically place tesselation lines on each surface where they " - "seem to be needed most.\n\n"); - - show_text(" !ap", 10, - "Do not move lines automatically; use a strict uniform " - "tesselation.\n\n"); - - show_text(" ad", 10, - "Automatically distribute polygons to the surfaces that seem to " - "need them the most.\n\n"); - - show_text(" !ad", 10, - "Do not automatically distribute polygons; distribute " - "them according to the number of isoparams of each surface.\n\n"); - - show_text(" arNUM", 10, - "Specify the ratio of dominance of size to curvature.\n\n"); - - nout << - "The hash symbol '#' begins a comment if it is preceded by whitespace or at the " - "beginning of a line. The backslash character at the end of a line can be used " - "to indicate a continuation.\n\n"; -} - -/** - * Recursively walks the egg graph, collecting all the NURBS surfaces found. - */ -void EggQtess:: -find_surfaces(EggNode *egg_node) { - if (egg_node->is_of_type(EggNurbsSurface::get_class_type())) { - PT(QtessSurface) surface = - new QtessSurface(DCAST(EggNurbsSurface, egg_node)); - if (surface->is_valid()) { - _surfaces.push_back(surface); - QtessInputEntry::Type match_type = _qtess_file.match(surface); - nassertv(match_type != QtessInputEntry::T_undefined); - } - } - - if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); - EggGroupNode::const_iterator ci; - for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { - find_surfaces(*ci); - } - } -} - -int main(int argc, char *argv[]) { - EggQtess prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/egg-qtess/eggQtess.h b/pandatool/src/egg-qtess/eggQtess.h deleted file mode 100644 index c18db52e..00000000 --- a/pandatool/src/egg-qtess/eggQtess.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggQtess.h - * @author drose - * @date 2003-10-13 - */ - -#ifndef EGGQTESS_H -#define EGGQTESS_H - -#include "pandatoolbase.h" -#include "eggFilter.h" -#include "qtessInputFile.h" -#include "qtessSurface.h" -#include "pointerTo.h" -#include "pvector.h" - -/** - * A program to tesselate NURBS surfaces appearing within an egg file into - * polygons, using variations on a quick uniform tesselation. - */ -class EggQtess : public EggFilter { -public: - EggQtess(); - - void run(); - -protected: - virtual bool handle_args(ProgramBase::Args &args); - -private: - void describe_qtess_format(); - void find_surfaces(EggNode *egg_node); - - Filename _qtess_filename; - double _uniform_per_isoparam; - int _uniform_per_surface; - int _total_tris; - bool _qtess_output; - bool _describe_qtess; - - QtessInputFile _qtess_file; - - typedef pvector< PT(QtessSurface) > Surfaces; - Surfaces _surfaces; -}; - -#endif diff --git a/pandatool/src/egg-qtess/isoPlacer.I b/pandatool/src/egg-qtess/isoPlacer.I deleted file mode 100644 index f773b8fb..00000000 --- a/pandatool/src/egg-qtess/isoPlacer.I +++ /dev/null @@ -1,28 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file isoPlacer.I - * @author drose - * @date 2003-10-13 - */ - -/** - * - */ -INLINE IsoPlacer:: -IsoPlacer() { -} - - -/** - * - */ -INLINE double IsoPlacer:: -get_total_score() const { - return _cint[_maxi]; -} diff --git a/pandatool/src/egg-qtess/isoPlacer.cxx b/pandatool/src/egg-qtess/isoPlacer.cxx deleted file mode 100644 index 0f7a6a3f..00000000 --- a/pandatool/src/egg-qtess/isoPlacer.cxx +++ /dev/null @@ -1,228 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file isoPlacer.cxx - * @author drose - * @date 2003-10-13 - */ - -#include "isoPlacer.h" -#include "qtessSurface.h" -#include "subdivSegment.h" -#include "nurbsSurfaceResult.h" -#include "pvector.h" - - -/** - * - */ -void IsoPlacer:: -get_scores(int subdiv, int across, double ratio, - NurbsSurfaceResult *surf, bool s) { - _maxi = subdiv - 1; - - _cscore.clear(); - _sscore.clear(); - - _cscore.reserve(_maxi); - _sscore.reserve(_maxi); - - // First, tally up the curvature and stretch scores across the surface. - int i = 0; - for (i = 0; i < _maxi; i++) { - _cscore.push_back(0.0); - _sscore.push_back(0.0); - } - - int a; - for (a = 0; a <= across; a++) { - double v = (double)a / (double)across; - - LVecBase3 p1, p2, p3, pnext; - LVecBase3 v1, v2; - if (s) { - surf->eval_point(0.0, v, p3); - } else { - surf->eval_point(v, 0.0, p3); - } - int num_points = 1; - - for (i = -1; i < _maxi; i++) { - double u = (double)(i+1) / (double)(_maxi+1); - if (s) { - surf->eval_point(u, v, pnext); - } else { - surf->eval_point(v, u, pnext); - } - - // We'll ignore consecutive equal points. They don't contribute to - // curvature or size. - if (!pnext.almost_equal(p3)) { - num_points++; - p1 = p2; - p2 = p3; - p3 = pnext; - - v1 = v2; - v2 = p3 - p2; - double vlength = length(v2); - v2 /= vlength; - - if (i >= 0) { - _sscore[i] += vlength; - } - - if (num_points >= 3) { - // We only have a meaningful v1, v2 when we've read at least three - // non-equal points. - double d = v1.dot(v2); - - _cscore[i] += acos(std::max(std::min(d, 1.0), -1.0)); - } - } - } - } - - // Now integrate. - _cint.clear(); - _cint.reserve(_maxi + 1); - - double net = 0.0; - double ad = (double)(across+1); - _cint.push_back(0.0); - for (i = 0; i < _maxi; i++) { - net += _cscore[i]/ad + ratio * _sscore[i]/ad; - _cint.push_back(net); - } -} - -/** - * - */ -void IsoPlacer:: -place(int count, pvector &iso_points) { - // Count up the average curvature. - /* - double avg_curve = 0.0; - for (i = 0; i < _maxi; i++) { - avg_curve += _cscore[i]; - } - avg_curve /= (double)_maxi; - */ - - // Find all the local maxima in the curvature table. These are bend points. - typedef pvector BendPoints; - BendPoints bpoints; - BendPoints::iterator bi, bnext; - - typedef pvector Segments; - Segments segments; - Segments::iterator si; - - /* - // Having problems with bend points right now. Maybe this is just a bad - // idea. It seems to work pretty well without them, anyway. - for (i = 1; i < _maxi-1; i++) { - // A point must be measurably higher than both its neighbors, as well as - // at least 50% more curvy than the average curvature, to qualify as a - // bend point. - if (_cscore[i] > _cscore[i-1]+0.001 && - _cscore[i] > _cscore[i+1]+0.001 && - _cscore[i] > 1.5 * avg_curve) { - bpoints.push_back(i); - } - } - */ - - // Now make sure there aren't any two bend points closer together than - // maxicount. If there are, remove the smaller of the two. - bi = bpoints.begin(); - int min_separation = _maxi/count; - while (bi != bpoints.end()) { - bnext = bi; - ++bnext; - - if (bnext != bpoints.end() && (*bnext) - (*bi) < min_separation) { - // Too close. Remove one. - if (_cscore[*bnext] > _cscore[*bi]) { - *bi = *bnext; - } - bpoints.erase(bnext); - } else { - // Not too close; keep going; - bi = bnext; - } - } - - // Now, if we have fewer total subdivisions than bend points, then remove - // the smallest bend points. - while (count - 1 < (int)bpoints.size()) { - bi = bpoints.begin(); - BendPoints::iterator mi = bi; - for (++bi; bi != bpoints.end(); ++bi) { - if (_cscore[*bi] < _cscore[*mi]) { - mi = bi; - } - } - bpoints.erase(mi); - } - - // Now all the remaining bend points are valid. - bi = bpoints.begin(); - int last = 0; - for (bi = bpoints.begin(); bi != bpoints.end(); ++bi) { - segments.push_back(SubdivSegment(&_cint[0], last, *bi)); - last = *bi; - } - segments.push_back(SubdivSegment(&_cint[0], last, _maxi)); - - int nr = count - segments.size(); - - // Now we have subdivided the curve into a number of smaller curves at the - // bend points. We still have nr remaining cuts to make; distribute these - // cuts among the curves evenly according to score. - - // Divvy out the extra cuts. First, each segment gets an amount - // proportional to its score. - double net_score = _cint[_maxi]; - nassertv(net_score > 0.0); - int ns = 0; - for (si = segments.begin(); si != segments.end(); ++si) { - (*si)._num_cuts = (int)floor(nr * (*si).get_score() / net_score); - nassertv((*si)._num_cuts <= nr); // This fails if net_score is nan. - ns += (*si)._num_cuts; - } - - // Then, assign the remaining cuts to the neediest segments. - nr -= ns; - while (nr > 0) { - si = min_element(segments.begin(), segments.end()); - (*si)._num_cuts++; - nr--; - } - - // Now cut up the segments as indicated. - for (si = segments.begin(); si != segments.end(); ++si) { - (*si).cut(); - } - - // Finally, return the result. - iso_points.erase(iso_points.begin(), iso_points.end()); - - iso_points.push_back(0.0); - for (si = segments.begin(); si != segments.end(); ++si) { - pvector::iterator ci; - for (ci = (*si)._cuts.begin(); ci != (*si)._cuts.end(); ++ci) { - iso_points.push_back((*ci+1) / (double)(_maxi+1)); - } - iso_points.push_back(((*si)._t+1) / (double)(_maxi+1)); - } - - // Oh, wait. The last segment is actually drawn all the way to 1. - iso_points.back() = 1.0; -} diff --git a/pandatool/src/egg-qtess/isoPlacer.h b/pandatool/src/egg-qtess/isoPlacer.h deleted file mode 100644 index b4696340..00000000 --- a/pandatool/src/egg-qtess/isoPlacer.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file isoPlacer.h - * @author drose - * @date 2003-10-13 - */ - -#ifndef ISOPLACER_H -#define ISOPLACER_H - -#include "pandatoolbase.h" -#include "pvector.h" -#include "vector_double.h" - -class NurbsSurfaceResult; - -/** - * Contains the logic used to place isoparams where they'll do the most good - * on a surface. - */ -class IsoPlacer { -public: - INLINE IsoPlacer(); - - void get_scores(int subdiv, int across, double ratio, - NurbsSurfaceResult *surf, bool s); - void place(int count, pvector &iso_points); - - INLINE double get_total_score() const; - - vector_double _cscore, _sscore, _cint; - int _maxi; -}; - -#include "isoPlacer.I" - -#endif diff --git a/pandatool/src/egg-qtess/qtessGlobals.cxx b/pandatool/src/egg-qtess/qtessGlobals.cxx deleted file mode 100644 index 85fb91fb..00000000 --- a/pandatool/src/egg-qtess/qtessGlobals.cxx +++ /dev/null @@ -1,19 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessGlobals.cxx - * @author drose - * @date 2003-10-13 - */ - -#include "qtessGlobals.h" - -bool QtessGlobals::_auto_place = false; -bool QtessGlobals::_auto_distribute = false; -double QtessGlobals::_curvature_ratio = 5.0; -bool QtessGlobals::_respect_egg = false; diff --git a/pandatool/src/egg-qtess/qtessGlobals.h b/pandatool/src/egg-qtess/qtessGlobals.h deleted file mode 100644 index d7412934..00000000 --- a/pandatool/src/egg-qtess/qtessGlobals.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessGlobals.h - * @author drose - * @date 2003-10-13 - */ - -#ifndef QTESS_GLOBALS_H -#define QTESS_GLOBALS_H - -#include "pandatoolbase.h" - -/** - * Simply used as a namespace to scope some global variables for this program, - * set from the command line. - */ -class QtessGlobals { -public: - static bool _auto_place; - static bool _auto_distribute; - static double _curvature_ratio; - static bool _respect_egg; -}; - -#endif diff --git a/pandatool/src/egg-qtess/qtessInputEntry.I b/pandatool/src/egg-qtess/qtessInputEntry.I deleted file mode 100644 index d8ab6de6..00000000 --- a/pandatool/src/egg-qtess/qtessInputEntry.I +++ /dev/null @@ -1,156 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessInputEntry.I - * @author drose - * @date 2003-10-13 - */ - -/** - * - */ -INLINE QtessInputEntry:: -QtessInputEntry(const QtessInputEntry ©) { - (*this) = copy; -} - -/** - * - */ -INLINE void QtessInputEntry:: -add_node_name(const std::string &name) { - _node_names.push_back(GlobPattern(name)); -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_importance(double i) { - _importance = i; - _type = T_importance; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_match_uu() { - _type = T_match_uu; - _constrain_u = nullptr; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_match_vv() { - _type = T_match_vv; - _constrain_v = nullptr; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_match_uv() { - _type = T_match_uv; - _constrain_u = nullptr; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_match_vu() { - _type = T_match_vu; - _constrain_v = nullptr; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_min_u(int min_u) { - _type = T_min_u; - _num_u = min_u; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_min_v(int min_v) { - _type = T_min_v; - _num_v = min_v; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_undefined() { - _type = T_undefined; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_omit() { - _type = T_omit; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_num_tris(int nt) { - _num_tris = nt; - _type = T_num_tris; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_uv(int u, int v) { - set_uv(u, v, nullptr, 0); -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_per_isoparam(double pi) { - _per_isoparam = pi; - _type = T_per_isoparam; -} - -/** - * - */ -INLINE void QtessInputEntry:: -set_per_score(double pi) { - _per_isoparam = pi; - _type = T_per_score; -} - -/** - * - */ -INLINE int QtessInputEntry:: -get_num_surfaces() const { - return _surfaces.size(); -} - - -INLINE std::ostream &operator << (std::ostream &out, const QtessInputEntry &entry) { - entry.output(out); - return out; -} diff --git a/pandatool/src/egg-qtess/qtessInputEntry.cxx b/pandatool/src/egg-qtess/qtessInputEntry.cxx deleted file mode 100644 index 66df4c88..00000000 --- a/pandatool/src/egg-qtess/qtessInputEntry.cxx +++ /dev/null @@ -1,465 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessInputEntry.cxx - * @author drose - * @date 2003-10-13 - */ - -#include "qtessInputEntry.h" -#include "qtessSurface.h" -#include "qtessGlobals.h" -#include "config_egg_qtess.h" -#include "indent.h" -#include "string_utils.h" - -#include -#include - -using std::string; - -/** - * - */ -QtessInputEntry:: -QtessInputEntry(const string &name) { - _type = T_undefined; - _num_patches = 0.0; - _auto_place = QtessGlobals::_auto_place; - _auto_distribute = QtessGlobals::_auto_distribute; - _curvature_ratio = QtessGlobals::_curvature_ratio; - if (!name.empty()) { - add_node_name(name); - } -} - -/** - * - */ -void QtessInputEntry:: -operator = (const QtessInputEntry ©) { - _node_names = copy._node_names; - _type = copy._type; - _num_tris = copy._num_tris; - _num_u = copy._num_u; - _num_v = copy._num_v; - _per_isoparam = copy._per_isoparam; - _iso_u = copy._iso_u; - _iso_v = copy._iso_v; - _surfaces = copy._surfaces; - _num_patches = copy._num_patches; - _auto_place = copy._auto_place; - _auto_distribute = copy._auto_distribute; - _curvature_ratio = copy._curvature_ratio; - _importance = copy._importance; - _constrain_u = copy._constrain_u; - _constrain_v = copy._constrain_v; -} - -/** - * An STL function object to determine if two doubles are very nearly equal. - * Used in set_uv(), below. - */ -class DoublesAlmostEqual { -public: - int operator ()(double a, double b) const { - return fabs(a - b) < 0.00001; - } -}; - -/** - * An STL function object to determine if a double is vert nearly equal the - * supplied value . Used in set_uv(), below. - */ -class DoubleAlmostMatches { -public: - DoubleAlmostMatches(double v) : _v(v) {} - int operator ()(double a) const { - return fabs(a - _v) < 0.00001; - } - double _v; -}; - - -/** - * Sets specific tesselation. The tesselation will be u by v quads, with the - * addition of any isoparams described in the list of params. - */ -void QtessInputEntry:: -set_uv(int u, int v, const string params[], int num_params) { - _num_u = u; - _num_v = v; - - // First, fill up the arrays with the defaults. - int i; - for (i = 0; i <= _num_u; i++) { - _iso_u.push_back(i); - } - for (i = 0; i <= _num_v; i++) { - _iso_v.push_back(i); - } - - // Then get out all the additional entries. - for (i = 0; i < num_params; i++) { - const string ¶m = params[i]; - - if (param[0] == '!' && param.size() > 2) { - double value; - if (!string_to_double(param.substr(2), value)) { - qtess_cat.warning() - << "Ignoring invalid parameter: " << param << "\n"; - } else { - switch (tolower(param[1])) { - case 'u': - _auto_place = false; - _iso_u.erase(remove_if(_iso_u.begin(), _iso_u.end(), - DoubleAlmostMatches(value)), - _iso_u.end()); - break; - - case 'v': - _auto_place = false; - _iso_v.erase(remove_if(_iso_v.begin(), _iso_v.end(), - DoubleAlmostMatches(value)), - _iso_v.end()); - break; - - default: - qtess_cat.warning() - << "Ignoring invalid parameter: " << params[i] << "\n"; - } - } - } else { - double value; - if (!string_to_double(param.substr(1), value)) { - qtess_cat.warning() - << "Ignoring invalid parameter: " << param << "\n"; - } else { - switch (tolower(param[0])) { - case 'u': - _auto_place = false; - _iso_u.push_back(value); - break; - - case 'v': - _auto_place = false; - _iso_v.push_back(value); - break; - - default: - qtess_cat.warning() - << "Ignoring invalid parameter: " << params[i] << "\n"; - } - } - } - } - - // Now sort them into ascending order and remove duplicates. - sort(_iso_u.begin(), _iso_u.end()); - sort(_iso_v.begin(), _iso_v.end()); - _iso_u.erase(unique(_iso_u.begin(), _iso_u.end(), DoublesAlmostEqual()), _iso_u.end()); - _iso_v.erase(unique(_iso_v.begin(), _iso_v.end(), DoublesAlmostEqual()), _iso_v.end()); - - _type = T_uv; -} - - -/** - * May be called a number of times before set_uv() to add specific additional - * isoparams to the tesselation. - */ -void QtessInputEntry:: -add_extra_u_isoparam(double u) { - _iso_u.push_back(u); -} - -/** - * May be called a number of times before set_uv() to add specific additional - * isoparams to the tesselation. - */ -void QtessInputEntry:: -add_extra_v_isoparam(double v) { - _iso_v.push_back(v); -} - -/** - * Tests the surface to see if it matches any of the regular expressions that - * define this node entry. If so, adds it to the set of matched surfaces and - * returns the type of the matching entry. If no match is found, returns - * T_undefined. - */ -QtessInputEntry::Type QtessInputEntry:: -match(QtessSurface *surface) { - const string &name = surface->get_name(); - - NodeNames::const_iterator nni; - for (nni = _node_names.begin(); - nni != _node_names.end(); - ++nni) { - const GlobPattern &pattern = (*nni); - if (pattern.matches(name)) { - // We have a winner! - switch (_type) { - case T_importance: - // A type of "Importance" is a special case. This entry doesn't - // specify any kind of tesselation on the surface, and in fact doesn't - // preclude the surface from matching anything later. It just - // specifies the relative importance of the surface to all the other - // surfaces. - if (qtess_cat.is_debug()) { - qtess_cat.debug() - << "Assigning importance of " << _importance*100.0 - << "% to " << name << "\n"; - } - surface->set_importance(_importance); - return T_undefined; - - case T_match_uu: - case T_match_uv: - // Similarly for type "matchUU". This indicates that all the surfaces - // that match this one must all share the U-tesselation with whichever - // surface first matched against the first node name. - if (nni == _node_names.begin() && _constrain_u==nullptr) { - // This is the lucky surface that dominates! - _constrain_u = surface; - } else { - if (_type == T_match_uu) { - surface->set_match_u(&_constrain_u, true); - } else { - surface->set_match_v(&_constrain_u, false); - } - } - return T_undefined; - - case T_match_vv: - case T_match_vu: - // Ditto for "matchVV". - if (nni == _node_names.begin() && _constrain_v==nullptr) { - // This is the lucky surface that dominates! - _constrain_v = surface; - } else { - if (_type == T_match_vv) { - surface->set_match_v(&_constrain_v, true); - } else { - surface->set_match_u(&_constrain_v, false); - } - } - return T_undefined; - - case T_min_u: - // And for min U and V. - if (qtess_cat.is_debug()) { - qtess_cat.debug() - << "Assigning minimum of " << _num_u << " in U to " - << name << "\n"; - } - surface->set_min_u(_num_u); - return T_undefined; - - case T_min_v: - if (qtess_cat.is_debug()) { - qtess_cat.debug() - << "Assigning minimum of " << _num_v << " in V to " - << name << "\n"; - } - surface->set_min_v(_num_v); - return T_undefined; - - default: - _surfaces.push_back(surface); - if (_auto_distribute) { - _num_patches += surface->get_score(_curvature_ratio); - } else { - _num_patches += surface->count_patches(); - } - return _type; - } - } - } - - return T_undefined; -} - -/** - * Determines the tesselation u,v amounts of each attached surface, and stores - * this information in the surface pointer. Returns the total number of tris - * that will be produced. - */ -int QtessInputEntry:: -count_tris(double tri_factor, int attempts) { - int total_tris = 0; - bool aim_for_tris = false; - - if (_type == T_num_tris && _num_patches > 0.0) { - // If we wanted to aim for a particular number of triangles for the group, - // choose a per-isoparam setting that will approximately achieve this. - if (_auto_distribute) { - set_per_score(sqrt(0.5 * (double)_num_tris / _num_patches / tri_factor)); - } else { - set_per_isoparam(sqrt(0.5 * (double)_num_tris / _num_patches / tri_factor)); - } - aim_for_tris = true; - } - - Surfaces::iterator si; - for (si = _surfaces.begin(); si != _surfaces.end(); ++si) { - QtessSurface *surface = (*si); - - switch (_type) { - case T_undefined: - case T_omit: - surface->omit(); - break; - - case T_uv: - if (!_iso_u.empty() && !_iso_v.empty() && !_auto_place) { - surface->tesselate_specific(_iso_u, _iso_v); - } else { - surface->tesselate_uv(_num_u, _num_v, _auto_place, _curvature_ratio); - } - break; - - case T_per_isoparam: - surface->tesselate_per_isoparam(_per_isoparam, _auto_place, _curvature_ratio); - break; - - case T_per_score: - surface->tesselate_per_score(_per_isoparam, _auto_place, _curvature_ratio); - break; - - default: - break; - } - - total_tris += surface->count_tris(); - } - - if (aim_for_tris && attempts < 10 && - (double)total_tris / (double)_num_tris > 1.1) { - // We'd like to get within 10% of the requested number of triangles, if - // possible. Keep trying until we do, or until we just need to give up. - set_num_tris(_num_tris); - return count_tris(tri_factor * total_tris / _num_tris, attempts + 1); - } - - return total_tris; -} - - -/** - * This function is used to identify the extra isoparams in the list added by - * user control. - */ -void QtessInputEntry:: -output_extra(std::ostream &out, const pvector &iso, char axis) { - pvector::const_iterator di; - int expect = 0; - for (di = iso.begin(); di != iso.end(); ++di) { - while ((*di) > (double)expect) { - // Didn't find one we were expecting. Omit it. - out << " !" << axis << expect; - } - if ((*di)==(double)expect) { - // Here's one we were expecting; ignore it. - expect++; - } else { - // Here's a new one. Write it. - out << " " << axis << *di; - } - } -} - -/** - * - */ -void QtessInputEntry:: -output(std::ostream &out) const { - NodeNames::const_iterator nni; - for (nni = _node_names.begin(); - nni != _node_names.end(); - ++nni) { - out << (*nni) << " "; - } - out << ": "; - - bool show_auto = false; - - switch (_type) { - case T_undefined: - break; - - case T_omit: - out << "omit"; - break; - - case T_num_tris: - out << _num_tris; - show_auto = true; - break; - - case T_uv: - out << _num_u << " " << _num_v; - output_extra(out, _iso_u, 'u'); - output_extra(out, _iso_v, 'v'); - show_auto = true; - break; - - case T_per_isoparam: - case T_per_score: - out << "i" << _per_isoparam; - show_auto = true; - break; - - case T_importance: - out << _importance * 100.0 << "%"; - break; - - case T_match_uu: - out << "matchuu"; - break; - - case T_match_vv: - out << "matchvv"; - break; - - case T_match_uv: - out << "matchuv"; - break; - - case T_match_vu: - out << "matchvu"; - break; - - case T_min_u: - out << "minu " << _num_u; - break; - - case T_min_v: - out << "minv " << _num_v; - break; - - default: - out << "Invalid!"; - } - - if (show_auto) { - out << " " << (_auto_place?"":"!") << "ap" - << " " << (_auto_distribute?"":"!") << "ad"; - if (_auto_place || _auto_distribute) { - out << " ar" << _curvature_ratio; - } - } -} - -/** - * - */ -void QtessInputEntry:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) << (*this) << "\n"; -} diff --git a/pandatool/src/egg-qtess/qtessInputEntry.h b/pandatool/src/egg-qtess/qtessInputEntry.h deleted file mode 100644 index bffcca0d..00000000 --- a/pandatool/src/egg-qtess/qtessInputEntry.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessInputEntry.h - * @author drose - * @date 2003-10-13 - */ - -#ifndef QTESSINPUTENTRY_H -#define QTESSINPUTENTRY_H - -#include "pandatoolbase.h" -#include "globPattern.h" -#include "pvector.h" - -class QtessSurface; - -/** - * Stores one entry in the qtess input file. This consists of a list of name - * patterns and a set of tesselation parameters. - */ -class QtessInputEntry { -public: - enum Type { - T_undefined, T_omit, T_num_tris, T_uv, T_per_isoparam, T_per_score, - T_importance, T_match_uu, T_match_vv, T_match_uv, T_match_vu, - T_min_u, T_min_v - }; - - QtessInputEntry(const std::string &name = std::string()); - INLINE QtessInputEntry(const QtessInputEntry ©); - void operator = (const QtessInputEntry ©); - - INLINE void add_node_name(const std::string &name); - INLINE void set_importance(double i); - INLINE void set_match_uu(); - INLINE void set_match_vv(); - INLINE void set_match_uv(); - INLINE void set_match_vu(); - INLINE void set_min_u(int min_u); - INLINE void set_min_v(int min_v); - INLINE void set_undefined(); - INLINE void set_omit(); - INLINE void set_num_tris(int nt); - INLINE void set_uv(int u, int v); - void set_uv(int u, int v, const std::string params[], int num_params); - INLINE void set_per_isoparam(double pi); - INLINE void set_per_score(double pi); - void add_extra_u_isoparam(double u); - void add_extra_v_isoparam(double u); - - Type match(QtessSurface *surface); - INLINE int get_num_surfaces() const; - int count_tris(double tri_factor = 1.0, int attempts = 0); - - static void output_extra(std::ostream &out, const pvector &iso, char axis); - void output(std::ostream &out) const; - void write(std::ostream &out, int indent_level) const; - - bool _auto_place, _auto_distribute; - double _curvature_ratio; - double _importance; - QtessSurface *_constrain_u, *_constrain_v; - -private: - typedef pvector NodeNames; - NodeNames _node_names; - - int _num_tris; - int _num_u, _num_v; - double _per_isoparam; - pvector _iso_u, _iso_v; - Type _type; - - typedef pvector Surfaces; - Surfaces _surfaces; - - double _num_patches; -}; - -INLINE std::ostream &operator << (std::ostream &out, const QtessInputEntry &entry); - -#include "qtessInputEntry.I" - -#endif diff --git a/pandatool/src/egg-qtess/qtessInputFile.I b/pandatool/src/egg-qtess/qtessInputFile.I deleted file mode 100644 index 313b59c8..00000000 --- a/pandatool/src/egg-qtess/qtessInputFile.I +++ /dev/null @@ -1,29 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessInputFile.I - * @author drose - * @date 2003-10-13 - */ - -/** - * - */ -INLINE QtessInputFile:: -QtessInputFile(const QtessInputFile ©) : - _entries(copy._entries) -{ -} - -/** - * - */ -INLINE void QtessInputFile:: -operator = (const QtessInputFile ©) { - _entries = copy._entries; -} diff --git a/pandatool/src/egg-qtess/qtessInputFile.cxx b/pandatool/src/egg-qtess/qtessInputFile.cxx deleted file mode 100644 index 180a2e95..00000000 --- a/pandatool/src/egg-qtess/qtessInputFile.cxx +++ /dev/null @@ -1,327 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessInputFile.cxx - * @author drose - * @date 2003-10-13 - */ - -#include "qtessInputFile.h" -#include "config_egg_qtess.h" -#include "string_utils.h" - -using std::string; - -/** - * - */ -QtessInputFile:: -QtessInputFile() { -} - -/** - * reads the input file. - */ -bool QtessInputFile:: -read(const Filename &filename) { - _filename = Filename::text_filename(filename); - _entries.clear(); - - std::ifstream input; - if (!_filename.open_read(input)) { - qtess_cat.error() - << "Unable to open input file " << _filename << "\n"; - return false; - } - - string complete_line; - - int line_number = 0; - string line; - while (std::getline(input, line)) { - line_number++; - - // Eliminate comments. We have to scan the line repeatedly until we find - // the first hash mark that's preceded by whitespace. - size_t comment = line.find('#'); - while (comment != string::npos) { - if (comment == 0 || isspace(line[comment - 1])) { - line = line.substr(0, comment); - comment = string::npos; - - } else { - comment = line.find('#', comment + 1); - } - } - - // Check for a trailing backslash: continuation character. - line = trim_right(line); - if (!line.empty() && line[line.size() - 1] == '\\') { - // We have a continuation character; go back and read some more. - complete_line += line.substr(0, line.size() - 1); - - } else { - // It's a complete line. Begin parsing. - line = trim(complete_line + line); - complete_line = string(); - - if (!line.empty()) { - QtessInputEntry entry; - - // Scan for the first colon followed by whitespace. - size_t colon = line.find(": "); - if (colon == string::npos) { - qtess_cat.error() - << _filename << ": line " << line_number - << " has no colon followed by whitespace.\n"; - return false; - } - if (colon == 0) { - qtess_cat.error() - << _filename << ": line " << line_number - << " has no nodes.\n"; - return false; - } - - // Split the line into two groups of words at the colon: names before - // the colon, and params following it. - vector_string names, params; - extract_words(line.substr(0, colon), names); - extract_words(line.substr(colon + 1), params); - - vector_string::const_iterator ni; - for (ni = names.begin(); ni != names.end(); ++ni) { - entry.add_node_name(*ni); - } - - // Scan for things like ap, ad, ar, and pull them out of the stream. - vector_string::iterator ci, cnext; - ci = params.begin(); - while (ci != params.end()) { - cnext = ci; - ++cnext; - - string param = *ci; - bool invert = false; - if (param[0] == '!' && param.size() > 1) { - invert = true; - param = param.substr(1); - } - if (tolower(param[0]) == 'a' && param.size() > 1) { - switch (tolower(param[1])) { - case 'p': - entry._auto_place = !invert; - break; - - case 'd': - entry._auto_distribute = !invert; - break; - - case 'r': - if (!string_to_double(param.substr(2), entry._curvature_ratio)) { - qtess_cat.error() - << _filename << ": line " << line_number - << " - invalid field " << param << "\n"; - return false; - } - break; - - default: - qtess_cat.error() - << _filename << ": invalid parameters at line " - << line_number << ".\n"; - return false; - } - params.erase(ci); - } else { - ci = cnext; - } - } - - if (!params.empty()) { - bool okflag = true; - if (cmp_nocase(params[0], "omit")==0) { - entry.set_omit(); - - } else if (cmp_nocase(params[0], "matchuu")==0) { - entry.set_match_uu(); - if (params.size() > 1 && cmp_nocase(params[1], "matchvv")==0) { - entry.set_match_vv(); - } - - } else if (cmp_nocase(params[0], "matchvv")==0) { - entry.set_match_vv(); - if (params.size() > 1 && cmp_nocase(params[1], "matchuu")==0) { - entry.set_match_uu(); - } - - } else if (cmp_nocase(params[0], "matchuv")==0) { - entry.set_match_uv(); - if (params.size() > 1 && cmp_nocase(params[1], "matchvu")==0) { - entry.set_match_vu(); - } - - } else if (cmp_nocase(params[0], "matchvu")==0) { - entry.set_match_vu(); - if (params.size() > 1 && cmp_nocase(params[1], "matchuv")==0) { - entry.set_match_uv(); - } - - } else if (cmp_nocase(params[0], "minu")==0) { - // minu #: minimum tesselation in U. - if (params.size() < 2) { - okflag = false; - } else { - int value = 0; - okflag = string_to_int(params[1], value); - entry.set_min_u(value); - } - - } else if (cmp_nocase(params[0], "minv")==0) { - // minu #: minimum tesselation in V. - if (params.size() < 2) { - okflag = false; - } else { - int value = 0; - okflag = string_to_int(params[1], value); - entry.set_min_v(value); - } - - } else if (tolower(params[0][0]) == 'i') { - // "i#": per-isoparam tesselation. - int value = 0; - okflag = string_to_int(params[0].substr(1), value); - entry.set_per_isoparam(value); - - } else if (params[0][params[0].length() - 1] == '%') { - double value = 0.0; - okflag = string_to_double(params[0].substr(0, params[0].length() - 1), value); - entry.set_importance(value / 100.0); - - } else if (params.size() == 1) { - // One numeric parameter: the number of triangles. - int value = 0; - okflag = string_to_int(params[0], value); - entry.set_num_tris(value); - - } else if (params.size() >= 2) { - // Two or more numeric parameters: the number of u by v quads, - // followed by an optional list of specific isoparams. - int u = 0, v = 0; - okflag = string_to_int(params[0], u) && string_to_int(params[1], v); - entry.set_uv(u, v, ¶ms[2], params.size() - 2); - - } else { - okflag = false; - } - - if (!okflag) { - qtess_cat.error() - << _filename << ": invalid parameters at line " - << line_number << ".\n"; - return false; - } - } - _entries.push_back(entry); - } - } - } - - if (qtess_cat.is_info()) { - qtess_cat.info() - << "read qtess parameter file " << _filename << ".\n"; - if (qtess_cat.is_debug()) { - write(qtess_cat.debug(false)); - } - } - - add_default_entry(); - - return true; -} - -/** - * Returns a reference to the last entry on the list, which is the "default" - * entry that will match any surface that does not get explicitly named in the - * input file. - */ -QtessInputEntry &QtessInputFile:: -get_default_entry() { - if (_entries.empty()) { - // No entries; create one. - add_default_entry(); - } - return _entries.back(); -} - - -/** - * Attempts to find a match for the given surface in the user input entries. - * Searches in the order in which the entries were defined, and chooses the - * first match. - * - * When a match is found, the surface is added to the entry's set of matched - * surfaces. Returns the type of the matching node if a match is found, or - * T_undefined otherwise. - */ -QtessInputEntry::Type QtessInputFile:: -match(QtessSurface *surface) { - QtessInputEntry::Type type; - - if (_entries.empty()) { - // No entries; create one. - add_default_entry(); - } - - Entries::iterator ei; - for (ei = _entries.begin(); ei != _entries.end(); ++ei) { - type = (*ei).match(surface); - if (type != QtessInputEntry::T_undefined) { - return type; - } - } - return QtessInputEntry::T_undefined; -} - -/** - * Determines the tesselation u,v amounts of each attached surface, and stores - * this information in the surface pointer. Returns the total number of tris - * that will be produced. - */ -int QtessInputFile:: -count_tris() { - int total_tris = 0; - - Entries::iterator ei; - for (ei = _entries.begin(); ei != _entries.end(); ++ei) { - total_tris += (*ei).count_tris(); - } - return total_tris; -} - -/** - * - */ -void QtessInputFile:: -write(std::ostream &out, int indent_level) const { - Entries::const_iterator ei; - for (ei = _entries.begin(); ei != _entries.end(); ++ei) { - (*ei).write(out, indent_level); - } -} - -/** - * Adds one more entry to the end of the list, to catch all of the surfaces - * that didn't get explicitly named. - */ -void QtessInputFile:: -add_default_entry() { - QtessInputEntry entry("*"); - entry.set_omit(); - _entries.push_back(entry); -} diff --git a/pandatool/src/egg-qtess/qtessInputFile.h b/pandatool/src/egg-qtess/qtessInputFile.h deleted file mode 100644 index c5cb5fab..00000000 --- a/pandatool/src/egg-qtess/qtessInputFile.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessInputFile.h - * @author drose - * @date 2003-10-13 - */ - -#ifndef QTESSINPUTFILE_H -#define QTESSINPUTFILE_H - -#include "pandatoolbase.h" -#include "qtessInputEntry.h" -#include "filename.h" -#include "pvector.h" -#include "vector_double.h" - -class QtessSurface; - -/** - * Stores all the information read from a tesselation input file: a list of - * QtessInputEntry's. - */ -class QtessInputFile { -public: - QtessInputFile(); - INLINE QtessInputFile(const QtessInputFile ©); - INLINE void operator = (const QtessInputFile ©); - - bool read(const Filename &filename); - QtessInputEntry &get_default_entry(); - - QtessInputEntry::Type match(QtessSurface *surface); - int count_tris(); - - void write(std::ostream &out, int indent_level = 0) const; - -private: - void add_default_entry(); - - Filename _filename; - - typedef pvector Entries; - Entries _entries; -}; - -#include "qtessInputFile.I" - -#endif diff --git a/pandatool/src/egg-qtess/qtessSurface.I b/pandatool/src/egg-qtess/qtessSurface.I deleted file mode 100644 index d65f82c3..00000000 --- a/pandatool/src/egg-qtess/qtessSurface.I +++ /dev/null @@ -1,154 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessSurface.I - * @author drose - * @date 2003-10-13 - */ - -/** - * - */ -INLINE const std::string &QtessSurface:: -get_name() const { - return _egg_surface->get_name(); -} - -/** - * Returns true if the defined surface is valid, false otherwise. - */ -INLINE bool QtessSurface:: -is_valid() const { - return (_nurbs != nullptr); -} - -/** - * Sets the importance of the surface, as a ratio in proportion to the square - * of its size. - */ -INLINE void QtessSurface:: -set_importance(double importance2) { - _importance = sqrt(importance2); - _importance2 = importance2; -} - -/** - * Indicates the surface to which this surface must match in its U direction. - * If u_to_u is true, it matches to the other surface's U direction; - * otherwise, it matches to the other surface's V direction. - * - * Note that the surface pointer is an indirect pointer. The value passed in - * is the address of the pointer to the actual surface (which may or may not - * be filled in yet). The actual pointer may be filled in later. - */ -INLINE void QtessSurface:: -set_match_u(QtessSurface **match_u, bool match_u_to_u) { - _match_u = match_u; - _match_u_to_u = match_u_to_u; -} - -/** - * Indicates the surface to which this surface must match in its V direction. - * If v_to_v is true, it matches to the other surface's V direction; - * otherwise, it matches to the other surface's U direction. - * - * Note that the surface pointer is an indirect pointer. The value passed in - * is the address of the pointer to the actual surface (which may or may not - * be filled in yet). The actual pointer may be filled in later. - */ -INLINE void QtessSurface:: -set_match_v(QtessSurface **match_v, bool match_v_to_v) { - _match_v = match_v; - _match_v_to_v = match_v_to_v; -} - -/** - * Specifies the absolute minimum number of segments allowed in the U - * direction. - */ -INLINE void QtessSurface:: -set_min_u(int min_u) { - _min_u = min_u; -} - -/** - * Specifies the absolute minimum number of segments allowed in the V - * direction. - */ -INLINE void QtessSurface:: -set_min_v(int min_v) { - _min_v = min_v; -} - - -/** - * Returns the number of patches the NURBS contains. Each patch is a square - * area bounded by isoparams. This actually scales by the importance of the - * surface, if it is not 1. - */ -INLINE double QtessSurface:: -count_patches() const { - return _num_u * _num_v * _importance2; -} - -/** - * Returns the number of triangles that will be generated by the current - * tesselation parameters. - */ -INLINE int QtessSurface:: -count_tris() const { - return _tess_u * _tess_v * 2; -} - -/** - * Returns the extra dimension number within the surface where the vertex - * membership in the indicated joint should be stored. - */ -INLINE int QtessSurface:: -get_joint_membership_index(EggGroup *joint) { - JointTable::iterator jti = _joint_table.find(joint); - if (jti != _joint_table.end()) { - return (*jti).second; - } - int d = _next_d; - _next_d++; - _joint_table[joint] = d; - return d; -} - -/** - * Returns the extra dimension number within the surface where the indicated - * Dxyz morph offset should be stored. - */ -INLINE int QtessSurface:: -get_dxyz_index(const std::string &morph_name) { - MorphTable::iterator mti = _dxyz_table.find(morph_name); - if (mti != _dxyz_table.end()) { - return (*mti).second; - } - int d = _next_d; - _next_d += 3; - _dxyz_table[morph_name] = d; - return d; -} - -/** - * Returns the extra dimension number within the surface where the indicated - * Drgba morph offset should be stored. - */ -INLINE int QtessSurface:: -get_drgba_index(const std::string &morph_name) { - MorphTable::iterator mti = _drgba_table.find(morph_name); - if (mti != _drgba_table.end()) { - return (*mti).second; - } - int d = _next_d; - _next_d += 4; - _drgba_table[morph_name] = d; - return d; -} diff --git a/pandatool/src/egg-qtess/qtessSurface.cxx b/pandatool/src/egg-qtess/qtessSurface.cxx deleted file mode 100644 index d7ccebe7..00000000 --- a/pandatool/src/egg-qtess/qtessSurface.cxx +++ /dev/null @@ -1,565 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessSurface.cxx - * @author drose - * @date 2003-10-13 - */ - -#include "qtessSurface.h" -#include "qtessGlobals.h" -#include "qtessInputEntry.h" -#include "config_egg_qtess.h" -#include "eggPolygon.h" -#include "eggVertexPool.h" -#include "eggVertex.h" -#include "eggComment.h" -#include "egg_parametrics.h" -#include "pset.h" -#include "pmap.h" - -using std::max; -using std::string; - -/** - * - */ -QtessSurface:: -QtessSurface(EggNurbsSurface *egg_surface) : - _egg_surface(egg_surface) -{ - _nurbs = make_nurbs_surface(_egg_surface, LMatrix4d::ident_mat()); - _has_vertex_color = _egg_surface->has_vertex_color(); - - // The first four slots are reserved for vertex color. - _next_d = 4; - - _importance = 1.0; - _importance2 = 1.0; - _match_u = _match_v = nullptr; - _tess_u = _tess_v = 0; - _got_scores = false; - - // If the surface is closed in either dimension, the mininum tesselation in - // that dimension is by default 3, so we don't ribbonize the surface. - // Otherwise the minimum is 1. - _min_u = _min_v = 1; - if (egg_surface->is_closed_u()) { - _min_u = 3; - } - if (egg_surface->is_closed_v()) { - _min_v = 3; - } - - if (_nurbs == nullptr) { - _num_u = _num_v = 0; - - } else { - record_vertex_extras(); - - _nurbs->normalize_u_knots(); - _nurbs->normalize_v_knots(); - _nurbs_result = _nurbs->evaluate(); - - _num_u = _nurbs->get_num_u_segments(); - _num_v = _nurbs->get_num_v_segments(); - - if (QtessGlobals::_respect_egg) { - if (egg_surface->get_u_subdiv() != 0) { - _num_u = egg_surface->get_u_subdiv(); - } - if (egg_surface->get_v_subdiv() != 0) { - _num_v = egg_surface->get_v_subdiv(); - } - } - } -} - -/** - * Computes the curvature/stretch score for the surface, if it has not been - * already computed, and returns the net surface score. This is used both for - * automatically distributing isoparams among the surfaces by curvature, as - * well as for automatically placing the isoparams within each surface by - * curvature. - */ -double QtessSurface:: -get_score(double ratio) { - if (_nurbs == nullptr) { - return 0.0; - } - - if (!_got_scores) { - _u_placer.get_scores(_nurbs->get_num_u_segments() * 100, - _nurbs->get_num_v_segments() * 2, - ratio, _nurbs_result, true); - _v_placer.get_scores(_nurbs->get_num_v_segments() * 100, - _nurbs->get_num_u_segments() * 2, - ratio, _nurbs_result, false); - _got_scores = true; - } - - return _u_placer.get_total_score() * _v_placer.get_total_score() * _importance2; -} - -/** - * Applies the appropriate tesselation to the surface, and replaces its node - * in the tree with an EggGroup containing both the new vertex pool and all of - * the polygons. - */ -int QtessSurface:: -tesselate() { - apply_match(); - int tris = 0; - - PT(EggGroup) group = do_uniform_tesselate(tris); - PT(EggNode) new_node = group.p(); - if (new_node == nullptr) { - new_node = new EggComment(_egg_surface->get_name(), - "Omitted NURBS surface."); - tris = 0; - } - EggGroupNode *parent = _egg_surface->get_parent(); - nassertr(parent != nullptr, 0); - parent->remove_child(_egg_surface); - parent->add_child(new_node); - - return tris; -} - -/** - * Writes a line to the given output file telling qtess how this surface - * should be tesselated uniformly. Returns the number of tris. - */ -int QtessSurface:: -write_qtess_parameter(std::ostream &out) { - apply_match(); - - if (_tess_u == 0 || _tess_v == 0) { - out << get_name() << " : omit\n"; - - } else if (_iso_u.empty() || _iso_v.empty()) { - out << get_name() << " : " << _tess_u << " " << _tess_v << "\n"; - - } else { - out << get_name() << " : " << _iso_u.back() << " " << _iso_v.back(); - QtessInputEntry::output_extra(out, _iso_u, 'u'); - QtessInputEntry::output_extra(out, _iso_v, 'v'); - out << "\n"; - } - - return count_tris(); -} - - -/** - * Sets up the surface to omit itself from the output. - */ -void QtessSurface:: -omit() { - _tess_u = 0; - _tess_v = 0; -} - -/** - * Sets the surface up to tesselate itself uniformly at u x v, or if autoplace - * is true, automatically with u x v quads. - */ -void QtessSurface:: -tesselate_uv(int u, int v, bool autoplace, double ratio) { - _tess_u = u; - _tess_v = v; - _iso_u.clear(); - _iso_v.clear(); - if (autoplace) { - tesselate_auto(_tess_u, _tess_v, ratio); - } -} - -/** - * Sets the surface up to tesselate itself at specific isoparams only. - */ -void QtessSurface:: -tesselate_specific(const pvector &u_list, - const pvector &v_list) { - _iso_u = u_list; - _iso_v = v_list; - _tess_u = (int)_iso_u.size() - 1; - _tess_v = (int)_iso_v.size() - 1; -} - -/** - * Sets the surface up to tesselate itself to a uniform amount per isoparam. - */ -void QtessSurface:: -tesselate_per_isoparam(double pi, bool autoplace, double ratio) { - if (_num_u == 0 || _num_v == 0) { - omit(); - - } else { - _tess_u = max(_min_u, (int)floor(_num_u * _importance * pi + 0.5)); - _tess_v = max(_min_v, (int)floor(_num_v * _importance * pi + 0.5)); - _iso_u.clear(); - _iso_v.clear(); - if (autoplace) { - tesselate_auto(_tess_u, _tess_v, ratio); - } - } -} - - -/** - * Sets the surface up to tesselate itself according to its computed curvature - * score in both dimensions. - */ -void QtessSurface:: -tesselate_per_score(double pi, bool autoplace, double ratio) { - if (get_score(ratio) <= 0.0) { - omit(); - - } else { - _tess_u = max(_min_u, (int)floor(_u_placer.get_total_score() * _importance * pi + 0.5)); - _tess_v = max(_min_v, (int)floor(_v_placer.get_total_score() * _importance * pi + 0.5)); - _iso_u.clear(); - _iso_v.clear(); - if (autoplace) { - tesselate_auto(_tess_u, _tess_v, ratio); - } - } -} - -/** - * Sets the surface up to tesselate itself by automatically determining the - * best place to put the indicated u x v isoparams. - */ -void QtessSurface:: -tesselate_auto(int u, int v, double ratio) { - if (get_score(ratio) <= 0.0) { - omit(); - - } else { - _u_placer.place(u, _iso_u); - _v_placer.place(v, _iso_v); - _tess_u = (int)_iso_u.size() - 1; - _tess_v = (int)_iso_v.size() - 1; - } -} - -/** - * Records the joint membership and morph offsets of each control vertex in - * the extra-dimensional space of the NURBS, so that we can extract this data - * out again later to apply to the polygon vertices. - */ -void QtessSurface:: -record_vertex_extras() { - int num_u_vertices = _egg_surface->get_num_u_cvs(); - int num_v_vertices = _egg_surface->get_num_v_cvs(); - - for (int ui = 0; ui < num_u_vertices; ui++) { - for (int vi = 0; vi < num_v_vertices; vi++) { - int i = _egg_surface->get_vertex_index(ui, vi); - EggVertex *egg_vertex = _egg_surface->get_vertex(i); - - // The joint membership. - EggVertex::GroupRef::const_iterator gi; - for (gi = egg_vertex->gref_begin(); gi != egg_vertex->gref_end(); ++gi) { - EggGroup *joint = (*gi); - int d = get_joint_membership_index(joint); - double membership = joint->get_vertex_membership(egg_vertex); - _nurbs->set_extended_vertex(ui, vi, d, membership); - } - - // The xyz morphs. - EggMorphVertexList::const_iterator dxi; - for (dxi = egg_vertex->_dxyzs.begin(); - dxi != egg_vertex->_dxyzs.end(); - ++dxi) { - const string &morph_name = (*dxi).get_name(); - LVector3 delta = LCAST(PN_stdfloat, (*dxi).get_offset()); - int d = get_dxyz_index(morph_name); - _nurbs->set_extended_vertices(ui, vi, d, delta.get_data(), 3); - } - - // The rgba morphs. - EggMorphColorList::const_iterator dri; - for (dri = egg_vertex->_drgbas.begin(); - dri != egg_vertex->_drgbas.end(); - ++dri) { - const string &morph_name = (*dri).get_name(); - const LVector4 &delta = (*dri).get_offset(); - int d = get_drgba_index(morph_name); - _nurbs->set_extended_vertices(ui, vi, d, delta.get_data(), 4); - } - } - } -} - -/** - * If the surface was set up to copy its tesselation in either axis from - * another surface, makes this copy now. - */ -void QtessSurface:: -apply_match() { - if (_match_u != nullptr) { - QtessSurface *m = *_match_u; - if (m == nullptr) { - qtess_cat.warning() - << "No surface to match " << get_name() << " to in U.\n"; - } else { - if (qtess_cat.is_debug()) { - qtess_cat.debug() - << "Matching " << get_name() << " in U to " << m->get_name() - << " in " << (_match_u_to_u?'U':'V') << ".\n"; - } - if (_match_u_to_u) { - _tess_u = m->_tess_u; - _iso_u = m->_iso_u; - } else { - _tess_u = m->_tess_v; - _iso_u = m->_iso_v; - } - } - } - - if (_match_v != nullptr) { - QtessSurface *m = *_match_v; - if (m == nullptr) { - qtess_cat.warning() - << "No surface to match " << get_name() << " in V.\n"; - } else { - if (qtess_cat.is_debug()) { - qtess_cat.debug() - << "Matching " << get_name() << " in V to " << m->get_name() - << " in " << (_match_v_to_v?'V':'U') << ".\n"; - } - if (_match_v_to_v) { - _tess_v = m->_tess_v; - _iso_v = m->_iso_v; - } else { - _tess_v = m->_tess_u; - _iso_v = m->_iso_u; - } - } - } -} - -/** - * Subdivide the surface uniformly according to the parameters specified by an - * earlier call to omit(), teseselate_uv(), or tesselate_per_isoparam(). - */ -PT(EggGroup) QtessSurface:: -do_uniform_tesselate(int &tris) const { - tris = 0; - - if (_tess_u == 0 || _tess_v == 0) { - // No tesselation! - if (qtess_cat.is_debug()) { - qtess_cat.debug() - << get_name() << " : omit\n"; - } - return nullptr; - } - - PT(EggGroup) group = new EggGroup(_egg_surface->get_name()); - - // _tess_u and _tess_v are the number of patches to create. Convert that to - // the number of vertices. - - int num_u = _tess_u + 1; - int num_v = _tess_v + 1; - - if (qtess_cat.is_debug()) { - qtess_cat.debug() << get_name() << " : " << tris << "\n"; - } - - assert(_iso_u.empty() || (int)_iso_u.size() == num_u); - assert(_iso_v.empty() || (int)_iso_v.size() == num_v); - - // Now how many vertices is that total, and how many vertices per strip? - int num_verts = num_u * num_v; - - // Create a vertex pool. - PT(EggVertexPool) vpool = new EggVertexPool(_egg_surface->get_name()); - group->add_child(vpool); - - // Create all the vertices. - int ui, vi; - double u, v; - - typedef pvector VertexList; - VertexList new_verts; - new_verts.reserve(num_verts); - - // Also collect the vertices into this set to group them by spatial position - // only. This is relevant for calculating normals. - typedef pset NVertexGroup; - typedef pmap NVertexCollection; - NVertexCollection n_collection; - - for (vi = 0; vi < num_v; vi++) { - if (_iso_v.empty()) { - v = (double)vi / (double)(num_v-1); - } else { - v = _iso_v[vi] / _iso_v.back(); - } - for (ui = 0; ui < num_u; ui++) { - if (_iso_u.empty()) { - u = (double)ui / (double)(num_u-1); - } else { - u = _iso_u[ui] / _iso_u.back(); - } - - PT(EggVertex) egg_vertex = evaluate_vertex(u, v); - vpool->add_vertex(egg_vertex); - new_verts.push_back(egg_vertex); - n_collection[egg_vertex->get_pos3()].insert(egg_vertex); - } - } - nassertr((int)new_verts.size() == num_verts, nullptr); - - // Now create a bunch of quads. - for (vi = 1; vi < num_v; vi++) { - for (ui = 1; ui < num_u; ui++) { - PT(EggPolygon) poly = new EggPolygon; - poly->add_vertex(new_verts[vi*num_u + (ui-1)]); - poly->add_vertex(new_verts[(vi-1)*num_u + (ui-1)]); - poly->add_vertex(new_verts[(vi-1)*num_u + ui]); - poly->add_vertex(new_verts[vi*num_u + ui]); - - poly->copy_attributes(*_egg_surface); - - // We compute a polygon normal just so we can verify the calculated - // vertex normals. It's also helpful for identifying degenerate - // polygons. - if (poly->recompute_polygon_normal()) { - tris += 2; - group->add_child(poly); - } - } - } - - // Now check all the vertex normals by comparing them to the polygon - // normals. Some might have not been computed at all; others might be - // facing in the wrong direction. - - // Now go back through and normalize the computed normals. - NVertexCollection::const_iterator nci; - for (nci = n_collection.begin(); nci != n_collection.end(); ++nci) { - const NVertexGroup &group = (*nci).second; - - // Calculate the normal these vertices should have based on the polygons - // that share it. - LNormald normal = LNormald::zero(); - int num_polys = 0; - NVertexGroup::const_iterator ngi; - for (ngi = group.begin(); ngi != group.end(); ++ngi) { - EggVertex *egg_vertex = (*ngi); - EggVertex::PrimitiveRef::const_iterator pri; - for (pri = egg_vertex->pref_begin(); - pri != egg_vertex->pref_end(); - ++pri) { - EggPrimitive *egg_primitive = (*pri); - nassertr(egg_primitive->has_normal(), nullptr); - normal += egg_primitive->get_normal(); - num_polys++; - } - } - - if (num_polys > 0) { - normal /= (double)num_polys; - - // Now compare this normal with what the NURBS representation - // calculated. It should be facing in at least vaguely the same - // direction. - for (ngi = group.begin(); ngi != group.end(); ++ngi) { - EggVertex *egg_vertex = (*ngi); - if (egg_vertex->has_normal()) { - if (normal.dot(egg_vertex->get_normal()) < 0.0) { - // This one is backwards. - egg_vertex->set_normal(-egg_vertex->get_normal()); - } - } else { - // This vertex doesn't have a normal; it gets the computed normal. - egg_vertex->set_normal(normal); - } - } - } - } - - return group; -} - -/** - * Evaluates the surface at the given u, v position and sets the vertex to the - * appropriate values. Also sets the joint membership of the vertex. - */ -PT(EggVertex) QtessSurface:: -evaluate_vertex(double u, double v) const { - PT(EggVertex) egg_vertex = new EggVertex; - - LVertex point; - LNormal normal; - _nurbs_result->eval_point(u, v, point); - _nurbs_result->eval_normal(u, v, normal); - - // If the normal is too short, don't consider it--it's probably inaccurate - // due to numerical limitations. We'll recompute it later based on the - // polygon normals. - PN_stdfloat length = normal.length(); - if (length > 0.0001f) { - normal /= length; - egg_vertex->set_normal(LCAST(double, normal)); - } - - egg_vertex->set_pos(LCAST(double, point)); - egg_vertex->set_uv(LVecBase2d(u, v)); - - // The color is stored, by convention, in slots 0-4 of the surface. - if (_has_vertex_color) { - LColor rgba; - _nurbs_result->eval_extended_points(u, v, 0, &rgba[0], 4); - egg_vertex->set_color(rgba); - } - - // Also fill in the joint membership. - JointTable::const_iterator jti; - for (jti = _joint_table.begin(); jti != _joint_table.end(); ++jti) { - EggGroup *joint = (*jti).first; - int d = (*jti).second; - - double membership = _nurbs_result->eval_extended_point(u, v, d); - if (membership > 0.0) { - joint->ref_vertex(egg_vertex, membership); - } - } - - // And the morphs. - MorphTable::const_iterator mti; - for (mti = _dxyz_table.begin(); mti != _dxyz_table.end(); ++mti) { - const string &morph_name = (*mti).first; - int d = (*mti).second; - - LVector3 delta; - _nurbs_result->eval_extended_points(u, v, d, &delta[0], 3); - if (!delta.almost_equal(LVector3::zero())) { - egg_vertex->_dxyzs.insert(EggMorphVertex(morph_name, LCAST(double, delta))); - } - } - - for (mti = _drgba_table.begin(); mti != _drgba_table.end(); ++mti) { - const string &morph_name = (*mti).first; - int d = (*mti).second; - - LVector4 delta; - _nurbs_result->eval_extended_points(u, v, d, &delta[0], 4); - if (!delta.almost_equal(LVector4::zero())) { - egg_vertex->_drgbas.insert(EggMorphColor(morph_name, delta)); - } - } - - return egg_vertex; -} diff --git a/pandatool/src/egg-qtess/qtessSurface.h b/pandatool/src/egg-qtess/qtessSurface.h deleted file mode 100644 index fc3720e5..00000000 --- a/pandatool/src/egg-qtess/qtessSurface.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file qtessSurface.h - * @author drose - * @date 2003-10-13 - */ - -#ifndef QTESSSURFACE_H -#define QTESSSURFACE_H - -#include "pandatoolbase.h" -#include "isoPlacer.h" -#include "eggNurbsSurface.h" -#include "eggGroup.h" -#include "eggVertex.h" -#include "nurbsSurfaceEvaluator.h" -#include "nurbsSurfaceResult.h" -#include "referenceCount.h" -#include "pointerTo.h" - -/** - * A reference to an EggNurbsSurface in the egg file, and its parameters as - * set by the user input file and as computed in relation to the other - * surfaces. - */ -class QtessSurface : public ReferenceCount { -public: - QtessSurface(EggNurbsSurface *egg_surface); - - INLINE const std::string &get_name() const; - INLINE bool is_valid() const; - - INLINE void set_importance(double importance2); - INLINE void set_match_u(QtessSurface **match_u, bool match_u_to_u); - INLINE void set_match_v(QtessSurface **match_v, bool match_v_to_v); - INLINE void set_min_u(int min_u); - INLINE void set_min_v(int min_v); - - INLINE double count_patches() const; - INLINE int count_tris() const; - - double get_score(double ratio); - - int tesselate(); - int write_qtess_parameter(std::ostream &out); - void omit(); - void tesselate_uv(int u, int v, bool autoplace, double ratio); - void tesselate_specific(const pvector &u_list, - const pvector &v_list); - void tesselate_per_isoparam(double pi, bool autoplace, double ratio); - void tesselate_per_score(double pi, bool autoplace, double ratio); - void tesselate_auto(int u, int v, double ratio); - -private: - void record_vertex_extras(); - INLINE int get_joint_membership_index(EggGroup *joint); - INLINE int get_dxyz_index(const std::string &morph_name); - INLINE int get_drgba_index(const std::string &morph_name); - - void apply_match(); - PT(EggGroup) do_uniform_tesselate(int &tris) const; - PT(EggVertex) evaluate_vertex(double u, double v) const; - - PT(EggNurbsSurface) _egg_surface; - PT(NurbsSurfaceEvaluator) _nurbs; - PT(NurbsSurfaceResult) _nurbs_result; - bool _has_vertex_color; - - // Mapping arbitrary attributes to integer extended dimension values, so we - // can hang arbitrary data in the extra dimensional space of the surface. - int _next_d; - typedef std::map JointTable; - JointTable _joint_table; - typedef std::map MorphTable; - MorphTable _dxyz_table; - MorphTable _drgba_table; - - int _num_u, _num_v; - int _tess_u, _tess_v; - pvector _iso_u, _iso_v; // If nonempty, isoparams at which to tess. - - // _importance is the relative importance of the surface along either axis; - // _importance2 is this number squared, which is the value set by - // set_importance(). - double _importance; - double _importance2; - - // _match_u and _match_v indicate which surface we must match exactly for - // tesselation in U or V. This helps get edges to line up properly. They - // are indirect pointers because we go through the surfaces in one pass, and - // might need to fill in the correct value later. - QtessSurface **_match_u, **_match_v; - bool _match_u_to_u, _match_v_to_v; - - // _min_u and _min_v specify a mininum number of quads below which we should - // not attempt to subdivide the surface in either dimension. This is - // intended to prevent degenerate cases like knife-fingers. - int _min_u, _min_v; - - IsoPlacer _u_placer, _v_placer; - bool _got_scores; -}; - -#include "qtessSurface.I" - -#endif diff --git a/pandatool/src/egg-qtess/subdivSegment.I b/pandatool/src/egg-qtess/subdivSegment.I deleted file mode 100644 index 2210032e..00000000 --- a/pandatool/src/egg-qtess/subdivSegment.I +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file subdivSegment.I - * @author drose - * @date 2003-10-14 - */ - -/** - * - */ -INLINE SubdivSegment:: -SubdivSegment(const double *cint, int f, int t) : - _cint(cint), - _f(f), - _t(t) -{ -} - -/** - * Returns the net score of the segment. - */ -INLINE double SubdivSegment:: -get_score() const { - return _cint[_t] - _cint[_f]; -} - -/** - * Returns a score that indicates how badly the segment needs to be further - * subdivided. The greater the number, the greater the need. - */ -INLINE double SubdivSegment:: -get_need() const { - return get_score() / (double)(_num_cuts+1); -} - -/** - * Sorts the segments in descending order of need. - */ -INLINE bool SubdivSegment:: -operator < (const SubdivSegment &other) const { - return get_need() > other.get_need(); -} diff --git a/pandatool/src/egg-qtess/subdivSegment.cxx b/pandatool/src/egg-qtess/subdivSegment.cxx deleted file mode 100644 index 3c036e56..00000000 --- a/pandatool/src/egg-qtess/subdivSegment.cxx +++ /dev/null @@ -1,79 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file subdivSegment.cxx - * @author drose - * @date 2003-10-14 - */ - -#include "subdivSegment.h" - - - - -/** - * Performs a standard binary search. This utility function is used below. - */ -static int -binary_search(double val, const double *array, int bot, int top) { - if (top < bot) { - return bot; - } - int mid = (bot + top)/2; - - if (array[mid] < val) { - return binary_search(val, array, mid+1, top); - } else { - return binary_search(val, array, bot, mid-1); - } -} - - -/** - * Applies _num_cuts cuts to the segment. - */ -void SubdivSegment:: -cut() { - int c; - double ct = get_score(); - - _cuts.erase(_cuts.begin(), _cuts.end()); - int last = _f; - for (c = 1; c < _num_cuts+1; c++) { - double val = (double)c * ct / (double)(_num_cuts+1) + _cint[_f]; - int i = binary_search(val, _cint, _f, _t); - if (i != last && i < _t) { - _cuts.push_back(i); - } - last = i; - } - - while ((int)_cuts.size() < _num_cuts) { - // Do we have any extra? Assign them into likely places. - int last = _f; - int mc = -1; - int mv = 0; - for (c = 0; c < (int)_cuts.size(); c++) { - if (mc == -1 || _cuts[c] - last > mv) { - mc = c; - mv = _cuts[c] - last; - } - last = _cuts[c]; - } - - if (mc==-1) { - // Surrender. - return; - } - if (mc==0) { - _cuts.insert(_cuts.begin() + mc, (_cuts[mc] + _f) / 2); - } else { - _cuts.insert(_cuts.begin() + mc, (_cuts[mc] + _cuts[mc-1]) / 2); - } - } -} diff --git a/pandatool/src/egg-qtess/subdivSegment.h b/pandatool/src/egg-qtess/subdivSegment.h deleted file mode 100644 index abe6e58a..00000000 --- a/pandatool/src/egg-qtess/subdivSegment.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file subdivSegment.h - * @author drose - * @date 2003-10-14 - */ - -#ifndef SUBDIVSEGMENT_H -#define SUBDIVSEGMENT_H - -#include "pandatoolbase.h" -#include "pvector.h" -#include "vector_int.h" - -/** - * Represents a single hypothetical subdivided segment, under consideration by - * the IsoPlacer. - */ -class SubdivSegment { -public: - INLINE SubdivSegment(const double *cint, int f, int t); - - INLINE double get_score() const; - INLINE double get_need() const; - INLINE bool operator < (const SubdivSegment &other) const; - - void cut(); - - const double *_cint; - int _f, _t; - int _num_cuts; - vector_int _cuts; -}; - -#include "subdivSegment.I" - -#endif diff --git a/pandatool/src/eggbase/CMakeLists.txt b/pandatool/src/eggbase/CMakeLists.txt deleted file mode 100644 index 892e8bb8..00000000 --- a/pandatool/src/eggbase/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3EGGBASE_HEADERS - eggBase.h eggConverter.h eggFilter.h - eggMakeSomething.h - eggMultiBase.h eggMultiFilter.h - eggReader.h eggSingleBase.h - eggToSomething.h eggWriter.h - somethingToEgg.h -) - -set(P3EGGBASE_SOURCES - eggBase.cxx eggConverter.cxx eggFilter.cxx - eggMakeSomething.cxx - eggMultiBase.cxx - eggMultiFilter.cxx eggReader.cxx eggSingleBase.cxx - eggToSomething.cxx - eggWriter.cxx somethingToEgg.cxx -) - -composite_sources(p3eggbase P3EGGBASE_SOURCES) -add_library(p3eggbase STATIC ${P3EGGBASE_HEADERS} ${P3EGGBASE_SOURCES}) -target_link_libraries(p3eggbase p3progbase p3converter) - -install(TARGETS p3eggbase - EXPORT ToolsDevel COMPONENT ToolsDevel - DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d - ARCHIVE COMPONENT ToolsDevel) -install(FILES ${P3EGGBASE_HEADERS} COMPONENT ToolsDevel DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d) diff --git a/pandatool/src/eggbase/eggBase.cxx b/pandatool/src/eggbase/eggBase.cxx deleted file mode 100644 index 83d07a0a..00000000 --- a/pandatool/src/eggbase/eggBase.cxx +++ /dev/null @@ -1,405 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggBase.cxx - * @author drose - * @date 2000-02-14 - */ - -#include "eggBase.h" - -#include "eggGroupNode.h" -#include "eggTexture.h" -#include "eggFilenameNode.h" -#include "eggComment.h" -#include "dcast.h" -#include "string_utils.h" - -using std::string; - -/** - * - */ -EggBase:: -EggBase() { - add_option - ("cs", "coordinate-system", 80, - "Specify the coordinate system to operate in. This may be one of " - "'y-up', 'z-up', 'y-up-left', or 'z-up-left'.", - &EggBase::dispatch_coordinate_system, - &_got_coordinate_system, &_coordinate_system); - - _normals_mode = NM_preserve; - _normals_threshold = 0.0; - - _got_tbnall = false; - _got_tbnauto = false; - _make_points = false; - - _got_transform = false; - _transform = LMatrix4d::ident_mat(); - - _got_coordinate_system = false; - _coordinate_system = CS_yup_right; - - _noabs = false; -} - -/** - * Adds -no, -np, etc. as valid options for this program. If the user - * specifies one of the options on the command line, the normals will be - * adjusted when the egg file is written out. - */ -void EggBase:: -add_normals_options() { - static NormalsMode strip = NM_strip; - static NormalsMode polygon = NM_polygon; - static NormalsMode vertex = NM_vertex; - static NormalsMode preserve = NM_preserve; - - add_option - ("no", "", 48, - "Strip all normals.", - &EggBase::dispatch_normals, nullptr, &strip); - - add_option - ("np", "", 48, - "Strip existing normals and redefine polygon normals.", - &EggBase::dispatch_normals, nullptr, &polygon); - - add_option - ("nv", "threshold", 48, - "Strip existing normals and redefine vertex normals. Consider an edge " - "between adjacent polygons to be smooth if the angle between them " - "is less than threshold degrees.", - &EggBase::dispatch_normals, nullptr, &vertex); - - add_option - ("nn", "", 48, - "Preserve normals exactly as they are. This is the default.", - &EggBase::dispatch_normals, nullptr, &preserve); - - add_option - ("tbn", "name", 48, - "Compute tangent and binormal for the named texture coordinate " - "set(s). The name may include wildcard characters such as * and ?. " - "The normal must already exist or have been computed via one of the " - "above options. The tangent and binormal are used to implement " - "bump mapping and related texture-based lighting effects. This option " - "may be repeated as necessary to name multiple texture coordinate sets.", - &EggBase::dispatch_vector_string, nullptr, &_tbn_names); - - add_option - ("tbnall", "", 48, - "Compute tangent and binormal for all texture coordinate " - "sets. This is equivalent to -tbn \"*\".", - &EggBase::dispatch_none, &_got_tbnall); - - add_option - ("tbnauto", "", 48, - "Compute tangent and binormal for all normal maps. ", - &EggBase::dispatch_none, &_got_tbnauto); -} - -/** - * Adds -points as a valid option for this program. - */ -void EggBase:: -add_points_options() { - add_option - ("points", "", 46, - "Construct entries for any unreferenced vertices, to make them visible.", - &EggBase::dispatch_none, &_make_points); -} - -/** - * Adds -TS, -TT, etc. as valid options for this program. If the user - * specifies one of the options on the command line, the data will be - * transformed when the egg file is written out. - */ -void EggBase:: -add_transform_options() { - add_option - ("TS", "sx[,sy,sz]", 49, - "Scale the model uniformly by the given factor (if only one number " - "is given) or in each axis by sx, sy, sz (if three numbers are given).", - &EggBase::dispatch_scale, &_got_transform, &_transform); - - add_option - ("TR", "x,y,z", 49, - "Rotate the model x degrees about the x axis, then y degrees about the " - "y axis, and then z degrees about the z axis.", - &EggBase::dispatch_rotate_xyz, &_got_transform, &_transform); - - add_option - ("TA", "angle,x,y,z", 49, - "Rotate the model angle degrees counterclockwise about the given " - "axis.", - &EggBase::dispatch_rotate_axis, &_got_transform, &_transform); - - add_option - ("TT", "x,y,z", 49, - "Translate the model by the indicated amount.\n\n" - "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are " - "applied in the order they are encountered on the command line.", - &EggBase::dispatch_translate, &_got_transform, &_transform); -} - -/** - * Recursively walks the egg hierarchy. Any filenames encountered are - * replaced according to the indicated PathReplace. - */ -void EggBase:: -convert_paths(EggNode *node, PathReplace *path_replace, - const DSearchPath &additional_path) { - if (node->is_of_type(EggTexture::get_class_type())) { - EggTexture *egg_tex = DCAST(EggTexture, node); - Filename fullpath, outpath; - path_replace->full_convert_path(egg_tex->get_filename(), additional_path, - fullpath, outpath); - egg_tex->set_filename(outpath); - egg_tex->set_fullpath(fullpath); - - if (egg_tex->has_alpha_filename()) { - Filename alpha_fullpath, alpha_outpath; - path_replace->full_convert_path(egg_tex->get_alpha_filename(), additional_path, - alpha_fullpath, alpha_outpath); - egg_tex->set_alpha_filename(alpha_outpath); - egg_tex->set_alpha_fullpath(alpha_fullpath); - } - - } else if (node->is_of_type(EggFilenameNode::get_class_type())) { - EggFilenameNode *egg_fnode = DCAST(EggFilenameNode, node); - - Filename fullpath, outpath; - path_replace->full_convert_path(egg_fnode->get_filename(), additional_path, - fullpath, outpath); - egg_fnode->set_filename(outpath); - egg_fnode->set_fullpath(fullpath); - - } else if (node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *egg_group = DCAST(EggGroupNode, node); - EggGroupNode::const_iterator ci; - for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { - convert_paths(*ci, path_replace, additional_path); - } - } -} - -/** - * Inserts a comment into the beginning of the indicated egg file - * corresponding to the command line that invoked this program. - * - * Normally this function is called automatically when appropriate by - * EggWriter, and it's not necessary to call it explicitly. - */ -void EggBase:: -append_command_comment(EggData *data) { - append_command_comment(data, get_exec_command()); -} - -/** - * Inserts a comment into the beginning of the indicated egg file - * corresponding to the command line that invoked this program. - * - * Normally this function is called automatically when appropriate by - * EggWriter, and it's not necessary to call it explicitly. - */ -void EggBase:: -append_command_comment(EggData *data, const string &comment) { - data->insert(data->begin(), new EggComment("", comment)); -} - -/** - * Accepts one of -no, -np, etc. and sets _normals_mode as indicated. The - * void * argument is a pointer to a NormalsMode variable that indicates which - * switch was passed. - */ -bool EggBase:: -dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) { - EggBase *base = (EggBase *)self; - return base->ns_dispatch_normals(opt, arg, mode); -} - -/** - * Accepts one of -no, -np, etc. and sets _normals_mode as indicated. The - * void * argument is a pointer to a NormalsMode variable that indicates which - * switch was passed. - */ -bool EggBase:: -ns_dispatch_normals(const string &opt, const string &arg, void *mode) { - _normals_mode = *(NormalsMode *)mode; - - if (_normals_mode == NM_vertex) { - if (!string_to_double(arg, _normals_threshold)) { - nout << "Invalid numeric parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - } - - return true; -} - -/** - * Handles -TS, which specifies a scale transform. Var is an LMatrix4d. - */ -bool EggBase:: -dispatch_scale(const string &opt, const string &arg, void *var) { - LMatrix4d *transform = (LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - double sx, sy, sz; - - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_double(words[0], sx) && - string_to_double(words[1], sy) && - string_to_double(words[2], sz); - - } else if (words.size() == 1) { - okflag = - string_to_double(words[0], sx); - sy = sz = sx; - } - - if (!okflag) { - nout << "-" << opt - << " requires one or three numbers separated by commas.\n"; - return false; - } - - *transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz); - - return true; -} - -/** - * Handles -TR, which specifies a rotate transform about the three cardinal - * axes. Var is an LMatrix4d. - */ -bool EggBase:: -dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) { - EggBase *base = (EggBase *)self; - return base->ns_dispatch_rotate_xyz(opt, arg, var); -} - -/** - * Handles -TR, which specifies a rotate transform about the three cardinal - * axes. Var is an LMatrix4d. - */ -bool EggBase:: -ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) { - LMatrix4d *transform = (LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - LVecBase3d xyz; - - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_double(words[0], xyz[0]) && - string_to_double(words[1], xyz[1]) && - string_to_double(words[2], xyz[2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires three numbers separated by commas.\n"; - return false; - } - - LMatrix4d mat = - LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) * - LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) * - LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system); - - *transform = (*transform) * mat; - - return true; -} - -/** - * Handles -TA, which specifies a rotate transform about an arbitrary axis. - * Var is an LMatrix4d. - */ -bool EggBase:: -dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) { - EggBase *base = (EggBase *)self; - return base->ns_dispatch_rotate_axis(opt, arg, var); -} - -/** - * Handles -TA, which specifies a rotate transform about an arbitrary axis. - * Var is an LMatrix4d. - */ -bool EggBase:: -ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) { - LMatrix4d *transform = (LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - double angle; - LVecBase3d axis; - - bool okflag = false; - if (words.size() == 4) { - okflag = - string_to_double(words[0], angle) && - string_to_double(words[1], axis[0]) && - string_to_double(words[2], axis[1]) && - string_to_double(words[3], axis[2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires four numbers separated by commas.\n"; - return false; - } - - *transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system); - - return true; -} - -/** - * Handles -TT, which specifies a translate transform. Var is an LMatrix4d. - */ -bool EggBase:: -dispatch_translate(const string &opt, const string &arg, void *var) { - LMatrix4d *transform = (LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - LVector3d trans; - - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_double(words[0], trans[0]) && - string_to_double(words[1], trans[1]) && - string_to_double(words[2], trans[2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires three numbers separated by commas.\n"; - return false; - } - - *transform = (*transform) * LMatrix4d::translate_mat(trans); - - return true; -} diff --git a/pandatool/src/eggbase/eggBase.h b/pandatool/src/eggbase/eggBase.h deleted file mode 100644 index 4c6b1567..00000000 --- a/pandatool/src/eggbase/eggBase.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggBase.h - * @author drose - * @date 2000-02-14 - */ - -#ifndef EGGBASE_H -#define EGGBASE_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "eggData.h" - -/** - * This is a base class for both EggSingleBase and EggMultiBase. Don't - * inherit directly from this; use one of those two classes instead. - * - * This is just a base class; see EggReader, EggWriter, or EggFilter according - * to your particular I/O needs. - */ -class EggBase : public ProgramBase { -public: - EggBase(); - - void add_normals_options(); - void add_points_options(); - void add_transform_options(); - - static void convert_paths(EggNode *node, PathReplace *path_replace, - const DSearchPath &additional_path); - -protected: - void append_command_comment(EggData *_data); - static void append_command_comment(EggData *_data, const std::string &comment); - - static bool dispatch_normals(ProgramBase *self, const std::string &opt, const std::string &arg, void *mode); - bool ns_dispatch_normals(const std::string &opt, const std::string &arg, void *mode); - - static bool dispatch_scale(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_rotate_xyz(ProgramBase *self, const std::string &opt, const std::string &arg, void *var); - bool ns_dispatch_rotate_xyz(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_rotate_axis(ProgramBase *self, const std::string &opt, const std::string &arg, void *var); - bool ns_dispatch_rotate_axis(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_translate(const std::string &opt, const std::string &arg, void *var); - -protected: - enum NormalsMode { - NM_strip, - NM_polygon, - NM_vertex, - NM_preserve - }; - NormalsMode _normals_mode; - double _normals_threshold; - vector_string _tbn_names; - bool _got_tbnall; - bool _got_tbnauto; - - bool _make_points; - - bool _got_transform; - LMatrix4d _transform; - - bool _got_coordinate_system; - CoordinateSystem _coordinate_system; - - bool _noabs; -}; - -#endif diff --git a/pandatool/src/eggbase/eggConverter.cxx b/pandatool/src/eggbase/eggConverter.cxx deleted file mode 100644 index 036b7dea..00000000 --- a/pandatool/src/eggbase/eggConverter.cxx +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggConverter.cxx - * @author drose - * @date 2000-02-15 - */ - -#include "eggConverter.h" - -/** - * The first parameter to the constructor should be the one-word name of the - * alien file format that is to be read or written, for instance "OpenFlight" - * or "Alias". It's just used in printing error messages and such. The - * second parameter is the preferred extension of files of this form, if any, - * with a leading dot. - */ -EggConverter:: -EggConverter(const std::string &format_name, - const std::string &preferred_extension, - bool allow_last_param, - bool allow_stdout) : - EggFilter(allow_last_param, allow_stdout), - _format_name(format_name) -{ - // Indicate the extension name we expect the user to supply for output - // files. - _preferred_extension = preferred_extension; -} diff --git a/pandatool/src/eggbase/eggConverter.h b/pandatool/src/eggbase/eggConverter.h deleted file mode 100644 index 3922a6b8..00000000 --- a/pandatool/src/eggbase/eggConverter.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggConverter.h - * @author drose - * @date 2000-02-15 - */ - -#ifndef EGGCONVERTER_H -#define EGGCONVERTER_H - -#include "pandatoolbase.h" - -#include "eggFilter.h" - -/** - * This is a general base class for programs that convert between egg files - * and some other format. See EggToSomething and SomethingToEgg. - */ -class EggConverter : public EggFilter { -public: - EggConverter(const std::string &format_name, - const std::string &preferred_extension = std::string(), - bool allow_last_param = true, - bool allow_stdout = true); - -protected: - std::string _format_name; -}; - -#endif diff --git a/pandatool/src/eggbase/eggFilter.cxx b/pandatool/src/eggbase/eggFilter.cxx deleted file mode 100644 index ef6c2967..00000000 --- a/pandatool/src/eggbase/eggFilter.cxx +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggFilter.cxx - * @author drose - * @date 2000-02-14 - */ - -#include "eggFilter.h" - -/** - * - */ -EggFilter:: -EggFilter(bool allow_last_param, bool allow_stdout) : - EggWriter(allow_last_param, allow_stdout) -{ - // The default path store for programs that read egg files and write them - // again is PS_relative. - _path_replace->_path_store = PS_relative; - - clear_runlines(); - if (allow_last_param) { - add_runline("[opts] input.egg output.egg"); - } - add_runline("[opts] -o output.egg input.egg"); - if (allow_stdout) { - add_runline("[opts] input.egg >output.egg"); - } - - redescribe_option - ("cs", - "Specify the coordinate system of the resulting egg file. This may be " - "one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default " - "is the same coordinate system as the input egg file. If this is " - "different from the input egg file, a conversion will be performed."); -} - - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggFilter:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 1)) { - return false; - } - - if (!_got_path_directory && _got_output_filename) { - // Put in the name of the output directory. - _path_replace->_path_directory = _output_filename.get_dirname(); - } - - return EggReader::handle_args(args); -} - -/** - * - */ -bool EggFilter:: -post_command_line() { - // writer first, so we can fiddle with the _path_replace options if - // necessary. - return EggWriter::post_command_line() && EggReader::post_command_line(); -} diff --git a/pandatool/src/eggbase/eggFilter.h b/pandatool/src/eggbase/eggFilter.h deleted file mode 100644 index ebd6c87d..00000000 --- a/pandatool/src/eggbase/eggFilter.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggFilter.h - * @author drose - * @date 2000-02-14 - */ - -#ifndef EGGFILTER_H -#define EGGFILTER_H - -#include "pandatoolbase.h" - -#include "eggReader.h" -#include "eggWriter.h" - -/** - * This is the base class for a program that reads an egg file, operates on - * it, and writes another egg file out. - */ -class EggFilter : public EggReader, public EggWriter { -public: - EggFilter(bool allow_last_param = false, bool allow_stdout = true); - -protected: - virtual bool handle_args(Args &args); - virtual bool post_command_line(); -}; - -#endif diff --git a/pandatool/src/eggbase/eggMakeSomething.cxx b/pandatool/src/eggbase/eggMakeSomething.cxx deleted file mode 100644 index 52543ec0..00000000 --- a/pandatool/src/eggbase/eggMakeSomething.cxx +++ /dev/null @@ -1,25 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMakeSomething.cxx - * @author drose - * @date 2003-10-01 - */ - -#include "eggMakeSomething.h" - -/** - * - */ -EggMakeSomething:: -EggMakeSomething() : - EggWriter(true, true) -{ - add_normals_options(); - add_transform_options(); -} diff --git a/pandatool/src/eggbase/eggMakeSomething.h b/pandatool/src/eggbase/eggMakeSomething.h deleted file mode 100644 index b34aa348..00000000 --- a/pandatool/src/eggbase/eggMakeSomething.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMakeSomething.h - * @author drose - * @date 2003-10-01 - */ - -#ifndef EGGMAKESOMETHING_H -#define EGGMAKESOMETHING_H - -#include "pandatoolbase.h" - -#include "eggWriter.h" - -/** - * A base class for a family of programs that generate egg models of various - * fundamental shapes. - */ -class EggMakeSomething : public EggWriter { -public: - EggMakeSomething(); -}; - -#endif diff --git a/pandatool/src/eggbase/eggMultiBase.cxx b/pandatool/src/eggbase/eggMultiBase.cxx deleted file mode 100644 index 426b62a9..00000000 --- a/pandatool/src/eggbase/eggMultiBase.cxx +++ /dev/null @@ -1,187 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMultiBase.cxx - * @author drose - * @date 2000-11-02 - */ - -#include "eggMultiBase.h" -#include "eggBase.h" -#include "eggData.h" -#include "eggComment.h" -#include "filename.h" -#include "dSearchPath.h" - -/** - * - */ -EggMultiBase:: -EggMultiBase() { - add_option - ("f", "", 80, - "Force complete loading: load up the egg file along with all of its " - "external references.", - &EggMultiBase::dispatch_none, &_force_complete); - - add_option - ("noabs", "", 0, - "Don't allow any of the named egg files to have absolute pathnames. " - "If any do, abort with an error. This option is designed to help " - "detect errors when populating or building a standalone model tree, " - "which should be self-contained and include only relative pathnames.", - &EggMultiBase::dispatch_none, &_noabs); -} - -/** - * Performs any processing of the egg file(s) that is appropriate before - * writing them out. This includes any normal adjustments the user requested - * via -np, etc. - * - * Normally, you should not need to call this function directly; - * write_egg_files() calls it for you. You should call this only if you do - * not use write_egg_files() to write out the resulting egg files. - */ -void EggMultiBase:: -post_process_egg_files() { - if (_eggs.empty()) { - return; - } - - Eggs::iterator ei; - if (_got_transform) { - nout << "Applying transform matrix:\n"; - _transform.write(nout, 2); - LVecBase3d scale, hpr, translate; - if (decompose_matrix(_transform, scale, hpr, translate, - _eggs[0]->get_coordinate_system())) { - nout << "(scale " << scale << ", hpr " << hpr << ", translate " - << translate << ")\n"; - } - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - (*ei)->transform(_transform); - } - } - - if (_make_points) { - nout << "Making points\n"; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - (*ei)->make_point_primitives(); - } - } - - switch (_normals_mode) { - case NM_strip: - nout << "Stripping normals.\n"; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - (*ei)->strip_normals(); - (*ei)->remove_unused_vertices(true); - } - break; - - case NM_polygon: - nout << "Recomputing polygon normals.\n"; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - (*ei)->recompute_polygon_normals(); - (*ei)->remove_unused_vertices(true); - } - break; - - case NM_vertex: - nout << "Recomputing vertex normals.\n"; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - (*ei)->recompute_vertex_normals(_normals_threshold); - (*ei)->remove_unused_vertices(true); - } - break; - - case NM_preserve: - // Do nothing. - break; - } - - if (_got_tbnall) { - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - if ((*ei)->recompute_tangent_binormal(GlobPattern("*"))) { - (*ei)->remove_unused_vertices(true); - } - } - } else { - if (_got_tbnauto) { - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - if ((*ei)->recompute_tangent_binormal_auto()) { - (*ei)->remove_unused_vertices(true); - } - } - } - - for (vector_string::const_iterator si = _tbn_names.begin(); - si != _tbn_names.end(); - ++si) { - GlobPattern uv_name(*si); - nout << "Computing tangent and binormal for \"" << uv_name << "\"\n"; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - (*ei)->recompute_tangent_binormal(uv_name); - (*ei)->remove_unused_vertices(true); - } - } - } -} - - -/** - * Allocates and returns a new EggData structure that represents the indicated - * egg file. If the egg file cannot be read for some reason, returns NULL. - * - * This can be overridden by derived classes to control how the egg files are - * read, or to extend the information stored with each egg structure, by - * deriving from EggData. - */ -PT(EggData) EggMultiBase:: -read_egg(const Filename &filename) { - PT(EggData) data = new EggData; - - if (!data->read(filename)) { - // Failure reading. - return nullptr; - } - - if (_noabs && data->original_had_absolute_pathnames()) { - nout << filename.get_basename() - << " includes absolute pathnames!\n"; - return nullptr; - } - - DSearchPath file_path; - file_path.append_directory(filename.get_dirname()); - - // We always resolve filenames first based on the source egg filename, since - // egg files almost always store relative paths. This is a temporary kludge - // around integrating the path_replace system with the EggData better. - // Update: I believe this kludge is obsolete. Commenting out. - Josh. - // data->resolve_filenames(file_path); - - if (_force_complete) { - if (!data->load_externals()) { - return nullptr; - } - } - - // Now resolve the filenames again according to the user's specified - // _path_replace. - EggBase::convert_paths(data, _path_replace, file_path); - - if (_got_coordinate_system) { - data->set_coordinate_system(_coordinate_system); - } else { - _coordinate_system = data->get_coordinate_system(); - _got_coordinate_system = true; - } - - return data; -} diff --git a/pandatool/src/eggbase/eggMultiBase.h b/pandatool/src/eggbase/eggMultiBase.h deleted file mode 100644 index 1442de61..00000000 --- a/pandatool/src/eggbase/eggMultiBase.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMultiBase.h - * @author drose - * @date 2000-11-02 - */ - -#ifndef EGGMULTIBASE_H -#define EGGMULTIBASE_H - -#include "pandatoolbase.h" - -#include "eggBase.h" -#include "coordinateSystem.h" -#include "eggData.h" -#include "pointerTo.h" - -class Filename; - -/** - * This specialization of ProgramBase is intended for programs that read - * and/or write multiple egg files. - * - * See also EggMultiFilter, for a class that also knows how to read a bunch of - * egg files in and write them out again. - */ -class EggMultiBase : public EggBase { -public: - EggMultiBase(); - - void post_process_egg_files(); - -protected: - virtual PT(EggData) read_egg(const Filename &filename); - -protected: - typedef pvector< PT(EggData) > Eggs; - Eggs _eggs; - - bool _force_complete; -}; - -#endif diff --git a/pandatool/src/eggbase/eggMultiFilter.cxx b/pandatool/src/eggbase/eggMultiFilter.cxx deleted file mode 100644 index 981c8ad4..00000000 --- a/pandatool/src/eggbase/eggMultiFilter.cxx +++ /dev/null @@ -1,210 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMultiFilter.cxx - * @author drose - * @date 2000-11-02 - */ - -#include "eggMultiFilter.h" - -#include "pnotify.h" -#include "eggData.h" - -/** - * - */ -EggMultiFilter:: -EggMultiFilter(bool allow_empty) : _allow_empty(allow_empty) { - clear_runlines(); - add_runline("-o output.egg [opts] input.egg"); - add_runline("-d dirname [opts] file.egg [file.egg ...]"); - add_runline("-inplace [opts] file.egg [file.egg ...]"); - add_runline("-inf input_list_filename [opts]"); - - add_option - ("o", "filename", 50, - "Specify the filename to which the resulting egg file will be written. " - "This is only valid when there is only one input egg file on the command " - "line. If you want to process multiple files simultaneously, you must " - "use either -d or -inplace.", - &EggMultiFilter::dispatch_filename, &_got_output_filename, &_output_filename); - - add_option - ("d", "dirname", 50, - "Specify the name of the directory in which to write the resulting egg " - "files. If you are processing only one egg file, this may be omitted " - "in lieu of the -o option. If you are processing multiple egg files, " - "this may be omitted only if you specify -inplace instead.", - &EggMultiFilter::dispatch_filename, &_got_output_dirname, &_output_dirname); - - add_option - ("inplace", "", 50, - "If this option is given, the input egg files will be rewritten in " - "place with the results. This obviates the need to specify -d " - "for an output directory; however, it's risky because the original " - "input egg files are lost.", - &EggMultiFilter::dispatch_none, &_inplace); - - add_option - ("inf", "filename", 95, - "Reads input args from a text file instead of the command line. " - "Useful for really, really large lists of args that break the " - "OS-imposed limits on the length of command lines.", - &EggMultiFilter::dispatch_filename, &_got_input_filename, &_input_filename); - - // Derived programs will set this true when they discover some command-line - // option that will prevent the program from generating output. This - // removes some checks for an output specification in handle_args. - _read_only = false; -} - - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggMultiFilter:: -handle_args(ProgramBase::Args &args) { - if (_got_input_filename) { - nout << "Populating args from input file: " << _input_filename << "\n"; - // Makes sure the file is set is_text - _filename = Filename::text_filename(_input_filename); - std::ifstream input; - if (!_filename.open_read(input)) { - nout << "Error opening file: " << _input_filename << "\n"; - return false; - } - std::string line; - // File should be a space-delimited list of egg files - while (std::getline(input, line, ' ')) { - args.push_back(line); - } - } - if (args.empty()) { - if (!_allow_empty) { - nout << "You must specify the egg file(s) to read on the command line.\n"; - return false; - } - } else { - // These only apply if we have specified any egg files. - if (_got_output_filename && args.size() == 1) { - if (_got_output_dirname) { - nout << "Cannot specify both -o and -d.\n"; - return false; - } else if (_inplace) { - nout << "Cannot specify both -o and -inplace.\n"; - return false; - } - - } else { - if (_got_output_filename) { - nout << "Cannot use -o when multiple egg files are specified.\n"; - return false; - } - - if (_got_output_dirname && _inplace) { - nout << "Cannot specify both -inplace and -d.\n"; - return false; - - } else if (!_got_output_dirname && !_inplace) { - if (!_read_only) { - nout << "You must specify either -inplace or -d.\n"; - return false; - } - } - } - } - - // We need to set up _path_replace before we call read_egg(). - if (!_got_path_directory) { - // Put in the name of the output directory. - if (_got_output_filename) { - _path_replace->_path_directory = _output_filename.get_dirname(); - } else if (_got_output_dirname) { - _path_replace->_path_directory = _output_dirname; - } - } - - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - PT(EggData) data = read_egg(Filename::from_os_specific(*ai)); - if (data == nullptr) { - // Rather than returning false, we simply exit here, so the ProgramBase - // won't try to tell the user how to run the program just because we got - // a bad egg file. - exit(1); - } - - _eggs.push_back(data); - } - - return true; -} - -/** - * - */ -bool EggMultiFilter:: -post_command_line() { - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - EggData *data = (*ei); - if (_got_coordinate_system) { - data->set_coordinate_system(_coordinate_system); - } - append_command_comment(data); - } - - return EggMultiBase::post_command_line(); -} - -/** - * Returns the output filename of the egg file with the given input filename. - * This is based on the user's choice of -inplace, -o, or -d. - */ -Filename EggMultiFilter:: -get_output_filename(const Filename &source_filename) const { - if (_got_output_filename) { - nassertr(!_inplace && !_got_output_dirname && _eggs.size() == 1, Filename()); - return _output_filename; - - } else if (_got_output_dirname) { - nassertr(!_inplace, Filename()); - Filename result = source_filename; - result.set_dirname(_output_dirname); - return result; - } - - nassertr(_inplace, Filename()); - return source_filename; -} - -/** - * Writes out all of the egg files in the _eggs vector, to the output - * directory if one is specified, or over the input files if -inplace was - * specified. - */ -void EggMultiFilter:: -write_eggs() { - nassertv(!_read_only); - post_process_egg_files(); - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - EggData *data = (*ei); - Filename filename = get_output_filename(data->get_egg_filename()); - - nout << "Writing " << filename << "\n"; - filename.make_dir(); - if (!data->write_egg(filename)) { - // Error writing an egg file; abort. - exit(1); - } - } -} diff --git a/pandatool/src/eggbase/eggMultiFilter.h b/pandatool/src/eggbase/eggMultiFilter.h deleted file mode 100644 index 402e5183..00000000 --- a/pandatool/src/eggbase/eggMultiFilter.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMultiFilter.h - * @author drose - * @date 2000-11-02 - */ - -#ifndef EGGMULTIFILTER_H -#define EGGMULTIFILTER_H - -#include "pandatoolbase.h" - -#include "eggMultiBase.h" - -/** - * This is a base class for a program that reads in a number of egg files, - * operates on them, and writes them out again (presumably to a different - * directory). - */ -class EggMultiFilter : public EggMultiBase { -public: - EggMultiFilter(bool allow_empty = false); - -protected: - virtual bool handle_args(Args &args); - virtual bool post_command_line(); - - Filename get_output_filename(const Filename &source_filename) const; - virtual void write_eggs(); - -protected: - bool _allow_empty; - bool _got_output_filename; - Filename _output_filename; - bool _got_output_dirname; - Filename _output_dirname; - bool _inplace; - Filename _input_filename; - Filename _filename; - bool _got_input_filename; - - bool _read_only; -}; - -#endif diff --git a/pandatool/src/eggbase/eggReader.cxx b/pandatool/src/eggbase/eggReader.cxx deleted file mode 100644 index 4146189a..00000000 --- a/pandatool/src/eggbase/eggReader.cxx +++ /dev/null @@ -1,375 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggReader.cxx - * @author drose - * @date 2000-02-14 - */ - -#include "eggReader.h" - -#include "pnmImage.h" -#include "config_putil.h" -#include "eggTextureCollection.h" -#include "eggGroup.h" -#include "eggGroupNode.h" -#include "eggSwitchCondition.h" -#include "string_utils.h" -#include "dcast.h" - -/** - * - */ -EggReader:: -EggReader() { - clear_runlines(); - add_runline("[opts] input.egg"); - - redescribe_option - ("cs", - "Specify the coordinate system to operate in. This may be " - " one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default " - "is the coordinate system of the input egg file."); - - add_option - ("f", "", 80, - "Force complete loading: load up the egg file along with all of its " - "external references.", - &EggReader::dispatch_none, &_force_complete); - - add_option - ("noabs", "", 0, - "Don't allow the input egg file to have absolute pathnames. " - "If it does, abort with an error. This option is designed to help " - "detect errors when populating or building a standalone model tree, " - "which should be self-contained and include only relative pathnames.", - &EggReader::dispatch_none, &_noabs); - - _tex_type = nullptr; - _delod = -1.0; - - _got_tex_dirname = false; - _got_tex_extension = false; - _exit_on_failure = true; -} - -/** - * Adds -td, -te, etc. as valid options for this program. If the user - * specifies one of the options on the command line, the textures will be - * copied and converted as each egg file is read. - * - * Note that if you call this function to add these options, you must call - * do_reader_options() at the appropriate point before or during processing to - * execute the options if the user specified them. - */ -void EggReader:: -add_texture_options() { - add_option - ("td", "dirname", 40, - "Copy textures to the indicated directory. The copy is performed " - "only if the destination file does not exist or is older than the " - "source file.", - &EggReader::dispatch_filename, &_got_tex_dirname, &_tex_dirname); - - add_option - ("te", "ext", 40, - "Rename textures to have the indicated extension. This also " - "automatically copies them to the new filename (possibly in a " - "different directory if -td is also specified), and may implicitly " - "convert to a different image format according to the extension.", - &EggReader::dispatch_string, &_got_tex_extension, &_tex_extension); - - add_option - ("tt", "type", 40, - "Explicitly specifies the image format to convert textures to " - "when copying them via -td or -te. Normally, this is unnecessary as " - "the image format can be determined by the extension, but sometimes " - "the extension is insufficient to unambiguously specify an image " - "type.", - &EggReader::dispatch_image_type, nullptr, &_tex_type); -} - -/** - * Adds -delod as a valid option for this program. - * - * Note that if you call this function to add these options, you must call - * do_reader_options() at the appropriate point before or during processing to - * execute the options if the user specified them. - */ -void EggReader:: -add_delod_options(double default_delod) { - _delod = default_delod; - - if (default_delod < 0) { - add_option - ("delod", "dist", 40, - "Eliminate LOD's by choosing the level that would be appropriate for " - "a camera at the indicated fixed distance from each LOD. " - "Use -delod -1 to keep all the LOD's as they are, which is " - "the default.\n", - &EggReader::dispatch_double, nullptr, &_delod); - - } else { - add_option - ("delod", "dist", 40, - "Eliminate LOD's by choosing the level that would be appropriate for " - "a camera at the indicated fixed distance from each LOD. " - "Use -delod -1 to keep all the LOD's as they are. The default value " - "is " + format_string(default_delod) + ".", - &EggReader::dispatch_double, nullptr, &_delod); - } -} - -/** - * Sets whether the reader will quit the program upon encountering a fatal error. - * - * If true, the entire program will quit as soon as an egg loading error occurs. - */ -void EggReader:: -set_exit_on_failure(bool exit_on_failure) { - _exit_on_failure = exit_on_failure; -} - -/** - * Returns this object as an EggReader pointer, if it is in fact an EggReader, - * or NULL if it is not. - * - * This is intended to work around the C++ limitation that prevents downcasts - * past virtual inheritance. Since both EggReader and EggWriter inherit - * virtually from EggSingleBase, we need functions like this to downcast to - * the appropriate pointer. - */ -EggReader *EggReader:: -as_reader() { - return this; -} - -/** - * Performs any processing of the egg file that is appropriate after reading - * it in. - * - * Normally, you should not need to call this function directly; it is called - * automatically at startup. - */ -void EggReader:: -pre_process_egg_file() { -} - -/** - * - */ -bool EggReader:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the egg file(s) to read on the command line.\n"; - return false; - } - - // Any separate egg files that are listed on the command line will get - // implicitly loaded up into one big egg file. - - if (!args.empty()) { - _data->set_egg_filename(Filename::from_os_specific(args[0])); - } - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - Filename filename = Filename::from_os_specific(*ai); - - EggData file_data; - if (filename != "-") { - if (!file_data.read(filename)) { - // Rather than returning false, we simply exit here, so the ProgramBase - // won't try to tell the user how to run the program just because we got - // a bad egg file. - if (_exit_on_failure) { - exit(1); - } - return false; - } - } else { - if (!file_data.read(std::cin)) { - if (_exit_on_failure) { - exit(1); - } - return false; - } - } - - if (_noabs && file_data.original_had_absolute_pathnames()) { - nout << filename.get_basename() - << " includes absolute pathnames!\n"; - if (_exit_on_failure) { - exit(1); - } - return false; - } - - DSearchPath file_path; - file_path.append_directory(filename.get_dirname()); - - if (_force_complete) { - if (!file_data.load_externals(file_path)) { - if (_exit_on_failure) { - exit(1); - } - return false; - } - } - - // Now resolve the filenames again according to the user's specified - // _path_replace. - convert_paths(&file_data, _path_replace, file_path); - - _data->merge(file_data); - } - - pre_process_egg_file(); - - return true; -} - -/** - * This is called after the command line has been completely processed, and it - * gives the program a chance to do some last-minute processing and validation - * of the options and arguments. It should return true if everything is fine, - * false if there is an error. - */ -bool EggReader:: -post_command_line() { - return EggSingleBase::post_command_line(); -} - -/** - * Postprocesses the egg file as the user requested according to whatever - * command-line options are in effect. Returns true if everything is done - * correctly, false if there was some problem. - */ -bool EggReader:: -do_reader_options() { - bool okflag = true; - - if (_got_tex_dirname || _got_tex_extension) { - if (!copy_textures()) { - okflag = false; - } - } - - if (_delod >= 0.0) { - do_delod(_data); - } - - return okflag; -} - -/** - * Renames and copies the textures referenced in the egg file, if so specified - * by the -td and -te options. Returns true if all textures are copied - * successfully, false if any one of them failed. - */ -bool EggReader:: -copy_textures() { - bool success = true; - EggTextureCollection textures; - textures.find_used_textures(_data); - - EggTextureCollection::const_iterator ti; - for (ti = textures.begin(); ti != textures.end(); ++ti) { - EggTexture *tex = (*ti); - Filename orig_filename = tex->get_filename(); - if (!orig_filename.exists()) { - bool found = orig_filename.resolve_filename(get_model_path()); - if (!found) { - nout << "Cannot find " << orig_filename << "\n"; - success = false; - continue; - } - } - - Filename new_filename = orig_filename; - if (_got_tex_dirname) { - new_filename.set_dirname(_tex_dirname); - } - if (_got_tex_extension) { - new_filename.set_extension(_tex_extension); - } - - if (orig_filename != new_filename) { - tex->set_filename(new_filename); - - // The new filename is different; does it need copying? - int compare = - orig_filename.compare_timestamps(new_filename, true, true); - if (compare > 0) { - // Yes, it does. Copy it! - nout << "Reading " << orig_filename << "\n"; - PNMImage image; - if (!image.read(orig_filename)) { - nout << " unable to read!\n"; - success = false; - } else { - nout << "Writing " << new_filename << "\n"; - if (!image.write(new_filename, _tex_type)) { - nout << " unable to write!\n"; - success = false; - } - } - } - } - } - - return success; -} - -/** - * Removes all the LOD's in the egg file by treating the camera as being - * _delod distance from each LOD. Returns true if this particular group should - * be preserved, false if it should be removed. - */ -bool EggReader:: -do_delod(EggNode *node) { - if (node->is_of_type(EggGroup::get_class_type())) { - EggGroup *group = DCAST(EggGroup, node); - if (group->has_lod()) { - const EggSwitchCondition &cond = group->get_lod(); - if (cond.is_of_type(EggSwitchConditionDistance::get_class_type())) { - const EggSwitchConditionDistance *dist = - DCAST(EggSwitchConditionDistance, &cond); - if (_delod >= dist->_switch_out && _delod < dist->_switch_in) { - // Preserve this group node, but not the LOD information itself. - nout << "Preserving LOD " << node->get_name() - << " (" << dist->_switch_out << " to " << dist->_switch_in - << ")\n"; - group->clear_lod(); - } else { - // Remove this group node. - nout << "Eliminating LOD " << node->get_name() - << " (" << dist->_switch_out << " to " << dist->_switch_in - << ")\n"; - return false; - } - } - } - } - - // Now process all the children. - if (node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, node); - EggGroupNode::iterator ci; - ci = group->begin(); - while (ci != group->end()) { - EggNode *child = *ci; - ++ci; - - if (!do_delod(child)) { - group->remove_child(child); - } - } - } - - return true; -} diff --git a/pandatool/src/eggbase/eggReader.h b/pandatool/src/eggbase/eggReader.h deleted file mode 100644 index 305b58a2..00000000 --- a/pandatool/src/eggbase/eggReader.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggReader.h - * @author drose - * @date 2000-02-14 - */ - -#ifndef EGGREADER_H -#define EGGREADER_H - -#include "pandatoolbase.h" - -#include "eggSingleBase.h" -#include "filename.h" - -class PNMFileType; - -/** - * This is the base class for a program that reads egg files, but doesn't - * write an egg file. - */ -class EggReader : virtual public EggSingleBase { -public: - EggReader(); - - void add_texture_options(); - void add_delod_options(double default_delod = -1.0); - void set_exit_on_failure(bool exit_on_failure); - - virtual EggReader *as_reader(); - virtual void pre_process_egg_file(); - -protected: - virtual bool handle_args(Args &args); - virtual bool post_command_line(); - - bool do_reader_options(); - -private: - bool copy_textures(); - bool do_delod(EggNode *node); - -protected: - bool _force_complete; - bool _exit_on_failure; - -private: - Filename _tex_dirname; - bool _got_tex_dirname; - std::string _tex_extension; - bool _got_tex_extension; - PNMFileType *_tex_type; - double _delod; -}; - -#endif diff --git a/pandatool/src/eggbase/eggSingleBase.cxx b/pandatool/src/eggbase/eggSingleBase.cxx deleted file mode 100644 index a3cda117..00000000 --- a/pandatool/src/eggbase/eggSingleBase.cxx +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggSingleBase.cxx - * @author drose - * @date 2003-07-21 - */ - -#include "eggSingleBase.h" - -#include "eggGroupNode.h" -#include "eggTexture.h" -#include "eggFilenameNode.h" -#include "eggComment.h" -#include "dcast.h" -#include "string_utils.h" - -/** - * - */ -EggSingleBase:: -EggSingleBase() : - _data(new EggData) -{ -} - -/** - * Returns this object as an EggReader pointer, if it is in fact an EggReader, - * or NULL if it is not. - * - * This is intended to work around the C++ limitation that prevents downcasts - * past virtual inheritance. Since both EggReader and EggWriter inherit - * virtually from EggSingleBase, we need functions like this to downcast to - * the appropriate pointer. - */ -EggReader *EggSingleBase:: -as_reader() { - return nullptr; -} - -/** - * Returns this object as an EggWriter pointer, if it is in fact an EggWriter, - * or NULL if it is not. - * - * This is intended to work around the C++ limitation that prevents downcasts - * past virtual inheritance. Since both EggReader and EggWriter inherit - * virtually from EggSingleBase, we need functions like this to downcast to - * the appropriate pointer. - */ -EggWriter *EggSingleBase:: -as_writer() { - return nullptr; -} - -/** - * - */ -bool EggSingleBase:: -post_command_line() { - if (_got_coordinate_system) { - _data->set_coordinate_system(_coordinate_system); - } - - return EggBase::post_command_line(); -} diff --git a/pandatool/src/eggbase/eggSingleBase.h b/pandatool/src/eggbase/eggSingleBase.h deleted file mode 100644 index 32c15d83..00000000 --- a/pandatool/src/eggbase/eggSingleBase.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggSingleBase.h - * @author drose - * @date 2003-07-21 - */ - -#ifndef EGGSINGLEBASE_H -#define EGGSINGLEBASE_H - -#include "pandatoolbase.h" - -#include "eggBase.h" -#include "coordinateSystem.h" -#include "eggData.h" -#include "pointerTo.h" - -class EggReader; -class EggWriter; -class EggNode; -class PathReplace; - -/** - * This specialization of EggBase is intended for programs that read and/or - * write a single egg file. (See EggMultiBase for programs that operate on - * multiple egg files at once.) - * - * This is just a base class; see EggReader, EggWriter, or EggFilter according - * to your particular I/O needs. - */ -class EggSingleBase : public EggBase { -public: - EggSingleBase(); - - virtual EggReader *as_reader(); - virtual EggWriter *as_writer(); - -protected: - virtual bool post_command_line(); - -protected: - PT(EggData) _data; -}; - -#endif diff --git a/pandatool/src/eggbase/eggToSomething.cxx b/pandatool/src/eggbase/eggToSomething.cxx deleted file mode 100644 index eb6adc89..00000000 --- a/pandatool/src/eggbase/eggToSomething.cxx +++ /dev/null @@ -1,155 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToSomething.cxx - * @author drose - * @date 2000-02-15 - */ - -#include "eggToSomething.h" - -/** - * The first parameter to the constructor should be the one-word name of the - * file format that is to be read, for instance "OpenFlight" or "Alias". It's - * just used in printing error messages and such. - */ -EggToSomething:: -EggToSomething(const std::string &format_name, - const std::string &preferred_extension, - bool allow_last_param, bool allow_stdout) : - EggConverter(format_name, preferred_extension, allow_last_param, - allow_stdout) -{ - clear_runlines(); - if (_allow_last_param) { - add_runline("[opts] input.egg output" + _preferred_extension); - } - add_runline("[opts] -o output" + _preferred_extension + " input.egg"); - if (_allow_stdout) { - add_runline("[opts] input.egg >output" + _preferred_extension); - } - - std::string o_description; - - if (_allow_stdout) { - if (_allow_last_param) { - o_description = - "Specify the filename to which the resulting " + format_name + - " file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file, or standard output is used if there are no " - "other parameters."; - } else { - o_description = - "Specify the filename to which the resulting " + format_name + - " file will be written. " - "If this option is omitted, the " + format_name + - " file is written to standard output."; - } - } else { - if (_allow_last_param) { - o_description = - "Specify the filename to which the resulting " + format_name + - " file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file."; - } else { - o_description = - "Specify the filename to which the resulting " + format_name + - " file will be written."; - } - } - - redescribe_option("o", o_description); - - redescribe_option - ("cs", - "Specify the coordinate system of the resulting " + _format_name + - " file. This may be " - "one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default " - "is the same coordinate system as the input egg file. If this is " - "different from the input egg file, a conversion will be performed."); - - _input_units = DU_invalid; - _output_units = DU_invalid; -} - -/** - * Adds -ui and -uo as valid options for this program. If the user specifies - * -uo and -ui, or just -uo and the program specifies -ui by setting - * _input_units, the indicated units conversion will be automatically applied - * before writing out the egg file. - */ -void EggToSomething:: -add_units_options() { - add_option - ("ui", "units", 40, - "Specify the units of the input egg file. If this is " - "specified, the vertices in the egg file will be scaled as " - "necessary to make the appropriate units conversion; otherwise, " - "the vertices will be left as they are.", - &EggToSomething::dispatch_units, nullptr, &_input_units); - - add_option - ("uo", "units", 40, - "Specify the units of the resulting " + _format_name + - " file. Normally, the default units for the format are used.", - &EggToSomething::dispatch_units, nullptr, &_output_units); -} - -/** - * Applies the scale indicated by the input and output units to the indicated - * egg file. This is normally done automatically when the file is read in. - */ -void EggToSomething:: -apply_units_scale(EggData *data) { - - // [gjeon] since maya's internal unit is fixed to cm and when we can't - // change UI unit without affecting data we need to convert data to cm for - // now this will be set later to proper output unit user provided by using - // MayaApi::set_units() in eggToMaya.cxx - DistanceUnit output_units = _output_units; - if (_format_name == "Maya") - _output_units = DU_centimeters; - - if (_output_units != DU_invalid && _input_units != DU_invalid && - _input_units != _output_units) { - nout << "Converting from " << format_long_unit(_input_units) - << " to " << format_long_unit(_output_units) << "\n"; - double scale = convert_units(_input_units, _output_units); - data->transform(LMatrix4d::scale_mat(scale)); - } - _output_units = output_units; -} - -/** - * Performs any processing of the egg file that is appropriate after reading - * it in. - * - * Normally, you should not need to call this function directly; it is called - * automatically at startup. - */ -void EggToSomething:: -pre_process_egg_file() { - apply_units_scale(_data); - EggConverter::pre_process_egg_file(); -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggToSomething:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 1)) { - return false; - } - - return EggConverter::handle_args(args); -} diff --git a/pandatool/src/eggbase/eggToSomething.h b/pandatool/src/eggbase/eggToSomething.h deleted file mode 100644 index aafc045a..00000000 --- a/pandatool/src/eggbase/eggToSomething.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToSomething.h - * @author drose - * @date 2000-02-15 - */ - -#ifndef EGGTOSOMETHING_H -#define EGGTOSOMETHING_H - -#include "pandatoolbase.h" - -#include "eggConverter.h" -#include "distanceUnit.h" - -/** - * This is the general base class for a file-converter program that reads some - * model file format and generates an egg file. - */ -class EggToSomething : public EggConverter { -public: - EggToSomething(const std::string &format_name, - const std::string &preferred_extension = std::string(), - bool allow_last_param = true, - bool allow_stdout = true); - - void add_units_options(); - -protected: - void apply_units_scale(EggData *data); - virtual void pre_process_egg_file(); - virtual bool handle_args(Args &args); - - DistanceUnit _input_units; - DistanceUnit _output_units; -}; - -#endif diff --git a/pandatool/src/eggbase/eggWriter.cxx b/pandatool/src/eggbase/eggWriter.cxx deleted file mode 100644 index c881991a..00000000 --- a/pandatool/src/eggbase/eggWriter.cxx +++ /dev/null @@ -1,224 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggWriter.cxx - * @author drose - * @date 2000-02-14 - */ - -#include "eggWriter.h" - -#include "string_utils.h" -#include "compose_matrix.h" -#include "globPattern.h" - -/** - * Egg-writing type programs may specify their output file using either the - * last-filename convention, the -o convention, and/or implicitly writing the - * result to standard output. Not all interfaces are appropriate for all - * applications; some may be confusing or dangerous. - * - * The calling application should pass allow_last_param true to allow the user - * to specify the output filename as the last parameter on the command line - * (the most dangerous, but convenient, method), and allow_stdout true to - * allow the user to omit the output filename altogether and have the output - * implicitly go to standard output (not terribly dangerous, but inappropriate - * when writing binary file formats). - */ -EggWriter:: -EggWriter(bool allow_last_param, bool allow_stdout) : - WithOutputFile(allow_last_param, allow_stdout, false) -{ - // Indicate the extension name we expect the user to supply for output - // files. - _preferred_extension = ".egg"; - - clear_runlines(); - if (_allow_last_param) { - add_runline("[opts] output.egg"); - } - add_runline("[opts] -o output.egg"); - if (_allow_stdout) { - add_runline("[opts] >output.egg"); - } - - std::string o_description; - - if (_allow_stdout) { - if (_allow_last_param) { - o_description = - "Specify the filename to which the resulting egg file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file, or standard output is used if there are no " - "other parameters."; - } else { - o_description = - "Specify the filename to which the resulting egg file will be written. " - "If this option is omitted, the egg file is written to standard output."; - } - } else { - if (_allow_last_param) { - o_description = - "Specify the filename to which the resulting egg file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file."; - } else { - o_description = - "Specify the filename to which the resulting egg file will be written."; - } - } - - add_option - ("o", "filename", 50, o_description, - &EggWriter::dispatch_filename, &_got_output_filename, &_output_filename); - - redescribe_option - ("cs", - "Specify the coordinate system of the resulting egg file. This may be " - "one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is " - "y-up."); -} - - -/** - * Returns this object as an EggWriter pointer, if it is in fact an EggWriter, - * or NULL if it is not. - * - * This is intended to work around the C++ limitation that prevents downcasts - * past virtual inheritance. Since both EggReader and EggWriter inherit - * virtually from EggSingleBase, we need functions like this to downcast to - * the appropriate pointer. - */ -EggWriter *EggWriter:: -as_writer() { - return this; -} - -/** - * Performs any processing of the egg file that is appropriate before writing - * it out. This includes any normal adjustments the user requested via -np, - * etc. - * - * Normally, you should not need to call this function directly; - * write_egg_file() calls it for you. You should call this only if you do not - * use write_egg_file() to write out the resulting egg file. - */ -void EggWriter:: -post_process_egg_file() { - if (_got_transform) { - nout << "Applying transform matrix:\n"; - _transform.write(nout, 2); - LVecBase3d scale, hpr, translate; - if (decompose_matrix(_transform, scale, hpr, translate, - _data->get_coordinate_system())) { - nout << "(scale " << scale << ", hpr " << hpr << ", translate " - << translate << ")\n"; - } - _data->transform(_transform); - } - - if (_make_points) { - nout << "Making points\n"; - _data->make_point_primitives(); - } - - bool needs_remove = false; - - switch (_normals_mode) { - case NM_strip: - nout << "Stripping normals.\n"; - _data->strip_normals(); - needs_remove = true; - break; - - case NM_polygon: - nout << "Recomputing polygon normals.\n"; - _data->recompute_polygon_normals(); - needs_remove = true; - break; - - case NM_vertex: - nout << "Recomputing vertex normals.\n"; - _data->recompute_vertex_normals(_normals_threshold); - needs_remove = true; - break; - - case NM_preserve: - // Do nothing. - break; - } - - if (_got_tbnall) { - needs_remove |= _data->recompute_tangent_binormal(GlobPattern("*")); - } else { - if (_got_tbnauto) { - needs_remove |= _data->recompute_tangent_binormal_auto(); - } - needs_remove |= _data->recompute_tangent_binormal(_tbn_names); - } - - if (needs_remove) { - _data->remove_unused_vertices(true); - } -} - -/** - * Writes out the egg file as the normal result of the program. This calls - * post_process_egg_file() to perform any last minute processing (like normal - * computation) and then writes out the file to the output stream returned by - * get_output(). - */ -void EggWriter:: -write_egg_file() { - post_process_egg_file(); - _data->write_egg(get_output()); -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggWriter:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 0)) { - return false; - } - - if (!args.empty()) { - nout << "Unexpected arguments on command line:\n"; - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - nout << (*ai) << " "; - } - nout << "\r"; - return false; - } - - if (!_got_path_directory && _got_output_filename) { - // Put in the name of the output directory. - _path_replace->_path_directory = _output_filename.get_dirname(); - } - - return true; -} - -/** - * - */ -bool EggWriter:: -post_command_line() { - if (!_allow_stdout && !_got_output_filename) { - nout << "You must specify the filename to write with -o.\n"; - return false; - } - - append_command_comment(_data); - - return EggSingleBase::post_command_line(); -} diff --git a/pandatool/src/eggbase/eggWriter.h b/pandatool/src/eggbase/eggWriter.h deleted file mode 100644 index 9037fe7e..00000000 --- a/pandatool/src/eggbase/eggWriter.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggWriter.h - * @author drose - * @date 2000-02-14 - */ - -#ifndef EGGWRITER_H -#define EGGWRITER_H - -#include "pandatoolbase.h" -#include "eggSingleBase.h" -#include "withOutputFile.h" - -#include "filename.h" -#include "luse.h" - -/** - * This is the base class for a program that generates an egg file output, but - * doesn't read any for input. - */ -class EggWriter : virtual public EggSingleBase, public WithOutputFile { -public: - EggWriter(bool allow_last_param = false, bool allow_stdout = true); - - virtual EggWriter *as_writer(); - - virtual void post_process_egg_file(); - void write_egg_file(); - -protected: - virtual bool handle_args(Args &args); - virtual bool post_command_line(); - -private: - std::ofstream _output_stream; -}; - -#endif diff --git a/pandatool/src/eggbase/p3eggbase_composite1.cxx b/pandatool/src/eggbase/p3eggbase_composite1.cxx deleted file mode 100644 index 7f2f3a72..00000000 --- a/pandatool/src/eggbase/p3eggbase_composite1.cxx +++ /dev/null @@ -1,13 +0,0 @@ - -#include "eggBase.cxx" -#include "eggConverter.cxx" -#include "eggFilter.cxx" -#include "eggMakeSomething.cxx" -#include "eggMultiBase.cxx" -#include "eggMultiFilter.cxx" -#include "eggReader.cxx" -#include "eggWriter.cxx" -#include "eggSingleBase.cxx" -#include "eggToSomething.cxx" -#include "somethingToEgg.cxx" - diff --git a/pandatool/src/eggbase/somethingToEgg.cxx b/pandatool/src/eggbase/somethingToEgg.cxx deleted file mode 100644 index 45d705f1..00000000 --- a/pandatool/src/eggbase/somethingToEgg.cxx +++ /dev/null @@ -1,328 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file somethingToEgg.cxx - * @author drose - * @date 2000-02-15 - */ - -#include "somethingToEgg.h" -#include "somethingToEggConverter.h" - -#include "config_putil.h" - -/** - * The first parameter to the constructor should be the one-word name of the - * file format that is to be read, for instance "OpenFlight" or "Alias". It's - * just used in printing error messages and such. - */ -SomethingToEgg:: -SomethingToEgg(const std::string &format_name, - const std::string &preferred_extension, - bool allow_last_param, bool allow_stdout) : - EggConverter(format_name, preferred_extension, allow_last_param, allow_stdout) -{ - clear_runlines(); - if (_allow_last_param) { - add_runline("[opts] input" + _preferred_extension + " output.egg"); - } - add_runline("[opts] -o output.egg input" + _preferred_extension); - if (_allow_stdout) { - add_runline("[opts] input" + _preferred_extension + " >output.egg"); - } - - // -f doesn't make sense if we aren't reading egg files. - remove_option("f"); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. Normally, this can inferred from the file itself."); - - add_option - ("noabs", "", 0, - "Don't allow the input " + _format_name + " file to have absolute pathnames. " - "If it does, abort with an error. This option is designed to help " - "detect errors when populating or building a standalone model tree, " - "which should be self-contained and include only relative pathnames.", - &SomethingToEgg::dispatch_none, &_noabs); - - add_option - ("noexist", "", 0, - "Don't treat it as an error if the input file references pathnames " - "(e.g. textures) that don't exist. Normally, this will be flagged as " - "an error and the command aborted; with this option, an egg file will " - "be generated anyway, referencing pathnames that do not exist.", - &SomethingToEgg::dispatch_none, &_noexist); - - add_option - ("ignore", "", 0, - "Ignore non-fatal errors and generate an egg file anyway.", - &SomethingToEgg::dispatch_none, &_allow_errors); - - _input_units = DU_invalid; - _output_units = DU_invalid; - _animation_convert = AC_none; - _got_start_frame = false; - _got_end_frame = false; - _got_frame_inc = false; - _got_neutral_frame = false; - _got_input_frame_rate = false; - _got_output_frame_rate = false; - _merge_externals = false; -} - -/** - * Adds -ui and -uo as valid options for this program. If the user specifies - * -uo and -ui, or just -uo and the program specifies -ui by setting - * _input_units, the indicated units conversion will be automatically applied - * before writing out the egg file. - */ -void SomethingToEgg:: -add_units_options() { - add_option - ("ui", "units", 40, - "Specify the units of the input " + _format_name + - " file. Normally, this can be inferred from the file itself.", - &SomethingToEgg::dispatch_units, nullptr, &_input_units); - - add_option - ("uo", "units", 40, - "Specify the units of the resulting egg file. If this is " - "specified, the vertices in the egg file will be scaled as " - "necessary to make the appropriate units conversion; otherwise, " - "the vertices will be left as they are.", - &SomethingToEgg::dispatch_units, nullptr, &_output_units); -} - -/** - * Adds options appropriate to animation packages. - */ -void SomethingToEgg:: -add_animation_options() { - add_option - ("a", "animation-mode", 40, - "Specifies how animation from the " + _format_name + " file is " - "converted to egg, if at all. At present, the following keywords " - "are supported: none, pose, flip, strobe, model, chan, or both. " - "The default is none, which means not to convert animation.", - &SomethingToEgg::dispatch_animation_convert, nullptr, &_animation_convert); - - add_option - ("cn", "name", 40, - "Specifies the name of the animation character. This should match " - "between all of the model files and all of the channel files for a " - "particular model and its associated channels.", - &SomethingToEgg::dispatch_string, nullptr, &_character_name); - - add_option - ("sf", "start-frame", 40, - "Specifies the starting frame of animation to extract. If omitted, " - "the first frame of the time slider will be used. For -a pose, this " - "is the one frame of animation to extract.", - &SomethingToEgg::dispatch_double, &_got_start_frame, &_start_frame); - - add_option - ("ef", "end-frame", 40, - "Specifies the ending frame of animation to extract. If omitted, " - "the last frame of the time slider will be used.", - &SomethingToEgg::dispatch_double, &_got_end_frame, &_end_frame); - - add_option - ("if", "frame-inc", 40, - "Specifies the increment between successive frames. If omitted, " - "this is taken from the time slider settings, or 1.0 if the time " - "slider does not specify.", - &SomethingToEgg::dispatch_double, &_got_frame_inc, &_frame_inc); - - add_option - ("nf", "neutral-frame", 40, - "Specifies the frame number to use for the neutral pose. The model " - "will be set to this frame before extracting out the neutral character. " - "If omitted, the current frame of the model is used. This is only " - "relevant for -a model or -a both.", - &SomethingToEgg::dispatch_double, &_got_neutral_frame, &_neutral_frame); - - add_option - ("fri", "fps", 40, - "Specify the frame rate (frames per second) of the input " + _format_name + - " file. Normally, this can be inferred from the file itself.", - &SomethingToEgg::dispatch_double, &_got_input_frame_rate, &_input_frame_rate); - - add_option - ("fro", "fps", 40, - "Specify the frame rate (frames per second) of the generated animation. " - "If this is specified, the animation speed is scaled by the appropriate " - "factor based on the frame rate of the input file (see -fri).", - &SomethingToEgg::dispatch_double, &_got_output_frame_rate, &_output_frame_rate); -} - -/** - * Adds -f. - */ -void SomethingToEgg:: -add_merge_externals_options() { - add_option - ("f", "", 40, - "Follow and convert all external references in the source file.", - &SomethingToEgg::dispatch_none, &_merge_externals); -} - -/** - * Applies the scale indicated by the input and output units to the indicated - * egg file. This is normally done automatically when the file is written - * out. - */ -void SomethingToEgg:: -apply_units_scale(EggData *data) { - if (_output_units != DU_invalid && _input_units != DU_invalid && - _input_units != _output_units) { - nout << "Converting from " << format_long_unit(_input_units) - << " to " << format_long_unit(_output_units) << "\n"; - double scale = convert_units(_input_units, _output_units); - data->transform(LMatrix4d::scale_mat(scale)); - } -} - -/** - * Copies the relevant parameters specified by the user on the command line - * (if add_path_replace_options(), add_path_store_options(), or - * add_animation_options() was used) to the converter. - */ -void SomethingToEgg:: -apply_parameters(SomethingToEggConverter &converter) { - _path_replace->_noabs = _noabs; - _path_replace->_exists = !_noexist; - converter.set_path_replace(_path_replace); - - converter.set_animation_convert(_animation_convert); - converter.set_character_name(_character_name); - if (_got_start_frame) { - converter.set_start_frame(_start_frame); - } - if (_got_end_frame) { - converter.set_end_frame(_end_frame); - } - if (_got_frame_inc) { - converter.set_frame_inc(_frame_inc); - } - if (_got_neutral_frame) { - converter.set_neutral_frame(_neutral_frame); - } - if (_got_input_frame_rate) { - converter.set_input_frame_rate(_input_frame_rate); - } - if (_got_output_frame_rate) { - converter.set_output_frame_rate(_output_frame_rate); - } -} - -/** - * - */ -bool SomethingToEgg:: -handle_args(Args &args) { - if (_allow_last_param && !_got_output_filename && args.size() > 1) { - _got_output_filename = true; - _output_filename = Filename::from_os_specific(args.back()); - args.pop_back(); - - if (!(_output_filename.get_extension() == "egg")) { - nout << "Output filename " << _output_filename - << " does not end in .egg. If this is really what you intended, " - "use the -o output_file syntax.\n"; - return false; - } - - if (!verify_output_file_safe()) { - return false; - } - } - - if (args.empty()) { - nout << "You must specify the " << _format_name - << " file to read on the command line.\n"; - return false; - } - - if (args.size() != 1) { - nout << "You may only specify one " << _format_name - << " file to read on the command line. " - << "You specified: "; - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - nout << (*ai) << " "; - } - nout << "\n"; - return false; - } - - _input_filename = Filename::from_os_specific(args[0]); - - if (!_input_filename.exists()) { - nout << "Cannot find input file " << _input_filename << "\n"; - return false; - } - - if (!_got_path_directory && _got_output_filename) { - // Put in the name of the output directory. - _path_replace->_path_directory = _output_filename.get_dirname(); - } - - return true; -} - -/** - * This is called after the command line has been completely processed, and it - * gives the program a chance to do some last-minute processing and validation - * of the options and arguments. It should return true if everything is fine, - * false if there is an error. - */ -bool SomethingToEgg:: -post_command_line() { - // Prepend the source filename to the model path. - ConfigVariableSearchPath &model_path = get_model_path(); - Filename directory = _input_filename.get_dirname(); - if (directory.empty()) { - directory = "."; - } - model_path.prepend_directory(directory); - - return EggConverter::post_command_line(); -} - -/** - * Performs any processing of the egg file that is appropriate before writing - * it out. This includes any normal adjustments the user requested via -np, - * etc. - * - * Normally, you should not need to call this function directly; - * write_egg_file() calls it for you. You should call this only if you do not - * use write_egg_file() to write out the resulting egg file. - */ -void SomethingToEgg:: -post_process_egg_file() { - apply_units_scale(_data); - EggConverter::post_process_egg_file(); -} - -/** - * Dispatch function to set the given animation convert mode according to the - * specified parameter. var is a pointer to an AnimationConvert variable. - */ -bool SomethingToEgg:: -dispatch_animation_convert(const std::string &opt, const std::string &arg, void *var) { - AnimationConvert *ip = (AnimationConvert *)var; - (*ip) = string_animation_convert(arg); - if ((*ip) == AC_invalid) { - nout << "Invalid keyword for -" << opt << ": " << arg << "\n"; - return false; - } - - return true; -} diff --git a/pandatool/src/eggbase/somethingToEgg.h b/pandatool/src/eggbase/somethingToEgg.h deleted file mode 100644 index 5c5427dc..00000000 --- a/pandatool/src/eggbase/somethingToEgg.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file somethingToEgg.h - * @author drose - * @date 2000-02-15 - */ - -#ifndef SOMETHINGTOEGG_H -#define SOMETHINGTOEGG_H - -#include "pandatoolbase.h" - -#include "eggConverter.h" -#include "distanceUnit.h" -#include "animationConvert.h" - -class SomethingToEggConverter; - -/** - * This is the general base class for a file-converter program that reads some - * model file format and generates an egg file. - */ -class SomethingToEgg : public EggConverter { -public: - SomethingToEgg(const std::string &format_name, - const std::string &preferred_extension = std::string(), - bool allow_last_param = true, - bool allow_stdout = true); - - void add_units_options(); - void add_animation_options(); - void add_merge_externals_options(); - -protected: - void apply_units_scale(EggData *data); - void apply_parameters(SomethingToEggConverter &converter); - - virtual bool handle_args(Args &args); - virtual bool post_command_line(); - virtual void post_process_egg_file(); - - static bool dispatch_animation_convert(const std::string &opt, const std::string &arg, void *var); - - - Filename _input_filename; - - DistanceUnit _input_units; - DistanceUnit _output_units; - - AnimationConvert _animation_convert; - std::string _character_name; - double _start_frame; - double _end_frame; - double _frame_inc; - double _neutral_frame; - double _input_frame_rate; - double _output_frame_rate; - bool _got_start_frame; - bool _got_end_frame; - bool _got_frame_inc; - bool _got_neutral_frame; - bool _got_input_frame_rate; - bool _got_output_frame_rate; - - bool _merge_externals; - bool _noexist; - bool _allow_errors; -}; - -#endif diff --git a/pandatool/src/eggcharbase/CMakeLists.txt b/pandatool/src/eggcharbase/CMakeLists.txt deleted file mode 100644 index 384bebe0..00000000 --- a/pandatool/src/eggcharbase/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3EGGCHARBASE_HEADERS - config_eggcharbase.h - eggBackPointer.h - eggCharacterCollection.h eggCharacterCollection.I - eggCharacterData.h eggCharacterData.I - eggCharacterDb.h eggCharacterDb.I - eggCharacterFilter.h - eggComponentData.h eggComponentData.I - eggJointData.h eggJointData.I - eggJointNodePointer.h - eggJointPointer.h eggJointPointer.I - eggMatrixTablePointer.h - eggScalarTablePointer.h - eggSliderData.h eggSliderData.I - eggSliderPointer.h - eggVertexPointer.h -) - -set(P3EGGCHARBASE_SOURCES - config_eggcharbase.cxx - eggBackPointer.cxx - eggCharacterCollection.cxx - eggCharacterData.cxx - eggCharacterDb.cxx - eggCharacterFilter.cxx - eggComponentData.cxx - eggJointData.cxx - eggJointNodePointer.cxx - eggJointPointer.cxx - eggMatrixTablePointer.cxx - eggScalarTablePointer.cxx - eggSliderData.cxx - eggSliderPointer.cxx - eggVertexPointer.cxx -) - -composite_sources(p3eggcharbase P3EGGCHARBASE_SOURCES) -add_library(p3eggcharbase STATIC ${P3EGGCHARBASE_HEADERS} ${P3EGGCHARBASE_SOURCES}) -target_link_libraries(p3eggcharbase p3eggbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/eggcharbase/config_eggcharbase.cxx b/pandatool/src/eggcharbase/config_eggcharbase.cxx deleted file mode 100644 index 734939a4..00000000 --- a/pandatool/src/eggcharbase/config_eggcharbase.cxx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_eggcharbase.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "config_eggcharbase.h" -#include "eggBackPointer.h" -#include "eggComponentData.h" -#include "eggJointData.h" -#include "eggJointNodePointer.h" -#include "eggJointPointer.h" -#include "eggMatrixTablePointer.h" -#include "eggScalarTablePointer.h" -#include "eggSliderData.h" -#include "eggSliderPointer.h" -#include "eggVertexPointer.h" - -#include "dconfig.h" - - -Configure(config_eggcharbase); - -// NotifyCategoryDef(eggcharbase, ""); - -ConfigureFn(config_eggcharbase) { - init_libeggcharbase(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libeggcharbase() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - EggBackPointer::init_type(); - EggComponentData::init_type(); - EggJointData::init_type(); - EggJointNodePointer::init_type(); - EggJointPointer::init_type(); - EggMatrixTablePointer::init_type(); - EggScalarTablePointer::init_type(); - EggSliderData::init_type(); - EggSliderPointer::init_type(); - EggVertexPointer::init_type(); -} diff --git a/pandatool/src/eggcharbase/config_eggcharbase.h b/pandatool/src/eggcharbase/config_eggcharbase.h deleted file mode 100644 index d6d1404e..00000000 --- a/pandatool/src/eggcharbase/config_eggcharbase.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_eggcharbase.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef CONFIG_EGGCHARBASE_H -#define CONFIG_EGGCHARBASE_H - -#include "pandabase.h" - -// Commented out to resolve link problem #include "notifyCategoryProxy.h" -// NotifyCategoryDecl(eggcharbase, EXPCL_MISC, EXPTP_MISC); - -extern void init_libeggcharbase(); - -#endif diff --git a/pandatool/src/eggcharbase/eggBackPointer.cxx b/pandatool/src/eggcharbase/eggBackPointer.cxx deleted file mode 100644 index cc6110d0..00000000 --- a/pandatool/src/eggcharbase/eggBackPointer.cxx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggBackPointer.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggBackPointer.h" - -#include "pnotify.h" - - -TypeHandle EggBackPointer::_type_handle; - -/** - * - */ -EggBackPointer:: -EggBackPointer() { -} - -/** - * Returns the stated frame rate of this particular joint, or 0.0 if it - * doesn't state. - */ -double EggBackPointer:: -get_frame_rate() const { - return 0.0; -} - -/** - * Extends the table to the indicated number of frames. - */ -void EggBackPointer:: -extend_to(int num_frames) { - // Whoops, can't extend this kind of table! - nassert_raise("can't extend this kind of table"); -} - -/** - * Returns true if there are any vertices referenced by the node this points - * to, false otherwise. For certain kinds of back pointers (e.g. table - * animation entries), this is always false. - */ -bool EggBackPointer:: -has_vertices() const { - return false; -} - -/** - * Applies the indicated name change to the egg file. - */ -void EggBackPointer:: -set_name(const std::string &name) { -} diff --git a/pandatool/src/eggcharbase/eggBackPointer.h b/pandatool/src/eggcharbase/eggBackPointer.h deleted file mode 100644 index 2595c09d..00000000 --- a/pandatool/src/eggcharbase/eggBackPointer.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggBackPointer.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGBACKPOINTER_H -#define EGGBACKPOINTER_H - -#include "pandatoolbase.h" - -#include "typedObject.h" - -/** - * This stores a pointer from an EggJointData or EggSliderData object back to - * the referencing data in an egg file. One of these objects corresponds to - * each model appearing in an egg file, and may reference either a single - * node, or a table, or a slew of vertices and primitives, depending on the - * type of data stored. - * - * This is just an abstract base class. The actual details are stored in the - * various subclasses. - */ -class EggBackPointer : public TypedObject { -public: - EggBackPointer(); - - virtual double get_frame_rate() const; - virtual int get_num_frames() const=0; - virtual void extend_to(int num_frames); - virtual bool has_vertices() const; - - virtual void set_name(const std::string &name); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedObject::init_type(); - register_type(_type_handle, "EggBackPointer", - TypedObject::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; -}; - -#endif diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.I b/pandatool/src/eggcharbase/eggCharacterCollection.I deleted file mode 100644 index fc1f2696..00000000 --- a/pandatool/src/eggcharbase/eggCharacterCollection.I +++ /dev/null @@ -1,94 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterCollection.I - * @author drose - * @date 2001-02-26 - */ - -/** - * Returns the number of egg files that have successfully been added to the - * Character table. - */ -INLINE int EggCharacterCollection:: -get_num_eggs() const { - return _eggs.size(); -} - -/** - * Returns the ith egg file. - */ -INLINE EggData *EggCharacterCollection:: -get_egg(int i) const { - nassertr(i >= 0 && i < (int)_eggs.size(), nullptr); - return _eggs[i]._egg; -} - -/** - * Returns the first model index associated with the indicated egg file. An - * egg file may contain multiple models, which will be consecutive integers - * beginning at get_first_model_index() and continuing for get_num_models(). - * - * Each "model" corresponds to a single character model, or one LOD of a - * multiple-LOD model, or a single animation bundle. - */ -INLINE int EggCharacterCollection:: -get_first_model_index(int egg_index) const { - nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0); - return _eggs[egg_index]._first_model_index; -} - -/** - * Returns the number of different models found in the indicated egg file. An - * egg file may contain multiple models, which will be consecutive integers - * beginning at get_first_model_index() and continuing for get_num_models(). - * - * Each "model" corresponds to a single character model, or one LOD of a - * multiple-LOD model, or a single animation bundle. - */ -INLINE int EggCharacterCollection:: -get_num_models(int egg_index) const { - nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0); - return _eggs[egg_index]._models.size(); -} - -/** - * Returns the number of separate Characters that have been discovered in the - * various egg files added to the collection. - */ -INLINE int EggCharacterCollection:: -get_num_characters() const { - return _characters.size(); -} - -/** - * Returns the ith character in the collection. - */ -INLINE EggCharacterData *EggCharacterCollection:: -get_character(int i) const { - nassertr(i >= 0 && i < (int)_characters.size(), nullptr); - return _characters[i]; -} - -/** - * Returns the character associated with the indicated model index. - */ -INLINE EggCharacterData *EggCharacterCollection:: -get_character_by_model_index(int model_index) const { - nassertr(model_index >= 0 && model_index < (int)_characters_by_model_index.size(), - nullptr); - return _characters_by_model_index[model_index]; -} - -/** - * - */ -INLINE EggCharacterCollection::ModelDescription:: -ModelDescription() { - _root_node = nullptr; -} diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.cxx b/pandatool/src/eggcharbase/eggCharacterCollection.cxx deleted file mode 100644 index f90c7d9a..00000000 --- a/pandatool/src/eggcharbase/eggCharacterCollection.cxx +++ /dev/null @@ -1,680 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterCollection.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggCharacterCollection.h" -#include "eggCharacterData.h" -#include "eggJointData.h" -#include "eggSliderData.h" - -#include "dcast.h" -#include "eggGroup.h" -#include "eggTable.h" -#include "eggPrimitive.h" -#include "eggVertex.h" -#include "eggVertexUV.h" -#include "eggMorphList.h" -#include "eggSAnimData.h" -#include "indirectCompareNames.h" -#include "indent.h" - -#include - -using std::string; - - -/** - * - */ -EggCharacterCollection:: -EggCharacterCollection() { - _next_model_index = 0; -} - -/** - * - */ -EggCharacterCollection:: -~EggCharacterCollection() { - Characters::iterator ci; - - for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - delete (*ci); - } -} - -/** - * Adds a new egg file to the list of models and animation files for this - * particular character. - * - * Returns the new egg_index if the file is successfully added, or -1 if there - * is some problem (for instance, it does not contain a character model or - * animation table). - * - * If the joint hierarchy does not match the existing joint hierarchy, a best - * match is attempted. - */ -int EggCharacterCollection:: -add_egg(EggData *egg) { - _top_egg_nodes.clear(); - - if (!scan_hierarchy(egg)) { - return -1; - } - - int egg_index = _eggs.size(); - _eggs.push_back(EggInfo()); - EggInfo &egg_info = _eggs.back(); - egg_info._egg = egg; - egg_info._first_model_index = 0; - - // Now, for each model, add an entry in the egg_info and match the joint - // hierarchy to the known joints. - TopEggNodesByName::iterator tni; - for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) { - string character_name = (*tni).first; - TopEggNodes &top_nodes = (*tni).second; - EggCharacterData *char_data = make_character(character_name); - EggJointData *root_joint = char_data->get_root_joint(); - - TopEggNodes::iterator ti; - for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) { - EggNode *model_root = (*ti).first; - ModelDescription &desc = (*ti).second; - - int model_index = _next_model_index++; - if (egg_info._models.empty()) { - egg_info._first_model_index = model_index; - } - egg_info._models.push_back(model_root); - - char_data->add_model(model_index, model_root, egg); - nassertr(model_index == (int)_characters_by_model_index.size(), -1); - _characters_by_model_index.push_back(char_data); - root_joint->add_back_pointer(model_index, desc._root_node); - - match_egg_nodes(char_data, root_joint, desc._top_nodes, - egg_index, model_index); - - scan_for_morphs(model_root, model_index, char_data); - scan_for_sliders(model_root, model_index, char_data); - } - } - - return egg_index; -} - -/** - * Returns the Character with the indicated name, if it exists in the - * collection, or NULL if it does not. - */ -EggCharacterData *EggCharacterCollection:: -get_character_by_name(const string &character_name) const { - Characters::const_iterator ci; - for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - EggCharacterData *char_data = (*ci); - if (char_data->get_name() == character_name) { - return char_data; - } - } - - return nullptr; -} - - -/** - * Allocates and returns a new EggCharacterData structure. This is primarily - * intended as a hook so derived classes can customize the type of - * EggCharacterData nodes used to represent the characters in this collection. - */ -EggCharacterData *EggCharacterCollection:: -make_character_data() { - return new EggCharacterData(this); -} - -/** - * Allocates and returns a new EggJointData structure for the given character. - * This is primarily intended as a hook so derived classes can customize the - * type of EggJointData nodes used to represent the joint hierarchy. - */ -EggJointData *EggCharacterCollection:: -make_joint_data(EggCharacterData *char_data) { - return new EggJointData(this, char_data); -} - -/** - * Allocates and returns a new EggSliderData structure for the given - * character. This is primarily intended as a hook so derived classes can - * customize the type of EggSliderData nodes used to represent the slider - * list. - */ -EggSliderData *EggCharacterCollection:: -make_slider_data(EggCharacterData *char_data) { - return new EggSliderData(this, char_data); -} - -/** - * Allocates and returns a new EggCharacterData object representing the named - * character, if there is not already a character by that name. - */ -EggCharacterData *EggCharacterCollection:: -make_character(const string &character_name) { - // Does the named character exist yet? - - Characters::iterator ci; - for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - EggCharacterData *char_data = (*ci); - if (char_data->get_name() == character_name) { - return char_data; - } - } - - // Define a new character. - EggCharacterData *char_data = make_character_data(); - char_data->set_name(character_name); - _characters.push_back(char_data); - return char_data; -} - -/** - * Walks the given egg data's hierarchy, looking for either the start of an - * animation channel or the start of a character model. Returns true if - * either (or both) is found, false if the model appears to have nothing to do - * with characters. - * - * Fills up the _top_egg_nodes according to the nodes found. - */ -bool EggCharacterCollection:: -scan_hierarchy(EggNode *egg_node) { - if (egg_node->is_of_type(EggGroup::get_class_type())) { - EggGroup *group = DCAST(EggGroup, egg_node); - if (group->get_dart_type() != EggGroup::DT_none) { - // A group with a flag begins a character model. - scan_for_top_joints(group, group, group->get_name()); - return true; - } - - } else if (egg_node->is_of_type(EggTable::get_class_type())) { - EggTable *table = DCAST(EggTable, egg_node); - if (table->get_table_type() == EggTable::TT_bundle) { - // A begins an animation table. - scan_for_top_tables(table, table, table->get_name()); - return true; - } - } - - bool character_found = false; - if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, egg_node); - EggGroupNode::iterator gi; - for (gi = group->begin(); gi != group->end(); ++gi) { - if (scan_hierarchy(*gi)) { - character_found = true; - } - } - } - - return character_found; -} - -/** - * Once a character model has been found, continue scanning the egg hierarchy - * to look for the topmost nodes encountered. - */ -void EggCharacterCollection:: -scan_for_top_joints(EggNode *egg_node, EggNode *model_root, - const string &character_name) { - if (egg_node->is_of_type(EggGroup::get_class_type())) { - EggGroup *group = DCAST(EggGroup, egg_node); - - if (group->has_lod()) { - // This group has an LOD specification; that indicates multiple skeleton - // hierarchies for this character, one for each LOD. We call each of - // these a separate model. - model_root = group; - } - if (group->get_group_type() == EggGroup::GT_joint) { - // A node begins a model hierarchy. - ModelDescription &desc = _top_egg_nodes[character_name][model_root]; - desc._root_node = model_root; - desc._top_nodes.push_back(group); - return; - } - } - - if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, egg_node); - EggGroupNode::iterator gi; - for (gi = group->begin(); gi != group->end(); ++gi) { - scan_for_top_joints(*gi, model_root, character_name); - } - } -} - -/** - * Once an animation has been found, continue scanning the egg hierarchy to - * look for the topmost nodes encountered. - */ -void EggCharacterCollection:: -scan_for_top_tables(EggTable *bundle, EggNode *model_root, - const string &character_name) { - // We really only need to check the immediate children of the bundle for a - // table node called "". - EggGroupNode::iterator gi; - for (gi = bundle->begin(); gi != bundle->end(); ++gi) { - EggNode *child = (*gi); - if (child->is_of_type(EggTable::get_class_type())) { - EggTable *table = DCAST(EggTable, child); - if (table->get_name() == "") { - // Here it is! Now the immediate children of this node are the top - // tables. - ModelDescription &desc = _top_egg_nodes[character_name][model_root]; - desc._root_node = table; - - EggGroupNode::iterator cgi; - for (cgi = table->begin(); cgi != table->end(); ++cgi) { - EggNode *grandchild = (*cgi); - if (grandchild->is_of_type(EggTable::get_class_type())) { - desc._top_nodes.push_back(grandchild); - } - } - } - } - } -} - -/** - * Go back through a model's hierarchy and look for morph targets on the - * vertices and primitives. - */ -void EggCharacterCollection:: -scan_for_morphs(EggNode *egg_node, int model_index, - EggCharacterData *char_data) { - if (egg_node->is_of_type(EggPrimitive::get_class_type())) { - EggPrimitive *prim = DCAST(EggPrimitive, egg_node); - // Check for morphs on the primitive. - add_morph_back_pointers(prim, prim, model_index, char_data); - - // Also check for morphs on each of the prim's vertices. - EggPrimitive::const_iterator vi; - for (vi = prim->begin(); vi != prim->end(); ++vi) { - EggVertex *vertex = (*vi); - - add_morph_back_pointers(vertex, vertex, model_index, char_data); - add_morph_back_pointers_vertex(vertex, vertex, model_index, char_data); - - EggMorphVertexList::const_iterator mvi; - for (mvi = vertex->_dxyzs.begin(); - mvi != vertex->_dxyzs.end(); - ++mvi) { - const EggMorphVertex &morph = (*mvi); - char_data->make_slider(morph.get_name())->add_back_pointer(model_index, vertex); - } - } - } - - if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, egg_node); - EggGroupNode::iterator gi; - for (gi = group->begin(); gi != group->end(); ++gi) { - scan_for_morphs(*gi, model_index, char_data); - } - } -} - -/** - * Go back to the animation tables and look for morph slider animation - * channels. - */ -void EggCharacterCollection:: -scan_for_sliders(EggNode *egg_node, int model_index, - EggCharacterData *char_data) { - if (egg_node->is_of_type(EggTable::get_class_type())) { - EggTable *bundle = DCAST(EggTable, egg_node); - - // We really only need to check the immediate children of the bundle for a - // table node called "morph". This is a sibling of "", which we - // found a minute ago, but we weren't ready to scan for the morph sliders - // at the time, so we have to look again now. - - EggGroupNode::iterator gi; - for (gi = bundle->begin(); gi != bundle->end(); ++gi) { - EggNode *child = (*gi); - if (child->is_of_type(EggTable::get_class_type())) { - EggTable *table = DCAST(EggTable, child); - if (table->get_name() == "morph") { - // Here it is! Now the immediate children of this node are all the - // slider channels. - - EggGroupNode::iterator cgi; - for (cgi = table->begin(); cgi != table->end(); ++cgi) { - EggNode *grandchild = (*cgi); - if (grandchild->is_of_type(EggSAnimData::get_class_type())) { - char_data->make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild); - } - } - } - } - } - } -} - -/** - * Adds the back pointers for the kinds of morphs we might find in an - * EggAttributes object. - */ -void EggCharacterCollection:: -add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, - int model_index, EggCharacterData *char_data) { - EggMorphNormalList::const_iterator mni; - for (mni = attrib->_dnormals.begin(); - mni != attrib->_dnormals.end(); - ++mni) { - const EggMorphNormal &morph = (*mni); - char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); - } - - EggMorphColorList::const_iterator mci; - for (mci = attrib->_drgbas.begin(); - mci != attrib->_drgbas.end(); - ++mci) { - const EggMorphColor &morph = (*mci); - char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); - } -} - -/** - * Adds the back pointers for the kinds of morphs we might find in an - * EggVertex object. - */ -void EggCharacterCollection:: -add_morph_back_pointers_vertex(EggVertex *vertex, EggObject *egg_object, - int model_index, EggCharacterData *char_data) { - EggVertex::const_uv_iterator ui; - for (ui = vertex->uv_begin(); ui != vertex->uv_end(); ++ui) { - EggVertexUV *vert_uv = (*ui); - EggMorphTexCoordList::const_iterator mti; - for (mti = vert_uv->_duvs.begin(); - mti != vert_uv->_duvs.end(); - ++mti) { - const EggMorphTexCoord &morph = (*mti); - char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object); - } - } -} - -/** - * Attempts to match up the indicated list of egg_nodes with the children of - * the given joint_data, by name if possible. - * - * Also recurses on each matched joint to build up the entire joint hierarchy. - */ -void EggCharacterCollection:: -match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data, - EggNodeList &egg_nodes, int egg_index, int model_index) { - // Sort the list of egg_nodes in order by name. This will make the matching - // up by names easier and more reliable. - sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames()); - - if (joint_data->_children.empty()) { - // If the EggJointData has no children yet, we must be the first. - // Gleefully define all the joints. - EggNodeList::iterator ei; - for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) { - EggNode *egg_node = (*ei); - EggJointData *data = make_joint_data(char_data); - joint_data->_children.push_back(data); - char_data->_joints.push_back(data); - char_data->_components.push_back(data); - data->_parent = joint_data; - data->_new_parent = joint_data; - found_egg_match(char_data, data, egg_node, egg_index, model_index); - } - - } else { - // The EggJointData already has children; therefore, we have to match our - // joints up with the already-existing ones. - - EggNodeList extra_egg_nodes; - EggJointData::Children extra_data; - - EggNodeList::iterator ei; - EggJointData::Children::iterator di; - - ei = egg_nodes.begin(); - di = joint_data->_children.begin(); - - while (ei != egg_nodes.end() && di != joint_data->_children.end()) { - EggNode *egg_node = (*ei); - EggJointData *data = (*di); - - if (egg_node->get_name() < data->get_name()) { - // Here's a joint in the egg file, unmatched in the data. - extra_egg_nodes.push_back(egg_node); - ++ei; - - } else if (data->get_name() < egg_node->get_name()) { - // Here's a joint in the data, umatched by the egg file. - extra_data.push_back(data); - ++di; - - } else { - // Hey, these two match! Hooray! - found_egg_match(char_data, data, egg_node, egg_index, model_index); - ++ei; - ++di; - } - } - - while (ei != egg_nodes.end()) { - EggNode *egg_node = (*ei); - - // Here's a joint in the egg file, unmatched in the data. - extra_egg_nodes.push_back(egg_node); - ++ei; - } - - while (di != joint_data->_children.end()) { - EggJointData *data = (*di); - - // Here's a joint in the data, umatched by the egg file. - extra_data.push_back(data); - ++di; - } - - if (!extra_egg_nodes.empty()) { - // If we have some extra egg_nodes, we have to find a place to match - // them. (If we only had extra data, we don't care.) - - // First, check to see if any of the names match any past-used name. - EggNodeList more_egg_nodes; - - for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) { - EggNode *egg_node = (*ei); - bool matched = false; - for (di = extra_data.begin(); di != extra_data.end(); ++di) { - EggJointData *data = (*di); - if (data->matches_name(egg_node->get_name())) { - found_egg_match(char_data, data, egg_node, egg_index, model_index); - extra_data.erase(di); - matched = true; - break; - } - } - - if (!matched) { - // This joint name was never seen before. - more_egg_nodes.push_back(egg_node); - } - } - extra_egg_nodes.swap(more_egg_nodes); - } - - if (!extra_egg_nodes.empty()) { - // Ok, we've still got to find a home for these remaining egg_nodes. - if (extra_egg_nodes.size() == extra_data.size()) { - // Match 'em up one-for-one. - size_t i; - for (i = 0; i < extra_egg_nodes.size(); i++) { - EggNode *egg_node = extra_egg_nodes[i]; - EggJointData *data = extra_data[i]; - found_egg_match(char_data, data, egg_node, egg_index, model_index); - } - - } else { - // Just tack 'em on the end. - EggNodeList::iterator ei; - for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) { - EggNode *egg_node = (*ei); - EggJointData *data = make_joint_data(char_data); - joint_data->_children.push_back(data); - char_data->_joints.push_back(data); - char_data->_components.push_back(data); - data->_parent = joint_data; - data->_new_parent = joint_data; - found_egg_match(char_data, data, egg_node, egg_index, model_index); - } - } - } - } - - // Now sort the generated joint data hierarchy by name, just to be sure. - sort(joint_data->_children.begin(), joint_data->_children.end(), - IndirectCompareNames()); -} - -/** - * Marks a one-to-one association between the indicated EggJointData and the - * indicated EggNode, and then recurses below. - */ -void EggCharacterCollection:: -found_egg_match(EggCharacterData *char_data, EggJointData *joint_data, - EggNode *egg_node, int egg_index, int model_index) { - if (egg_node->has_name()) { - joint_data->add_name(egg_node->get_name(), char_data->_component_names); - } - egg_node->set_name(joint_data->get_name()); - joint_data->add_back_pointer(model_index, egg_node); - - if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group_node = DCAST(EggGroupNode, egg_node); - - // Now consider all the children of egg_node that are themselves joints or - // tables. - EggNodeList egg_nodes; - - // Two approaches: either we are scanning a model with joints, or an - // animation bundle with tables. - - if (egg_node->is_of_type(EggGroup::get_class_type())) { - // A model with joints. - EggGroupNode::iterator gi; - for (gi = group_node->begin(); gi != group_node->end(); ++gi) { - EggNode *child = (*gi); - if (child->is_of_type(EggGroup::get_class_type())) { - EggGroup *group = DCAST(EggGroup, child); - if (group->get_group_type() == EggGroup::GT_joint) { - egg_nodes.push_back(group); - } - } - } - - } else { - // An animation bundle with tables. - EggGroupNode::iterator gi; - for (gi = group_node->begin(); gi != group_node->end(); ++gi) { - EggNode *child = (*gi); - if (child->is_of_type(EggTable::get_class_type())) { - EggTable *table = DCAST(EggTable, child); - if (!(table->get_name() == "xform")) { - egg_nodes.push_back(table); - } - } - } - } - - if (!egg_nodes.empty()) { - match_egg_nodes(char_data, joint_data, egg_nodes, - egg_index, model_index); - } - } -} - -/** - * Renames the ith character to the indicated name. This name must not - * already be used by another character in the collection. - */ -void EggCharacterCollection:: -rename_char(int i, const string &name) { - nassertv(i >= 0 && i < (int)_characters.size()); - - EggCharacterData *char_data = _characters[i]; - if (char_data->get_name() != name) { - nassertv(get_character_by_name(name) == nullptr); - char_data->rename_char(name); - } -} - -/** - * - */ -void EggCharacterCollection:: -write(std::ostream &out, int indent_level) const { - Characters::const_iterator ci; - - for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - EggCharacterData *char_data = (*ci); - char_data->write(out, indent_level); - } -} - -/** - * Can be called after the collection has been completely filled up with egg - * files to output any messages from warning conditions that have been - * detected, such as inconsistent animation tables. - * - * In addition to reporting this errors, calling this function will also - * ensure that they are all repaired. Pass force_initial_rest_frame as true - * to also force rest frames from different models to be the same if they are - * initially different. - */ -void EggCharacterCollection:: -check_errors(std::ostream &out, bool force_initial_rest_frame) { - Characters::const_iterator ci; - for (ci = _characters.begin(); ci != _characters.end(); ++ci) { - EggCharacterData *char_data = (*ci); - int num_joints = char_data->get_num_joints(); - for (int j = 0; j < num_joints; j++) { - EggJointData *joint_data = char_data->get_joint(j); - if (joint_data->rest_frames_differ()) { - if (force_initial_rest_frame) { - joint_data->force_initial_rest_frame(); - out << "Forced rest frames the same for " << joint_data->get_name() - << ".\n"; - } else { - out << "Warning: rest frames for " << joint_data->get_name() - << " differ.\n"; - } - } - } - - int num_models = char_data->get_num_models(); - for (int mi = 0; mi < num_models; mi++) { - int model_index = char_data->get_model_index(mi); - if (!char_data->check_num_frames(model_index)) { - out << "Warning: animation from " - << char_data->get_egg_data(model_index)->get_egg_filename().get_basename() - << " had an inconsistent number of frames.\n"; - } - } - } -} diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.h b/pandatool/src/eggcharbase/eggCharacterCollection.h deleted file mode 100644 index 8a0bbd4f..00000000 --- a/pandatool/src/eggcharbase/eggCharacterCollection.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterCollection.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGCHARACTERCOLLECTION_H -#define EGGCHARACTERCOLLECTION_H - -#include "pandatoolbase.h" - -#include "eggCharacterData.h" - -#include "eggData.h" -#include "eggNode.h" -#include "pointerTo.h" - -class EggTable; -class EggAttributes; - -/** - * Represents a set of characters, as read and collected from possibly several - * model and/or animation egg files. - */ -class EggCharacterCollection { -public: - EggCharacterCollection(); - virtual ~EggCharacterCollection(); - - int add_egg(EggData *egg); - - INLINE int get_num_eggs() const; - INLINE EggData *get_egg(int i) const; - INLINE int get_first_model_index(int egg_index) const; - INLINE int get_num_models(int egg_index) const; - - INLINE int get_num_characters() const; - INLINE EggCharacterData *get_character(int i) const; - EggCharacterData *get_character_by_name(const std::string &character_name) const; - - INLINE EggCharacterData *get_character_by_model_index(int model_index) const; - - void rename_char(int i, const std::string &name); - - virtual void write(std::ostream &out, int indent_level = 0) const; - void check_errors(std::ostream &out, bool force_initial_rest_frame); - - virtual EggCharacterData *make_character_data(); - virtual EggJointData *make_joint_data(EggCharacterData *char_data); - virtual EggSliderData *make_slider_data(EggCharacterData *char_data); - -public: - EggCharacterData *make_character(const std::string &character_name); - - class EggInfo { - public: - PT(EggData) _egg; - typedef pvector< PT(EggNode) > Models; - Models _models; - int _first_model_index; - }; - - typedef pvector Eggs; - Eggs _eggs; - - typedef pvector Characters; - Characters _characters; - Characters _characters_by_model_index; - -private: - bool scan_hierarchy(EggNode *egg_node); - void scan_for_top_joints(EggNode *egg_node, EggNode *model_root, - const std::string &character_name); - void scan_for_top_tables(EggTable *bundle, EggNode *model_root, - const std::string &character_name); - void scan_for_morphs(EggNode *egg_node, int model_index, - EggCharacterData *char_data); - void scan_for_sliders(EggNode *egg_node, int model_index, - EggCharacterData *char_data); - - void add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object, - int model_index, EggCharacterData *char_data); - void add_morph_back_pointers_vertex(EggVertex *vertex, EggObject *egg_object, - int model_index, EggCharacterData *char_data); - - // The _top_egg_nodes member is only used temporarily, when adding each pre- - // existing egg file to the structure for the first time. - typedef pvector EggNodeList; - class ModelDescription { - public: - INLINE ModelDescription(); - EggNodeList _top_nodes; - EggObject *_root_node; - }; - - typedef pmap TopEggNodes; - typedef pmap TopEggNodesByName; - TopEggNodesByName _top_egg_nodes; - - int _next_model_index; - - void match_egg_nodes(EggCharacterData *char_Data, EggJointData *joint_data, - EggNodeList &egg_nodes, int egg_index, int model_index); - void found_egg_match(EggCharacterData *char_data, EggJointData *joint_data, - EggNode *egg_node, int egg_index, int model_index); -}; - -#include "eggCharacterCollection.I" - -#endif diff --git a/pandatool/src/eggcharbase/eggCharacterData.I b/pandatool/src/eggcharbase/eggCharacterData.I deleted file mode 100644 index fc3d3f1b..00000000 --- a/pandatool/src/eggcharbase/eggCharacterData.I +++ /dev/null @@ -1,150 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterData.I - * @author drose - * @date 2001-02-23 - */ - -/** - * Returns the total number of models associated with this character. - * - * A "model" here is either a character model (or one LOD of a character - * model), or a character animation file: in either case, a hierarchy of - * joints. - */ -INLINE int EggCharacterData:: -get_num_models() const { - return _models.size(); -} - -/** - * Returns the model_index of the nth model associated with this character. - * This model_index may be used to ask questions about the particular model - * from the EggCharacterCollection object, or from the individual EggJointData - * and EggSliderData objects. - * - * A "model" here is either a character model (or one LOD of a character - * model), or a character animation file: in either case, a hierarchy of - * joints. - */ -INLINE int EggCharacterData:: -get_model_index(int n) const { - nassertr(n >= 0 && n < (int)_models.size(), 0); - return _models[n]._model_index; -} - -/** - * Returns the model_root of the nth model associated with this character. - * - * This is the node at which the character, animation bundle, or LOD - * officially began within its particular egg file. - */ -INLINE EggNode *EggCharacterData:: -get_model_root(int n) const { - nassertr(n >= 0 && n < (int)_models.size(), nullptr); - return _models[n]._model_root; -} - -/** - * Returns the EggData representing the egg file that defined this particular - * model. Note that one egg file might contain multiple models. - */ -INLINE EggData *EggCharacterData:: -get_egg_data(int n) const { - nassertr(n >= 0 && n < (int)_models.size(), nullptr); - return _models[n]._egg_data; -} - -/** - * Returns the root joint of the character hierarchy. This root joint does - * not represent an actual joint in the hierarchy, but instead is a fictitious - * joint that is the parent of all the top joints in the hierarchy (since the - * hierarchy may actually contain zero or more top joints). - */ -INLINE EggJointData *EggCharacterData:: -get_root_joint() const { - return _root_joint; -} - -/** - * Returns the first joint found with the indicated name, or NULL if no joint - * has that name. - */ -INLINE EggJointData *EggCharacterData:: -find_joint(const std::string &name) const { - return _root_joint->find_joint(name); -} - -/** - * Creates a new joint as a child of the indicated joint and returns it. The - * new joint will be initialized to the identity transform, so that in - * inherits the net transform of the indicated parent joint. - */ -INLINE EggJointData *EggCharacterData:: -make_new_joint(const std::string &name, EggJointData *parent) { - EggJointData *joint = parent->make_new_joint(name); - _joints.push_back(joint); - _components.push_back(joint); - return joint; -} - -/** - * Returns the total number of joints in the character joint hierarchy. - */ -INLINE int EggCharacterData:: -get_num_joints() const { - return _joints.size(); -} - -/** - * Returns the nth joint in the character joint hierarchy. This returns all - * of the joints in the hierarchy in an arbitrary ordering. - */ -INLINE EggJointData *EggCharacterData:: -get_joint(int n) const { - nassertr(n >= 0 && n < (int)_joints.size(), nullptr); - return _joints[n]; -} - -/** - * Returns the number of sliders in the character slider list. - */ -INLINE int EggCharacterData:: -get_num_sliders() const { - return _sliders.size(); -} - -/** - * Returns the nth slider in the character slider list. - */ -INLINE EggSliderData *EggCharacterData:: -get_slider(int n) const { - nassertr(n >= 0 && n < (int)_sliders.size(), nullptr); - return _sliders[n]; -} - -/** - * Returns the total number of joints and sliders in the character. - */ -INLINE int EggCharacterData:: -get_num_components() const { - return _components.size(); -} - -/** - * Returns the nth joint or slider in the character. This can be used to walk - * linearly through all joints and sliders in the character when you don't - * care about making a distinction between the two; it returns the same - * objects that can also be discovered via get_slider() and get_root_joint(). - */ -INLINE EggComponentData *EggCharacterData:: -get_component(int n) const { - nassertr(n >= 0 && n < (int)_components.size(), nullptr); - return _components[n]; -} diff --git a/pandatool/src/eggcharbase/eggCharacterData.cxx b/pandatool/src/eggcharbase/eggCharacterData.cxx deleted file mode 100644 index d3c7a545..00000000 --- a/pandatool/src/eggcharbase/eggCharacterData.cxx +++ /dev/null @@ -1,410 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterData.cxx - * @author drose - * @date 2001-02-23 - */ - -#include "eggCharacterData.h" -#include "eggCharacterCollection.h" -#include "eggCharacterDb.h" -#include "eggJointData.h" -#include "eggSliderData.h" -#include "indent.h" - -#include - -// An STL function object to sort the joint list in order from highest to -// lowest in the new hierarchy. Used in do_reparent(). -class OrderJointsByNewDepth { -public: - bool operator()(const EggJointData *a, const EggJointData *b) const { - return a->_new_parent_depth < b->_new_parent_depth; - } -}; - - -/** - * - */ -EggCharacterData:: -EggCharacterData(EggCharacterCollection *collection) : - _component_names("_", "joint_") -{ - _collection = collection; - _root_joint = _collection->make_joint_data(this); - // The fictitious root joint is not added to the _components list. -} - -/** - * - */ -EggCharacterData:: -~EggCharacterData() { - delete _root_joint; - - Sliders::iterator si; - for (si = _sliders.begin(); si != _sliders.end(); ++si) { - EggSliderData *slider = (*si); - delete slider; - } -} - -/** - * Renames all of the models in the character data to the indicated name. - * This is the name that is used to identify unique skeleton hierarchies; if - * you set two different models to the same name, they will be loaded together - * as if they are expected to have the same skeleton hierarchy. - */ -void EggCharacterData:: -rename_char(const std::string &name) { - Models::iterator mi; - for (mi = _models.begin(); mi != _models.end(); ++mi) { - (*mi)._model_root->set_name(name); - } - - set_name(name); -} - -/** - * Indicates that the given model_index (with the indicated model_root) is - * associated with this character. This is normally called by the - * EggCharacterCollection class as new models are discovered. - * - * A "model" here is either a character model (or one LOD of a character - * model), or a character animation file: in either case, a hierarchy of - * joints. - */ -void EggCharacterData:: -add_model(int model_index, EggNode *model_root, EggData *egg_data) { - Model m; - m._model_index = model_index; - m._model_root = model_root; - m._egg_data = egg_data; - _models.push_back(m); -} - -/** - * Returns the number of frames of animation of the indicated model. This is - * more reliable than asking a particular joint or slider of the animation for - * its number of frames, since a particular joint may have only 1 frame (if it - * is unanimated), even though the overall animation has many frames. - */ -int EggCharacterData:: -get_num_frames(int model_index) const { - int max_num_frames = 0; - Components::const_iterator ci; - for (ci = _components.begin(); ci != _components.end(); ++ci) { - EggComponentData *component = (*ci); - int num_frames = component->get_num_frames(model_index); - if (num_frames > 1) { - // We have a winner. Assume all other components will be similar. - return num_frames; - } - max_num_frames = std::max(max_num_frames, num_frames); - } - - // Every component had either 1 frame or 0 frames. Return the maximum of - // these. - return max_num_frames; -} - -/** - * Returns the stated frame rate of the specified model. Similar to - * get_num_frames(). - */ -double EggCharacterData:: -get_frame_rate(int model_index) const { - Components::const_iterator ci; - for (ci = _components.begin(); ci != _components.end(); ++ci) { - EggComponentData *component = (*ci); - double frame_rate = component->get_frame_rate(model_index); - if (frame_rate != 0.0) { - // We have a winner. Assume all other components will be similar. - return frame_rate; - } - } - - return 0.0; -} - -/** - * Walks through each component and ensures that all have the same number of - * frames of animation (except for those that contain 0 or 1 frames, of - * course). Returns true if all are valid, false if there is a discreprency - * (in which case the shorter component are extended). - */ -bool EggCharacterData:: -check_num_frames(int model_index) { - int max_num_frames = 0; - bool any_violations = false; - Components::const_iterator ci; - for (ci = _components.begin(); ci != _components.end(); ++ci) { - EggComponentData *component = (*ci); - int num_frames = component->get_num_frames(model_index); - if (num_frames > 1 && max_num_frames > 1 && - max_num_frames != num_frames) { - // If we have two different opinions about the number of frames (other - // than 0 or 1), we have a discrepency. This is an error condition. - any_violations = true; - } - max_num_frames = std::max(max_num_frames, num_frames); - } - - if (any_violations) { - // Now go back through and force all components to the appropriate length. - for (ci = _components.begin(); ci != _components.end(); ++ci) { - EggComponentData *component = (*ci); - int num_frames = component->get_num_frames(model_index); - if (num_frames > 1 && max_num_frames != num_frames) { - component->extend_to(model_index, max_num_frames); - } - } - } - - return !any_violations; -} - -/** - * Begins the process of restructuring the joint hierarchy according to the - * previous calls to reparent_to() on various joints. This will reparent the - * joint hierachy in all models as requested, while adjusting the transforms - * as appropriate so that each joint retains the same net transform across all - * frames that it had before the operation. Returns true on success, false on - * failure. - */ -bool EggCharacterData:: -do_reparent() { - typedef pset InvalidSet; - InvalidSet invalid_set; - - // To begin, make sure the list of new_children is accurate. - Joints::const_iterator ji; - for (ji = _joints.begin(); ji != _joints.end(); ++ji) { - EggJointData *joint_data = (*ji); - joint_data->do_begin_reparent(); - } - // We also need to clear the children on the root joint, but the root joint - // doesn't get any of the other operations (including finish_reparent) - // applied to it. - _root_joint->do_begin_reparent(); - - - // Now, check for cycles in the new parenting hierarchy, and also sort the - // joints in order from top to bottom in the new hierarchy. - for (ji = _joints.begin(); ji != _joints.end(); ++ji) { - EggJointData *joint_data = (*ji); - pset chain; - if (joint_data->calc_new_parent_depth(chain)) { - nout << "Cycle detected in parent chain for " << joint_data->get_name() - << "!\n"; - return false; - } - } - sort(_joints.begin(), _joints.end(), OrderJointsByNewDepth()); - - // Now compute the new transforms for the joints' new positions. This is - // done recursively through the new parent hierarchy, so we can take - // advantage of caching the net value for a particular frame. - Models::const_iterator mi; - for (mi = _models.begin(); mi != _models.end(); ++mi) { - EggCharacterDb db; - int model_index = (*mi)._model_index; - int num_frames = get_num_frames(model_index); - nout << " computing " << (mi - _models.begin()) + 1 - << " of " << _models.size() - << ": " << (*mi)._egg_data->get_egg_filename() - << " (" << num_frames << " frames)\n"; - for (int f = 0; f < num_frames; f++) { - // First, walk through all the joints and flush the computed net - // transforms from before. - for (ji = _joints.begin(); ji != _joints.end(); ++ji) { - EggJointData *joint_data = (*ji); - joint_data->do_begin_compute_reparent(); - } - _root_joint->do_begin_compute_reparent(); - - // Now go back through and compute the reparented transforms, caching - // net transforms as necessary. - for (ji = _joints.begin(); ji != _joints.end(); ++ji) { - EggJointData *joint_data = (*ji); - if (!joint_data->do_compute_reparent(model_index, f, db)) { - // Oops, we got an invalid transform. - invalid_set.insert(joint_data); - } - } - } - - // Finally, apply the computations to the joints. - for (ji = _joints.begin(); ji != _joints.end(); ++ji) { - EggJointData *joint_data = (*ji); - if (!joint_data->do_joint_rebuild(model_index, db)) { - invalid_set.insert(joint_data); - } - } - } - - // Now remove all of the old children and add in the new children. - for (ji = _joints.begin(); ji != _joints.end(); ++ji) { - EggJointData *joint_data = (*ji); - joint_data->do_finish_reparent(); - } - - // Report the set of joints that failed. It really shouldn't be possible - // for any joints to fail, so if you see anything reported here, something - // went wrong at a fundamental level. Perhaps a problem with - // decompose_matrix(). - InvalidSet::const_iterator si; - for (si = invalid_set.begin(); si != invalid_set.end(); ++si) { - EggJointData *joint_data = (*si); - // Don't bother reporting joints that no longer have a parent, since we - // don't care about joints that are now outside the hierarchy. - if (joint_data->get_parent() != nullptr) { - nout << "Warning: reparenting " << joint_data->get_name() - << " to "; - if (joint_data->get_parent() == _root_joint) { - nout << "the root"; - } else { - nout << joint_data->get_parent()->get_name(); - } - nout << " results in an invalid transform.\n"; - } - } - - return invalid_set.empty(); -} - -/** - * Chooses the best possible parent joint for each of the joints in the - * hierarchy, based on the score computed by - * EggJointData::score_reparent_to(). This is a fairly expensive operation - * that involves lots of recomputing of transforms across the hierarchy. - * - * The joints are not actually reparented yet, but the new_parent of each - * joint is set. Call do_reparent() to actually perform the suggested - * reparenting operation. - */ -void EggCharacterData:: -choose_optimal_hierarchy() { - EggCharacterDb db; - - Joints::const_iterator ji, jj; - for (ji = _joints.begin(); ji != _joints.end(); ++ji) { - EggJointData *joint_data = (*ji); - - EggJointData *best_parent = joint_data->get_parent(); - int best_score = joint_data->score_reparent_to(best_parent, db); - - for (jj = _joints.begin(); jj != _joints.end(); ++jj) { - EggJointData *possible_parent = (*jj); - if (possible_parent != joint_data && possible_parent != best_parent && - !joint_data->is_new_ancestor(possible_parent)) { - - int score = joint_data->score_reparent_to(possible_parent, db); - if (score >= 0 && (best_score < 0 || score < best_score)) { - best_parent = possible_parent; - best_score = score; - } - } - } - - // Also consider reparenting the node to the root. - EggJointData *possible_parent = get_root_joint(); - if (possible_parent != best_parent) { - int score = joint_data->score_reparent_to(possible_parent, db); - if (score >= 0 && (best_score < 0 || score < best_score)) { - best_parent = possible_parent; - best_score = score; - } - } - - if (best_parent != nullptr && - best_parent != joint_data->_parent) { - nout << "best parent for " << joint_data->get_name() << " is " - << best_parent->get_name() << "\n"; - joint_data->reparent_to(best_parent); - } - } -} - -/** - * Returns the slider with the indicated name, or NULL if no slider has that - * name. - */ -EggSliderData *EggCharacterData:: -find_slider(const std::string &name) const { - SlidersByName::const_iterator si; - si = _sliders_by_name.find(name); - if (si != _sliders_by_name.end()) { - return (*si).second; - } - - return nullptr; -} - -/** - * Returns the slider matching the indicated name. If no such slider exists - * already, creates a new one. - */ -EggSliderData *EggCharacterData:: -make_slider(const std::string &name) { - SlidersByName::const_iterator si; - si = _sliders_by_name.find(name); - if (si != _sliders_by_name.end()) { - return (*si).second; - } - - EggSliderData *slider = _collection->make_slider_data(this); - slider->set_name(name); - _sliders_by_name.insert(SlidersByName::value_type(name, slider)); - _sliders.push_back(slider); - _components.push_back(slider); - return slider; -} - -/** - * Returns the estimated amount of memory, in megabytes, that will be required - * to perform the do_reparent() operation. This is used mainly be - * EggCharacterDb to decide up front whether to store this data in-RAM or on- - * disk. - */ -size_t EggCharacterData:: -estimate_db_size() const { - // Count how much memory we will need to store the interim transforms. This - // is models * joints * frames * 3 * sizeof(LMatrix4d). - size_t mj_frames = 0; - Models::const_iterator mi; - for (mi = _models.begin(); mi != _models.end(); ++mi) { - int model_index = (*mi)._model_index; - size_t num_frames = (size_t)get_num_frames(model_index); - mj_frames += num_frames * _joints.size(); - } - - // We do this operation a bit carefully, to guard against integer overflow. - size_t mb_needed = ((mj_frames * 3 / 1024) * sizeof(LMatrix4d)) / 1024; - - return mb_needed; -} - - -/** - * - */ -void EggCharacterData:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << "Character " << get_name() << ":\n"; - get_root_joint()->write(out, indent_level + 2); - - Sliders::const_iterator si; - for (si = _sliders.begin(); si != _sliders.end(); ++si) { - EggSliderData *slider = (*si); - slider->write(out, indent_level + 2); - } -} diff --git a/pandatool/src/eggcharbase/eggCharacterData.h b/pandatool/src/eggcharbase/eggCharacterData.h deleted file mode 100644 index f488e335..00000000 --- a/pandatool/src/eggcharbase/eggCharacterData.h +++ /dev/null @@ -1,121 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterData.h - * @author drose - * @date 2001-02-23 - */ - -#ifndef EGGCHARACTERDATA_H -#define EGGCHARACTERDATA_H - -#include "pandatoolbase.h" - -#include "eggJointData.h" -#include "eggNode.h" -#include "eggData.h" -#include "pointerTo.h" -#include "namable.h" -#include "nameUniquifier.h" - -#include "pmap.h" - -class EggCharacterCollection; -class EggSliderData; -class EggCharacterDb; - -/** - * Represents a single character, as read and collected from several models - * and animation files. This contains a hierarchy of EggJointData nodes - * representing the skeleton, as well as a list of EggSliderData nodes - * representing the morph channels for the character. - * - * This is very similar to the Character class from Panda, in that it's - * capable of associating skeleton-morph animation channels with models and - * calculating the vertex position for each frame. To some degree, it - * duplicates the functionality of Character. However, it differs in one - * fundamental principle: it is designed to be a non-real-time operation, - * working directly on the Egg structures as they are, instead of first - * boiling the Egg data into native Panda Geom tables for real-time animation. - * Because of this, it is (a) double-precision instead of single precision, - * (b) capable of generating modified Egg files, and (c) about a hundred times - * slower than the Panda Character class. - * - * The data in this structure is normally filled in by the - * EggCharacterCollection class. - */ -class EggCharacterData : public Namable { -public: - EggCharacterData(EggCharacterCollection *collection); - virtual ~EggCharacterData(); - - void rename_char(const std::string &name); - - void add_model(int model_index, EggNode *model_root, EggData *egg_data); - INLINE int get_num_models() const; - INLINE int get_model_index(int n) const; - INLINE EggNode *get_model_root(int n) const; - INLINE EggData *get_egg_data(int n) const; - int get_num_frames(int model_index) const; - bool check_num_frames(int model_index); - double get_frame_rate(int model_index) const; - - INLINE EggJointData *get_root_joint() const; - INLINE EggJointData *find_joint(const std::string &name) const; - INLINE EggJointData *make_new_joint(const std::string &name, EggJointData *parent); - INLINE int get_num_joints() const; - INLINE EggJointData *get_joint(int n) const; - - bool do_reparent(); - void choose_optimal_hierarchy(); - - INLINE int get_num_sliders() const; - INLINE EggSliderData *get_slider(int n) const; - EggSliderData *find_slider(const std::string &name) const; - EggSliderData *make_slider(const std::string &name); - - INLINE int get_num_components() const; - INLINE EggComponentData *get_component(int n) const; - - size_t estimate_db_size() const; - - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - class Model { - public: - int _model_index; - PT(EggNode) _model_root; - PT(EggData) _egg_data; - }; - typedef pvector Models; - Models _models; - - EggCharacterCollection *_collection; - EggJointData *_root_joint; - - typedef pmap SlidersByName; - SlidersByName _sliders_by_name; - - typedef pvector Sliders; - Sliders _sliders; - - typedef pvector Joints; - Joints _joints; - - typedef pvector Components; - Components _components; - - NameUniquifier _component_names; - - friend class EggCharacterCollection; -}; - -#include "eggCharacterData.I" - -#endif diff --git a/pandatool/src/eggcharbase/eggCharacterDb.I b/pandatool/src/eggcharbase/eggCharacterDb.I deleted file mode 100644 index f530b93a..00000000 --- a/pandatool/src/eggcharbase/eggCharacterDb.I +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterDb.I - * @author drose - * @date 2006-10-05 - */ - -/** - * - */ -INLINE EggCharacterDb::Key:: -Key(const EggJointPointer *joint, TableType table_type, int frame) : - _joint(joint), - _table_type(table_type), - _frame(frame) -{ -} - -/** - * Provides an arbitrary unique ordering for all keys. - */ -INLINE bool EggCharacterDb::Key:: -operator < (const EggCharacterDb::Key &other) const { - if (_joint != other._joint) { - return _joint < other._joint; - } - if (_table_type != other._table_type) { - return _table_type < other._table_type; - } - return _frame < other._frame; -} diff --git a/pandatool/src/eggcharbase/eggCharacterDb.cxx b/pandatool/src/eggcharbase/eggCharacterDb.cxx deleted file mode 100644 index e959499b..00000000 --- a/pandatool/src/eggcharbase/eggCharacterDb.cxx +++ /dev/null @@ -1,125 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterDb.cxx - * @author drose - * @date 2006-10-05 - */ - -#include "eggCharacterDb.h" -#include "eggCharacterData.h" - -/** - * Constructs a database for storing the interim work for the indicated - * EggCharacterData. The parameter max_ram_mb indicates the maximum amount of - * RAM (in MB) that the database should consume; if it the database would - * roughly fit within this limit, it will be stored in RAM; otherwise, it will - * be written to disk (if Berkeley DB is available). - */ -EggCharacterDb:: -EggCharacterDb() { - /* -#ifdef HAVE_BDB - _db = NULL; - - _db = new Db(NULL, 0); - _db_filename = Filename::temporary("", "eggc_", ".db"); - - string os_db_filename = _db_filename.to_os_specific(); - _db->open(NULL, os_db_filename.c_str(), NULL, - DB_BTREE, DB_CREATE | DB_EXCL, 0); - - nout << "Using " << os_db_filename << " for rebuild database.\n"; -#endif // HAVE_BDB - */ -} - -/** - * - */ -EggCharacterDb:: -~EggCharacterDb() { - /* -#ifdef HAVE_BDB - if (_db != (Db *)NULL){ - _db->close(0); - delete _db; - _db = NULL; - - string os_db_filename = _db_filename.to_os_specific(); - Db rmdb(NULL, 0); - rmdb.remove(os_db_filename.c_str(), NULL, 0); - } -#endif // HAVE_BDB - */ -} - -/** - * Looks up the data for the indicated joint, type, and frame, and fills it in - * result (and returns true) if it is found. Returns false if this data has - * not been stored in the database. - */ -bool EggCharacterDb:: -get_matrix(const EggJointPointer *joint, TableType type, - int frame, LMatrix4d &mat) const { - Key key(joint, type, frame); - - /* -#ifdef HAVE_BDB - if (_db != (Db *)NULL){ - Dbt db_key(&key, sizeof(Key)); - Dbt db_data(&mat, sizeof(LMatrix4d)); - db_data.set_ulen(sizeof(LMatrix4d)); - db_data.set_flags(DB_DBT_USERMEM); - - int result = _db->get(NULL, &db_key, &db_data, 0); - if (result == DB_NOTFOUND) { - return false; - } - nassertr(result == 0, false); - return true; - } -#endif // HAVE_BDB - */ - - Table::const_iterator ti; - ti = _table.find(key); - if (ti == _table.end()) { - return false; - } - - mat = (*ti).second; - return true; -} - -/** - * Stores the matrix for the indicated joint, type, and frame in the database. - * It is an error to call this more than once for any given key combination - * (not for any technical reason, but because we don't expect this to happen). - */ -void EggCharacterDb:: -set_matrix(const EggJointPointer *joint, TableType type, - int frame, const LMatrix4d &mat) { - Key key(joint, type, frame); - - /* -#ifdef HAVE_BDB - if (_db != (Db *)NULL){ - Dbt db_key(&key, sizeof(Key)); - Dbt db_data((void *)&mat, sizeof(LMatrix4d)); - int result = _db->put(NULL, &db_key, &db_data, DB_NOOVERWRITE); - nassertv(result != DB_KEYEXIST); - nassertv(result == 0); - return; - } -#endif // HAVE_BDB - */ - - bool inserted = _table.insert(Table::value_type(key, mat)).second; - nassertv(inserted); -} diff --git a/pandatool/src/eggcharbase/eggCharacterDb.h b/pandatool/src/eggcharbase/eggCharacterDb.h deleted file mode 100644 index 31af55f2..00000000 --- a/pandatool/src/eggcharbase/eggCharacterDb.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterDb.h - * @author drose - * @date 2006-10-05 - */ - -#ifndef EGGCHARACTERDB_H -#define EGGCHARACTERDB_H - -#include "pandatoolbase.h" -#include "pmap.h" - -/* -#ifdef HAVE_BDB - -// Apparently, we have to define this to make db_cxx files include the modern -// header files. -#define HAVE_CXX_STDHEADERS 1 -#include - -#endif // HAVE_BDB -*/ - -class EggJointPointer; -class LMatrix4d; - -/** - * This class is used during joint optimization or restructuring to store the - * table of interim joint computations. - * - * That is to say, this class provides an temporary data store for three - * tables of matrices per each EggJointPointer per frame. - */ -class EggCharacterDb { -public: - EggCharacterDb(); - ~EggCharacterDb(); - - enum TableType { - TT_rebuild_frame, - TT_net_frame, - TT_net_frame_inv, - }; - - bool get_matrix(const EggJointPointer *joint, TableType type, - int frame, LMatrix4d &mat) const; - void set_matrix(const EggJointPointer *joint, TableType type, - int frame, const LMatrix4d &mat); - -private: - class Key { - public: - INLINE Key(const EggJointPointer *joint, - TableType table_type, - int frame); - INLINE bool operator < (const Key &other) const; - - private: - const EggJointPointer *_joint; - TableType _table_type; - int _frame; - }; - - /* -#ifdef HAVE_BDB - Db *_db; - Filename _db_filename; -#endif // HAVE_BDB - */ - - typedef pmap Table; - Table _table; -}; - -#include "eggCharacterDb.I" - -#endif diff --git a/pandatool/src/eggcharbase/eggCharacterFilter.cxx b/pandatool/src/eggcharbase/eggCharacterFilter.cxx deleted file mode 100644 index 02289dbe..00000000 --- a/pandatool/src/eggcharbase/eggCharacterFilter.cxx +++ /dev/null @@ -1,108 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterFilter.cxx - * @author drose - * @date 2001-02-23 - */ - -#include "eggCharacterFilter.h" -#include "eggCharacterCollection.h" -#include "eggCharacterData.h" - - -/** - * - */ -EggCharacterFilter:: -EggCharacterFilter() : EggMultiFilter(false) { - _collection = nullptr; - - _force_initial_rest_frame = false; -} - -/** - * - */ -EggCharacterFilter:: -~EggCharacterFilter() { - delete _collection; -} - -/** - * - */ -void EggCharacterFilter:: -add_fixrest_option() { - add_option - ("fixrest", "", 30, - "Specify this to force all the initial rest frames of the various " - "model files to the same value as the first model specified. This " - "is a fairly drastic way to repair models whose initial rest frame " - "values are completely bogus, but should not be performed when the " - "input models are correct.", - &EggCharacterFilter::dispatch_none, &_force_initial_rest_frame); -} - - -/** - * - */ -bool EggCharacterFilter:: -post_command_line() { - if (_collection == nullptr) { - _collection = make_collection(); - } - - if (!EggMultiFilter::post_command_line()) { - return false; - } - - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - EggData *data = (*ei); - - if (_collection->add_egg(data) < 0) { - nout << data->get_egg_filename().get_basename() - << " does not contain a character model or animation channel.\n"; - return false; - } - } - - _collection->check_errors(nout, _force_initial_rest_frame); - - return true; -} - -/** - * Writes out all of the egg files in the _eggs vector, to the output - * directory if one is specified, or over the input files if -inplace was - * specified. - */ -void EggCharacterFilter:: -write_eggs() { - // Optimize (that is, collapse redudant nodes) in all of the characters' - // joint tables before writing them out. - int num_characters = _collection->get_num_characters(); - for (int i = 0; i < num_characters; i++) { - EggCharacterData *char_data = _collection->get_character(i); - char_data->get_root_joint()->optimize(); - } - - EggMultiFilter::write_eggs(); -} - -/** - * Allocates and returns a new EggCharacterCollection structure. This is - * primarily intended as a hook so derived classes can customize the type of - * EggCharacterCollection object used to represent the character information. - */ -EggCharacterCollection *EggCharacterFilter:: -make_collection() { - return new EggCharacterCollection; -} diff --git a/pandatool/src/eggcharbase/eggCharacterFilter.h b/pandatool/src/eggcharbase/eggCharacterFilter.h deleted file mode 100644 index c58536fa..00000000 --- a/pandatool/src/eggcharbase/eggCharacterFilter.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCharacterFilter.h - * @author drose - * @date 2001-02-23 - */ - -#ifndef EGGCHARACTERFILTER_H -#define EGGCHARACTERFILTER_H - -#include "pandatoolbase.h" - -#include "eggMultiFilter.h" - -class EggCharacterData; -class EggCharacterCollection; - -/** - * This is the base class for a family of programs that operate on a number of - * character models and their associated animation files together. It reads - * in a number of egg files, any combination of model files or character files - * which must all represent the same character skeleton, and maintains a - * single hierarchy of joints and sliders that may be operated on before - * writing the files back out. - */ -class EggCharacterFilter : public EggMultiFilter { -public: - EggCharacterFilter(); - virtual ~EggCharacterFilter(); - - void add_fixrest_option(); - -protected: - virtual bool post_command_line(); - virtual void write_eggs(); - - virtual EggCharacterCollection *make_collection(); - - EggCharacterCollection *_collection; - bool _force_initial_rest_frame; -}; - -#endif diff --git a/pandatool/src/eggcharbase/eggComponentData.I b/pandatool/src/eggcharbase/eggComponentData.I deleted file mode 100644 index e0064948..00000000 --- a/pandatool/src/eggcharbase/eggComponentData.I +++ /dev/null @@ -1,47 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggComponentData.I - * @author drose - * @date 2001-02-26 - */ - -/** - * Returns the maximum number of back pointers this component may have. The - * component may store a back pointer for models indexed 0 .. num_models - 1. - * You must call has_model() on each model index to confirm whether a - * particular model in that range has a back pointer. - */ -INLINE int EggComponentData:: -get_num_models() const { - return _back_pointers.size(); -} - -/** - * Returns true if the component has a back pointer to an egg file somewhere - * for the indicated model, false otherwise. - */ -INLINE bool EggComponentData:: -has_model(int model_index) const { - if (model_index >= 0 && model_index < (int)_back_pointers.size()) { - return _back_pointers[model_index] != nullptr; - } - return false; -} - -/** - * Returns the back pointer to an egg file for the indicated model if it - * exists, or NULL if it does not. - */ -INLINE EggBackPointer *EggComponentData:: -get_model(int model_index) const { - if (model_index >= 0 && model_index < (int)_back_pointers.size()) { - return _back_pointers[model_index]; - } - return nullptr; -} diff --git a/pandatool/src/eggcharbase/eggComponentData.cxx b/pandatool/src/eggcharbase/eggComponentData.cxx deleted file mode 100644 index ab57e5bd..00000000 --- a/pandatool/src/eggcharbase/eggComponentData.cxx +++ /dev/null @@ -1,128 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggComponentData.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggComponentData.h" -#include "eggBackPointer.h" -#include "nameUniquifier.h" - -#include "indent.h" - -TypeHandle EggComponentData::_type_handle; - - -/** - * - */ -EggComponentData:: -EggComponentData(EggCharacterCollection *collection, - EggCharacterData *char_data) : - _collection(collection), - _char_data(char_data) -{ -} - -/** - * - */ -EggComponentData:: -~EggComponentData() { - for (EggBackPointer *back : _back_pointers) { - delete back; - } -} - -/** - * Adds the indicated name to the set of names that this component can be - * identified with. If this is the first name added, it becomes the primary - * name of the component; later names added do not replace the primary name, - * but do get added to the list of names that will be accepted by - * matched_name(). - */ -void EggComponentData:: -add_name(const std::string &name, NameUniquifier &uniquifier) { - if (_names.insert(name).second) { - // This is a new name for this component. - if (!has_name()) { - set_name(uniquifier.add_name(name)); - if (get_name() != name) { - nout << "Warning: renamed " << name << " to " << get_name() - << " to avoid naming conflict.\n"; - } - } - } -} - -/** - * Returns true if the indicated name matches any name that was ever matched - * with this particular joint, false otherwise. - */ -bool EggComponentData:: -matches_name(const std::string &name) const { - if (name == get_name()) { - return true; - } - return (_names.find(name) != _names.end()); -} - -/** - * Returns the number of frames of animation for this particular component in - * the indicated model. - */ -int EggComponentData:: -get_num_frames(int model_index) const { - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - return 0; - } - return back->get_num_frames(); -} - -/** - * Extends the number of frames in the indicated model (presumably an - * animation table model) to the given number. - */ -void EggComponentData:: -extend_to(int model_index, int num_frames) const { - EggBackPointer *back = get_model(model_index); - nassertv(back != nullptr); - back->extend_to(num_frames); -} - -/** - * Returns the number of frames of animation for this particular component in - * the indicated model. - */ -double EggComponentData:: -get_frame_rate(int model_index) const { - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - return 0.0; - } - return back->get_frame_rate(); -} - -/** - * Sets the back_pointer associated with the given model_index. - */ -void EggComponentData:: -set_model(int model_index, EggBackPointer *back) { - while ((int)_back_pointers.size() <= model_index) { - _back_pointers.push_back(nullptr); - } - - if (_back_pointers[model_index] != nullptr) { - nout << "Warning: deleting old back pointer.\n"; - delete _back_pointers[model_index]; - } - _back_pointers[model_index] = back; -} diff --git a/pandatool/src/eggcharbase/eggComponentData.h b/pandatool/src/eggcharbase/eggComponentData.h deleted file mode 100644 index b54c20ff..00000000 --- a/pandatool/src/eggcharbase/eggComponentData.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggComponentData.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGCOMPONENTDATA_H -#define EGGCOMPONENTDATA_H - -#include "pandatoolbase.h" - -#include "eggObject.h" -#include "namable.h" -#include "pset.h" - -class EggCharacterCollection; -class EggCharacterData; -class EggBackPointer; -class NameUniquifier; - -/** - * This is the base class of both EggJointData and EggSliderData. It - * represents a single component of a character, either a joint or a slider, - * along with back pointers to the references to this component in all model - * and animation egg files read. - */ -class EggComponentData : public EggObject, public Namable { -public: - EggComponentData(EggCharacterCollection *collection, - EggCharacterData *char_data); - virtual ~EggComponentData(); - - void add_name(const std::string &name, NameUniquifier &uniquifier); - bool matches_name(const std::string &name) const; - - int get_num_frames(int model_index) const; - void extend_to(int model_index, int num_frames) const; - double get_frame_rate(int model_index) const; - - virtual void add_back_pointer(int model_index, EggObject *egg_object)=0; - virtual void write(std::ostream &out, int indent_level = 0) const=0; - - INLINE int get_num_models() const; - INLINE bool has_model(int model_index) const; - INLINE EggBackPointer *get_model(int model_index) const; - void set_model(int model_index, EggBackPointer *back); - -protected: - - // This points back to all the egg structures that reference this particular - // table or slider. - typedef pvector BackPointers; - BackPointers _back_pointers; - - typedef pset Names; - Names _names; - - EggCharacterCollection *_collection; - EggCharacterData *_char_data; - - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggObject::init_type(); - register_type(_type_handle, "EggComponentData", - EggObject::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 "eggComponentData.I" - -#endif diff --git a/pandatool/src/eggcharbase/eggJointData.I b/pandatool/src/eggcharbase/eggJointData.I deleted file mode 100644 index c8b81967..00000000 --- a/pandatool/src/eggcharbase/eggJointData.I +++ /dev/null @@ -1,93 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointData.I - * @author drose - * @date 2001-02-23 - */ - -/** - * - */ -INLINE EggJointData *EggJointData:: -get_parent() const { - return _parent; -} - -/** - * - */ -INLINE int EggJointData:: -get_num_children() const { - return _children.size(); -} - -/** - * - */ -INLINE EggJointData *EggJointData:: -get_child(int n) const { - nassertr(n >= 0 && n < (int)_children.size(), nullptr); - return _children[n]; -} - -/** - * Returns the first descendent joint found with the indicated name, or NULL - * if no joint has that name. - */ -INLINE EggJointData *EggJointData:: -find_joint(const std::string &name) { - EggJointData *joint = find_joint_exact(name); - if (joint == nullptr) { - joint = find_joint_matches(name); - } - return joint; -} - - -/** - * Returns true if the joint knows its rest frame, false otherwise. In - * general, this will be true as long as the joint is included in at least one - * model file, or false if it appears only in animation files. - */ -INLINE bool EggJointData:: -has_rest_frame() const { - return _has_rest_frame; -} - -/** - * Returns true if the rest frames for different models differ in their - * initial value. This is not technically an error, but it is unusual enough - * to be suspicious. - */ -INLINE bool EggJointData:: -rest_frames_differ() const { - return _rest_frames_differ; -} - -/** - * Returns the rest frame of the joint. This is the matrix value that appears - * for the joint in each model file; it should be the same transform in each - * model. - */ -INLINE const LMatrix4d &EggJointData:: -get_rest_frame() const { - nassertr(has_rest_frame(), LMatrix4d::ident_mat()); - return _rest_frame; -} - -/** - * Indicates an intention to change the parent of this joint to the indicated - * joint, or NULL to remove it from the hierarchy. The joint is not - * reparented immediately, but rather all of the joints are reparented at once - * when do_reparent() is called. - */ -INLINE void EggJointData:: -reparent_to(EggJointData *new_parent) { - _new_parent = new_parent; -} diff --git a/pandatool/src/eggcharbase/eggJointData.cxx b/pandatool/src/eggcharbase/eggJointData.cxx deleted file mode 100644 index ebf656b1..00000000 --- a/pandatool/src/eggcharbase/eggJointData.cxx +++ /dev/null @@ -1,769 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointData.cxx - * @author drose - * @date 2001-02-23 - */ - -#include "eggJointData.h" - -#include "eggCharacterDb.h" -#include "eggJointNodePointer.h" -#include "eggMatrixTablePointer.h" -#include "pvector.h" -#include "dcast.h" -#include "eggGroup.h" -#include "eggTable.h" -#include "indent.h" -#include "fftCompressor.h" -#include "zStream.h" - -using std::string; - -TypeHandle EggJointData::_type_handle; - - -/** - * - */ -EggJointData:: -EggJointData(EggCharacterCollection *collection, - EggCharacterData *char_data) : - EggComponentData(collection, char_data) -{ - _parent = nullptr; - _new_parent = nullptr; - _has_rest_frame = false; - _rest_frames_differ = false; -} - -/** - * Returns the local transform matrix corresponding to this joint position in - * the nth frame in the indicated model. - */ -LMatrix4d EggJointData:: -get_frame(int model_index, int n) const { - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - return LMatrix4d::ident_mat(); - } - - EggJointPointer *joint; - DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); - - return joint->get_frame(n); -} - -/** - * Returns the complete transform from the root corresponding to this joint - * position in the nth frame in the indicated model. - */ -LMatrix4d EggJointData:: -get_net_frame(int model_index, int n, EggCharacterDb &db) const { - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - return LMatrix4d::ident_mat(); - } - - EggJointPointer *joint; - DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); - - LMatrix4d mat; - if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame, n, mat)) { - // Compute this frame's net, and stuff it in. - mat = get_frame(model_index, n); - if (_parent != nullptr) { - mat = mat * _parent->get_net_frame(model_index, n, db); - } - db.set_matrix(joint, EggCharacterDb::TT_net_frame, n, mat); - } - - return mat; -} - -/** - * Returns the inverse of get_net_frame(). - */ -LMatrix4d EggJointData:: -get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const { - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - return LMatrix4d::ident_mat(); - } - - EggJointPointer *joint; - DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); - - LMatrix4d mat; - if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat)) { - // Compute this frame's net inverse, and stuff it in. - LMatrix4d mat = get_net_frame(model_index, n, db); - mat.invert_in_place(); - db.set_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat); - } - - return mat; -} - -/** - * Forces all of the joints to have the same rest frame value as the first - * joint read in. This is a drastic way to repair models whose rest frame - * values are completely bogus, but should not be performed on models that are - * otherwise correct. - */ -void EggJointData:: -force_initial_rest_frame() { - if (!has_rest_frame()) { - return; - } - int num_models = get_num_models(); - for (int model_index = 0; model_index < num_models; model_index++) { - if (has_model(model_index)) { - EggJointPointer *joint; - DCAST_INTO_V(joint, get_model(model_index)); - if (joint->is_of_type(EggJointNodePointer::get_class_type())) { - joint->set_frame(0, get_rest_frame()); - } - } - } - _rest_frames_differ = false; -} - -/** - * Moves the vertices assigned to this joint into the indicated joint, without - * changing their weight assignments. - */ -void EggJointData:: -move_vertices_to(EggJointData *new_owner) { - int num_models = get_num_models(); - - if (new_owner == nullptr) { - for (int model_index = 0; model_index < num_models; model_index++) { - if (has_model(model_index)) { - EggJointPointer *joint; - DCAST_INTO_V(joint, get_model(model_index)); - joint->move_vertices_to(nullptr); - } - } - } else { - for (int model_index = 0; model_index < num_models; model_index++) { - if (has_model(model_index) && new_owner->has_model(model_index)) { - EggJointPointer *joint, *new_joint; - DCAST_INTO_V(joint, get_model(model_index)); - DCAST_INTO_V(new_joint, new_owner->get_model(model_index)); - joint->move_vertices_to(new_joint); - } - } - } -} - -/** - * Computes a score >= 0 reflecting the similarity of the current joint's - * animation (in world space) to that of the indicated potential parent joint - * (in world space). The lower the number, the more similar the motion, and - * the more suitable is the proposed parent-child relationship. Returns -1 if - * there is an error. - */ -int EggJointData:: -score_reparent_to(EggJointData *new_parent, EggCharacterDb &db) { - if (!FFTCompressor::is_compression_available()) { - // If we don't have compression compiled in, we can't meaningfully score - // the joints. - return -1; - } - - // First, build up a big array of the new transforms this joint would - // receive in all frames of all models, were it reparented to the indicated - // joint. - vector_stdfloat i, j, k, a, b, c, x, y, z; - pvector hprs; - int num_rows = 0; - - int num_models = get_num_models(); - for (int model_index = 0; model_index < num_models; model_index++) { - EggBackPointer *back = get_model(model_index); - if (back != nullptr) { - EggJointPointer *joint; - DCAST_INTO_R(joint, back, false); - - int num_frames = get_num_frames(model_index); - for (int n = 0; n < num_frames; n++) { - LMatrix4d transform; - if (_parent == new_parent) { - // We already have this parent. - transform = LMatrix4d::ident_mat(); - - } else if (_parent == nullptr) { - // We are moving from outside the joint hierarchy to within it. - transform = new_parent->get_net_frame_inv(model_index, n, db); - - } else if (new_parent == nullptr) { - // We are moving from within the hierarchy to outside it. - transform = _parent->get_net_frame(model_index, n, db); - - } else { - // We are changing parents within the hierarchy. - transform = - _parent->get_net_frame(model_index, n, db) * - new_parent->get_net_frame_inv(model_index, n, db); - } - - transform = joint->get_frame(n) * transform; - LVecBase3d scale, shear, hpr, translate; - if (!decompose_matrix(transform, scale, shear, hpr, translate)) { - // Invalid transform. - return -1; - } - i.push_back(scale[0]); - j.push_back(scale[1]); - k.push_back(scale[2]); - a.push_back(shear[0]); - b.push_back(shear[1]); - c.push_back(shear[2]); - hprs.push_back(LCAST(PN_stdfloat, hpr)); - x.push_back(translate[0]); - y.push_back(translate[1]); - z.push_back(translate[2]); - num_rows++; - } - } - } - - if (num_rows == 0) { - // No data, no score. - return -1; - } - - // Now, we derive a score, by the simple expedient of using the - // FFTCompressor to compress the generated transforms, and measuring the - // length of the resulting bitstream. - FFTCompressor compressor; - Datagram dg; - compressor.write_reals(dg, &i[0], num_rows); - compressor.write_reals(dg, &j[0], num_rows); - compressor.write_reals(dg, &k[0], num_rows); - compressor.write_reals(dg, &a[0], num_rows); - compressor.write_reals(dg, &b[0], num_rows); - compressor.write_reals(dg, &c[0], num_rows); - compressor.write_hprs(dg, &hprs[0], num_rows); - compressor.write_reals(dg, &x[0], num_rows); - compressor.write_reals(dg, &y[0], num_rows); - compressor.write_reals(dg, &z[0], num_rows); - - -#ifndef HAVE_ZLIB - return dg.get_length(); - -#else - // The FFTCompressor does minimal run-length encoding, but to really get an - // accurate measure we should zlib-compress the resulting stream. - std::ostringstream sstr; - OCompressStream zstr(&sstr, false); - zstr.write((const char *)dg.get_data(), dg.get_length()); - zstr.flush(); - return sstr.str().length(); -#endif -} - -/** - * Calls do_rebuild() on all models, and recursively on all joints at this - * node and below. Returns true if all models returned true, false otherwise. - */ -bool EggJointData:: -do_rebuild_all(EggCharacterDb &db) { - bool all_ok = true; - - BackPointers::iterator bpi; - for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { - EggBackPointer *back = (*bpi); - if (back != nullptr) { - EggJointPointer *joint; - DCAST_INTO_R(joint, back, false); - if (!joint->do_rebuild(db)) { - all_ok = false; - } - } - } - - Children::iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - if (!child->do_rebuild_all(db)) { - all_ok = false; - } - } - - return all_ok; -} - -/** - * Calls optimize() on all models, and recursively on all joints at this node - * and below. - */ -void EggJointData:: -optimize() { - BackPointers::iterator bpi; - for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { - EggBackPointer *back = (*bpi); - if (back != nullptr) { - EggJointPointer *joint; - DCAST_INTO_V(joint, back); - joint->optimize(); - } - } - - Children::iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - child->optimize(); - } -} - -/** - * Calls expose() on all models for this joint, but does not recurse - * downwards. - */ -void EggJointData:: -expose(EggGroup::DCSType dcs_type) { - BackPointers::iterator bpi; - for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { - EggBackPointer *back = (*bpi); - if (back != nullptr) { - EggJointPointer *joint; - DCAST_INTO_V(joint, back); - joint->expose(dcs_type); - } - } -} - -/** - * Calls zero_channels() on all models for this joint, but does not recurse - * downwards. - */ -void EggJointData:: -zero_channels(const string &components) { - BackPointers::iterator bpi; - for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { - EggBackPointer *back = (*bpi); - if (back != nullptr) { - EggJointPointer *joint; - DCAST_INTO_V(joint, back); - joint->zero_channels(components); - } - } -} - -/** - * Calls quantize_channels() on all models for this joint, and then recurses - * downwards to all joints below. - */ -void EggJointData:: -quantize_channels(const string &components, double quantum) { - BackPointers::iterator bpi; - for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { - EggBackPointer *back = (*bpi); - if (back != nullptr) { - EggJointPointer *joint; - DCAST_INTO_V(joint, back); - joint->quantize_channels(components, quantum); - } - } - - Children::iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - child->quantize_channels(components, quantum); - } -} - -/** - * Applies the pose from the indicated frame of the indicated source - * model_index as the initial pose for this joint, and does this recursively - * on all joints below. - */ -void EggJointData:: -apply_default_pose(int source_model, int frame) { - if (has_model(source_model)) { - EggJointPointer *source_joint; - DCAST_INTO_V(source_joint, _back_pointers[source_model]); - BackPointers::iterator bpi; - for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) { - EggBackPointer *back = (*bpi); - if (back != nullptr) { - EggJointPointer *joint; - DCAST_INTO_V(joint, back); - joint->apply_default_pose(source_joint, frame); - } - } - } - - Children::iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - child->apply_default_pose(source_model, frame); - } -} - -/** - * Adds the indicated model joint or anim table to the data. - */ -void EggJointData:: -add_back_pointer(int model_index, EggObject *egg_object) { - nassertv(egg_object != nullptr); - if (egg_object->is_of_type(EggGroup::get_class_type())) { - // It must be a . - EggJointNodePointer *joint = new EggJointNodePointer(egg_object); - set_model(model_index, joint); - if (!_has_rest_frame) { - _rest_frame = joint->get_frame(0); - _has_rest_frame = true; - - } else { - // If this new node doesn't come within an acceptable tolerance of our - // first reading of this joint's rest frame, set a warning flag. - if (!_rest_frame.almost_equal(joint->get_frame(0), 0.0001)) { - _rest_frames_differ = true; - } - } - - } else if (egg_object->is_of_type(EggTable::get_class_type())) { - // It's a
with an "xform" child beneath it. - EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object); - set_model(model_index, xform); - - } else { - nout << "Invalid object added to joint for back pointer.\n"; - } -} - -/** - * - */ -void EggJointData:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << "Joint " << get_name() - << " (models:"; - int num_models = get_num_models(); - for (int model_index = 0; model_index < num_models; model_index++) { - if (has_model(model_index)) { - out << " " << model_index; - } - } - out << ") {\n"; - - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - (*ci)->write(out, indent_level + 2); - } - - indent(out, indent_level) << "}\n"; -} - -/** - * Clears out the _children vector in preparation for refilling it from the - * _new_parent information. - */ -void EggJointData:: -do_begin_reparent() { - _got_new_parent_depth = false; - _children.clear(); -} - -/** - * Calculates the number of joints above this joint in its intended position, - * as specified by a recent call to reparent_to(), and also checks for a cycle - * in the new parent chain. Returns true if a cycle is detected, and false - * otherwise. If a cycle is not detected, _new_parent_depth can be consulted - * for the depth in the new hierarchy. - * - * This is used by EggCharacterData::do_reparent() to determine the order in - * which to apply the reparent operations. It should be called after - * do_begin_reparent(). - */ -bool EggJointData:: -calc_new_parent_depth(pset &chain) { - if (_got_new_parent_depth) { - return false; - } - if (_new_parent == nullptr) { - // Here's the top of the new hierarchy. - _got_new_parent_depth = true; - _new_parent_depth = 0; - return false; - } - if (!chain.insert(this).second) { - // We've already visited this joint; that means there's a cycle. - return true; - } - bool cycle = _new_parent->calc_new_parent_depth(chain); - _new_parent_depth = _new_parent->_new_parent_depth + 1; - return cycle; -} - -/** - * Eliminates any cached values before beginning a walk through all the joints - * for do_compute_reparent(), for a given model/frame. - */ -void EggJointData:: -do_begin_compute_reparent() { - _got_new_net_frame = false; - _got_new_net_frame_inv = false; - _computed_reparent = false; -} - -/** - * Prepares the reparent operation by computing a new transform for each frame - * of each model, designed to keep the net transform the same when the joint - * is moved to its new parent. Returns true on success, false on failure. - */ -bool EggJointData:: -do_compute_reparent(int model_index, int n, EggCharacterDb &db) { - if (_computed_reparent) { - // We've already done this joint. This is possible because we have to - // recursively compute joints upwards, so we might visit the same joint - // more than once. - return _computed_ok; - } - _computed_reparent = true; - - if (_parent == _new_parent) { - // Trivial (and most common) case: we are not moving the joint. No - // recomputation necessary. - _computed_ok = true; - return true; - } - - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - // This joint doesn't have any data to modify. - _computed_ok = true; - return true; - } - - EggJointPointer *joint; - DCAST_INTO_R(joint, back, false); - - LMatrix4d transform; - if (_parent == nullptr) { - // We are moving from outside the joint hierarchy to within it. - transform = _new_parent->get_new_net_frame_inv(model_index, n, db); - - } else if (_new_parent == nullptr) { - // We are moving from within the hierarchy to outside it. - transform = _parent->get_net_frame(model_index, n, db); - - } else { - // We are changing parents within the hierarchy. - transform = - _parent->get_net_frame(model_index, n, db) * - _new_parent->get_new_net_frame_inv(model_index, n, db); - } - - db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, - joint->get_frame(n) * transform); - _computed_ok = true; - - return _computed_ok; -} - -/** - * Calls do_rebuild() on the joint for the indicated model index. Returns - * true on success, false on failure (false shouldn't be possible). - */ -bool EggJointData:: -do_joint_rebuild(int model_index, EggCharacterDb &db) { - bool all_ok = true; - - EggJointPointer *parent_joint = nullptr; - if (_new_parent != nullptr && _new_parent->has_model(model_index)) { - DCAST_INTO_R(parent_joint, _new_parent->get_model(model_index), false); - } - - if (has_model(model_index)) { - EggJointPointer *joint; - DCAST_INTO_R(joint, get_model(model_index), false); - if (!joint->do_rebuild(db)) { - all_ok = false; - } - } - - return all_ok; -} - -/** - * Performs the actual reparenting operation by removing all of the old - * children and replacing them with the set of new children. - */ -void EggJointData:: -do_finish_reparent() { - int num_models = get_num_models(); - for (int model_index = 0; model_index < num_models; model_index++) { - EggJointPointer *parent_joint = nullptr; - if (_new_parent != nullptr && _new_parent->has_model(model_index)) { - DCAST_INTO_V(parent_joint, _new_parent->get_model(model_index)); - } - - if (has_model(model_index)) { - EggJointPointer *joint; - DCAST_INTO_V(joint, get_model(model_index)); - joint->do_finish_reparent(parent_joint); - } - } - - _parent = _new_parent; - if (_parent != nullptr) { - _parent->_children.push_back(this); - } -} - -/** - * Creates a new joint as a child of this joint and returns it. This is - * intended to be called only from EggCharacterData::make_new_joint(). - */ -EggJointData *EggJointData:: -make_new_joint(const string &name) { - EggJointData *child = new EggJointData(_collection, _char_data); - child->set_name(name); - child->_parent = this; - child->_new_parent = this; - _children.push_back(child); - - // Also create new back pointers in each of the models. - int num_models = get_num_models(); - for (int i = 0; i < num_models; i++) { - if (has_model(i)) { - EggJointPointer *joint; - DCAST_INTO_R(joint, get_model(i), nullptr); - EggJointPointer *new_joint = joint->make_new_joint(name); - child->set_model(i, new_joint); - } - } - - return child; -} - -/** - * The recursive implementation of find_joint, this flavor searches - * recursively for an exact match of the preferred joint name. - */ -EggJointData *EggJointData:: -find_joint_exact(const string &name) { - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - if (child->get_name() == name) { - return child; - } - EggJointData *result = child->find_joint_exact(name); - if (result != nullptr) { - return result; - } - } - - return nullptr; -} - -/** - * The recursive implementation of find_joint, this flavor searches - * recursively for any acceptable match. - */ -EggJointData *EggJointData:: -find_joint_matches(const string &name) { - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - EggJointData *child = (*ci); - if (child->matches_name(name)) { - return child; - } - EggJointData *result = child->find_joint_matches(name); - if (result != nullptr) { - return result; - } - } - - return nullptr; -} - -/** - * Returns true if this joint is an ancestor of the indicated joint, in the - * "new" hierarchy (that is, the one defined by _new_parent, as set by - * reparent_to() before do_finish_reparent() is called). - */ -bool EggJointData:: -is_new_ancestor(EggJointData *child) const { - if (child == this) { - return true; - } - - if (child->_new_parent == nullptr) { - return false; - } - - return is_new_ancestor(child->_new_parent); -} - -/** - * Similar to get_net_frame(), but computed for the prospective new parentage - * of the node, before do_finish_reparent() is called. This is generally - * useful only when called within do_compute_reparent(). - */ -const LMatrix4d &EggJointData:: -get_new_net_frame(int model_index, int n, EggCharacterDb &db) { - if (!_got_new_net_frame) { - _new_net_frame = get_new_frame(model_index, n, db); - if (_new_parent != nullptr) { - _new_net_frame = _new_net_frame * _new_parent->get_new_net_frame(model_index, n, db); - } - _got_new_net_frame = true; - } - return _new_net_frame; -} - -/** - * Returns the inverse of get_new_net_frame(). - */ -const LMatrix4d &EggJointData:: -get_new_net_frame_inv(int model_index, int n, EggCharacterDb &db) { - if (!_got_new_net_frame_inv) { - _new_net_frame_inv.invert_from(get_new_frame(model_index, n, db)); - if (_new_parent != nullptr) { - _new_net_frame_inv = _new_parent->get_new_net_frame_inv(model_index, n, db) * _new_net_frame_inv; - } - _got_new_net_frame_inv = true; - } - return _new_net_frame_inv; -} - -/** - * Returns the local transform matrix corresponding to this joint position in - * the nth frame in the indicated model, as it will be when - * do_finish_reparent() is called. - */ -LMatrix4d EggJointData:: -get_new_frame(int model_index, int n, EggCharacterDb &db) { - do_compute_reparent(model_index, n, db); - - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - return LMatrix4d::ident_mat(); - } - - EggJointPointer *joint; - DCAST_INTO_R(joint, back, LMatrix4d::ident_mat()); - - LMatrix4d mat; - if (!db.get_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, mat)) { - // No rebuild frame; return the regular frame. - return joint->get_frame(n); - } - - // Return the rebuild frame, as computed. - return mat; -} diff --git a/pandatool/src/eggcharbase/eggJointData.h b/pandatool/src/eggcharbase/eggJointData.h deleted file mode 100644 index bf9cf7b3..00000000 --- a/pandatool/src/eggcharbase/eggJointData.h +++ /dev/null @@ -1,126 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointData.h - * @author drose - * @date 2001-02-23 - */ - -#ifndef EGGJOINTDATA_H -#define EGGJOINTDATA_H - -#include "pandatoolbase.h" -#include "eggComponentData.h" -#include "eggGroup.h" -#include "luse.h" -#include "pset.h" - -class EggCharacterDb; - -/** - * This is one node of a hierarchy of EggJointData nodes, each of which - * represents a single joint of the character hierarchy across all loaded - * files: the various models, the LOD's of each model, and the various - * animation channel files. - */ -class EggJointData : public EggComponentData { -public: - EggJointData(EggCharacterCollection *collection, - EggCharacterData *char_data); - - INLINE EggJointData *get_parent() const; - INLINE int get_num_children() const; - INLINE EggJointData *get_child(int n) const; - INLINE EggJointData *find_joint(const std::string &name); - - LMatrix4d get_frame(int model_index, int n) const; - LMatrix4d get_net_frame(int model_index, int n, EggCharacterDb &db) const; - LMatrix4d get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const; - - INLINE bool has_rest_frame() const; - INLINE bool rest_frames_differ() const; - INLINE const LMatrix4d &get_rest_frame() const; - void force_initial_rest_frame(); - - INLINE void reparent_to(EggJointData *new_parent); - void move_vertices_to(EggJointData *new_owner); - int score_reparent_to(EggJointData *new_parent, EggCharacterDb &db); - - bool do_rebuild_all(EggCharacterDb &db); - void optimize(); - void expose(EggGroup::DCSType dcs_type = EggGroup::DC_default); - void zero_channels(const std::string &components); - void quantize_channels(const std::string &components, double quantum); - void apply_default_pose(int source_model, int frame); - - virtual void add_back_pointer(int model_index, EggObject *egg_object); - virtual void write(std::ostream &out, int indent_level = 0) const; - -protected: - void do_begin_reparent(); - bool calc_new_parent_depth(pset &chain); - void do_begin_compute_reparent(); - bool do_compute_reparent(int model_index, int n, EggCharacterDb &db); - bool do_joint_rebuild(int model_index, EggCharacterDb &db); - void do_finish_reparent(); - -private: - EggJointData *make_new_joint(const std::string &name); - EggJointData *find_joint_exact(const std::string &name); - EggJointData *find_joint_matches(const std::string &name); - - bool is_new_ancestor(EggJointData *child) const; - const LMatrix4d &get_new_net_frame(int model_index, int n, EggCharacterDb &db); - const LMatrix4d &get_new_net_frame_inv(int model_index, int n, EggCharacterDb &db); - LMatrix4d get_new_frame(int model_index, int n, EggCharacterDb &db); - - bool _has_rest_frame; - bool _rest_frames_differ; - LMatrix4d _rest_frame; - - // These are used to cache the above results for optimizing - // do_compute_reparent(). - LMatrix4d _new_net_frame, _new_net_frame_inv; - bool _got_new_net_frame, _got_new_net_frame_inv; - bool _computed_reparent; - bool _computed_ok; - -protected: - typedef pvector Children; - Children _children; - EggJointData *_parent; - EggJointData *_new_parent; - int _new_parent_depth; - bool _got_new_parent_depth; - - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggComponentData::init_type(); - register_type(_type_handle, "EggJointData", - EggComponentData::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; - - friend class EggCharacterCollection; - friend class EggCharacterData; - friend class OrderJointsByNewDepth; -}; - -#include "eggJointData.I" - -#endif diff --git a/pandatool/src/eggcharbase/eggJointNodePointer.cxx b/pandatool/src/eggcharbase/eggJointNodePointer.cxx deleted file mode 100644 index 23bf7ea4..00000000 --- a/pandatool/src/eggcharbase/eggJointNodePointer.cxx +++ /dev/null @@ -1,209 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointNodePointer.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggJointNodePointer.h" - -#include "dcast.h" -#include "eggCharacterDb.h" -#include "eggGroup.h" -#include "eggObject.h" -#include "pointerTo.h" - - -TypeHandle EggJointNodePointer::_type_handle; - -/** - * - */ -EggJointNodePointer:: -EggJointNodePointer(EggObject *object) { - _joint = DCAST(EggGroup, object); - - if (_joint != nullptr && _joint->is_joint()) { - // Quietly insist that the joint has a transform, for neatness. If it - // does not, give it the identity transform. - if (!_joint->has_transform()) { - _joint->set_transform3d(LMatrix4d::ident_mat()); - } - } -} - -/** - * Returns the number of frames of animation for this particular joint. - * - * In the case of a EggJointNodePointer, which just stores a pointer to a - * entry for a character model (not an animation table), there is - * always exactly one frame: the rest pose. - */ -int EggJointNodePointer:: -get_num_frames() const { - return 1; -} - -/** - * Returns the transform matrix corresponding to this joint position in the - * nth frame. - * - * In the case of a EggJointNodePointer, which just stores a pointer to a - * entry for a character model (not an animation table), there is - * always exactly one frame: the rest pose. - */ -LMatrix4d EggJointNodePointer:: -get_frame(int n) const { - nassertr(n == 0, LMatrix4d::ident_mat()); - return _joint->get_transform3d(); -} - -/** - * Sets the transform matrix corresponding to this joint position in the nth - * frame. - * - * In the case of a EggJointNodePointer, which just stores a pointer to a - * entry for a character model (not an animation table), there is - * always exactly one frame: the rest pose. - */ -void EggJointNodePointer:: -set_frame(int n, const LMatrix4d &mat) { - nassertv(n == 0); - _joint->set_transform3d(mat); -} - -/** - * Performs the actual reparenting operation by removing the node from its old - * parent and associating it with its new parent, if any. - */ -void EggJointNodePointer:: -do_finish_reparent(EggJointPointer *new_parent) { - if (new_parent == nullptr) { - // No new parent; unparent the joint. - EggGroupNode *egg_parent = _joint->get_parent(); - if (egg_parent != nullptr) { - egg_parent->remove_child(_joint.p()); - egg_parent->steal_children(*_joint); - } - - } else { - // Reparent the joint to its new parent (implicitly unparenting it from - // its previous parent). - EggJointNodePointer *new_node = DCAST(EggJointNodePointer, new_parent); - if (new_node->_joint != _joint->get_parent()) { - new_node->_joint->add_child(_joint.p()); - } - } -} - -/** - * Moves the vertices assigned to this joint into the other joint (which - * should be of the same type). - */ -void EggJointNodePointer:: -move_vertices_to(EggJointPointer *new_joint) { - if (new_joint == nullptr) { - _joint->unref_all_vertices(); - - } else { - EggJointNodePointer *new_node; - DCAST_INTO_V(new_node, new_joint); - - new_node->_joint->steal_vrefs(_joint); - } -} - -/** - * Rebuilds the entire table all at once, based on the frames added by - * repeated calls to add_rebuild_frame() since the last call to - * begin_rebuild(). - * - * Until do_rebuild() is called, the animation table is not changed. - * - * The return value is true if all frames are acceptable, or false if there is - * some problem. - */ -bool EggJointNodePointer:: -do_rebuild(EggCharacterDb &db) { - LMatrix4d mat; - if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) { - // No rebuild frame; this is OK. - return true; - } - - _joint->set_transform3d(mat); - - // We shouldn't have a frame 1. - nassertr(!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 1, mat), false); - - return true; -} - -/** - * Flags the joint with the indicated DCS flag so that it will be loaded as a - * separate node in the player. - */ -void EggJointNodePointer:: -expose(EggGroup::DCSType dcs_type) { - if (_joint != nullptr) { - _joint->set_dcs_type(dcs_type); - } -} - -/** - * Applies the pose from the indicated frame of the indicated source joint as - * the initial pose for this joint. - */ -void EggJointNodePointer:: -apply_default_pose(EggJointPointer *source_joint, int frame) { - if (_joint != nullptr) { - LMatrix4d pose; - if (frame >= 0 && frame < source_joint->get_num_frames()) { - pose = source_joint->get_frame(frame); - } else { - pose = get_frame(0); - } - _joint->clear_default_pose(); - _joint->modify_default_pose().add_matrix4(pose); - } -} - -/** - * Returns true if there are any vertices referenced by the node this points - * to, false otherwise. For certain kinds of back pointers (e.g. table - * animation entries), this is always false. - */ -bool EggJointNodePointer:: -has_vertices() const { - if (_joint != nullptr) { - return (_joint->vref_size() != 0) || _joint->joint_has_primitives(); - } - - return false; -} - -/** - * Creates a new child of the current joint in the egg data, and returns a - * pointer to it. - */ -EggJointPointer *EggJointNodePointer:: -make_new_joint(const std::string &name) { - EggGroup *new_joint = new EggGroup(name); - new_joint->set_group_type(EggGroup::GT_joint); - _joint->add_child(new_joint); - return new EggJointNodePointer(new_joint); -} - -/** - * Applies the indicated name change to the egg file. - */ -void EggJointNodePointer:: -set_name(const std::string &name) { - _joint->set_name(name); -} diff --git a/pandatool/src/eggcharbase/eggJointNodePointer.h b/pandatool/src/eggcharbase/eggJointNodePointer.h deleted file mode 100644 index 8a979f11..00000000 --- a/pandatool/src/eggcharbase/eggJointNodePointer.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointNodePointer.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGJOINTNODEPOINTER_H -#define EGGJOINTNODEPOINTER_H - -#include "pandatoolbase.h" - -#include "eggJointPointer.h" - -#include "eggGroup.h" -#include "pointerTo.h" - -/** - * This stores a pointer back to a node. - */ -class EggJointNodePointer : public EggJointPointer { -public: - EggJointNodePointer(EggObject *object); - - virtual int get_num_frames() const; - virtual LMatrix4d get_frame(int n) const; - virtual void set_frame(int n, const LMatrix4d &mat); - - virtual void do_finish_reparent(EggJointPointer *new_parent); - virtual void move_vertices_to(EggJointPointer *new_joint); - - virtual bool do_rebuild(EggCharacterDb &db); - virtual void expose(EggGroup::DCSType dcs_type); - virtual void apply_default_pose(EggJointPointer *source_joint, int frame); - - virtual bool has_vertices() const; - - virtual EggJointPointer *make_new_joint(const std::string &name); - - virtual void set_name(const std::string &name); - -private: - PT(EggGroup) _joint; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggJointPointer::init_type(); - register_type(_type_handle, "EggJointNodePointer", - EggJointPointer::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; -}; - -#endif diff --git a/pandatool/src/eggcharbase/eggJointPointer.I b/pandatool/src/eggcharbase/eggJointPointer.I deleted file mode 100644 index 57bd7cf3..00000000 --- a/pandatool/src/eggcharbase/eggJointPointer.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointPointer.I - * @author drose - * @date 2003-07-20 - */ diff --git a/pandatool/src/eggcharbase/eggJointPointer.cxx b/pandatool/src/eggcharbase/eggJointPointer.cxx deleted file mode 100644 index 6a5ed440..00000000 --- a/pandatool/src/eggcharbase/eggJointPointer.cxx +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointPointer.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggJointPointer.h" - - -TypeHandle EggJointPointer::_type_handle; - - -/** - * Appends a new frame onto the end of the data, if possible; returns true if - * not possible, or false otherwise (e.g. for a static joint). - */ -bool EggJointPointer:: -add_frame(const LMatrix4d &) { - return false; -} - -/** - * Moves the vertices assigned to this joint into the other joint (which - * should be of the same type). - */ -void EggJointPointer:: -move_vertices_to(EggJointPointer *) { -} - -/** - * Rebuilds the entire table all at once, based on the frames added by - * repeated calls to add_rebuild_frame() since the last call to - * begin_rebuild(). - * - * Until do_rebuild() is called, the animation table is not changed. - * - * The return value is true if all frames are acceptable, or false if there is - * some problem. - */ -bool EggJointPointer:: -do_rebuild(EggCharacterDb &db) { - return true; -} - -/** - * Resets the table before writing to disk so that redundant rows (e.g. i { 1 - * 1 1 1 1 1 1 1 }) are collapsed out. - */ -void EggJointPointer:: -optimize() { -} - -/** - * Flags the joint with the indicated DCS flag so that it will be loaded as a - * separate node in the player. - */ -void EggJointPointer:: -expose(EggGroup::DCSType) { -} - -/** - * Zeroes out the named components of the transform in the animation frames. - */ -void EggJointPointer:: -zero_channels(const std::string &) { -} - -/** - * Rounds the named components of the transform to the nearest multiple of - * quantum. - */ -void EggJointPointer:: -quantize_channels(const std::string &, double) { -} - -/** - * Applies the pose from the indicated frame of the indicated source joint as - * the initial pose for this joint. - */ -void EggJointPointer:: -apply_default_pose(EggJointPointer *source_joint, int frame) { -} diff --git a/pandatool/src/eggcharbase/eggJointPointer.h b/pandatool/src/eggcharbase/eggJointPointer.h deleted file mode 100644 index 94a8a318..00000000 --- a/pandatool/src/eggcharbase/eggJointPointer.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggJointPointer.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGJOINTPOINTER_H -#define EGGJOINTPOINTER_H - -#include "pandatoolbase.h" -#include "eggBackPointer.h" -#include "eggGroup.h" -#include "luse.h" - -class EggCharacterDb; - -/** - * This is a base class for EggJointNodePointer and EggMatrixTablePointer. It - * stores a back pointer to either a entry or an xform
data, - * and thus presents an interface that returns 1-n matrices, one for each - * frame. ( entries, for model files, appear the same as one-frame - * animations.) - */ -class EggJointPointer : public EggBackPointer { -public: - virtual int get_num_frames() const=0; - virtual LMatrix4d get_frame(int n) const=0; - virtual void set_frame(int n, const LMatrix4d &mat)=0; - virtual bool add_frame(const LMatrix4d &mat); - - virtual void do_finish_reparent(EggJointPointer *new_parent)=0; - virtual void move_vertices_to(EggJointPointer *new_joint); - - virtual bool do_rebuild(EggCharacterDb &db); - - virtual void optimize(); - virtual void expose(EggGroup::DCSType dcs_type); - virtual void zero_channels(const std::string &components); - virtual void quantize_channels(const std::string &components, double quantum); - virtual void apply_default_pose(EggJointPointer *source_joint, int frame); - - virtual EggJointPointer *make_new_joint(const std::string &name)=0; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggBackPointer::init_type(); - register_type(_type_handle, "EggJointPointer", - EggBackPointer::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 "eggJointPointer.I" - -#endif diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx deleted file mode 100644 index 26729648..00000000 --- a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx +++ /dev/null @@ -1,295 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMatrixTablePointer.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggMatrixTablePointer.h" - -#include "dcast.h" -#include "eggCharacterDb.h" -#include "eggSAnimData.h" -#include "eggXfmAnimData.h" -#include "eggXfmSAnim.h" - -using std::string; - -TypeHandle EggMatrixTablePointer::_type_handle; - -/** - * - */ -EggMatrixTablePointer:: -EggMatrixTablePointer(EggObject *object) { - _table = DCAST(EggTable, object); - - if (_table != nullptr) { - // Now search for the child named "xform". This contains the actual table - // data. - EggGroupNode::iterator ci; - bool found = false; - for (ci = _table->begin(); ci != _table->end() && !found; ++ci) { - EggNode *child = (*ci); - if (child->get_name() == "xform") { - if (child->is_of_type(EggXfmSAnim::get_class_type())) { - _xform = DCAST(EggXfmSAnim, child); - _xform->normalize(); - found = true; - - } else if (child->is_of_type(EggXfmAnimData::get_class_type())) { - // Quietly replace old-style XfmAnim tables with new-style XfmSAnim - // tables. - PT(EggXfmAnimData) anim = DCAST(EggXfmAnimData, child); - _xform = new EggXfmSAnim(*anim); - _table->replace(ci, _xform.p()); - found = true; - } - } - } - } -} - -/** - * Returns the stated frame rate of this particular joint, or 0.0 if it - * doesn't state. - */ -double EggMatrixTablePointer:: -get_frame_rate() const { - if (_xform == nullptr || !_xform->has_fps()) { - return 0.0; - } else { - return _xform->get_fps(); - } -} - -/** - * Returns the number of frames of animation for this particular joint. - */ -int EggMatrixTablePointer:: -get_num_frames() const { - if (_xform == nullptr) { - return 0; - } else { - return _xform->get_num_rows(); - } -} - -/** - * Extends the table to the indicated number of frames. - */ -void EggMatrixTablePointer:: -extend_to(int num_frames) { - nassertv(_xform != nullptr); - _xform->normalize(); - int num_rows = _xform->get_num_rows(); - LMatrix4d last_mat; - if (num_rows == 0) { - last_mat = LMatrix4d::ident_mat(); - } else { - _xform->get_value(num_rows - 1, last_mat); - } - - while (num_rows < num_frames) { - _xform->add_data(last_mat); - num_rows++; - } -} - -/** - * Returns the transform matrix corresponding to this joint position in the - * nth frame. - */ -LMatrix4d EggMatrixTablePointer:: -get_frame(int n) const { - if (get_num_frames() == 1) { - // If we have exactly one frame, then we have as many frames as we want; - // just repeat the first frame. - n = 0; - - } else if (get_num_frames() == 0) { - // If we have no frames, we really have the identity matrix. - return LMatrix4d::ident_mat(); - } - - nassertr(n >= 0 && n < get_num_frames(), LMatrix4d::ident_mat()); - LMatrix4d mat; - _xform->get_value(n, mat); - return mat; -} - -/** - * Sets the transform matrix corresponding to this joint position in the nth - * frame. - */ -void EggMatrixTablePointer:: -set_frame(int n, const LMatrix4d &mat) { - nassertv(n >= 0 && n < get_num_frames()); - _xform->set_value(n, mat); -} - -/** - * Appends a new frame onto the end of the data, if possible; returns true if - * not possible, or false otherwise (e.g. for a static joint). - */ -bool EggMatrixTablePointer:: -add_frame(const LMatrix4d &mat) { - if (_xform == nullptr) { - return false; - } - - return _xform->add_data(mat); -} - -/** - * Performs the actual reparenting operation by removing the node from its old - * parent and associating it with its new parent, if any. - */ -void EggMatrixTablePointer:: -do_finish_reparent(EggJointPointer *new_parent) { - if (new_parent == nullptr) { - // No new parent; unparent the joint. - EggGroupNode *egg_parent = _table->get_parent(); - if (egg_parent != nullptr) { - egg_parent->remove_child(_table.p()); - } - - } else { - // Reparent the joint to its new parent (implicitly unparenting it from - // its previous parent). - EggMatrixTablePointer *new_node = DCAST(EggMatrixTablePointer, new_parent); - if (new_node->_table != _table->get_parent()) { - new_node->_table->add_child(_table.p()); - } - } -} - -/** - * Rebuilds the entire table all at once, based on the frames added by - * repeated calls to add_rebuild_frame() since the last call to - * begin_rebuild(). - * - * Until do_rebuild() is called, the animation table is not changed. - * - * The return value is true if all frames are acceptable, or false if there is - * some problem. - */ -bool EggMatrixTablePointer:: -do_rebuild(EggCharacterDb &db) { - LMatrix4d mat; - if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) { - // No rebuild frame; this is OK. - return true; - } - - if (_xform == nullptr) { - return false; - } - - bool all_ok = true; - - _xform->clear_data(); - if (!_xform->add_data(mat)) { - all_ok = false; - } - - // Assume all frames will be contiguous. - int n = 1; - while (db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, n, mat)) { - if (!_xform->add_data(mat)) { - all_ok = false; - } - ++n; - } - - return all_ok; -} - -/** - * Resets the table before writing to disk so that redundant rows (e.g. i { 1 - * 1 1 1 1 1 1 1 }) are collapsed out. - */ -void EggMatrixTablePointer:: -optimize() { - if (_xform != nullptr) { - _xform->optimize(); - } -} - -/** - * Zeroes out the named components of the transform in the animation frames. - */ -void EggMatrixTablePointer:: -zero_channels(const string &components) { - if (_xform == nullptr) { - return; - } - - // This is particularly easy: we only have to remove children from the - // _xform object whose name is listed in the components. - string::const_iterator si; - for (si = components.begin(); si != components.end(); ++si) { - string table_name(1, *si); - EggNode *child = _xform->find_child(table_name); - if (child != nullptr) { - _xform->remove_child(child); - } - } -} - -/** - * Rounds the named components of the transform to the nearest multiple of - * quantum. - */ -void EggMatrixTablePointer:: -quantize_channels(const string &components, double quantum) { - if (_xform == nullptr) { - return; - } - - // This is similar to the above: we quantize children of the _xform object - // whose name is listed in the components. - string::const_iterator si; - for (si = components.begin(); si != components.end(); ++si) { - string table_name(1, *si); - EggNode *child = _xform->find_child(table_name); - if (child != nullptr && - child->is_of_type(EggSAnimData::get_class_type())) { - EggSAnimData *anim = DCAST(EggSAnimData, child); - anim->quantize(quantum); - } - } -} - -/** - * Creates a new child of the current joint in the egg data, and returns a - * pointer to it. - */ -EggJointPointer *EggMatrixTablePointer:: -make_new_joint(const string &name) { - EggTable *new_table = new EggTable(name); - _table->add_child(new_table); - CoordinateSystem cs = CS_default; - if (_xform != nullptr) { - cs = _xform->get_coordinate_system(); - } - EggXfmSAnim *new_xform = new EggXfmSAnim("xform", cs); - new_table->add_child(new_xform); - new_xform->add_data(LMatrix4d::ident_mat()); - - return new EggMatrixTablePointer(new_table); -} - -/** - * Applies the indicated name change to the egg file. - */ -void EggMatrixTablePointer:: -set_name(const string &name) { - _table->set_name(name); -} diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.h b/pandatool/src/eggcharbase/eggMatrixTablePointer.h deleted file mode 100644 index cbdeeecc..00000000 --- a/pandatool/src/eggcharbase/eggMatrixTablePointer.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMatrixTablePointer.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGMATRIXTABLEPOINTER_H -#define EGGMATRIXTABLEPOINTER_H - -#include "pandatoolbase.h" - -#include "eggJointPointer.h" - -#include "eggTable.h" -#include "eggXfmSAnim.h" -#include "pointerTo.h" - -/** - * This stores a pointer back to an EggXfmSAnim table (i.e. an - * entry in an egg file), corresponding to the animation data from a single - * bundle for this joint. - */ -class EggMatrixTablePointer : public EggJointPointer { -public: - EggMatrixTablePointer(EggObject *object); - - virtual double get_frame_rate() const; - virtual int get_num_frames() const; - virtual void extend_to(int num_frames); - virtual LMatrix4d get_frame(int n) const; - virtual void set_frame(int n, const LMatrix4d &mat); - virtual bool add_frame(const LMatrix4d &mat); - - virtual void do_finish_reparent(EggJointPointer *new_parent); - - virtual bool do_rebuild(EggCharacterDb &db); - - virtual void optimize(); - virtual void zero_channels(const std::string &components); - virtual void quantize_channels(const std::string &components, double quantum); - - virtual EggJointPointer *make_new_joint(const std::string &name); - - virtual void set_name(const std::string &name); - -private: - PT(EggTable) _table; - PT(EggXfmSAnim) _xform; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggJointPointer::init_type(); - register_type(_type_handle, "EggMatrixTablePointer", - EggJointPointer::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; -}; - -#endif diff --git a/pandatool/src/eggcharbase/eggScalarTablePointer.cxx b/pandatool/src/eggcharbase/eggScalarTablePointer.cxx deleted file mode 100644 index 450bb548..00000000 --- a/pandatool/src/eggcharbase/eggScalarTablePointer.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggScalarTablePointer.cxx - * @author drose - * @date 2003-07-18 - */ - -#include "eggScalarTablePointer.h" - -#include "dcast.h" - -TypeHandle EggScalarTablePointer::_type_handle; - -/** - * - */ -EggScalarTablePointer:: -EggScalarTablePointer(EggObject *object) { - _data = DCAST(EggSAnimData, object); -} - -/** - * Returns the stated frame rate of this particular joint, or 0.0 if it - * doesn't state. - */ -double EggScalarTablePointer:: -get_frame_rate() const { - if (_data == nullptr || !_data->has_fps()) { - return 0.0; - } else { - return _data->get_fps(); - } -} - -/** - * Returns the number of frames of animation for this particular slider. - */ -int EggScalarTablePointer:: -get_num_frames() const { - if (_data == nullptr) { - return 0; - } else { - return _data->get_num_rows(); - } -} - -/** - * Extends the table to the indicated number of frames. - */ -void EggScalarTablePointer:: -extend_to(int num_frames) { - nassertv(_data != nullptr); - int num_rows = _data->get_num_rows(); - double last_value; - if (num_rows == 0) { - last_value = 0.0; - } else { - last_value = _data->get_value(num_rows - 1); - } - - while (num_rows < num_frames) { - _data->add_data(last_value); - num_rows++; - } -} - -/** - * Returns the value corresponding to this slider position in the nth frame. - */ -double EggScalarTablePointer:: -get_frame(int n) const { - if (get_num_frames() == 1) { - // If we have exactly one frame, then we have as many frames as we want; - // just repeat the first frame. - n = 0; - } - - nassertr(n >= 0 && n < get_num_frames(), 0.0); - return _data->get_value(n); -} - -/** - * Applies the indicated name change to the egg file. - */ -void EggScalarTablePointer:: -set_name(const std::string &name) { - // Actually, let's not rename the slider table (yet), because we haven't - // written the code to rename all of the morph targets. - - // _data->set_name(name); -} diff --git a/pandatool/src/eggcharbase/eggScalarTablePointer.h b/pandatool/src/eggcharbase/eggScalarTablePointer.h deleted file mode 100644 index c0a74879..00000000 --- a/pandatool/src/eggcharbase/eggScalarTablePointer.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggScalarTablePointer.h - * @author drose - * @date 2003-07-18 - */ - -#ifndef EGGSCALARTABLEPOINTER_H -#define EGGSCALARTABLEPOINTER_H - -#include "pandatoolbase.h" - -#include "eggSliderPointer.h" - -#include "eggSAnimData.h" -#include "pointerTo.h" - -/** - * This stores a pointer back to an EggSAnimData table (i.e. an - * entry in an egg file), corresponding to the animation data from a single - * bundle for this slider. - */ -class EggScalarTablePointer : public EggSliderPointer { -public: - EggScalarTablePointer(EggObject *object); - - virtual double get_frame_rate() const; - virtual int get_num_frames() const; - virtual void extend_to(int num_frames); - virtual double get_frame(int n) const; - - virtual void set_name(const std::string &name); - -private: - PT(EggSAnimData) _data; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggSliderPointer::init_type(); - register_type(_type_handle, "EggScalarTablePointer", - EggSliderPointer::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; -}; - -#endif diff --git a/pandatool/src/eggcharbase/eggSliderData.I b/pandatool/src/eggcharbase/eggSliderData.I deleted file mode 100644 index d925c04a..00000000 --- a/pandatool/src/eggcharbase/eggSliderData.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggSliderData.I - * @author drose - * @date 2001-02-26 - */ diff --git a/pandatool/src/eggcharbase/eggSliderData.cxx b/pandatool/src/eggcharbase/eggSliderData.cxx deleted file mode 100644 index 91d04136..00000000 --- a/pandatool/src/eggcharbase/eggSliderData.cxx +++ /dev/null @@ -1,102 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggSliderData.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggSliderData.h" -#include "eggVertexPointer.h" -#include "eggScalarTablePointer.h" -#include "eggSliderPointer.h" -#include "dcast.h" -#include "eggPrimitive.h" -#include "eggVertex.h" -#include "eggSAnimData.h" -#include "indent.h" - -TypeHandle EggSliderData::_type_handle; - -/** - * - */ -EggSliderData:: -EggSliderData(EggCharacterCollection *collection, - EggCharacterData *char_data) : - EggComponentData(collection, char_data) -{ -} - -/** - * Returns the value corresponding to this slider position in the nth frame in - * the indicated model. - */ -double EggSliderData:: -get_frame(int model_index, int n) const { - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - return 0.0; - } - - EggSliderPointer *slider; - DCAST_INTO_R(slider, back, 0.0); - - return slider->get_frame(n); -} - -/** - * Adds the indicated vertex, primitive, or morph table to the data. - */ -void EggSliderData:: -add_back_pointer(int model_index, EggObject *egg_object) { - if (egg_object->is_of_type(EggPrimitive::get_class_type())) { - // A primitive! - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - back = new EggVertexPointer(egg_object); - set_model(model_index, back); - } - - } else if (egg_object->is_of_type(EggVertex::get_class_type())) { - // A vertex! - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - back = new EggVertexPointer(egg_object); - set_model(model_index, back); - } - - } else if (egg_object->is_of_type(EggSAnimData::get_class_type())) { - // A slider animation table! Woo hoo! - EggBackPointer *back = get_model(model_index); - if (back == nullptr) { - back = new EggScalarTablePointer(egg_object); - set_model(model_index, back); - } - - } else { - nout << "Invalid object added to slider for back pointer.\n"; - } -} - -/** - * - */ -void EggSliderData:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << "Slider " << get_name() - << " (models:"; - int num_models = get_num_models(); - for (int model_index = 0; model_index < num_models; model_index++) { - if (has_model(model_index)) { - out << " " << model_index; - } - } - out << ")\n"; -} diff --git a/pandatool/src/eggcharbase/eggSliderData.h b/pandatool/src/eggcharbase/eggSliderData.h deleted file mode 100644 index dd0e4c34..00000000 --- a/pandatool/src/eggcharbase/eggSliderData.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggSliderData.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGSLIDERDATA_H -#define EGGSLIDERDATA_H - -#include "pandatoolbase.h" - -#include "eggComponentData.h" - - -/** - * This corresponds to a single morph slider control. It contains back - * pointers to all the vertices and primitives that reference this slider - * across all models, as well as all the tables in which it appears in all - * animation files. - */ -class EggSliderData : public EggComponentData { -public: - EggSliderData(EggCharacterCollection *collection, - EggCharacterData *char_data); - - double get_frame(int model_index, int n) const; - - virtual void add_back_pointer(int model_index, EggObject *egg_object); - virtual void write(std::ostream &out, int indent_level = 0) const; - - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggComponentData::init_type(); - register_type(_type_handle, "EggSliderData", - EggComponentData::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 "eggSliderData.I" - -#endif diff --git a/pandatool/src/eggcharbase/eggSliderPointer.cxx b/pandatool/src/eggcharbase/eggSliderPointer.cxx deleted file mode 100644 index bad2934a..00000000 --- a/pandatool/src/eggcharbase/eggSliderPointer.cxx +++ /dev/null @@ -1,16 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggSliderPointer.cxx - * @author drose - * @date 2003-07-18 - */ - -#include "eggSliderPointer.h" - -TypeHandle EggSliderPointer::_type_handle; diff --git a/pandatool/src/eggcharbase/eggSliderPointer.h b/pandatool/src/eggcharbase/eggSliderPointer.h deleted file mode 100644 index 19129f45..00000000 --- a/pandatool/src/eggcharbase/eggSliderPointer.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggSliderPointer.h - * @author drose - * @date 2003-07-18 - */ - -#ifndef EGGSLIDERPOINTER_H -#define EGGSLIDERPOINTER_H - -#include "pandatoolbase.h" - -#include "eggBackPointer.h" - -#include "luse.h" - -/** - * This is a base class for EggVertexPointer and EggScalarTablePointer. - */ -class EggSliderPointer : public EggBackPointer { -public: - virtual int get_num_frames() const=0; - virtual double get_frame(int n) const=0; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggBackPointer::init_type(); - register_type(_type_handle, "EggSliderPointer", - EggBackPointer::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; -}; - -#endif diff --git a/pandatool/src/eggcharbase/eggVertexPointer.cxx b/pandatool/src/eggcharbase/eggVertexPointer.cxx deleted file mode 100644 index 09af9d77..00000000 --- a/pandatool/src/eggcharbase/eggVertexPointer.cxx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggVertexPointer.cxx - * @author drose - * @date 2001-02-26 - */ - -#include "eggVertexPointer.h" - - -TypeHandle EggVertexPointer::_type_handle; - -/** - * - */ -EggVertexPointer:: -EggVertexPointer(EggObject *egg_object) { -} - -/** - * Returns the number of frames of animation for this particular slider. - */ -int EggVertexPointer:: -get_num_frames() const { - return 0; -} - -/** - * Returns the value corresponding to this slider position in the nth frame. - */ -double EggVertexPointer:: -get_frame(int n) const { - nassertr(false, 0.0); - return 0.0; -} - -/** - * Returns true if there are any vertices referenced by the node this points - * to, false otherwise. For certain kinds of back pointers (e.g. table - * animation entries), this is always false. - */ -bool EggVertexPointer:: -has_vertices() const { - return true; -} diff --git a/pandatool/src/eggcharbase/eggVertexPointer.h b/pandatool/src/eggcharbase/eggVertexPointer.h deleted file mode 100644 index 8403edab..00000000 --- a/pandatool/src/eggcharbase/eggVertexPointer.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggVertexPointer.h - * @author drose - * @date 2001-02-26 - */ - -#ifndef EGGVERTEXPOINTER_H -#define EGGVERTEXPOINTER_H - -#include "pandatoolbase.h" - -#include "eggSliderPointer.h" - -#include "eggGroup.h" -#include "pointerTo.h" - -/** - * This stores a pointer back to a , or to a particular pritimive like - * a , representing a morph offset. - */ -class EggVertexPointer : public EggSliderPointer { -public: - EggVertexPointer(EggObject *egg_object); - - virtual int get_num_frames() const; - virtual double get_frame(int n) const; - - virtual bool has_vertices() const; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggSliderPointer::init_type(); - register_type(_type_handle, "EggVertexPointer", - EggSliderPointer::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; -}; - -#endif diff --git a/pandatool/src/eggcharbase/p3eggcharbase_composite1.cxx b/pandatool/src/eggcharbase/p3eggcharbase_composite1.cxx deleted file mode 100644 index 5aa73594..00000000 --- a/pandatool/src/eggcharbase/p3eggcharbase_composite1.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include "config_eggcharbase.cxx" -#include "eggBackPointer.cxx" -#include "eggCharacterCollection.cxx" -#include "eggCharacterData.cxx" -#include "eggCharacterDb.cxx" -#include "eggCharacterFilter.cxx" -#include "eggComponentData.cxx" -#include "eggJointData.cxx" -#include "eggJointPointer.cxx" -#include "eggJointNodePointer.cxx" -#include "eggMatrixTablePointer.cxx" -#include "eggScalarTablePointer.cxx" -#include "eggSliderData.cxx" -#include "eggSliderPointer.cxx" -#include "eggVertexPointer.cxx" - diff --git a/pandatool/src/eggprogs/CMakeLists.txt b/pandatool/src/eggprogs/CMakeLists.txt deleted file mode 100644 index e845c57d..00000000 --- a/pandatool/src/eggprogs/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_EGG) - return() -endif() - -add_executable(egg-crop eggCrop.cxx eggCrop.h) -target_link_libraries(egg-crop p3eggbase) -install(TARGETS egg-crop EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg-list-textures eggListTextures.cxx eggListTextures.h) -target_link_libraries(egg-list-textures p3eggbase) -install(TARGETS egg-list-textures EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg-make-tube eggMakeTube.cxx eggMakeTube.h) -target_link_libraries(egg-make-tube p3eggbase) -install(TARGETS egg-make-tube EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg-rename eggRename.cxx eggRename.h) -target_link_libraries(egg-rename p3eggbase) -install(TARGETS egg-rename EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg-retarget-anim eggRetargetAnim.cxx eggRetargetAnim.h) -target_link_libraries(egg-retarget-anim p3eggcharbase) -install(TARGETS egg-retarget-anim EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg-texture-cards eggTextureCards.cxx eggTextureCards.h) -target_link_libraries(egg-texture-cards p3eggbase) -install(TARGETS egg-texture-cards EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg2c eggToC.cxx eggToC.h) -target_link_libraries(egg2c p3eggbase) -install(TARGETS egg2c EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg-topstrip eggTopstrip.cxx eggTopstrip.h) -target_link_libraries(egg-topstrip p3eggcharbase) -install(TARGETS egg-topstrip EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(egg-trans eggTrans.cxx eggTrans.h) -target_link_libraries(egg-trans p3eggbase) -install(TARGETS egg-trans EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/eggprogs/eggCrop.cxx b/pandatool/src/eggprogs/eggCrop.cxx deleted file mode 100644 index 38edb932..00000000 --- a/pandatool/src/eggprogs/eggCrop.cxx +++ /dev/null @@ -1,124 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCrop.cxx - * @author drose - * @date 2002-06-10 - */ - -#include "eggCrop.h" - -#include "eggGroupNode.h" -#include "eggPrimitive.h" -#include "eggVertex.h" -#include "dcast.h" - -/** - * - */ -EggCrop:: -EggCrop() { - set_program_brief("crop geometry in an .egg file"); - set_program_description - ("egg-crop strips out all parts of an egg file that fall outside of an " - "arbitrary bounding volume, specified with a minimum and maximum point " - "in world coordinates."); - - add_option - ("min", "x,y,z", 0, - "Specify the minimum point.", - &EggCrop::dispatch_double_triple, &_got_min, &_min[0]); - - add_option - ("max", "x,y,z", 0, - "Specify the maximum point.", - &EggCrop::dispatch_double_triple, &_got_max, &_max[0]); -} - -/** - * This is called after the command line has been completely processed, and it - * gives the program a chance to do some last-minute processing and validation - * of the options and arguments. It should return true if everything is fine, - * false if there is an error. - */ -bool EggCrop:: -post_command_line() { - if (!_got_min || !_got_max) { - nout << "You must specify both a minimum and a maximum bounds.\n"; - return false; - } - - return true; -} - -/** - * - */ -void EggCrop:: -run() { - int num_removed = strip_prims(_data); - nout << "Removed " << num_removed << " primitives.\n"; - - _data->remove_unused_vertices(true); - write_egg_file(); -} - - -/** - * Recursively walks the scene graph, looking for primitives that exceed the - * specified bounding volume, and removes them. Returns the number of - * primitives removed. - */ -int EggCrop:: -strip_prims(EggGroupNode *group) { - int num_removed = 0; - - EggGroupNode::iterator ci; - ci = group->begin(); - while (ci != group->end()) { - EggNode *child = (*ci); - bool all_in = true; - - if (child->is_of_type(EggPrimitive::get_class_type())) { - EggPrimitive *prim = DCAST(EggPrimitive, child); - EggPrimitive::iterator vi; - for (vi = prim->begin(); vi != prim->end() && all_in; ++vi) { - EggVertex *vert = (*vi); - LPoint3d pos = vert->get_pos3(); - - all_in = (pos[0] >= _min[0] && pos[0] <= _max[0] && - pos[1] >= _min[1] && pos[1] <= _max[1] && - pos[2] >= _min[2] && pos[2] <= _max[2]); - - } - } - - if (!all_in) { - // Reject this primitive. - ci = group->erase(ci); - num_removed++; - } else { - // Keep this primitive. - if (child->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group_child = DCAST(EggGroupNode, child); - num_removed += strip_prims(group_child); - } - ++ci; - } - } - - return num_removed; -} - - -int main(int argc, char *argv[]) { - EggCrop prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggCrop.h b/pandatool/src/eggprogs/eggCrop.h deleted file mode 100644 index df3203c8..00000000 --- a/pandatool/src/eggprogs/eggCrop.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggCrop.h - * @author drose - * @date 2002-06-10 - */ - -#ifndef EGGCROP_H -#define EGGCROP_H - -#include "pandatoolbase.h" - -#include "eggFilter.h" - -class EggGroupNode; - -/** - * A program to read an egg file and write an equivalent egg file, possibly - * performing some minor operations along the way. - */ -class EggCrop : public EggFilter { -public: - EggCrop(); - - virtual bool post_command_line(); - void run(); - -private: - int strip_prims(EggGroupNode *group); - - bool _got_min, _got_max; - LVecBase3d _min, _max; -}; - -#endif diff --git a/pandatool/src/eggprogs/eggListTextures.cxx b/pandatool/src/eggprogs/eggListTextures.cxx deleted file mode 100644 index fd44c73a..00000000 --- a/pandatool/src/eggprogs/eggListTextures.cxx +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggListTextures.cxx - * @author drose - * @date 2005-05-23 - */ - -#include "eggListTextures.h" -#include "eggTextureCollection.h" -#include "pnmImageHeader.h" - -/** - * - */ -EggListTextures:: -EggListTextures() { - set_program_brief("list textures referenced by an .egg file"); - set_program_description - ("egg-list-textures reads an egg file and writes a list of the " - "textures it references. It is particularly useful for building " - "up the textures.txa file used for egg-palettize, since the output " - "format is crafted to be compatible with that file's input format."); -} - -/** - * - */ -void EggListTextures:: -run() { - if (!do_reader_options()) { - exit(1); - } - - EggTextureCollection tc; - tc.find_used_textures(_data); - EggTextureCollection::TextureReplacement treplace; - tc.collapse_equivalent_textures(EggTexture::E_complete_filename, treplace); - tc.sort_by_basename(); - - EggTextureCollection::iterator ti; - for (ti = tc.begin(); ti != tc.end(); ++ti) { - Filename fullpath = (*ti)->get_fullpath(); - PNMImageHeader header; - if (header.read_header(fullpath)) { - std::cout << fullpath.get_basename() << " : " - << header.get_x_size() << " " << header.get_y_size() << "\n"; - } else { - std::cout << fullpath.get_basename() << " : unknown\n"; - } - } -} - - -int main(int argc, char *argv[]) { - EggListTextures prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggListTextures.h b/pandatool/src/eggprogs/eggListTextures.h deleted file mode 100644 index 5460b49e..00000000 --- a/pandatool/src/eggprogs/eggListTextures.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggListTextures.h - * @author drose - * @date 2005-05-23 - */ - -#ifndef EGGLISTTEXTURES_H -#define EGGLISTTEXTURES_H - -#include "pandatoolbase.h" - -#include "eggReader.h" - -/** - * Reads an egg file and outputs the list of textures it uses. - */ -class EggListTextures : public EggReader { -public: - EggListTextures(); - - void run(); -}; - -#endif diff --git a/pandatool/src/eggprogs/eggMakeTube.cxx b/pandatool/src/eggprogs/eggMakeTube.cxx deleted file mode 100644 index 85ec8508..00000000 --- a/pandatool/src/eggprogs/eggMakeTube.cxx +++ /dev/null @@ -1,270 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMakeTube.cxx - * @author drose - * @date 2003-10-01 - */ - -#include "eggMakeTube.h" -#include "eggGroup.h" -#include "eggVertexPool.h" -#include "eggVertex.h" -#include "eggPolygon.h" -#include "pointerTo.h" -#include "look_at.h" - -/** - * - */ -EggMakeTube:: -EggMakeTube() { - - set_program_brief("generate a tube or sphere from geometry in an .egg file"); - set_program_description - ("egg-make-tube generates an egg file representing a \"tube\" model, " - "a cylinder capped on both ends by hemispheres. This is similar " - "in shape to the CollisionCapsule object within Panda.\n\n" - "This program can also generate spheres if you omit -b; in this " - "case, you are generating a degenerate tube of length 0."); - - add_option - ("a", "x,y,z", 0, - "Specify the first endpoint of the tube.", - &EggWriter::dispatch_double_triple, nullptr, _point_a); - - add_option - ("b", "x,y,z", 0, - "Specify the second endpoint of the tube.", - &EggWriter::dispatch_double_triple, &_got_point_b, _point_b); - - add_option - ("r", "radius", 0, - "Specify the radius of the tube. The tube will extend beyond " - "the endpoints in each direction by the amount of radius.", - &EggWriter::dispatch_double, nullptr, &_radius); - - add_option - ("slices", "count", 0, - "Specify the number of slices appearing radially around the tube.", - &EggWriter::dispatch_int, nullptr, &_num_slices); - - add_option - ("crings", "count", 0, - "Specify the number of rings appearing in each endcap of the tube.", - &EggWriter::dispatch_int, nullptr, &_num_crings); - - add_option - ("trings", "count", 0, - "Specify the number of rings appearing in the cylindrical body " - "of the tube.", - &EggWriter::dispatch_int, nullptr, &_num_trings); - - _point_a[0] = 0.0; - _point_a[1] = 0.0; - _point_a[2] = 0.0; - - _point_b[0] = 0.0; - _point_b[1] = 0.0; - _point_b[2] = 0.0; - - _radius = 1.0; - - _num_slices = 8; - _num_crings = 4; - _num_trings = 1; -} - -/** - * - */ -void EggMakeTube:: -run() { - if (!_got_point_b) { - _point_b[0] = _point_a[0]; - _point_b[1] = _point_a[1]; - _point_b[2] = _point_a[2]; - } - - // We will generate the vertices in the canonical space (along the y axis), - // then transform it to the desired point. - LVector3d direction(_point_b[0] - _point_a[0], - _point_b[1] - _point_a[1], - _point_b[2] - _point_a[2]); - _length = direction.length(); - - // First, create an enclosing group and a vertex pool. - _group = new EggGroup("tube"); - _data->add_child(_group); - - _vpool = new EggVertexPool("tube"); - _group->add_child(_vpool); - - // Generate the first endcap. - int ri, si; - EggVertex *vtx_1; - EggVertex *vtx_2; - - for (ri = 0; ri < _num_crings; ri++) { - vtx_1 = nullptr; - vtx_2 = nullptr; - for (si = 0; si <= _num_slices; si++) { - EggVertex *vtx_3 = calc_sphere1_vertex(ri, si); - EggVertex *vtx_4 = calc_sphere1_vertex(ri + 1, si); - add_polygon(vtx_1, vtx_2, vtx_4, vtx_3); - vtx_1 = vtx_3; - vtx_2 = vtx_4; - } - } - - // Now the cylinder sides. - if (_length != 0.0) { - for (ri = 0; ri < _num_trings; ri++) { - vtx_1 = nullptr; - vtx_2 = nullptr; - for (si = 0; si <= _num_slices; si++) { - EggVertex *vtx_3 = calc_tube_vertex(ri, si); - EggVertex *vtx_4 = calc_tube_vertex(ri + 1, si); - add_polygon(vtx_1, vtx_2, vtx_4, vtx_3); - vtx_1 = vtx_3; - vtx_2 = vtx_4; - } - } - } - - // And the second endcap. - for (ri = _num_crings - 1; ri >= 0; ri--) { - vtx_1 = nullptr; - vtx_2 = nullptr; - for (si = 0; si <= _num_slices; si++) { - EggVertex *vtx_3 = calc_sphere2_vertex(ri + 1, si); - EggVertex *vtx_4 = calc_sphere2_vertex(ri, si); - add_polygon(vtx_1, vtx_2, vtx_4, vtx_3); - vtx_1 = vtx_3; - vtx_2 = vtx_4; - } - } - - // Now transform the vertices out of the canonical position. - LMatrix4d mat; - look_at(mat, direction, LVector3d(0.0, 0.0, 1.0), CS_zup_right); - mat.set_row(3, LPoint3d(_point_a[0], _point_a[1], _point_a[2])); - _group->transform(mat); - - write_egg_file(); -} - -/** - * Calculates a particular vertex on the surface of the first endcap - * hemisphere. - */ -EggVertex *EggMakeTube:: -calc_sphere1_vertex(int ri, int si) { - double r = (double)ri / (double)_num_crings; - double s = (double)si / (double)_num_slices; - - // Find the point on the rim, based on the slice. - double theta = s * 2.0 * MathNumbers::pi; - double x_rim = cos(theta); - double z_rim = sin(theta); - - // Now pull that point in towards the pole, based on the ring. - double phi = r * 0.5 * MathNumbers::pi; - double to_pole = sin(phi); - - double x = _radius * x_rim * to_pole; - double y = -_radius * cos(phi); - double z = _radius * z_rim * to_pole; - - EggVertex vert; - vert.set_pos(LPoint3d(x, y, z)); - - return _vpool->create_unique_vertex(vert); -} - -/** - * Calculates a vertex on the side of the cylindrical body of the tube. - */ -EggVertex *EggMakeTube:: -calc_tube_vertex(int ri, int si) { - double r = (double)ri / (double)_num_trings; - double s = (double)si / (double)_num_slices; - - // Find the point on the rim, based on the slice. - double theta = s * 2.0 * MathNumbers::pi; - double x_rim = cos(theta); - double z_rim = sin(theta); - - double x = _radius * x_rim; - double y = _length * r; - double z = _radius * z_rim; - - EggVertex vert; - vert.set_pos(LPoint3d(x, y, z)); - - return _vpool->create_unique_vertex(vert); -} - -/** - * Calculates a particular vertex on the surface of the second endcap - * hemisphere. - */ -EggVertex *EggMakeTube:: -calc_sphere2_vertex(int ri, int si) { - double r = (double)ri / (double)_num_crings; - double s = (double)si / (double)_num_slices; - - // Find the point on the rim, based on the slice. - double theta = s * 2.0 * MathNumbers::pi; - double x_rim = cos(theta); - double z_rim = sin(theta); - - // Now pull that point in towards the pole, based on the ring. - double phi = r * 0.5 * MathNumbers::pi; - double to_pole = sin(phi); - - double x = _radius * x_rim * to_pole; - double y = _length + _radius * cos(phi); - double z = _radius * z_rim * to_pole; - - EggVertex vert; - vert.set_pos(LPoint3d(x, y, z)); - - return _vpool->create_unique_vertex(vert); -} - -/** - * Adds the polygon defined by the indicated four vertices to the group. If - * the first vertex is NULL, does nothing. - */ -void EggMakeTube:: -add_polygon(EggVertex *a, EggVertex *b, EggVertex *c, EggVertex *d) { - if (a == nullptr) { - return; - } - - PT(EggPolygon) poly = new EggPolygon; - poly->add_vertex(a); - if (a != b) { - poly->add_vertex(b); - } - poly->add_vertex(c); - if (c != d) { - poly->add_vertex(d); - } - - _group->add_child(poly.p()); -} - - -int main(int argc, char *argv[]) { - EggMakeTube prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggMakeTube.h b/pandatool/src/eggprogs/eggMakeTube.h deleted file mode 100644 index 3031b1c7..00000000 --- a/pandatool/src/eggprogs/eggMakeTube.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggMakeTube.h - * @author drose - * @date 2003-10-01 - */ - -#ifndef EGGMAKETUBE_H -#define EGGMAKETUBE_H - -#include "pandatoolbase.h" - -#include "eggMakeSomething.h" - -class EggGroup; -class EggVertexPool; -class EggVertex; - -/** - * A program to generate an egg file representing a tube model, similar in - * shape to a CollisionCapsule. - */ -class EggMakeTube : public EggMakeSomething { -public: - EggMakeTube(); - - void run(); - -private: - EggVertex *calc_sphere1_vertex(int ri, int si); - EggVertex *calc_sphere2_vertex(int ri, int si); - EggVertex *calc_tube_vertex(int ri, int si); - void add_polygon(EggVertex *a, EggVertex *b, EggVertex *c, EggVertex *d); - -private: - double _point_a[3]; - double _point_b[3]; - bool _got_point_b; - double _radius; - int _num_slices; - int _num_crings; - int _num_trings; - - double _length; - EggGroup *_group; - EggVertexPool *_vpool; -}; - -#endif diff --git a/pandatool/src/eggprogs/eggRename.cxx b/pandatool/src/eggprogs/eggRename.cxx deleted file mode 100644 index 6b2c9869..00000000 --- a/pandatool/src/eggprogs/eggRename.cxx +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggRename.cxx - * @author masad - * @date 2005-04-22 - */ - -#include "eggRename.h" - -/** - * - */ -EggRename:: -EggRename() { - set_program_brief("rename nodes in .egg files"); - set_program_description - ("egg-rename reads one or more egg files and writes back with modified" - "node names. ie. suppressing prefix from all the nodes' names. "); - - add_option - ("strip_prefix", "name", 0, - "strips out the prefix that is put on all nodes, by maya ext. ref", - &EggRename::dispatch_vector_string, nullptr, &_strip_prefix); -} - -/** - * - */ -void EggRename:: -run() { - if (!_strip_prefix.empty()) { - nout << "Stripping prefix from nodes.\n"; - int num_renamed = 0; - //int num_egg_files = 0; - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - num_renamed += (*ei)->rename_nodes(_strip_prefix, true); - //++num_egg_files; - } - nout << " (" << num_renamed << " renamed.)\n"; - } - - write_eggs(); -} - - -int main(int argc, char *argv[]) { - EggRename prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggRename.h b/pandatool/src/eggprogs/eggRename.h deleted file mode 100644 index 51bd5344..00000000 --- a/pandatool/src/eggprogs/eggRename.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggRename.h - * @author masad - * @date 2005-04-22 - */ - -#ifndef EGGRENAME_H -#define EGGRENAME_H - -#include "pandatoolbase.h" - -#include "eggMultiFilter.h" - -/** - * A program to read an egg file and write an equivalent egg file, with - * stripping prefix for now, but more along the way. - */ -class EggRename : public EggMultiFilter { -public: - EggRename(); - - void run(); - - vector_string _strip_prefix; -}; - -#endif diff --git a/pandatool/src/eggprogs/eggRetargetAnim.cxx b/pandatool/src/eggprogs/eggRetargetAnim.cxx deleted file mode 100644 index ba55d19b..00000000 --- a/pandatool/src/eggprogs/eggRetargetAnim.cxx +++ /dev/null @@ -1,192 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggRetargetAnim.cxx - * @author drose - * @date 2005-05-05 - */ - -#include "eggRetargetAnim.h" - -#include "dcast.h" -#include "eggJointData.h" -#include "eggCharacterCollection.h" -#include "eggCharacterData.h" -#include "eggCharacterDb.h" -#include "eggJointPointer.h" -#include "eggTable.h" -#include "compose_matrix.h" - -/** - * - */ -EggRetargetAnim:: -EggRetargetAnim() { - add_path_replace_options(); - add_path_store_options(); - - set_program_brief("remove transformations from animation data in .egg files"); - set_program_description - ("egg-retarget-anim reads a character model and its associated animation " - "files, and removes the translations and scales from the animation " - "files, replacing them with the translations and scales from the " - "rest position of the character model.\n\n" - - "This allows an animation that was generated for a model with one " - "skeleton to be played successfully on a model with a different " - "skeleton, provided that both skeletons have the same hierarchy and " - "differ only in scales and/or translations of the various joints, " - "and that scales and translations are not part of the per-frame " - "animations."); - - add_option - ("r", "file.egg", 0, - "Read the reference model from the indicated egg file. All of the " - "animations will be retargeted to match the indicated file.", - &EggRetargetAnim::dispatch_filename, nullptr, &_reference_filename); - - add_option - ("keep", "joint[,joint...]", 0, - "Preserve the full animation on the named joint(s). This is especially " - "appropriate for the root joint.", - &EggRetargetAnim::dispatch_vector_string_comma, nullptr, &_keep_joints); -} - -/** - * - */ -void EggRetargetAnim:: -run() { - nassertv(_collection != nullptr); - nassertv(_collection->get_num_eggs() > 0); - - if (_reference_filename.empty()) { - nout << "No reference filename specified.\n"; - exit(1); - } - - int num_characters = _collection->get_num_characters(); - if (num_characters != 1) { - nout << "All animations must have the same character name.\n"; - exit(1); - } - - // Read in the extra egg file that we use for extracting the references out. - PT(EggData) reference_egg = read_egg(_reference_filename); - if (reference_egg == nullptr) { - nout << "Cannot read " << _reference_filename << "\n"; - exit(1); - } - - // First, we add it to a separate EggCharacterCollection, so we can figure - // out its name. - EggCharacterCollection col; - if (col.add_egg(reference_egg) < 0) { - nout << _reference_filename - << " does not contain a character model or animation reference.\n"; - exit(1); - } - - if (col.get_num_characters() != 1) { - nout << "Reference model must contain only one character.\n"; - exit(1); - } - - std::string ref_name = col.get_character(0)->get_name(); - - // Now rename all of the animations to the same name as the reference model, - // and add the reference animation in to the same collection to match it up - // joint-for-joint. - _collection->rename_char(0, ref_name); - int reference_egg_index = _collection->add_egg(reference_egg); - nassertv(reference_egg_index > 0); - nassertv(_collection->get_num_characters() == 1); - - int reference_model = _collection->get_first_model_index(reference_egg_index); - EggCharacterData *char_data = _collection->get_character(0); - nout << "Processing " << char_data->get_name() << "\n"; - - typedef pset Names; - Names keep_names; - - vector_string::const_iterator si; - for (si = _keep_joints.begin(); si != _keep_joints.end(); ++si) { - keep_names.insert(*si); - } - - EggCharacterDb db; - EggJointData *root_joint = char_data->get_root_joint(); - retarget_anim(char_data, root_joint, reference_model, keep_names, db); - root_joint->do_rebuild_all(db); - - write_eggs(); -} - -/** - * Recursively replaces the scale and translate information on all of the - * joints in the char_data hierarchy wiht this from reference_char. - */ -void EggRetargetAnim:: -retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, - int reference_model, const pset &keep_names, - EggCharacterDb &db) { - if (keep_names.find(joint_data->get_name()) != keep_names.end()) { - // Don't retarget this joint; keep the translation and scale and whatever. - - } else { - // Retarget this joint. - int num_models = joint_data->get_num_models(); - for (int i = 0; i < num_models; i++) { - if (joint_data->has_model(i)) { - int num_frames = char_data->get_num_frames(i); - - EggBackPointer *back = joint_data->get_model(i); - nassertv(back != nullptr); - EggJointPointer *joint; - DCAST_INTO_V(joint, back); - - LMatrix4d ref = joint_data->get_frame(reference_model, 0); - LVecBase3d ref_scale, ref_shear, ref_hpr, ref_translate; - if (!decompose_matrix(ref, ref_scale, ref_shear, ref_hpr, ref_translate)) { - nout << "Could not decompose rest frame for " - << joint_data->get_name() << "\n"; - } else { - int f; - for (f = 0; f < num_frames; f++) { - LMatrix4d mat = joint_data->get_frame(i, f); - - LVecBase3d scale, shear, hpr, translate; - if (decompose_matrix(mat, scale, shear, hpr, translate)) { - compose_matrix(mat, ref_scale, ref_shear, hpr, ref_translate); - } else { - nout << "Could not decompose matrix for " << joint_data->get_name() - << "\n"; - } - - db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, - f, mat); - } - } - } - } - } - - int num_children = joint_data->get_num_children(); - for (int i = 0; i < num_children; i++) { - EggJointData *next_joint_data = joint_data->get_child(i); - retarget_anim(char_data, next_joint_data, reference_model, keep_names, db); - } -} - - -int main(int argc, char *argv[]) { - EggRetargetAnim prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggRetargetAnim.h b/pandatool/src/eggprogs/eggRetargetAnim.h deleted file mode 100644 index 455942ae..00000000 --- a/pandatool/src/eggprogs/eggRetargetAnim.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggRetargetAnim.h - * @author drose - * @date 2005-05-05 - */ - -#ifndef EGGRETARGETANIM_H -#define EGGRETARGETANIM_H - -#include "pandatoolbase.h" - -#include "eggCharacterFilter.h" -#include "luse.h" -#include "pvector.h" -#include "pset.h" - -class EggCharacterData; -class EggJointData; -class EggCharacterDb; - -/** - * Retargets one or more animation files from one particular skeleton to a - * similar, but differently scaled skeleton by preserving the rotation - * information but discarding translation and/or scale. - */ -class EggRetargetAnim : public EggCharacterFilter { -public: - EggRetargetAnim(); - - void run(); - - void retarget_anim(EggCharacterData *char_data, EggJointData *joint_data, - int reference_model, const pset &keep_names, - EggCharacterDb &db); - - Filename _reference_filename; - vector_string _keep_joints; -}; - -#endif diff --git a/pandatool/src/eggprogs/eggTextureCards.cxx b/pandatool/src/eggprogs/eggTextureCards.cxx deleted file mode 100644 index 255b145a..00000000 --- a/pandatool/src/eggprogs/eggTextureCards.cxx +++ /dev/null @@ -1,492 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggTextureCards.cxx - * @author drose - * @date 2001-02-21 - */ - -#include "eggTextureCards.h" - -#include "eggGroup.h" -#include "eggVertexPool.h" -#include "eggVertex.h" -#include "eggTexture.h" -#include "eggPolygon.h" -#include "pnmImageHeader.h" - -#include - -using std::string; - -/** - * - */ -EggTextureCards:: -EggTextureCards() : EggWriter(true, true) { - set_program_brief("generate an .egg file containing texture cards"); - set_program_description - ("egg-texture-cards generates an egg file consisting of several " - "square polygons, one for each texture name that appears on the " - "command line.\n\n" - - "This is a handy thing to have for importing texture images through " - "egg-palettize, even when those textures do not appear on any real " - "geometry; it can also be used for creating a lot of simple polygons " - "for rendering click buttons and similar interfaces."); - - clear_runlines(); - add_runline("[opts] texture [texture ...] output.egg"); - add_runline("[opts] -o output.egg texture [texture ...]"); - add_runline("[opts] texture [texture ...] >output.egg"); - - add_option - ("g", "left,right,bottom,top", 0, - "Specifies the geometry of each polygon. The default is a unit polygon " - "centered on the origin: -0.5,0.5,-0.5,0.5. Polygons are always created " - "on the X-Y plane. If -p is not also specified, all polygons will be " - "the same size and shape.", - &EggTextureCards::dispatch_double_quad, nullptr, &_polygon_geometry[0]); - - add_option - ("p", "xpixels,ypixels", 0, - "Indicates that polygons should be sized in proportion to the pixel " - "size of the texture image. This will potentially create a " - "different size and shape polygon for each texture. The coordinate " - "pair represents the image size in " - "pixels that will exactly fill up the polygon described with -g (or the " - "default polygon if -g is not specified); smaller images will be " - "given proportionately smaller polygons, and larger images will be " - "given proportionately larger polygons.", - &EggTextureCards::dispatch_double_pair, &_got_pixel_scale, &_pixel_scale[0]); - - add_option - ("suffix", "string", 0, - "Normally, each polygon is given a name based on the basename of its " - "corresponding texture's filename (without the filename extension). " - "This option specifies an ignorable suffix in the texture filename(s); " - "if this suffix is present, it is not included in the polygon's name. " - "This option may be repeated multiple times.", - &EggTextureCards::dispatch_vector_string, nullptr, &_suffixes); - - add_option - ("c", "r,g,b[,a]", 0, - "Specifies the color of each polygon. The default is white: 1,1,1,1.", - &EggTextureCards::dispatch_color, nullptr, &_polygon_color[0]); - - add_option - ("wm", "wrap", 0, - "Indicates the wrap mode of the texture: \"repeat\", \"clamp\", " - "or any of the other modes supported by egg syntax. " - "The default is to leave this unspecified.", - &EggTextureCards::dispatch_wrap_mode, nullptr, &_wrap_mode); - - add_option - ("wmu", "wrap_u", 0, - "Indicates the wrap mode of the texture in the U direction. This " - "overrides -wm, if specified.", - &EggTextureCards::dispatch_wrap_mode, nullptr, &_wrap_u); - - add_option - ("wmv", "wrap_v", 0, - "Indicates the wrap mode of the texture in the V direction. This " - "overrides -wm, if specified.", - &EggTextureCards::dispatch_wrap_mode, nullptr, &_wrap_v); - - add_option - ("minf", "filter", 0, - "Indicates the minfilter mode of the texture: \"linear\", \"mipmap\", " - "or any of the other modes supported by egg syntax. " - "The default is to leave this unspecified.", - &EggTextureCards::dispatch_filter_type, nullptr, &_minfilter); - - add_option - ("magf", "filter", 0, - "Indicates the magfilter mode of the texture: \"linear\" or \"nearest\". " - "The default is to leave this unspecified.", - &EggTextureCards::dispatch_filter_type, nullptr, &_magfilter); - - add_option - ("aniso", "degree", 0, - "Indicates the anisotropic degree of the texture. " - "The default is to leave this unspecified.", - &EggTextureCards::dispatch_int, &_got_aniso_degree, &_aniso_degree); - - add_option - ("ql", "[default | fastest | normal | best]", 0, - "Specifies the quality level of the texture. This mainly affects " - "the tinydisplay software renderer.", - &EggTextureCards::dispatch_quality_level, nullptr, &_quality_level); - - add_option - ("f", "format", 0, - "Indicates the format for all textures: typical choices are \"rgba12\" " - "or \"rgb5\" or \"alpha\". The default is to leave this unspecified.", - &EggTextureCards::dispatch_format, nullptr, &_format); - - add_option - ("f1", "format", 0, - "Indicates the format for one-channel textures only. If specified, this " - "overrides the format specified by -f.", - &EggTextureCards::dispatch_format, nullptr, &_format_1); - - add_option - ("f2", "format", 0, - "Indicates the format for two-channel textures only. If specified, this " - "overrides the format specified by -f.", - &EggTextureCards::dispatch_format, nullptr, &_format_2); - - add_option - ("f3", "format", 0, - "Indicates the format for three-channel textures only. If specified, this " - "overrides the format specified by -f.", - &EggTextureCards::dispatch_format, nullptr, &_format_3); - - add_option - ("f4", "format", 0, - "Indicates the format for four-channel textures only. If specified, this " - "overrides the format specified by -f.", - &EggTextureCards::dispatch_format, nullptr, &_format_4); - - add_option - ("b", "", 0, - "Make the textured polygons backfaced (two-sided).", - &EggTextureCards::dispatch_none, &_apply_bface); - - add_option - ("fps", "frame-rate", 0, - "Normally, all of the texture cards are created as a series of nodes " - "beneath a SequenceNode. This allows all of the cards to be viewed, " - "one at a time, if the output file is loaded in pview. It also has the " - "nice side-effect of creating an automatic texture flip that can be " - "used directly by applications; use this parameter to specify the " - "frame rate of that texture flip.", - &EggTextureCards::dispatch_double, nullptr, &_frame_rate); - - add_option - ("noexist", "", 0, - "Don't treat it as an error if the input file references pathnames " - "(e.g. textures) that don't exist. Normally, this will be flagged as " - "an error and the command aborted; with this option, an egg file will " - "be generated anyway, referencing pathnames that do not exist.", - &EggTextureCards::dispatch_none, &_noexist); - - _polygon_geometry.set(-0.5, 0.5, -0.5, 0.5); - _polygon_color.set(1.0, 1.0, 1.0, 1.0); - _wrap_mode = EggTexture::WM_unspecified; - _wrap_u = EggTexture::WM_unspecified; - _wrap_v = EggTexture::WM_unspecified; - _minfilter = EggTexture::FT_unspecified; - _magfilter = EggTexture::FT_unspecified; - _aniso_degree = 0; - _quality_level = EggTexture::QL_unspecified; - _format = EggTexture::F_unspecified; - _format_1 = EggTexture::F_unspecified; - _format_2 = EggTexture::F_unspecified; - _format_3 = EggTexture::F_unspecified; - _format_4 = EggTexture::F_unspecified; - _frame_rate = 2.0; -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggTextureCards:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 0)) { - return false; - } - - if (args.empty()) { - nout << "No texture names specified on the command line.\n"; - return false; - } - - ProgramBase::Args::iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - _texture_names.push_back(Filename::from_os_specific(*ai)); - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a WrapMode string. The data pointer is to a WrapMode - * enum variable. - */ -bool EggTextureCards:: -dispatch_wrap_mode(const string &opt, const string &arg, void *var) { - EggTexture::WrapMode *wmp = (EggTexture::WrapMode *)var; - - *wmp = EggTexture::string_wrap_mode(arg); - if (*wmp == EggTexture::WM_unspecified) { - // An unknown string. Let's check for our special cases. - if (arg == "r") { - *wmp = EggTexture::WM_repeat; - } else if (arg == "c") { - *wmp = EggTexture::WM_clamp; - } else { - nout << "Invalid wrap mode parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a FilterType string. The data pointer is to a - * FilterType enum variable. - */ -bool EggTextureCards:: -dispatch_filter_type(const string &opt, const string &arg, void *var) { - EggTexture::FilterType *ftp = (EggTexture::FilterType *)var; - - *ftp = EggTexture::string_filter_type(arg); - if (*ftp == EggTexture::FT_unspecified) { - // An unknown string. - nout << "Invalid filter type parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a QualityLevel string. The data pointer is to a - * QualityLevel enum variable. - */ -bool EggTextureCards:: -dispatch_quality_level(const string &opt, const string &arg, void *var) { - EggTexture::QualityLevel *qlp = (EggTexture::QualityLevel *)var; - - *qlp = EggTexture::string_quality_level(arg); - if (*qlp == EggTexture::QL_unspecified) { - nout << "Invalid quality level parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a Format string. The data pointer is to a Format enum - * variable. - */ -bool EggTextureCards:: -dispatch_format(const string &opt, const string &arg, void *var) { - EggTexture::Format *fp = (EggTexture::Format *)var; - - *fp = EggTexture::string_format(arg); - if (*fp == EggTexture::F_unspecified) { - nout << "Invalid format parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - - return true; -} - - -/** - * Reads the texture image header to determine its size, and based on this - * size, computes the appropriate left,right,bottom,top geometry of the card - * that correspond to this texture. - * - * Returns true if successful, or false if the texture cannot be read. - */ -bool EggTextureCards:: -scan_texture(const Filename &filename, LVecBase4d &geometry, - int &num_channels) { - PNMImageHeader header; - if (!header.read_header(filename)) { - nout << "Unable to read image " << filename << "\n"; - return false; - } - - num_channels = header.get_num_channels(); - - double xscale = header.get_x_size() / _pixel_scale[0]; - double yscale = header.get_y_size() / _pixel_scale[1]; - - geometry.set(_polygon_geometry[0] * xscale, - _polygon_geometry[1] * xscale, - _polygon_geometry[2] * yscale, - _polygon_geometry[3] * yscale); - return true; -} - -/** - * Creates a set of four vertices for the polygon according to the - * left,right,bottom,top geometry. - */ -void EggTextureCards:: -make_vertices(const LPoint4d &geometry, EggVertexPool *vpool, - EggVertex *&v1, EggVertex *&v2, EggVertex *&v3, EggVertex *&v4) { - // 1 4 2 3 - - v1 = vpool->make_new_vertex - (LPoint3d(geometry[0], geometry[3], 0.0)); - v2 = vpool->make_new_vertex - (LPoint3d(geometry[0], geometry[2], 0.0)); - v3 = vpool->make_new_vertex - (LPoint3d(geometry[1], geometry[2], 0.0)); - v4 = vpool->make_new_vertex - (LPoint3d(geometry[1], geometry[3], 0.0)); - - v1->set_uv(LTexCoordd(0.0, 1.0)); - v2->set_uv(LTexCoordd(0.0, 0.0)); - v3->set_uv(LTexCoordd(1.0, 0.0)); - v4->set_uv(LTexCoordd(1.0, 1.0)); -} - -/** - * - */ -void EggTextureCards:: -run() { - // First, create an enclosing group and a vertex pool with four vertices. - // We can use the same four vertices on all polygons. - bool all_ok = true; - - EggGroup *group = new EggGroup(); - _data->add_child(group); - - // If we have more than one tile, make the group a sequence, as a - // convenience. If we view the egg file directly we can see all the tiles - // one at a time. - if (_texture_names.size() > 1) { - group->set_switch_flag(true); - group->set_switch_fps(_frame_rate); - } - - EggVertexPool *vpool = new EggVertexPool("vpool"); - group->add_child(vpool); - - EggVertex *v1, *v2, *v3, *v4; - - bool got_pixel_scale = _got_pixel_scale; - if (!got_pixel_scale) { - // If we don't have a per-texture pixel scale, all the polygons will be - // the same size, and hence may all share the same four vertices. - make_vertices(_polygon_geometry, vpool, v1, v2, v3, v4); - } - - // Now, create a texture reference and a polygon for each texture. - - vector_string::const_iterator ti; - for (ti = _texture_names.begin(); ti != _texture_names.end(); ++ti) { - Filename filename = (*ti); - string name = filename.get_basename_wo_extension(); - - // Strip off any suffixes from the name. - vector_string::const_iterator si; - for (si = _suffixes.begin(); si != _suffixes.end(); ++si) { - const string &suffix = (*si); - int prefix = (int)name.length() - (int)suffix.length(); - if (prefix > 0 && name.substr(prefix) == suffix) { - name = name.substr(0, prefix); - } - } - - // Read in the texture header and determine its size. - LVecBase4d geometry; - int num_channels; - bool texture_ok = scan_texture(filename, geometry, num_channels); - if (!texture_ok) { - all_ok = false; - } - - if (got_pixel_scale) { - if (texture_ok) { - make_vertices(geometry, vpool, v1, v2, v3, v4); - } else { - make_vertices(_polygon_geometry, vpool, v1, v2, v3, v4); - } - } - - EggTexture *tref = new EggTexture(name, filename); - tref->set_wrap_mode(_wrap_mode); - tref->set_wrap_u(_wrap_u); - tref->set_wrap_v(_wrap_v); - tref->set_minfilter(_minfilter); - tref->set_magfilter(_magfilter); - if (_got_aniso_degree) { - tref->set_anisotropic_degree(_aniso_degree); - } - tref->set_quality_level(_quality_level); - - if (texture_ok) { - switch (num_channels) { - case 1: - tref->set_format(_format_1); - break; - - case 2: - tref->set_format(_format_2); - break; - - case 3: - tref->set_format(_format_3); - break; - - case 4: - tref->set_format(_format_4); - break; - } - } - - if (tref->get_format() == EggTexture::F_unspecified) { - tref->set_format(_format); - } - - group->add_child(tref); - - // Each polygon gets placed in its own sub-group. This will make pulling - // them out by name at runtime possible. - EggGroup *sub_group = new EggGroup(name); - group->add_child(sub_group); - EggPolygon *poly = new EggPolygon(); - sub_group->add_child(poly); - poly->set_texture(tref); - poly->set_color(_polygon_color); - if (_apply_bface){ - poly->set_bface_flag(1); - } - - poly->add_vertex(v1); - poly->add_vertex(v2); - poly->add_vertex(v3); - poly->add_vertex(v4); - } - - // Done! - if (all_ok || _noexist) { - write_egg_file(); - } else { - nout << "Some textures not found; not generating egg file.\n"; - exit(1); - } -} - - -int main(int argc, char *argv[]) { - EggTextureCards prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggTextureCards.h b/pandatool/src/eggprogs/eggTextureCards.h deleted file mode 100644 index c30e926d..00000000 --- a/pandatool/src/eggprogs/eggTextureCards.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggTextureCards.h - * @author drose - * @date 2001-02-21 - */ - -#ifndef EGGTEXTURECARDS_H -#define EGGTEXTURECARDS_H - -#include "pandatoolbase.h" - -#include "eggWriter.h" -#include "eggTexture.h" -#include "luse.h" -#include "vector_string.h" - -class EggVertexPool; -class EggVertex; - -/** - * Generates an egg file featuring a number of polygons, one for each named - * texture. This is a support program for getting textures through egg- - * palettize. - */ -class EggTextureCards : public EggWriter { -public: - EggTextureCards(); - -protected: - virtual bool handle_args(Args &args); - - static bool dispatch_wrap_mode(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_filter_type(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_quality_level(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_format(const std::string &opt, const std::string &arg, void *var); - -private: - bool scan_texture(const Filename &filename, LVecBase4d &geometry, - int &num_channels); - void make_vertices(const LPoint4d &geometry, EggVertexPool *vpool, - EggVertex *&v1, EggVertex *&v2, EggVertex *&v3, EggVertex *&v4); - -public: - void run(); - - LVecBase4d _polygon_geometry; - LVecBase2d _pixel_scale; - bool _got_pixel_scale; - vector_string _suffixes; - LColor _polygon_color; - vector_string _texture_names; - EggTexture::WrapMode _wrap_mode; - EggTexture::WrapMode _wrap_u; - EggTexture::WrapMode _wrap_v; - EggTexture::FilterType _minfilter; - EggTexture::FilterType _magfilter; - bool _got_aniso_degree; - int _aniso_degree; - EggTexture::QualityLevel _quality_level; - EggTexture::Format _format; - EggTexture::Format _format_1, _format_2, _format_3, _format_4; - bool _apply_bface; - double _frame_rate; - bool _noexist; -}; - -#endif diff --git a/pandatool/src/eggprogs/eggToC.cxx b/pandatool/src/eggprogs/eggToC.cxx deleted file mode 100644 index bafc37fd..00000000 --- a/pandatool/src/eggprogs/eggToC.cxx +++ /dev/null @@ -1,373 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToC.cxx - * @author drose - * @date 2001-08-03 - */ - -#include "eggToC.h" - -#include "eggVertexPool.h" -#include "eggVertex.h" -#include "eggPolygon.h" -#include "eggPrimitive.h" -#include "eggGroupNode.h" -#include "eggPolysetMaker.h" -#include "eggBin.h" -#include "string_utils.h" - -using std::ostream; -using std::string; - -/** - * - */ -EggToC:: -EggToC() : - EggToSomething("C", ".c", true, true) -{ - set_program_brief("convert .egg geometry into compilable C tables"); - set_program_description - ("This program reads Egg files and outputs code that will almost " - "compile as a C or C++ program. You get to define the data structures " - "for the program after the fact; the program only generates tables " - "of vertices and polygons."); - - // -f is always in effect for egg2c. It doesn't make sense to provide it as - // an option to the user. - remove_option("f"); - - add_option - ("v", "", 0, - "Generate a table of vertex positions.", - &EggToC::dispatch_none, &_vertices); - - add_option - ("u", "", 0, - "Generate a table of UV's per each vertex.", - &EggToC::dispatch_none, &_uvs); - - add_option - ("vn", "", 0, - "Generate a table of normals per each vertex.", - &EggToC::dispatch_none, &_vertex_normals); - - add_option - ("vc", "", 0, - "Generate a table of colors per each vertex.", - &EggToC::dispatch_none, &_vertex_colors); - - add_option - ("p", "", 0, - "Generate a table of polygons that index into the above tables.", - &EggToC::dispatch_none, &_polygons); - - add_option - ("pn", "", 0, - "Generate a table of normals per each polygon.", - &EggToC::dispatch_none, &_polygon_normals); - - add_option - ("pc", "", 0, - "Generate a table of colors per each polygon.", - &EggToC::dispatch_none, &_polygon_colors); - - add_option - ("t", "", 0, - "Output only triangles by subdividing higher-order polygons.", - &EggToC::dispatch_none, &_triangulate_polygons); -} - -/** - * - */ -void EggToC:: -run() { - nout << "Removing invalid primitives.\n"; - int num_removed = _data->remove_invalid_primitives(true); - nout << " (" << num_removed << " removed.)\n"; - - if (_triangulate_polygons) { - nout << "Triangulating polygons.\n"; - int num_produced = _data->triangulate_polygons(~0); - nout << " (" << num_produced << " triangles produced.)\n"; - } - - _data->apply_texmats(); - _data->flatten_transforms(); - _data->remove_unused_vertices(true); - - // Collect all the polygons together into polysets. - EggPolysetMaker pmaker; - pmaker.set_properties(0); - pmaker.make_bins(_data); - - get_output() - << "/*\n" - << " * Generated by:\n" - << " * " << get_exec_command() << "\n" - << " *\n" - << " */\n\n"; - - _next_vpool_index = 0; - _next_bin_index = 0; - traverse(_data); -} - -/** - * - */ -void EggToC:: -traverse(EggNode *node) { - if (node->is_of_type(EggVertexPool::get_class_type())) { - write_vertex_pool(DCAST(EggVertexPool, node)); - - } else if (node->is_of_type(EggBin::get_class_type())) { - write_bin(DCAST(EggBin, node)); - - } else if (node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *group = DCAST(EggGroupNode, node); - - EggGroupNode::const_iterator ci; - for (ci = group->begin(); ci != group->end(); ++ci) { - traverse(*ci); - } - } -} - -/** - * - */ -void EggToC:: -write_vertex_pool(EggVertexPool *vpool) { - int highest_index = vpool->get_highest_index(); - int i; - - ostream &out = get_output(); - out << "/* Vertex pool index " << _next_vpool_index - << ": " << vpool->get_name() << " */\n"; - _vertex_pools[vpool] = _next_vpool_index; - _next_vpool_index++; - - if (_vertices) { - out << "/* Vertex definition for " << vpool->get_name() << " */\n" - << "vertex vertices_" << vpool->get_name() << "[" << highest_index - << "] = {\n"; - for (i = 0; i < highest_index; i++) { - EggVertex *vert = vpool->get_vertex(i); - if (vert == nullptr) { - out << " vertex(), /* " << i << " */\n"; - } else { - LPoint4d p = vert->get_pos4(); - switch (vert->get_num_dimensions()) { - case 1: - out << " vertex(" << p[0] << "), /* " << i << " */\n"; - break; - - case 2: - out << " vertex(" << p[0] << ", " << p[1] - << "), /* " << i << " */\n"; - break; - - case 3: - out << " vertex(" << p[0] << ", " << p[1] << ", " << p[2] - << "), /* " << i << " */\n"; - break; - - case 4: - out << " vertex(" << p[0] << ", " << p[1] << ", " << p[2] - << ", " << p[3] << "), /* " << i << " */\n"; - break; - - default: - out << " vertex(), /* error */\n"; - } - } - } - out << "};\n\n"; - } - - if (_uvs) { - out << "/* UV's for " << vpool->get_name() << " */\n" - << "uv uvs_" << vpool->get_name() << "[" << highest_index - << "] = {\n"; - for (i = 0; i < highest_index; i++) { - EggVertex *vert = vpool->get_vertex(i); - if (vert == nullptr || !vert->has_uv()) { - out << " uv(), /* " << i << " */\n"; - } else { - LTexCoordd uv = vert->get_uv(); - out << " uv(" << uv[0] << ", " << uv[1] - << "), /* " << i << " */\n"; - } - } - out << "};\n\n"; - } - - if (_vertex_normals) { - out << "/* Vertex normals for " << vpool->get_name() << " */\n" - << "normal normals_" << vpool->get_name() << "[" << highest_index - << "] = {\n"; - for (i = 0; i < highest_index; i++) { - EggVertex *vert = vpool->get_vertex(i); - if (vert == nullptr || !vert->has_normal()) { - out << " normal(), /* " << i << " */\n"; - } else { - LNormald n = vert->get_normal(); - out << " normal(" << n[0] << ", " << n[1] << ", " << n[2] - << "), /* " << i << " */\n"; - } - } - out << "};\n\n"; - } - - if (_vertex_colors) { - out << "/* Vertex colors for " << vpool->get_name() << " */\n" - << "color colors_" << vpool->get_name() << "[" << highest_index - << "] = {\n"; - for (i = 0; i < highest_index; i++) { - EggVertex *vert = vpool->get_vertex(i); - if (vert == nullptr || !vert->has_color()) { - out << " color(), /* " << i << " */\n"; - } else { - LColor c = vert->get_color(); - out << " color(" << c[0] << ", " << c[1] << ", " << c[2] - << ", " << c[3] << "), /* " << i << " */\n"; - } - } - out << "};\n\n"; - } -} - - -/** - * - */ -void EggToC:: -write_bin(EggBin *bin) { - ostream &out = get_output(); - string bin_name = bin->get_name(); - if (bin_name.empty()) { - bin_name = format_string(_next_bin_index); - _next_bin_index++; - } - - out << "/* Polygon group " << bin_name << " */\n"; - - size_t num_children = bin->size(); - - if (_polygons) { - out << "/* Polygon definitions for " << bin_name << " */\n"; - string prim_type = "polygon"; - if (_triangulate_polygons) { - prim_type = "triangle"; - } - - out << prim_type << " polys_" << bin_name << "[" << num_children - << "] = {\n"; - - if (_triangulate_polygons) { - out << " /* vpool index, vertex0, vertex1, vertex2 */\n"; - } else { - out << " /* vpool index, num vertices, vertex0, vertex1, vertex2, ... */\n"; - } - - EggGroupNode::const_iterator ci; - size_t prim_index = 0; - for (ci = bin->begin(); ci != bin->end(); ++ci) { - EggNode *child = (*ci); - if (!child->is_of_type(EggPrimitive::get_class_type())) { - out << " " << prim_type << "(), /* error */\n"; - } else { - EggPrimitive *prim = DCAST(EggPrimitive, child); - EggVertexPool *vpool = prim->get_pool(); - int vpool_index = -1; - VertexPools::const_iterator pi = _vertex_pools.find(vpool); - if (pi != _vertex_pools.end()) { - vpool_index = (*pi).second; - } - - out << " " << prim_type << "(" << vpool_index; - if (!_triangulate_polygons) { - out << ", " << prim->size(); - } - EggPrimitive::const_iterator vi; - for (vi = prim->begin(); vi != prim->end(); ++vi) { - EggVertex *vert = (*vi); - out << ", " << vert->get_index(); - } - out << "), /* " << prim_index << " */\n"; - prim_index++; - } - } - out << "};\n\n"; - } - - if (_polygon_normals) { - ostream &out = get_output(); - out << "/* Polygon normals for " << bin_name << " */\n"; - out << "normal polys_" << bin_name << "[" << num_children - << "] = {\n"; - - EggGroupNode::const_iterator ci; - size_t prim_index = 0; - for (ci = bin->begin(); ci != bin->end(); ++ci) { - EggNode *child = (*ci); - if (!child->is_of_type(EggPrimitive::get_class_type())) { - out << " normal(), /* error */\n"; - } else { - EggPrimitive *prim = DCAST(EggPrimitive, child); - if (!prim->has_normal()) { - out << " normal(), /* " << prim_index << " */\n"; - } else { - LNormald n = prim->get_normal(); - out << " normal(" << n[0] << ", " << n[1] << ", " << n[2] - << "), /* " << prim_index << " */\n"; - } - prim_index++; - } - } - out << "};\n\n"; - } - - if (_polygon_colors) { - ostream &out = get_output(); - out << "/* Polygon colors for " << bin_name << " */\n"; - out << "color polys_" << bin_name << "[" << num_children - << "] = {\n"; - - EggGroupNode::const_iterator ci; - size_t prim_index = 0; - for (ci = bin->begin(); ci != bin->end(); ++ci) { - EggNode *child = (*ci); - if (!child->is_of_type(EggPrimitive::get_class_type())) { - out << " color(), /* error */\n"; - } else { - EggPrimitive *prim = DCAST(EggPrimitive, child); - if (!prim->has_color()) { - out << " color(), /* " << prim_index << " */\n"; - } else { - LColor c = prim->get_color(); - out << " color(" << c[0] << ", " << c[1] << ", " << c[2] - << ", " << c[3] << "), /* " << prim_index << " */\n"; - } - prim_index++; - } - } - out << "};\n\n"; - } -} - - -int main(int argc, char *argv[]) { - EggToC prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggToC.h b/pandatool/src/eggprogs/eggToC.h deleted file mode 100644 index 9c5f328f..00000000 --- a/pandatool/src/eggprogs/eggToC.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToC.h - * @author drose - * @date 2001-08-03 - */ - -#ifndef EGGTOC_H -#define EGGTOC_H - -#include "pandatoolbase.h" - -#include "eggToSomething.h" - -#include "pmap.h" - -class EggNode; -class EggVertexPool; -class EggBin; - -/** - * - */ -class EggToC : public EggToSomething { -public: - EggToC(); - - void run(); - - void traverse(EggNode *node); - void write_vertex_pool(EggVertexPool *vpool); - void write_bin(EggBin *bin); - - bool _vertices; - bool _uvs; - bool _vertex_normals; - bool _vertex_colors; - bool _polygons; - bool _polygon_normals; - bool _polygon_colors; - - bool _triangulate_polygons; - - typedef pmap VertexPools; - VertexPools _vertex_pools; - int _next_vpool_index; - int _next_bin_index; -}; - -#endif diff --git a/pandatool/src/eggprogs/eggTopstrip.cxx b/pandatool/src/eggprogs/eggTopstrip.cxx deleted file mode 100644 index 2a46431f..00000000 --- a/pandatool/src/eggprogs/eggTopstrip.cxx +++ /dev/null @@ -1,349 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggTopstrip.cxx - * @author drose - * @date 2001-02-23 - */ - -#include "eggTopstrip.h" - -#include "dcast.h" -#include "eggJointData.h" -#include "eggCharacterCollection.h" -#include "eggCharacterData.h" -#include "eggCharacterDb.h" -#include "eggJointPointer.h" -#include "eggTable.h" -#include "compose_matrix.h" - -/** - * - */ -EggTopstrip:: -EggTopstrip() { - add_path_replace_options(); - add_path_store_options(); - - set_program_brief("unapplies animation from a joint in an .egg file"); - set_program_description - ("egg-topstrip reads a character model and its associated animation " - "files, and unapplies the animation from one of the top joints. " - "This effectively freezes that particular joint, and makes the rest " - "of the character relative to that joint.\n\n" - - "This is a particularly useful thing to do to generate character " - "models that can stack one on top of the other in a sensible way."); - - add_option - ("t", "name", 0, - "Specify the name of the 'top' joint, from which to draw the " - "animation channels which will be applied to the entire animation.", - &EggTopstrip::dispatch_string, nullptr, &_top_joint_name); - - add_option - ("i", "", 0, - "Invert the matrix before applying. This causes a subtractive " - "effect. This is the default unless -r is specified.", - &EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform); - - add_option - ("n", "", 0, - "Do not invert the matrix before applying. This causes an " - "additive effect.", - &EggTopstrip::dispatch_false, &_got_invert_transform, &_invert_transform); - - add_option - ("s", "[ijkphrxyz]", 0, - "Specify the components of the transform that are to be applied. Use " - "any combination of the nine token letters: i, j, k represent the " - "three scale axes; h, p, r represent rotation; and x, y, z represent " - "translation. The default is everything: -s ijkphrxyz.", - &EggTopstrip::dispatch_string, nullptr, &_transform_channels); - - add_option - ("r", "file.egg", 0, - "Read the animation channel from the indicated egg file. If this " - "is not specified, each egg file will supply its own animation channel.", - &EggTopstrip::dispatch_filename, nullptr, &_channel_filename); - - _invert_transform = true; - _transform_channels = "ijkphrxyz"; -} - -/** - * - */ -void EggTopstrip:: -run() { - nassertv(_collection != nullptr); - nassertv(_collection->get_num_eggs() > 0); - - check_transform_channels(); - - // Get the number of characters first, in case adding the _channel_egg - // changes this. - int num_characters = _collection->get_num_characters(); - - // Determine which model and character we'll be pulling the animation - // channels from. - int from_model = -1; - - if (!_channel_filename.empty()) { - // Read in the extra egg file that we use for extracting the channels out. - PT(EggData) channel_egg = read_egg(_channel_filename); - if (channel_egg == nullptr) { - nout << "Cannot read " << _channel_filename << "\n"; - exit(1); - } - int channel_egg_index = _collection->add_egg(channel_egg); - if (channel_egg_index < 0) { - nout << _channel_filename - << " does not contain a character model or animation channel.\n"; - exit(1); - } - - from_model = _collection->get_first_model_index(channel_egg_index); - - if (!_got_invert_transform) { - // With -r, the default is not to invert the transform. - _invert_transform = false; - } - } - - // Now process each character. - EggCharacterDb db; - - int ci; - for (ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - nout << "Processing " << char_data->get_name() << "\n"; - - EggJointData *root_joint = char_data->get_root_joint(); - - // We'll read the transform to apply from this character, which will be - // the same character unless -r was specified. - EggCharacterData *from_char = char_data; - if (from_model != -1) { - from_char = _collection->get_character_by_model_index(from_model); - } - - // Determine which joint we'll use to extract the transform to apply. - EggJointData *top_joint = nullptr; - if (_top_joint_name.empty()) { - // The default top joint name is the alphabetically first joint in the - // top level. - if (root_joint->get_num_children() == 0) { - nout << "Character " << from_char->get_name() << " has no joints.\n"; - exit(1); - } - top_joint = root_joint->get_child(0); - } else { - top_joint = from_char->find_joint(_top_joint_name); - if (top_joint == nullptr) { - nout << "Character " << from_char->get_name() - << " has no joint named " << _top_joint_name << "\n"; - exit(1); - } - } - - // First, transform all the joints. - int num_children = root_joint->get_num_children(); - for (int i = 0; i < num_children; i++) { - EggJointData *joint_data = root_joint->get_child(i); - strip_anim(char_data, joint_data, from_model, from_char, top_joint, db); - } - - // We also need to transform the vertices for any models involved here. - int num_models = char_data->get_num_models(); - for (int m = 0; m < num_models; m++) { - EggNode *node = char_data->get_model_root(m); - if (!node->is_of_type(EggTable::get_class_type())) { - strip_anim_vertices(node, char_data->get_model_index(m), - from_model, top_joint, db); - } - } - } - - // Now, trigger the actual rebuilding of all the joint data. - for (ci = 0; ci < num_characters; ci++) { - EggCharacterData *char_data = _collection->get_character(ci); - char_data->get_root_joint()->do_rebuild_all(db); - } - - write_eggs(); -} - -/** - * Checks the _transform_channels string to ensure that it contains only the - * expected nine letters, or a subset. - */ -void EggTopstrip:: -check_transform_channels() { - static std::string expected = "ijkphrxyz"; - static const int num_channels = 9; - bool has_each[num_channels]; - memset(has_each, 0, num_channels * sizeof(bool)); - - for (size_t p = 0; p < _transform_channels.size(); p++) { - int i = expected.find(_transform_channels[p]); - if (i == (int)std::string::npos) { - nout << "Invalid letter for -s: " << _transform_channels[p] << "\n"; - exit(1); - } - nassertv(i < num_channels); - has_each[i] = true; - } - - _transform_channels = ""; - for (int i = 0; i < num_channels; i++) { - if (has_each[i]) { - _transform_channels += expected[i]; - } - } - - if (_transform_channels.empty()) { - nout << "No transform specified for -s.\n"; - exit(1); - } -} - - -/** - * Applies the channels from joint _top_joint in model from_model to the joint - * referenced by joint_data. - */ -void EggTopstrip:: -strip_anim(EggCharacterData *char_data, EggJointData *joint_data, - int from_model, EggCharacterData *from_char, - EggJointData *top_joint, EggCharacterDb &db) { - int num_models = joint_data->get_num_models(); - for (int i = 0; i < num_models; i++) { - int model = (from_model < 0) ? i : from_model; - if (joint_data->has_model(i)) { - if (!top_joint->has_model(model)) { - nout << "Warning: Joint " << top_joint->get_name() - << " is not defined in all models.\n"; - return; - } - - int num_into_frames = char_data->get_num_frames(i); - int num_from_frames = from_char->get_num_frames(model); - - int num_frames = std::max(num_into_frames, num_from_frames); - - EggBackPointer *back = joint_data->get_model(i); - nassertv(back != nullptr); - EggJointPointer *joint; - DCAST_INTO_V(joint, back); - - // Compute and apply the new transforms. - - int f; - for (f = 0; f < num_frames; f++) { - LMatrix4d into = joint_data->get_frame(i, f % num_into_frames); - LMatrix4d from = top_joint->get_net_frame(model, f % num_from_frames, db); - - adjust_transform(from); - - db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, - f, into * from); - } - } - } -} - -/** - * Applies the channels from joint _top_joint in model from_model to the - * vertices at egg_node. - */ -void EggTopstrip:: -strip_anim_vertices(EggNode *egg_node, int into_model, int from_model, - EggJointData *top_joint, EggCharacterDb &db) { - int model = (from_model < 0) ? into_model : from_model; - if (!top_joint->has_model(model)) { - nout << "Warning: Joint " << top_joint->get_name() - << " is not defined in all models.\n"; - return; - } - - LMatrix4d from = top_joint->get_net_frame(model, 0, db); - adjust_transform(from); - - egg_node->transform_vertices_only(from); -} - - -/** - * Adjust the transform extracted from the "top" joint according to the -s and - * -i/-n options, prior to applying it to the skeleton. - */ -void EggTopstrip:: -adjust_transform(LMatrix4d &mat) const { - if (_transform_channels.length() != 9) { - // Decompose and recompose the matrix, so we can eliminate the parts the - // user doesn't want. - - LVecBase3d scale, hpr, translate; - bool result = decompose_matrix(mat, scale, hpr, translate, _coordinate_system); - if (!result) { - nout << "Warning: skew transform in animation.\n"; - } else { - LVecBase3d new_scale(1.0, 1.0, 1.0); - LVecBase3d new_hpr(0.0, 0.0, 0.0); - LVecBase3d new_translate(0.0, 0.0, 0.0); - - for (size_t i = 0; i < _transform_channels.size(); i++) { - switch (_transform_channels[i]) { - case 'i': - new_scale[0] = scale[0]; - break; - case 'j': - new_scale[1] = scale[1]; - break; - case 'k': - new_scale[2] = scale[2]; - break; - - case 'h': - new_hpr[0] = hpr[0]; - break; - case 'p': - new_hpr[1] = hpr[1]; - break; - case 'r': - new_hpr[2] = hpr[2]; - break; - - case 'x': - new_translate[0] = translate[0]; - break; - case 'y': - new_translate[1] = translate[1]; - break; - case 'z': - new_translate[2] = translate[2]; - break; - } - } - - compose_matrix(mat, new_scale, new_hpr, new_translate, _coordinate_system); - } - } - if (_invert_transform) { - mat.invert_in_place(); - } -} - - -int main(int argc, char *argv[]) { - EggTopstrip prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggTopstrip.h b/pandatool/src/eggprogs/eggTopstrip.h deleted file mode 100644 index 8e04b7e0..00000000 --- a/pandatool/src/eggprogs/eggTopstrip.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggTopstrip.h - * @author drose - * @date 2001-02-23 - */ - -#ifndef EGGTOPSTRIP_H -#define EGGTOPSTRIP_H - -#include "pandatoolbase.h" - -#include "eggCharacterFilter.h" -#include "luse.h" - -#include "pvector.h" - -class EggCharacterData; -class EggCharacterDb; -class EggJointData; -class EggJointPointer; - -/** - * Reads a character model and/or animations and strips out the animation from - * one of the top joints from the entire character. Particularly useful for - * generating stackable character models from separately-extracted characters. - */ -class EggTopstrip : public EggCharacterFilter { -public: - EggTopstrip(); - - void run(); - void check_transform_channels(); - - void strip_anim(EggCharacterData *char_data, EggJointData *joint_data, - int from_model, EggCharacterData *from_char, - EggJointData *top_joint, EggCharacterDb &db); - void strip_anim_vertices(EggNode *egg_node, int into_model, - int from_model, EggJointData *top_joint, - EggCharacterDb &db); - - void adjust_transform(LMatrix4d &mat) const; - - - std::string _top_joint_name; - bool _got_invert_transform; - bool _invert_transform; - std::string _transform_channels; - Filename _channel_filename; -}; - -#endif diff --git a/pandatool/src/eggprogs/eggTrans.cxx b/pandatool/src/eggprogs/eggTrans.cxx deleted file mode 100644 index 28d439e6..00000000 --- a/pandatool/src/eggprogs/eggTrans.cxx +++ /dev/null @@ -1,137 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggTrans.cxx - * @author drose - * @date 2000-02-14 - */ - -#include "eggTrans.h" -#include "eggGroupUniquifier.h" - -/** - * - */ -EggTrans:: -EggTrans() { - add_path_replace_options(); - add_path_store_options(); - add_normals_options(); - add_transform_options(); - add_texture_options(); - add_delod_options(); - - set_program_brief("apply transformations and optimizations to an .egg file"); - set_program_description - ("egg-trans reads an egg file and writes an essentially equivalent " - "egg file to the standard output, or to the file specified with -o. " - "Some simple operations on the egg file are supported."); - - add_option - ("F", "", 0, - "Flatten out transforms.", - &EggTrans::dispatch_none, &_flatten_transforms); - - add_option - ("t", "", 0, - "Apply texture matrices to UV's.", - &EggTrans::dispatch_none, &_apply_texmats); - - add_option - ("T", "", 0, - "Collapse equivalent texture references.", - &EggTrans::dispatch_none, &_collapse_equivalent_textures); - - add_option - ("c", "", 0, - "Clean out degenerate polygons and unused vertices.", - &EggTrans::dispatch_none, &_remove_invalid_primitives); - - add_option - ("C", "", 0, - "Clean out higher-order polygons by subdividing into triangles.", - &EggTrans::dispatch_none, &_triangulate_polygons); - - add_option - ("mesh", "", 0, - "Mesh triangles into triangle strips. This is mainly useful as a " - "tool to visualize the work that the mesher will do, since triangles " - "are automatically meshed whenever an egg file is loaded. Note that, " - "unlike the automatic meshing at load time, you are must ensure that " - "you do not start out with multiple triangles with different attributes " - "(e.g. texture) together in the same group.", - &EggTrans::dispatch_none, &_mesh_triangles); - - add_option - ("N", "", 0, - "Standardize and uniquify group names.", - &EggTrans::dispatch_none, &_standardize_names); - -} - -/** - * - */ -void EggTrans:: -run() { - if (_remove_invalid_primitives) { - nout << "Removing invalid primitives.\n"; - int num_removed = _data->remove_invalid_primitives(true); - nout << " (" << num_removed << " removed.)\n"; - _data->remove_unused_vertices(true); - } - - if (_triangulate_polygons) { - nout << "Triangulating polygons.\n"; - int num_produced = _data->triangulate_polygons(~0); - nout << " (" << num_produced << " triangles produced.)\n"; - } - - if (_mesh_triangles) { - nout << "Meshing triangles.\n"; - _data->mesh_triangles(~0); - } - - if (_apply_texmats) { - nout << "Applying texture matrices.\n"; - _data->apply_texmats(); - _data->remove_unused_vertices(true); - } - - if (_collapse_equivalent_textures) { - nout << "Collapsing equivalent textures.\n"; - int num_removed = _data->collapse_equivalent_textures(); - nout << " (" << num_removed << " removed.)\n"; - } - - if (_flatten_transforms) { - nout << "Flattening transforms.\n"; - _data->flatten_transforms(); - _data->remove_unused_vertices(true); - } - - if (_standardize_names) { - nout << "Standardizing group names.\n"; - EggGroupUniquifier uniquifier; - uniquifier.uniquify(_data); - } - - if (!do_reader_options()) { - exit(1); - } - - write_egg_file(); -} - - -int main(int argc, char *argv[]) { - EggTrans prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/eggprogs/eggTrans.h b/pandatool/src/eggprogs/eggTrans.h deleted file mode 100644 index 350ece14..00000000 --- a/pandatool/src/eggprogs/eggTrans.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggTrans.h - * @author drose - * @date 2000-02-14 - */ - -#ifndef EGGTRANS_H -#define EGGTRANS_H - -#include "pandatoolbase.h" - -#include "eggFilter.h" - -/** - * A program to read an egg file and write an equivalent egg file, possibly - * performing some minor operations along the way. - */ -class EggTrans : public EggFilter { -public: - EggTrans(); - - void run(); - - bool _flatten_transforms; - bool _apply_texmats; - bool _collapse_equivalent_textures; - bool _remove_invalid_primitives; - bool _triangulate_polygons; - bool _mesh_triangles; - bool _standardize_names; -}; - -#endif diff --git a/pandatool/src/flt/CMakeLists.txt b/pandatool/src/flt/CMakeLists.txt deleted file mode 100644 index 02f096b8..00000000 --- a/pandatool/src/flt/CMakeLists.txt +++ /dev/null @@ -1,90 +0,0 @@ -set(P3FLT_HEADERS - config_flt.h - fltBead.h - fltBeadID.h - fltCurve.h fltCurve.I - fltError.h - fltExternalReference.h - fltEyepoint.h - fltFace.h fltFace.I - fltGeometry.h fltGeometry.I - fltGroup.h - fltHeader.h - fltInstanceDefinition.h - fltInstanceRef.h - fltLightSourceDefinition.h - fltLocalVertexPool.h fltLocalVertexPool.I - fltLOD.h - fltMaterial.h - fltMesh.h fltMesh.I - fltMeshPrimitive.h fltMeshPrimitive.I - fltObject.h - fltOpcode.h - fltPackedColor.h fltPackedColor.I - fltRecord.h fltRecord.I - fltRecordReader.h - fltRecordWriter.h - fltTexture.h - fltTrackplane.h - fltTransformGeneralMatrix.h - fltTransformPut.h - fltTransformRecord.h - fltTransformRotateAboutEdge.h - fltTransformRotateAboutPoint.h - fltTransformRotateScale.h - fltTransformScale.h - fltTransformTranslate.h - fltUnsupportedRecord.h - fltVectorRecord.h - fltVertex.h fltVertex.I - fltVertexList.h -) - -set(P3FLT_SOURCES - config_flt.cxx - fltBead.cxx - fltBeadID.cxx - fltCurve.cxx - fltError.cxx - fltExternalReference.cxx - fltEyepoint.cxx - fltFace.cxx - fltGeometry.cxx - fltGroup.cxx - fltHeader.cxx - fltInstanceDefinition.cxx - fltInstanceRef.cxx - fltLightSourceDefinition.cxx - fltLocalVertexPool.cxx - fltLOD.cxx - fltMaterial.cxx - fltMesh.cxx - fltMeshPrimitive.cxx - fltObject.cxx - fltOpcode.cxx - fltPackedColor.cxx - fltRecord.cxx - fltRecordReader.cxx - fltRecordWriter.cxx - fltTexture.cxx - fltTrackplane.cxx - fltTransformGeneralMatrix.cxx - fltTransformPut.cxx - fltTransformRecord.cxx - fltTransformRotateAboutEdge.cxx - fltTransformRotateAboutPoint.cxx - fltTransformRotateScale.cxx - fltTransformScale.cxx - fltTransformTranslate.cxx - fltUnsupportedRecord.cxx - fltVectorRecord.cxx - fltVertex.cxx - fltVertexList.cxx -) - -composite_sources(p3flt P3FLT_SOURCES) -add_library(p3flt STATIC ${P3FLT_HEADERS} ${P3FLT_SOURCES}) -target_link_libraries(p3flt p3pandatoolbase panda) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/flt/config_flt.cxx b/pandatool/src/flt/config_flt.cxx deleted file mode 100644 index 1e4f0f9d..00000000 --- a/pandatool/src/flt/config_flt.cxx +++ /dev/null @@ -1,112 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_flt.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "config_flt.h" -#include "fltRecord.h" -#include "fltBead.h" -#include "fltBeadID.h" -#include "fltGroup.h" -#include "fltObject.h" -#include "fltGeometry.h" -#include "fltFace.h" -#include "fltCurve.h" -#include "fltMesh.h" -#include "fltLocalVertexPool.h" -#include "fltMeshPrimitive.h" -#include "fltVectorRecord.h" -#include "fltVertexList.h" -#include "fltLOD.h" -#include "fltInstanceDefinition.h" -#include "fltInstanceRef.h" -#include "fltHeader.h" -#include "fltVertex.h" -#include "fltMaterial.h" -#include "fltTexture.h" -#include "fltLightSourceDefinition.h" -#include "fltUnsupportedRecord.h" -#include "fltTransformRecord.h" -#include "fltTransformGeneralMatrix.h" -#include "fltTransformPut.h" -#include "fltTransformRotateAboutEdge.h" -#include "fltTransformRotateAboutPoint.h" -#include "fltTransformScale.h" -#include "fltTransformTranslate.h" -#include "fltTransformRotateScale.h" -#include "fltExternalReference.h" - -#include "dconfig.h" - -Configure(config_flt); -NotifyCategoryDef(flt, ""); - - -ConfigVariableBool flt_error_abort -("flt-error-abort", false, - PRC_DESC("Set this true to trigger an assertion failure (and core dump) " - "immediately when an error is detected on reading or writing a flt " - "file. This is primarily useful for debugging the flt reader itself, " - "to generate a stack trace to determine precisely at what point a flt " - - "file failed.")); - - -ConfigureFn(config_flt) { - init_libflt(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libflt() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - FltRecord::init_type(); - FltBead::init_type(); - FltBeadID::init_type(); - FltGroup::init_type(); - FltObject::init_type(); - FltGeometry::init_type(); - FltFace::init_type(); - FltCurve::init_type(); - FltMesh::init_type(); - FltLocalVertexPool::init_type(); - FltMeshPrimitive::init_type(); - FltVectorRecord::init_type(); - FltVertexList::init_type(); - FltLOD::init_type(); - FltInstanceDefinition::init_type(); - FltInstanceRef::init_type(); - FltHeader::init_type(); - FltVertex::init_type(); - FltMaterial::init_type(); - FltTexture::init_type(); - FltLightSourceDefinition::init_type(); - FltUnsupportedRecord::init_type(); - FltTransformRecord::init_type(); - FltTransformGeneralMatrix::init_type(); - FltTransformPut::init_type(); - FltTransformRotateAboutEdge::init_type(); - FltTransformRotateAboutPoint::init_type(); - FltTransformScale::init_type(); - FltTransformTranslate::init_type(); - FltTransformRotateScale::init_type(); - FltExternalReference::init_type(); -} diff --git a/pandatool/src/flt/config_flt.h b/pandatool/src/flt/config_flt.h deleted file mode 100644 index 789179ce..00000000 --- a/pandatool/src/flt/config_flt.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_flt.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef CONFIG_FLT_H -#define CONFIG_FLT_H - -#include "pandatoolbase.h" - -#include "notifyCategoryProxy.h" -#include "configVariableBool.h" - -NotifyCategoryDeclNoExport(flt); - -extern ConfigVariableBool flt_error_abort; - -extern void init_libflt(); - -static const int header_size = 4; - -#endif diff --git a/pandatool/src/flt/fltBead.cxx b/pandatool/src/flt/fltBead.cxx deleted file mode 100644 index 8cc21f8c..00000000 --- a/pandatool/src/flt/fltBead.cxx +++ /dev/null @@ -1,357 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltBead.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltBead.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltTransformGeneralMatrix.h" -#include "fltTransformPut.h" -#include "fltTransformRotateAboutEdge.h" -#include "fltTransformRotateAboutPoint.h" -#include "fltTransformScale.h" -#include "fltTransformTranslate.h" -#include "fltTransformRotateScale.h" -#include "config_flt.h" - -#include "dcast.h" - -#include - -TypeHandle FltBead::_type_handle; - -/** - * - */ -FltBead:: -FltBead(FltHeader *header) : FltRecord(header) { - _has_transform = false; - _transform = LMatrix4d::ident_mat(); - _replicate_count = 0; -} - -/** - * Returns true if the bead has been transformed, false otherwise. If this - * returns true, get_transform() will return the single-precision net - * transformation, and get_num_transform_steps() will return nonzero. - */ -bool FltBead:: -has_transform() const { - return _has_transform; -} - -/** - * Returns the single-precision 4x4 matrix that represents the transform - * applied to this bead, or the identity matrix if the bead has not been - * transformed. - */ -const LMatrix4d &FltBead:: -get_transform() const { - return _has_transform ? _transform : LMatrix4d::ident_mat(); -} - -/** - * Replaces the transform matrix on this bead. This implicitly removes all of - * the transform steps added previously, and replaces them with a single 4x4 - * general matrix transform step. - */ -void FltBead:: -set_transform(const LMatrix4d &mat) { - clear_transform(); - FltTransformGeneralMatrix *step = new FltTransformGeneralMatrix(_header); - step->set_matrix(mat); - add_transform_step(step); -} - -/** - * Removes any transform matrix and all transform steps on this bead. - */ -void FltBead:: -clear_transform() { - _has_transform = false; - _transform = LMatrix4d::ident_mat(); - _transform_steps.clear(); -} - -/** - * Returns the number of individual steps that define the net transform on - * this bead as returned by set_transform(). Each step is a single - * transformation; the concatenation of all transformations will produce the - * matrix represented by set_transform(). - */ -int FltBead:: -get_num_transform_steps() const { - return _transform_steps.size(); -} - -/** - * Returns the nth individual step that defines the net transform on this - * bead. See get_num_transform_steps(). - */ -FltTransformRecord *FltBead:: -get_transform_step(int n) { - nassertr(n >= 0 && n < (int)_transform_steps.size(), - nullptr); - return _transform_steps[n]; -} - -/** - * Returns the nth individual step that defines the net transform on this - * bead. See get_num_transform_steps(). - */ -const FltTransformRecord *FltBead:: -get_transform_step(int n) const { - nassertr(n >= 0 && n < (int)_transform_steps.size(), - nullptr); - return _transform_steps[n]; -} - -/** - * Applies the indicated transform step to the net transformation applied to - * the bead. - */ -void FltBead:: -add_transform_step(FltTransformRecord *record) { - if (!_has_transform) { - _has_transform = true; - _transform = record->get_matrix(); - } else { - _transform = record->get_matrix() * _transform; - } - _transform_steps.push_back(record); -} - -/** - * Returns the replicate count of this bead. If this is nonzero, it means - * that the bead is implicitly copied this number of additional times (for - * replicate_count + 1 total copies), applying the transform on this bead for - * each copy. In this case, the transform does *not* apply to the initial - * copy of the bead. - */ -int FltBead:: -get_replicate_count() const { - return _replicate_count; -} - -/** - * Changes the replicate count of this bead. If you are setting the replicate - * count to some nonzero number, you must also set a transform on the bead. - * See set_replicate_count(). - */ -void FltBead:: -set_replicate_count(int count) { - _replicate_count = count; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltBead:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - return true; -} - -/** - * Checks whether the given bead, which follows this bead sequentially in the - * file, is an ancillary record of this bead. If it is, extracts the relevant - * information and returns true; otherwise, leaves it alone and returns false. - */ -bool FltBead:: -extract_ancillary(FltRecordReader &reader) { - FltTransformRecord *step = nullptr; - - switch (reader.get_opcode()) { - case FO_transform_matrix: - return extract_transform_matrix(reader); - - case FO_general_matrix: - step = new FltTransformGeneralMatrix(_header); - break; - - case FO_put: - step = new FltTransformPut(_header); - break; - - case FO_rotate_about_edge: - step = new FltTransformRotateAboutEdge(_header); - break; - - case FO_rotate_about_point: - step = new FltTransformRotateAboutPoint(_header); - break; - - case FO_scale: - step = new FltTransformScale(_header); - break; - - case FO_translate: - step = new FltTransformTranslate(_header); - break; - - case FO_rotate_and_scale: - step = new FltTransformRotateScale(_header); - break; - - case FO_replicate: - return extract_replicate_count(reader); - - default: - return FltRecord::extract_ancillary(reader); - } - - // A transform step. - nassertr(step != nullptr, false); - if (!step->extract_record(reader)) { - return false; - } - _transform_steps.push_back(DCAST(FltTransformRecord, step)); - - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltBead:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - return true; -} - -/** - * Writes whatever ancillary records are required for this record. Returns - * FE_ok on success, or something else if there is some error. - */ -FltError FltBead:: -write_ancillary(FltRecordWriter &writer) const { - if (_has_transform) { - FltError result = write_transform(writer); - if (result != FE_ok) { - return result; - } - } - if (_replicate_count != 0) { - FltError result = write_replicate_count(writer); - if (result != FE_ok) { - return result; - } - } - - - return FltRecord::write_ancillary(writer); -} - -/** - * Reads a transform matrix ancillary bead. This defines the net - * transformation that has been applied to the bead, and precedes the set of - * individual transform steps that define how this net transform was computed. - */ -bool FltBead:: -extract_transform_matrix(FltRecordReader &reader) { - nassertr(reader.get_opcode() == FO_transform_matrix, false); - DatagramIterator &iterator = reader.get_iterator(); - - LMatrix4d matrix; - for (int r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - matrix(r, c) = iterator.get_be_float32(); - } - } - check_remaining_size(iterator); - - _transform_steps.clear(); - _has_transform = true; - _transform = matrix; - - return true; -} - -/** - * Reads a replicate count ancillary bead. - */ -bool FltBead:: -extract_replicate_count(FltRecordReader &reader) { - nassertr(reader.get_opcode() == FO_replicate, false); - DatagramIterator &iterator = reader.get_iterator(); - - _replicate_count = iterator.get_be_int16(); - iterator.skip_bytes(2); - - check_remaining_size(iterator); - return true; -} - -/** - * Writes out the transformation and all of its defining steps. - */ -FltError FltBead:: -write_transform(FltRecordWriter &writer) const { - // First, write out the initial transform indication. - writer.set_opcode(FO_transform_matrix); - Datagram &datagram = writer.update_datagram(); - - for (int r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - datagram.add_be_float32(_transform(r, c)); - } - } - - FltError result = writer.advance(); - if (result != FE_ok) { - return result; - } - - // Now, write out each of the steps of the transform. - Transforms::const_iterator ti; - for (ti = _transform_steps.begin(); ti != _transform_steps.end(); ++ti) { - if (!(*ti)->build_record(writer)) { - assert(!flt_error_abort); - return FE_invalid_record; - } - FltError result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - return FE_ok; -} - -/** - * Writes out the replicate count, if needed. - */ -FltError FltBead:: -write_replicate_count(FltRecordWriter &writer) const { - if (_replicate_count != 0) { - writer.set_opcode(FO_replicate); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int16(_replicate_count); - datagram.pad_bytes(2); - - FltError result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - return FE_ok; -} diff --git a/pandatool/src/flt/fltBead.h b/pandatool/src/flt/fltBead.h deleted file mode 100644 index d1b98779..00000000 --- a/pandatool/src/flt/fltBead.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltBead.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTBEAD_H -#define FLTBEAD_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" -#include "fltTransformRecord.h" - -#include "luse.h" - -/** - * A base class for any of a broad family of flt records that represent - * particular beads in the hierarchy. These are things like group beads and - * object beads, as opposed to things like push and pop or comment records. - */ -class FltBead : public FltRecord { -public: - FltBead(FltHeader *header); - - bool has_transform() const; - const LMatrix4d &get_transform() const; - void set_transform(const LMatrix4d &mat); - void clear_transform(); - - int get_num_transform_steps() const; - FltTransformRecord *get_transform_step(int n); - const FltTransformRecord *get_transform_step(int n) const; - void add_transform_step(FltTransformRecord *record); - - int get_replicate_count() const; - void set_replicate_count(int count); - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool extract_ancillary(FltRecordReader &reader); - - virtual bool build_record(FltRecordWriter &writer) const; - virtual FltError write_ancillary(FltRecordWriter &writer) const; - -private: - bool extract_transform_matrix(FltRecordReader &reader); - bool extract_replicate_count(FltRecordReader &reader); - - FltError write_transform(FltRecordWriter &writer) const; - FltError write_replicate_count(FltRecordWriter &writer) const; - -private: - bool _has_transform; - LMatrix4d _transform; - - typedef pvector Transforms; - Transforms _transform_steps; - - int _replicate_count; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltBead", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltBeadID.cxx b/pandatool/src/flt/fltBeadID.cxx deleted file mode 100644 index 4b6dc695..00000000 --- a/pandatool/src/flt/fltBeadID.cxx +++ /dev/null @@ -1,124 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltBeadID.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltBeadID.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltBeadID::_type_handle; - -/** - * - */ -FltBeadID:: -FltBeadID(FltHeader *header) : FltBead(header) { -} - -/** - * Returns the id (name) of this particular bead. Each MultiGen bead will - * have a unique name. - */ -const std::string &FltBeadID:: -get_id() const { - return _id; -} - -/** - * Changes the id (name) of this particular bead. This should be a name that - * is unique to this bead. - */ -void FltBeadID:: -set_id(const std::string &id) { - _id = id; -} - -/** - * Writes a quick one-line description of the record, but not its children. - * This is a human-readable description, primarily for debugging; to write a - * flt file, use FltHeader::write_flt(). - */ -void FltBeadID:: -output(std::ostream &out) const { - out << get_type(); - if (!_id.empty()) { - out << " " << _id; - } -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltBeadID:: -extract_record(FltRecordReader &reader) { - if (!FltBead::extract_record(reader)) { - return false; - } - - _id = reader.get_iterator().get_fixed_string(8); - return true; -} - -/** - * Checks whether the given bead, which follows this bead sequentially in the - * file, is an ancillary record of this bead. If it is, extracts the relevant - * information and returns true; otherwise, leaves it alone and returns false. - */ -bool FltBeadID:: -extract_ancillary(FltRecordReader &reader) { - if (reader.get_opcode() == FO_long_id) { - DatagramIterator &di = reader.get_iterator(); - _id = di.get_fixed_string(di.get_remaining_size()); - return true; - } - - return FltBead::extract_ancillary(reader); -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltBeadID:: -build_record(FltRecordWriter &writer) const { - if (!FltBead::build_record(writer)) { - return false; - } - - writer.update_datagram().add_fixed_string(_id.substr(0, 7), 8); - return true; -} - -/** - * Writes whatever ancillary records are required for this record. Returns - * FE_ok on success, or something else if there is some error. - */ -FltError FltBeadID:: -write_ancillary(FltRecordWriter &writer) const { - if (_id.length() > 7) { - Datagram dc; - - // Although the manual mentions nothing of this, it is essential that the - // length of the record be a multiple of 4 bytes. - dc.add_fixed_string(_id, (_id.length() + 3) & ~3); - - FltError result = writer.write_record(FO_long_id, dc); - if (result != FE_ok) { - return result; - } - } - - return FltBead::write_ancillary(writer); -} diff --git a/pandatool/src/flt/fltBeadID.h b/pandatool/src/flt/fltBeadID.h deleted file mode 100644 index d7e943b2..00000000 --- a/pandatool/src/flt/fltBeadID.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltBeadID.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTBEADID_H -#define FLTBEADID_H - -#include "pandatoolbase.h" - -#include "fltBead.h" - -/** - * A base class for any of a broad family of flt beads that include an ID. - */ -class FltBeadID : public FltBead { -public: - FltBeadID(FltHeader *header); - - const std::string &get_id() const; - void set_id(const std::string &id); - - virtual void output(std::ostream &out) const; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool extract_ancillary(FltRecordReader &reader); - - virtual bool build_record(FltRecordWriter &writer) const; - virtual FltError write_ancillary(FltRecordWriter &writer) const; - -private: - std::string _id; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBead::init_type(); - register_type(_type_handle, "FltBeadID", - FltBead::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltCurve.I b/pandatool/src/flt/fltCurve.I deleted file mode 100644 index cb3d37d2..00000000 --- a/pandatool/src/flt/fltCurve.I +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltCurve.I - * @author drose - * @date 2001-02-28 - */ - -/** - * Returns the number of control points assigned to the curve. - */ -INLINE int FltCurve:: -get_num_control_points() const { - return _control_points.size(); -} - -/** - * Returns the nth control point assigned to the curve. - */ -INLINE const LPoint3d &FltCurve:: -get_control_point(int n) const { -#ifndef NDEBUG - static LPoint3d bogus(0.0, 0.0, 0.0); - nassertr(n >= 0 && n < (int)_control_points.size(), bogus); -#endif - return _control_points[n]; -} diff --git a/pandatool/src/flt/fltCurve.cxx b/pandatool/src/flt/fltCurve.cxx deleted file mode 100644 index d9b3ae8b..00000000 --- a/pandatool/src/flt/fltCurve.cxx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltCurve.cxx - * @author drose - * @date 2001-02-28 - */ - -#include "fltCurve.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "fltMaterial.h" - -TypeHandle FltCurve::_type_handle; - -/** - * - */ -FltCurve:: -FltCurve(FltHeader *header) : FltBeadID(header) { - _curve_type = CT_b_spline; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltCurve:: -extract_record(FltRecordReader &reader) { - if (!FltBeadID::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_curve, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); - _curve_type = (CurveType)iterator.get_be_int32(); - - int num_control_points = iterator.get_be_int32(); - iterator.skip_bytes(8); - for (int i = 0; i < num_control_points; i++) { - double x = iterator.get_be_float64(); - double y = iterator.get_be_float64(); - double z = iterator.get_be_float64(); - _control_points.push_back(LPoint3d(x, y, z)); - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltCurve:: -build_record(FltRecordWriter &writer) const { - if (!FltBeadID::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_curve); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); - datagram.add_be_int32(_curve_type); - datagram.add_be_int32(_control_points.size()); - datagram.pad_bytes(8); - - ControlPoints::const_iterator ci; - for (ci = _control_points.begin(); ci != _control_points.end(); ++ci) { - const LPoint3d &p = (*ci); - datagram.add_be_float64(p[0]); - datagram.add_be_float64(p[1]); - datagram.add_be_float64(p[2]); - } - - return true; -} diff --git a/pandatool/src/flt/fltCurve.h b/pandatool/src/flt/fltCurve.h deleted file mode 100644 index 79f19daf..00000000 --- a/pandatool/src/flt/fltCurve.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltCurve.h - * @author drose - * @date 2001-02-28 - */ - -#ifndef FLTCURVE_H -#define FLTCURVE_H - -#include "pandatoolbase.h" - -#include "fltBeadID.h" -#include "fltHeader.h" - -#include "luse.h" - -/** - * A single curve, like a Bezier or B-Spline. - */ -class FltCurve : public FltBeadID { -public: - FltCurve(FltHeader *header); - - enum CurveType { - CT_b_spline = 4, - CT_cardinal = 5, - CT_bezier = 6 - }; - - typedef pvector ControlPoints; - - CurveType _curve_type; - ControlPoints _control_points; - -public: - INLINE int get_num_control_points() const; - INLINE const LPoint3d &get_control_point(int n) const; - - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBeadID::init_type(); - register_type(_type_handle, "FltCurve", - FltBeadID::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "fltCurve.I" - -#endif diff --git a/pandatool/src/flt/fltError.cxx b/pandatool/src/flt/fltError.cxx deleted file mode 100644 index b0b58ea6..00000000 --- a/pandatool/src/flt/fltError.cxx +++ /dev/null @@ -1,55 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltError.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltError.h" - -std::ostream & -operator << (std::ostream &out, FltError error) { - switch (error) { - case FE_ok: - return out << "no error"; - - case FE_could_not_open: - return out << "could not open file"; - - case FE_empty_file: - return out << "empty file"; - - case FE_end_of_file: - return out << "unexpected end of file"; - - case FE_read_error: - return out << "read error on file"; - - case FE_invalid_record: - return out << "invalid record"; - - case FE_extra_data: - return out << "extra data at end of file"; - - case FE_write_error: - return out << "write error on file"; - - case FE_bad_data: - return out << "bad data"; - - case FE_not_implemented: - return out << "not implemented"; - - case FE_internal: - return out << "internal error"; - - default: - return out << "unknown error " << (int)error; - } -} diff --git a/pandatool/src/flt/fltError.h b/pandatool/src/flt/fltError.h deleted file mode 100644 index 29c44538..00000000 --- a/pandatool/src/flt/fltError.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltError.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTERROR_H -#define FLTERROR_H - -#include "pandatoolbase.h" - -// Return values for various functions in the flt library. -enum FltError { - FE_ok = 0, - FE_could_not_open, - FE_empty_file, - FE_end_of_file, - FE_read_error, - FE_invalid_record, - FE_extra_data, - FE_write_error, - FE_bad_data, - FE_not_implemented, - FE_undefined_instance, - FE_internal -}; - -std::ostream &operator << (std::ostream &out, FltError error); - -#endif diff --git a/pandatool/src/flt/fltExternalReference.cxx b/pandatool/src/flt/fltExternalReference.cxx deleted file mode 100644 index fa6aaa05..00000000 --- a/pandatool/src/flt/fltExternalReference.cxx +++ /dev/null @@ -1,136 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltExternalReference.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltExternalReference.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "pathReplace.h" - -TypeHandle FltExternalReference::_type_handle; - -/** - * - */ -FltExternalReference:: -FltExternalReference(FltHeader *header) : FltBead(header) { - _flags = 0; -} - -/** - * Walks the hierarchy at this record and below and copies the - * _converted_filename record into the _orig_filename record, so the flt file - * will be written out with the converted filename instead of what was - * originally read in. - */ -void FltExternalReference:: -apply_converted_filenames() { - _orig_filename = _converted_filename.to_os_generic(); - FltBead::apply_converted_filenames(); -} - -/** - * Writes a quick one-line description of the record, but not its children. - * This is a human-readable description, primarily for debugging; to write a - * flt file, use FltHeader::write_flt(). - */ -void FltExternalReference:: -output(std::ostream &out) const { - out << "External " << get_ref_filename(); - if (!_bead_id.empty()) { - out << " (" << _bead_id << ")"; - } -} - -/** - * Returns the name of the referenced file. - */ -Filename FltExternalReference:: -get_ref_filename() const { - return _converted_filename; -} - -/** - * Changes the name of the referenced file. - */ -void FltExternalReference:: -set_ref_filename(const Filename &filename) { - _converted_filename = filename; - _orig_filename = _converted_filename.to_os_generic(); -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltExternalReference:: -extract_record(FltRecordReader &reader) { - if (!FltBead::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_external_ref, false); - DatagramIterator &iterator = reader.get_iterator(); - - std::string name = iterator.get_fixed_string(200); - iterator.skip_bytes(1 + 1); - iterator.skip_bytes(2); // Undocumented additional padding. - _flags = iterator.get_be_uint32(); - iterator.skip_bytes(2); - iterator.skip_bytes(2); // Undocumented additional padding. - - _orig_filename = name; - - if (!name.empty() && name[name.length() - 1] == '>') { - // Extract out the bead name. - size_t open = name.rfind('<'); - if (open != std::string::npos) { - _orig_filename = name.substr(0, open); - _bead_id = name.substr(open + 1, name.length() - open - 2); - } - } - _converted_filename = _header->convert_path(Filename::from_os_specific(_orig_filename)); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltExternalReference:: -build_record(FltRecordWriter &writer) const { - if (!FltBead::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_external_ref); - Datagram &datagram = writer.update_datagram(); - - std::string name = _orig_filename; - if (!_bead_id.empty()) { - name += "<" + _bead_id + ">"; - } - - datagram.add_fixed_string(name.substr(0, 199), 200); - datagram.pad_bytes(1 + 1); - datagram.pad_bytes(2); // Undocumented additional padding. - datagram.add_be_uint32(_flags); - datagram.pad_bytes(2); - datagram.pad_bytes(2); // Undocumented additional padding. - - return true; -} diff --git a/pandatool/src/flt/fltExternalReference.h b/pandatool/src/flt/fltExternalReference.h deleted file mode 100644 index 03cac968..00000000 --- a/pandatool/src/flt/fltExternalReference.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltExternalReference.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTEXTERNALREFERENCE_H -#define FLTEXTERNALREFERENCE_H - -#include "pandatoolbase.h" - -#include "fltBead.h" - -#include "filename.h" - -/** - * An external reference to another flt file (possibly to a specific bead - * within the flt file). - */ -class FltExternalReference : public FltBead { -public: - FltExternalReference(FltHeader *header); - - virtual void apply_converted_filenames(); - virtual void output(std::ostream &out) const; - - enum Flags { - F_color_palette_override = 0x80000000, - F_material_palette_override = 0x40000000, - F_texture_palette_override = 0x20000000, - F_line_style_palette_override = 0x10000000, - F_sound_palette_override = 0x08000000, - F_light_palette_override = 0x04000000 - }; - - std::string _orig_filename; - Filename _converted_filename; - std::string _bead_id; - int _flags; - - Filename get_ref_filename() const; - void set_ref_filename(const Filename &filename); - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBead::init_type(); - register_type(_type_handle, "FltExternalReference", - FltBead::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltEyepoint.cxx b/pandatool/src/flt/fltEyepoint.cxx deleted file mode 100644 index 068fc4ee..00000000 --- a/pandatool/src/flt/fltEyepoint.cxx +++ /dev/null @@ -1,135 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltEyepoint.cxx - * @author drose - * @date 2000-08-26 - */ - -#include "fltEyepoint.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -/** - * - */ -FltEyepoint:: -FltEyepoint() { - _rotation_center.set(0.0, 0.0, 0.0); - _hpr.set(0.0, 0.0, 0.0); - _rotation = LMatrix4::ident_mat(); - _fov = 60.0; - _scale = 1.0; - _near_clip = 0.1; - _far_clip = 10000.0; - _fly_through = LMatrix4::ident_mat(); - _eyepoint.set(0.0, 0.0, 0.0); - _fly_through_yaw = 0.0; - _fly_through_pitch = 0.0; - _eyepoint_direction.set(0.0, 1.0, 0.0); - _no_fly_through = true; - _ortho_mode = false; - _is_valid = true; - _image_offset_x = 0; - _image_offset_y = 0; - _image_zoom = 1; -} - -/** - * - */ -bool FltEyepoint:: -extract_record(FltRecordReader &reader) { - DatagramIterator &iterator = reader.get_iterator(); - - _rotation_center[0] = iterator.get_be_float64(); - _rotation_center[1] = iterator.get_be_float64(); - _rotation_center[2] = iterator.get_be_float64(); - _hpr[0] = iterator.get_be_float32(); - _hpr[1] = iterator.get_be_float32(); - _hpr[2] = iterator.get_be_float32(); - int r; - for (r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - _rotation(r, c) = iterator.get_be_float32(); - } - } - _fov = iterator.get_be_float32(); - _scale = iterator.get_be_float32(); - _near_clip = iterator.get_be_float32(); - _far_clip = iterator.get_be_float32(); - for (r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - _fly_through(r, c) = iterator.get_be_float32(); - } - } - _eyepoint[0] = iterator.get_be_float32(); - _eyepoint[1] = iterator.get_be_float32(); - _eyepoint[2] = iterator.get_be_float32(); - _fly_through_yaw = iterator.get_be_float32(); - _fly_through_pitch = iterator.get_be_float32(); - _eyepoint_direction[0] = iterator.get_be_float32(); - _eyepoint_direction[1] = iterator.get_be_float32(); - _eyepoint_direction[2] = iterator.get_be_float32(); - _no_fly_through = (iterator.get_be_int32() != 0); - _ortho_mode = (iterator.get_be_int32() != 0); - _is_valid = (iterator.get_be_int32() != 0); - _image_offset_x = iterator.get_be_int32(); - _image_offset_y = iterator.get_be_int32(); - _image_zoom = iterator.get_be_int32(); - iterator.skip_bytes(4*9); - - return true; -} - -/** - * - */ -bool FltEyepoint:: -build_record(FltRecordWriter &writer) const { - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_float64(_rotation_center[0]); - datagram.add_be_float64(_rotation_center[1]); - datagram.add_be_float64(_rotation_center[2]); - datagram.add_be_float32(_hpr[0]); - datagram.add_be_float32(_hpr[1]); - datagram.add_be_float32(_hpr[2]); - int r; - for (r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - datagram.add_be_float32(_rotation(r, c)); - } - } - datagram.add_be_float32(_fov); - datagram.add_be_float32(_scale); - datagram.add_be_float32(_near_clip); - datagram.add_be_float32(_far_clip); - for (r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - datagram.add_be_float32(_fly_through(r, c)); - } - } - datagram.add_be_float32(_eyepoint[0]); - datagram.add_be_float32(_eyepoint[1]); - datagram.add_be_float32(_eyepoint[2]); - datagram.add_be_float32(_fly_through_yaw); - datagram.add_be_float32(_fly_through_pitch); - datagram.add_be_float32(_eyepoint_direction[0]); - datagram.add_be_float32(_eyepoint_direction[1]); - datagram.add_be_float32(_eyepoint_direction[2]); - datagram.add_be_int32(_no_fly_through); - datagram.add_be_int32(_ortho_mode); - datagram.add_be_int32(_is_valid); - datagram.add_be_int32(_image_offset_x); - datagram.add_be_int32(_image_offset_y); - datagram.add_be_int32(_image_zoom); - datagram.pad_bytes(4*9); - - return true; -} diff --git a/pandatool/src/flt/fltEyepoint.h b/pandatool/src/flt/fltEyepoint.h deleted file mode 100644 index bef59fee..00000000 --- a/pandatool/src/flt/fltEyepoint.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltEyepoint.h - * @author drose - * @date 2000-08-26 - */ - -#ifndef FLTEYEPOINT_H -#define FLTEYEPOINT_H - -#include "pandatoolbase.h" - -#include "luse.h" - -class FltRecordReader; -class FltRecordWriter; - -/** - * A single eyepoint entry in the eyepoint/trackplane palette. - */ -class FltEyepoint { -public: - FltEyepoint(); - - bool extract_record(FltRecordReader &reader); - bool build_record(FltRecordWriter &writer) const; - -public: - LPoint3d _rotation_center; - LVecBase3 _hpr; - LMatrix4 _rotation; - PN_stdfloat _fov; - PN_stdfloat _scale; - PN_stdfloat _near_clip; - PN_stdfloat _far_clip; - LMatrix4 _fly_through; - LPoint3 _eyepoint; - PN_stdfloat _fly_through_yaw; - PN_stdfloat _fly_through_pitch; - LVector3 _eyepoint_direction; - bool _no_fly_through; - bool _ortho_mode; - bool _is_valid; - int _image_offset_x; - int _image_offset_y; - int _image_zoom; -}; - -#endif diff --git a/pandatool/src/flt/fltFace.I b/pandatool/src/flt/fltFace.I deleted file mode 100644 index 934927d7..00000000 --- a/pandatool/src/flt/fltFace.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltFace.I - * @author drose - * @date 2000-08-30 - */ diff --git a/pandatool/src/flt/fltFace.cxx b/pandatool/src/flt/fltFace.cxx deleted file mode 100644 index 8770d3b6..00000000 --- a/pandatool/src/flt/fltFace.cxx +++ /dev/null @@ -1,67 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltFace.cxx - * @author drose - * @date 2000-08-25 - */ - -#include "fltFace.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "fltMaterial.h" - -TypeHandle FltFace::_type_handle; - -/** - * - */ -FltFace:: -FltFace(FltHeader *header) : FltGeometry(header) { -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltFace:: -extract_record(FltRecordReader &reader) { - if (!FltBeadID::extract_record(reader)) { - return false; - } - if (!FltGeometry::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_face, false); - - DatagramIterator &iterator = reader.get_iterator(); - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltFace:: -build_record(FltRecordWriter &writer) const { - if (!FltBeadID::build_record(writer)) { - return false; - } - if (!FltGeometry::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_face); - - return true; -} diff --git a/pandatool/src/flt/fltFace.h b/pandatool/src/flt/fltFace.h deleted file mode 100644 index 404a4966..00000000 --- a/pandatool/src/flt/fltFace.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltFace.h - * @author drose - * @date 2000-08-25 - */ - -#ifndef FLTFACE_H -#define FLTFACE_H - -#include "pandatoolbase.h" - -#include "fltGeometry.h" - -/** - * A single face bead, e.g. a polygon. - */ -class FltFace : public FltGeometry { -public: - FltFace(FltHeader *header); - - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltGeometry::init_type(); - register_type(_type_handle, "FltFace", - FltGeometry::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "fltFace.I" - -#endif diff --git a/pandatool/src/flt/fltGeometry.I b/pandatool/src/flt/fltGeometry.I deleted file mode 100644 index c584c520..00000000 --- a/pandatool/src/flt/fltGeometry.I +++ /dev/null @@ -1,87 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltGeometry.I - * @author drose - * @date 2001-02-28 - */ - -/** - * Returns true if the face has a texture applied, false otherwise. - */ -INLINE bool FltGeometry:: -has_texture() const { - return (_texture_index >= 0 && _header->has_texture(_texture_index)); -} - -/** - * Returns the texture applied to this face, or NULL if no texture was - * applied. - */ -INLINE FltTexture *FltGeometry:: -get_texture() const { - return _header->get_texture(_texture_index); -} - -/** - * Applies the indicated texture to this face, or if the texture is NULL, - * clears it. - */ -INLINE void FltGeometry:: -set_texture(FltTexture *texture) { - if (texture == nullptr) { - _texture_index = -1; - } else { - _header->add_texture(texture); - _texture_index = texture->_pattern_index; - } -} - -/** - * Returns true if the face has a material applied, false otherwise. - */ -INLINE bool FltGeometry:: -has_material() const { - return (_material_index >= 0 && _header->has_material(_material_index)); -} - -/** - * Returns the material applied to this face, or NULL if no material was - * applied. - */ -INLINE FltMaterial *FltGeometry:: -get_material() const { - return _header->get_material(_material_index); -} - -/** - * Applies the indicated material to this face, or if the material is NULL, - * clears it. - */ -INLINE void FltGeometry:: -set_material(FltMaterial *material) { - if (material == nullptr) { - _material_index = -1; - } else { - _header->add_material(material); - _material_index = material->_material_index; - } -} - -/** - * Returns true if the face has a primary color indicated, false otherwise. - */ -INLINE bool FltGeometry:: -has_color() const { - // Even if the no_color bit is not set, if the color_index is -1, the face - // doesn't have a color (unless we've got packed color). On the other hand, - // if we have a material than we always have color. - return ((_flags & F_no_color) == 0 && - (_color_index != -1 || ((_flags & F_packed_color) != 0))) - || has_material(); -} diff --git a/pandatool/src/flt/fltGeometry.cxx b/pandatool/src/flt/fltGeometry.cxx deleted file mode 100644 index 25820487..00000000 --- a/pandatool/src/flt/fltGeometry.cxx +++ /dev/null @@ -1,262 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltGeometry.cxx - * @author drose - * @date 2001-02-28 - */ - -#include "fltGeometry.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "fltMaterial.h" - -TypeHandle FltGeometry::_type_handle; - -/** - * - */ -FltGeometry:: -FltGeometry(FltHeader *header) : FltBeadID(header) { - _ir_color = 0; - _relative_priority = 0; - _draw_type = DT_solid_cull_backface; - _texwhite = false; - _color_name_index = 0; - _alt_color_name_index = 0; - _billboard_type = BT_none; - _detail_texture_index = -1; - _texture_index = -1; - _material_index = -1; - _dfad_material_code = 0; - _dfad_feature_id = 0; - _ir_material_code = 0; - _transparency = 0; - _lod_generation_control = 0; - _line_style_index = 0; - _flags = F_no_color; - _light_mode = LM_face_no_normal; - _texture_mapping_index = 0; - _color_index = 0; - _alt_color_index = 0; -} - - -/** - * Returns the primary color of the face, as a four-component value (including - * alpha as the transparency channel). - * - * If has_color() is false, the result is white, but still reflects the - * transparency correctly. - */ -LColor FltGeometry:: -get_color() const { - LColor color; - - if (!has_color() || (_texwhite && has_texture())) { - // Force this one white. - color.set(1.0, 1.0, 1.0, 1.0); - - } else if (has_material()) { - // If we have a material, that replaces the color. - FltMaterial *material = get_material(); - color.set(material->_diffuse[0], - material->_diffuse[1], - material->_diffuse[2], - material->_alpha); - } else { - LRGBColor rgb = - _header->get_rgb(_color_index, (_flags & F_packed_color) != 0, - _packed_color); - color.set(rgb[0], rgb[1], rgb[2], 1.0); - } - - // Modify the whole thing by our transparency. - PN_stdfloat alpha = 1.0 - (_transparency / 65535.0); - color[3] *= alpha; - - return color; -} - -/** - * Sets the primary color of the face, using the packed color convention. - */ -void FltGeometry:: -set_color(const LColor &color) { - set_rgb(LRGBColor(color[0], color[1], color[2])); - _transparency = (int)floor((1.0 - color[3]) * 65535.0); -} - -/** - * Returns the primary color of the face, as a three-component value ignoring - * transparency. - */ -LRGBColor FltGeometry:: -get_rgb() const { - if (!has_color() || (_texwhite && has_texture())) { - // Force this one white. - return LRGBColor(1.0, 1.0, 1.0); - } - - if (has_material()) { - // If we have a material, that replaces the color. - FltMaterial *material = get_material(); - return material->_diffuse; - } - - return _header->get_rgb(_color_index, (_flags & F_packed_color) != 0, - _packed_color); -} - -/** - * Sets the primary color of the face, using the packed color convention; does - * not affect transparency. - */ -void FltGeometry:: -set_rgb(const LRGBColor &rgb) { - _packed_color.set_rgb(rgb); - _flags = ((_flags & ~F_no_color) | F_packed_color); - - // If we have a color, we can't have a material. - _material_index = -1; - _texwhite = false; -} - -/** - * Returns true if the face has an alternate color indicated, false otherwise. - */ -bool FltGeometry:: -has_alt_color() const { - return (_flags & F_no_alt_color) == 0; -} - -/** - * If has_alt_color() indicates true, returns the alternate color of the face, - * as a four-component value (including alpha as the transparency channel). - */ -LColor FltGeometry:: -get_alt_color() const { - nassertr(has_alt_color(), LColor(0.0, 0.0, 0.0, 0.0)); - - return _header->get_color(_alt_color_index, (_flags & F_packed_color) != 0, - _alt_packed_color, _transparency); -} - -/** - * If has_alt_color() indicates true, returns the alternate color of the face, - * as a three-component value ignoring transparency. - */ -LRGBColor FltGeometry:: -get_alt_rgb() const { - nassertr(has_alt_color(), LRGBColor(0.0, 0.0, 0.0)); - - return _header->get_rgb(_alt_color_index, (_flags & F_packed_color) != 0, - _alt_packed_color); -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltGeometry:: -extract_record(FltRecordReader &reader) { - DatagramIterator &iterator = reader.get_iterator(); - - _ir_color = iterator.get_be_int32(); - _relative_priority = iterator.get_be_int16(); - _draw_type = (DrawType)iterator.get_int8(); - _texwhite = (iterator.get_int8() != 0); - _color_name_index = iterator.get_be_int16(); - _alt_color_name_index = iterator.get_be_int16(); - iterator.skip_bytes(1); - _billboard_type = (BillboardType)iterator.get_int8(); - _detail_texture_index = iterator.get_be_int16(); - _texture_index = iterator.get_be_int16(); - _material_index = iterator.get_be_int16(); - _dfad_material_code = iterator.get_be_int16(); - _dfad_feature_id = iterator.get_be_int16(); - _ir_material_code = iterator.get_be_int32(); - _transparency = iterator.get_be_uint16(); - _lod_generation_control = iterator.get_uint8(); - _line_style_index = iterator.get_uint8(); - if (_header->get_flt_version() >= 1420) { - _flags = iterator.get_be_uint32(); - _light_mode = (LightMode)iterator.get_uint8(); - iterator.skip_bytes(1 + 4); - iterator.skip_bytes(2); // Undocumented padding. - - if (!_packed_color.extract_record(reader)) { - return false; - } - if (!_alt_packed_color.extract_record(reader)) { - return false; - } - - if (_header->get_flt_version() >= 1520) { - _texture_mapping_index = iterator.get_be_int16(); - iterator.skip_bytes(2); - _color_index = iterator.get_be_int32(); - _alt_color_index = iterator.get_be_int32(); - iterator.skip_bytes(2 + 2); - } - } - - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltGeometry:: -build_record(FltRecordWriter &writer) const { - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int32(_ir_color); - datagram.add_be_int16(_relative_priority); - datagram.add_int8(_draw_type); - datagram.add_int8(_texwhite); - datagram.add_be_uint16(_color_name_index); - datagram.add_be_uint16(_alt_color_name_index); - datagram.pad_bytes(1); - datagram.add_int8(_billboard_type); - datagram.add_be_int16(_detail_texture_index); - datagram.add_be_int16(_texture_index); - datagram.add_be_int16(_material_index); - datagram.add_be_int16(_dfad_material_code); - datagram.add_be_int16(_dfad_feature_id); - datagram.add_be_int32(_ir_material_code); - datagram.add_be_uint16(_transparency); - datagram.add_uint8(_lod_generation_control); - datagram.add_uint8(_line_style_index); - datagram.add_be_uint32(_flags); - datagram.add_uint8(_light_mode); - datagram.pad_bytes(1 + 4); - datagram.pad_bytes(2); // Undocumented padding. - - if (!_packed_color.build_record(writer)) { - return false; - } - if (!_alt_packed_color.build_record(writer)) { - return false; - } - - if (_header->get_flt_version() >= 1520) { - // New with 15.2 - datagram.add_be_int16(_texture_mapping_index); - datagram.pad_bytes(2); - datagram.add_be_int32(_color_index); - datagram.add_be_int32(_alt_color_index); - datagram.pad_bytes(2 + 2); - } - - return true; -} diff --git a/pandatool/src/flt/fltGeometry.h b/pandatool/src/flt/fltGeometry.h deleted file mode 100644 index f8041f10..00000000 --- a/pandatool/src/flt/fltGeometry.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltGeometry.h - * @author drose - * @date 2001-02-28 - */ - -#ifndef FLTGEOMETRY_H -#define FLTGEOMETRY_H - -#include "pandatoolbase.h" - -#include "fltBeadID.h" -#include "fltPackedColor.h" -#include "fltHeader.h" - -#include "luse.h" - -class FltTexture; -class FltMaterial; - -/** - * This is a base class for both FltFace and FltMesh, which are two different - * kinds of geometric primitives that might be encountered in a MultiGen file. - * They have similar properties. - */ -class FltGeometry : public FltBeadID { -public: - FltGeometry(FltHeader *header); - - enum DrawType { - DT_solid_cull_backface = 0, - DT_solid_no_cull = 1, - DT_wireframe = 2, - DT_wireframe_close = 3, - DT_wireframe_highlight = 4, - DT_omni_light = 8, - DT_uni_light = 9, - DT_bi_light = 10 - }; - - enum BillboardType { - BT_none = 0, - BT_fixed = 1, - BT_axial = 2, - BT_point = 4 - }; - - enum Flags { - F_terrain = 0x80000000, - F_no_color = 0x40000000, - F_no_alt_color = 0x20000000, - F_packed_color = 0x10000000, - F_terrain_footprint = 0x08000000, - F_hidden = 0x04000000 - }; - - enum LightMode { - LM_face_no_normal = 0, - LM_vertex_no_normal = 1, - LM_face_with_normal = 2, - LM_vertex_with_normal = 3 - }; - - int _ir_color; - int _relative_priority; - DrawType _draw_type; - bool _texwhite; - int _color_name_index; - int _alt_color_name_index; - BillboardType _billboard_type; - int _detail_texture_index; - int _texture_index; - int _material_index; - int _dfad_material_code; - int _dfad_feature_id; - int _ir_material_code; - int _transparency; - int _lod_generation_control; - int _line_style_index; - unsigned int _flags; - LightMode _light_mode; - FltPackedColor _packed_color; - FltPackedColor _alt_packed_color; - int _texture_mapping_index; - int _color_index; - int _alt_color_index; - -public: - INLINE bool has_texture() const; - INLINE FltTexture *get_texture() const; - INLINE void set_texture(FltTexture *texture); - - INLINE bool has_material() const; - INLINE FltMaterial *get_material() const; - INLINE void set_material(FltMaterial *material); - - INLINE bool has_color() const; - LColor get_color() const; - void set_color(const LColor &color); - LRGBColor get_rgb() const; - void set_rgb(const LRGBColor &rgb); - - bool has_alt_color() const; - LColor get_alt_color() const; - LRGBColor get_alt_rgb() const; - - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBeadID::init_type(); - register_type(_type_handle, "FltGeometry", - FltBeadID::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "fltGeometry.I" - -#endif diff --git a/pandatool/src/flt/fltGroup.cxx b/pandatool/src/flt/fltGroup.cxx deleted file mode 100644 index c194769f..00000000 --- a/pandatool/src/flt/fltGroup.cxx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltGroup.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltGroup.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" - -TypeHandle FltGroup::_type_handle; - -/** - * - */ -FltGroup:: -FltGroup(FltHeader *header) : FltBeadID(header) { - _relative_priority = 0; - _flags = 0; - _special_id1 = 0; - _special_id2 = 0; - _significance = 0; - _layer_id = 0; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltGroup:: -extract_record(FltRecordReader &reader) { - if (!FltBeadID::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_group, false); - DatagramIterator &iterator = reader.get_iterator(); - - _relative_priority = iterator.get_be_int16(); - iterator.skip_bytes(2); - _flags = iterator.get_be_uint32(); - _special_id1 = iterator.get_be_int16(); - _special_id2 = iterator.get_be_int16(); - _significance = iterator.get_be_int16(); - _layer_id = iterator.get_int8(); - iterator.skip_bytes(1); - if (_header->get_flt_version() >= 1420) { - iterator.skip_bytes(4); - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltGroup:: -build_record(FltRecordWriter &writer) const { - if (!FltBeadID::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_group); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int16(_relative_priority); - datagram.pad_bytes(2); - datagram.add_be_uint32(_flags); - datagram.add_be_int16(_special_id1); - datagram.add_be_int16(_special_id2); - datagram.add_be_int16(_significance); - datagram.add_int8(_layer_id); - datagram.pad_bytes(5); - - return true; -} diff --git a/pandatool/src/flt/fltGroup.h b/pandatool/src/flt/fltGroup.h deleted file mode 100644 index c1f38198..00000000 --- a/pandatool/src/flt/fltGroup.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltGroup.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTGROUP_H -#define FLTGROUP_H - -#include "pandatoolbase.h" - -#include "fltBeadID.h" - -/** - * The main grouping bead of the flt file. - */ -class FltGroup : public FltBeadID { -public: - FltGroup(FltHeader *header); - - enum Flags { - F_forward_animation = 0x40000000, - F_swing_animation = 0x20000000, - F_bounding_box = 0x10000000, - F_freeze_bounding_box = 0x08000000, - F_default_parent = 0x04000000, - }; - - int _relative_priority; - unsigned int _flags; - int _special_id1, _special_id2; - int _significance; - int _layer_id; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBeadID::init_type(); - register_type(_type_handle, "FltGroup", - FltBeadID::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltHeader.cxx b/pandatool/src/flt/fltHeader.cxx deleted file mode 100644 index a0874863..00000000 --- a/pandatool/src/flt/fltHeader.cxx +++ /dev/null @@ -1,1703 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltHeader.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltHeader.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltUnsupportedRecord.h" -#include "config_flt.h" -#include "zStream.h" -#include "nearly_zero.h" -#include "virtualFileSystem.h" - -#include -#include - -TypeHandle FltHeader::_type_handle; - -/** - * The FltHeader constructor accepts a PathReplace pointer; it uses this - * object to automatically convert all external filename and texture - * references. (This is necessary because the FltHeader has to look in the - * same directory as the texture to find the .attr file, so it must pre- - * convert at least the texture references.) - * - * Most of the other file converters do not have this requirement, so they do - * not need to pre-convert any pathname references. - */ -FltHeader:: -FltHeader(PathReplace *path_replace) : FltBeadID(this) { - if (path_replace == nullptr) { - _path_replace = new PathReplace; - _path_replace->_path_store = PS_absolute; - } else { - _path_replace = path_replace; - } - - _format_revision_level = 1570; - _edit_revision_level = 1570; - _next_group_id = 1; - _next_lod_id = 1; - _next_object_id = 1; - _next_face_id = 1; - _unit_multiplier = 1; - _vertex_units = U_feet; - _texwhite_new = false; - _flags = 0; - _projection_type = PT_flat_earth; - _next_dof_id = 1; - _vertex_storage_type = VTS_double; - _database_origin = DO_open_flight; - _sw_x = 0.0; - _sw_y = 0.0; - _delta_x = 0.0; - _delta_y = 0.0; - _next_sound_id = 1; - _next_path_id = 1; - _next_clip_id = 1; - _next_text_id = 1; - _next_bsp_id = 1; - _next_switch_id = 1; - _sw_lat = 0.0; - _sw_long = 0.0; - _ne_lat = 0.0; - _ne_long = 0.0; - _origin_lat = 0.0; - _origin_long = 0.0; - _lambert_upper_lat = 0.0; - _lambert_lower_lat = 0.0; - _next_light_id = 1; - _next_road_id = 1; - _next_cat_id = 1; - - // New with 15.2 - _earth_model = EM_wgs84; - - // New with 15.6 - _next_adaptive_id = 0; - _next_curve_id = 0; - - // New with 15.7 - _delta_z = 0.0; - _radius = 0.0; - _next_mesh_id = 0; - - _vertex_lookups_stale = false; - _current_vertex_offset = 0; - _next_material_index = 1; - _next_pattern_index = 1; - _got_color_palette = false; - _got_14_material_palette = false; - _got_eyepoint_trackplane_palette = false; - - _auto_attr_update = AU_if_missing; -} - -/** - * Walks the hierarchy at this record and below and copies the - * _converted_filename record into the _orig_filename record, so the flt file - * will be written out with the converted filename instead of what was - * originally read in. - */ -void FltHeader:: -apply_converted_filenames() { - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - FltTexture *texture = (*ti).second; - texture->apply_converted_filenames(); - } - - FltBeadID::apply_converted_filenames(); -} - -/** - * Replaces the PathReplace object (which specifies how to mangle paths from - * the source to the destination file) with a new one. - */ -void FltHeader:: -set_path_replace(PathReplace *path_replace) { - _path_replace = path_replace; -} - -/** - * Returns a pointer to the PathReplace object associated with this converter. - * If the converter is non-const, this returns a non-const pointer, which can - * be adjusted. - */ -PathReplace *FltHeader:: -get_path_replace() { - return _path_replace; -} - -/** - * Returns a pointer to the PathReplace object associated with this converter. - * If the converter is non-const, this returns a non-const pointer, which can - * be adjusted. - */ -const PathReplace *FltHeader:: -get_path_replace() const { - return _path_replace; -} - -/** - * Uses the PathReplace object to convert the named filename as read from the - * flt record to its actual name. - */ -Filename FltHeader:: -convert_path(const Filename &orig_filename, const DSearchPath &additional_path) { - DSearchPath file_path; - if (!_flt_filename.empty()) { - file_path.append_directory(_flt_filename.get_dirname()); - } - file_path.append_path(additional_path); - return _path_replace->convert_path(orig_filename, file_path); -} - -/** - * Sets the filename--especially the directory part--in which the flt file is - * considered to reside. This is also implicitly set by read_flt(). - */ -void FltHeader:: -set_flt_filename(const Filename &flt_filename) { - _flt_filename = flt_filename; -} - -/** - * Returns the directory in which the flt file is considered to reside. - */ -const Filename &FltHeader:: -get_flt_filename() const { - return _flt_filename; -} - -/** - * Opens the indicated filename for reading and attempts to read the complete - * Flt file. Returns FE_ok on success, otherwise on failure. - */ -FltError FltHeader:: -read_flt(Filename filename) { - filename.set_binary(); - _flt_filename = filename; - - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - std::istream *in = vfs->open_read_file(filename, true); - if (in == nullptr) { - assert(!flt_error_abort); - return FE_could_not_open; - } - FltError result = read_flt(*in); - vfs->close_read_file(in); - return result; -} - -/** - * Attempts to read a complete Flt file from the already-opened stream. - * Returns FE_ok on success, otherwise on failure. - */ -FltError FltHeader:: -read_flt(std::istream &in) { - FltRecordReader reader(in); - FltError result = reader.advance(); - if (result == FE_end_of_file) { - assert(!flt_error_abort); - return FE_empty_file; - } else if (result != FE_ok) { - return result; - } - - result = read_record_and_children(reader); - if (result != FE_ok) { - return result; - } - - if (!reader.eof()) { - assert(!flt_error_abort); - return FE_extra_data; - } - - return FE_ok; -} - - -/** - * Opens the indicated filename for writing and attempts to write the complete - * Flt file. Returns FE_ok on success, otherwise on failure. - */ -FltError FltHeader:: -write_flt(Filename filename) { - filename.set_binary(); - - std::ofstream out; - if (!filename.open_write(out)) { - assert(!flt_error_abort); - return FE_could_not_open; - } - -#ifdef HAVE_ZLIB - if (filename.get_extension() == "pz") { - // The filename ends in .pz, which means to automatically compress the flt - // file that we write. - OCompressStream compressor(&out, false); - return write_flt(compressor); - } -#endif // HAVE_ZLIB - - return write_flt(out); -} - -/** - * Attempts to write a complete Flt file to the already-opened stream. - * Returns FE_ok on success, otherwise on failure. - */ -FltError FltHeader:: -write_flt(std::ostream &out) { - FltRecordWriter writer(out); - FltError result = write_record_and_children(writer); - - if (out.fail()) { - assert(!flt_error_abort); - return FE_write_error; - } - return result; -} - -/** - * Controls whether texture .attr files are written automatically when - * write_flt() is called. There are three possibilities: - * - * AU_none: the .attr files are not written automatically; they must be - * written explicitly via a call to FltTexture::write_attr_data() if you want - * them to be written. - * - * AU_if_missing: the .attr files are written only if they do not already - * exist. This will not update any .attr files, even if the data is changed. - * - * AU_always: the .attr files are always rewritten, even if they already exist - * and even if the data has not changed. - * - * The default is AU_if_missing. - */ -void FltHeader:: -set_auto_attr_update(FltHeader::AttrUpdate attr) { - _auto_attr_update = attr; -} - -/** - * Returns the current setting of the auto_attr_update flag. See - * sett_auto_attr_update(). - */ -FltHeader::AttrUpdate FltHeader:: -get_auto_attr_update() const { - return _auto_attr_update; -} - -/** - * Returns the version number of the flt file as reported in the header, times - * 100. Divide by 100 to get the floating-point version number. - */ -int FltHeader:: -get_flt_version() const { - if (_format_revision_level < 1420) { - return _format_revision_level * 100; - } else { - return _format_revision_level; - } -} - -/** - * Changes the version number of the flt file that will be reported in the - * header. Pass in the floating-point version number times 100. - */ -void FltHeader:: -set_flt_version(int version) { - if (version < 14.2) { - _format_revision_level = version / 100; - } else { - _format_revision_level = version; - } -} - -/** - * Returns the earliest flt version number that this codebase supports (times - * 100). Earlier versions will probably not work. - */ -int FltHeader:: -min_flt_version() { - return 1400; -} - -/** - * Returns the latest flt version number that this codebase is known to - * support (times 100). Later versions might work, but then again they may - * not. - */ -int FltHeader:: -max_flt_version() { - return 1570; -} - -/** - * Verifies that the version number read from the header is an understood - * version number, and prints a warning to the user if this is not so--the - * read may or may not succeed. Returns true if the version number is - * acceptable (and no warning is printed), or false if it is questionable (and - * a warning is printed). - */ -bool FltHeader:: -check_version() const { - int version = get_flt_version(); - - if (version < min_flt_version()) { - nout << "Warning! The version number of this file appears to be " - << version / 100.0 << ", which is older than " << min_flt_version() / 100.0 - << ", the oldest OpenFlight version understood by this program. " - "It is unlikely that this program will be able to read the file " - "correctly.\n"; - return false; - } - - if (version > max_flt_version()) { - nout << "Warning! The version number of this file appears to be " - << version / 100.0 << ", which is newer than " << max_flt_version() / 100.0 - << ", the newest OpenFlight version understood by this program. " - "Chances are good that the program will still be able to read it " - "correctly, but any features in the file that are specific to " - "the latest version of OpenFlight will not be understood.\n"; - return false; - } - - return true; -} - -/** - * Returns the units indicated by the flt header, or DU_invalid if the units - * in the header are not understood. - */ -DistanceUnit FltHeader:: -get_units() const { - switch (_vertex_units) { - case FltHeader::U_meters: - return DU_meters; - - case FltHeader::U_kilometers: - return DU_kilometers; - - case FltHeader::U_feet: - return DU_feet; - - case FltHeader::U_inches: - return DU_inches; - - case FltHeader::U_nautical_miles: - return DU_nautical_miles; - } - - // Unknown units. - return DU_invalid; -} - -/** - * Returns true if a instance subtree with the given index has been defined. - */ -bool FltHeader:: -has_instance(int instance_index) const { - return (_instances.count(instance_index) != 0); -} - -/** - * Returns the instance subtree associated with the given index, or NULL if - * there is no such instance. - */ -FltInstanceDefinition *FltHeader:: -get_instance(int instance_index) const { - Instances::const_iterator mi; - mi = _instances.find(instance_index); - if (mi != _instances.end()) { - return (*mi).second; - } - return nullptr; -} - -/** - * Removes all instance subtrees from the instance pool. - */ -void FltHeader:: -clear_instances() { - _instances.clear(); -} - -/** - * Defines a new instance subtree. This subtree is not itself part of the - * hierarchy; it marks geometry that may be instanced to various beads - * elsewhere in the hierarchy by creating a corresponding FltInstanceRef bead. - */ -void FltHeader:: -add_instance(FltInstanceDefinition *instance) { - _instances[instance->_instance_index] = instance; -} - -/** - * Removes a particular instance subtree from the pool, if it exists. - */ -void FltHeader:: -remove_instance(int instance_index) { - _instances.erase(instance_index); -} - -/** - * Returns the number of vertices in the vertex palette. - */ -int FltHeader:: -get_num_vertices() const { - return _vertices.size(); -} - -/** - * Returns the nth vertex of the vertex palette. - */ -FltVertex *FltHeader:: -get_vertex(int n) const { - nassertr(n >= 0 && n < (int)_vertices.size(), nullptr); - return _vertices[n]; -} - -/** - * Removes all vertices from the vertex palette. - */ -void FltHeader:: -clear_vertices() { - _vertices.clear(); - _unique_vertices.clear(); - _vertices_by_offset.clear(); - _offsets_by_vertex.clear(); - _vertex_lookups_stale = false; -} - -/** - * Adds a new vertex to the end of the vertex palette. If this particular - * vertex was already present in the palette, does nothing. - */ -void FltHeader:: -add_vertex(FltVertex *vertex) { - bool inserted = _unique_vertices.insert(vertex).second; - if (inserted) { - _vertices.push_back(vertex); - } - _vertex_lookups_stale = true; - nassertv(_unique_vertices.size() == _vertices.size()); -} - -/** - * Returns the particular vertex pointer associated with the given byte offset - * into the vertex palette. If there is no such vertex in the palette, this - * generates an error message and returns NULL. - */ -FltVertex *FltHeader:: -get_vertex_by_offset(int offset) { - if (_vertex_lookups_stale) { - update_vertex_lookups(); - } - - VerticesByOffset::const_iterator vi; - vi = _vertices_by_offset.find(offset); - if (vi == _vertices_by_offset.end()) { - nout << "No vertex with offset " << offset << "\n"; - return nullptr; - } - return (*vi).second; -} - -/** - * Returns the byte offset into the vertex palette associated with the given - * vertex pointer. If there is no such vertex in the palette, this generates - * an error message and returns 0. - */ -int FltHeader:: -get_offset_by_vertex(FltVertex *vertex) { - if (_vertex_lookups_stale) { - update_vertex_lookups(); - } - - OffsetsByVertex::const_iterator vi; - vi = _offsets_by_vertex.find(vertex); - if (vi == _offsets_by_vertex.end()) { - nout << "Vertex does not appear in palette.\n"; - return 0; - } - return (*vi).second; -} - -/** - * Returns the total number of different colors in the color palette. This - * includes all different colors, and represents the complete range of - * alloable color indices. This is different from the actual number of color - * entries as read directly from the color palette, since each color entry - * defines a number of different intensity levels--the value returned by - * get_num_colors() is equal to get_num_color_entries() * - * get_num_color_shades(). - */ -int FltHeader:: -get_num_colors() const { - return _colors.size() * get_num_color_shades(); -} - -/** - * Returns the four-component color corresponding to the given color index. - * Each component will be in the range [0, 1]. - */ -LColor FltHeader:: -get_color(int color_index) const { - nassertr(color_index >= 0 && color_index < get_num_colors(), - LColor(0.0, 0.0, 0.0, 0.0)); - int num_color_shades = get_num_color_shades(); - - int index = (color_index / num_color_shades); - int level = (color_index % num_color_shades); - nassertr(index >= 0 && index < (int)_colors.size(), - LColor(0.0, 0.0, 0.0, 0.0)); - - LColor color = _colors[index].get_color(); - return color * ((double)level / (double)(num_color_shades - 1)); -} - -/** - * Returns the three-component color corresponding to the given color index, - * ignoring the alpha component. Each component will be in the range [0, 1]. - */ -LRGBColor FltHeader:: -get_rgb(int color_index) const { - nassertr(color_index >= 0 && color_index < get_num_colors(), - LRGBColor(0.0, 0.0, 0.0)); - int num_color_shades = get_num_color_shades(); - - int index = (color_index / num_color_shades); - int level = (color_index % num_color_shades); - nassertr(index >= 0 && index < (int)_colors.size(), - LRGBColor(0.0, 0.0, 0.0)); - - LRGBColor color = _colors[index].get_rgb(); - return color * ((double)level / (double)(num_color_shades - 1)); -} - -/** - * Returns true if the given color is named, false otherwise. - */ -bool FltHeader:: -has_color_name(int color_index) const { - return (_color_names.count(color_index) != 0); -} - -/** - * Returns the name associated with the given color, if any. - */ -std::string FltHeader:: -get_color_name(int color_index) const { - ColorNames::const_iterator ni; - ni = _color_names.find(color_index); - if (ni != _color_names.end()) { - return (*ni).second; - } - return std::string(); -} - -/** - * Returns the color index of the nearest color in the palette that matches - * the given four-component color, including alpha. - */ -int FltHeader:: -get_closest_color(const LColor &color0) const { - // Since the colortable stores the brightest colors, with num_color_shades - // scaled versions of each color implicitly available, we really only care - // about the relative brightnesses of the various components. Normalize the - // color in terms of the largest of these. - LColor color = color0; - - double scale = 1.0; - - if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0 && color[3] == 0.0) { - // Oh, this is invisible black. - scale = 0.0; - color.set(1.0, 1.0, 1.0, 1.0); - - } else { - if (color[0] >= color[1] && color[0] >= color[2] && color[0] >= color[3]) { - // color[0] is largest. - scale = color[0]; - - } else if (color[1] >= color[2] && color[1] >= color[3]) { - // color[1] is largest. - scale = color[1]; - - } else if (color[2] >= color[3]) { - // color[2] is largest. - scale = color[2]; - - } else { - // color[3] is largest. - scale = color[3]; - } - color /= scale; - } - - // Now search for the best match. - PN_stdfloat best_dist = 5.0; // Greater than 4. - int best_i = -1; - - int num_color_entries = get_num_color_entries(); - for (int i = 0; i < num_color_entries; i++) { - LColor consider = _colors[i].get_color(); - PN_stdfloat dist2 = dot(consider - color, consider - color); - nassertr(dist2 < 5.0, 0); - - if (dist2 < best_dist) { - best_dist = dist2; - best_i = i; - } - } - nassertr(best_i >= 0, 0); - - int num_color_shades = get_num_color_shades(); - int shade_index = (int)floor((num_color_shades-1) * scale + 0.5); - - return (best_i * num_color_shades) + shade_index; -} - -/** - * Returns the color index of the nearest color in the palette that matches - * the given three-component color, ignoring alpha. - */ -int FltHeader:: -get_closest_rgb(const LRGBColor &color0) const { - // Since the colortable stores the brightest colors, with num_color_shades - // scaled versions of each color implicitly available, we really only care - // about the relative brightnesses of the various components. Normalize the - // color in terms of the largest of these. - - LRGBColor color = color0; - double scale = 1.0; - - if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) { - // Oh, this is black. - scale = 0.0; - color.set(1.0, 1.0, 1.0); - - } else { - if (color[0] >= color[1] && color[0] >= color[2]) { - // color[0] is largest. - scale = color[0]; - - } else if (color[1] >= color[2]) { - // color[1] is largest. - scale = color[1]; - - } else { - // color[2] is largest. - scale = color[2]; - } - color /= scale; - } - - // Now search for the best match. - PN_stdfloat best_dist = 5.0; // Greater than 4. - int best_i = -1; - - int num_color_entries = get_num_color_entries(); - for (int i = 0; i < num_color_entries; i++) { - LRGBColor consider = _colors[i].get_rgb(); - PN_stdfloat dist2 = dot(consider - color, consider - color); - nassertr(dist2 < 5.0, 0); - - if (dist2 < best_dist) { - best_dist = dist2; - best_i = i; - } - } - nassertr(best_i >= 0, 0); - - int num_color_shades = get_num_color_shades(); - int shade_index = (int)floor((num_color_shades-1) * scale + 0.5); - - return (best_i * num_color_shades) + shade_index; -} - -/** - * Returns the number of actual entries in the color palette. This is based - * on the version of the flt file, and is usually either 512 or 1024. - */ -int FltHeader:: -get_num_color_entries() const { - return _colors.size(); -} - -/** - * Returns the number of shades of brightness of each entry in the color - * palette. This is a fixed property of MultiGen files: each entry in the - * palette actually represents a range of this many colors. - */ -int FltHeader:: -get_num_color_shades() const { - return 128; -} - -/** - * Decodes a MultiGen color, as stored on a face or vertex, into an actual - * four-component LColor. Normally you need not call this directly; there are - * color accessors defined on faces and vertices that do this. - */ -LColor FltHeader:: -get_color(int color_index, bool use_packed_color, - const FltPackedColor &packed_color, - int transparency) { - if (!use_packed_color) { - return get_color(color_index); - } - - LColor color; - color[0] = packed_color._r / 255.0; - color[1] = packed_color._g / 255.0; - color[2] = packed_color._b / 255.0; - // MultiGen doesn't yet use the A component of RGBA. color[3] = - // packed_color._a 255.0; - color[3] = 1.0 - (transparency / 65535.0); - return color; -} - -/** - * Decodes a MultiGen color, as stored on a face or vertex, into an actual - * three-component LRGBColor. Normally you need not call this directly; there - * are color accessors defined on faces and vertices that do this. - */ -LRGBColor FltHeader:: -get_rgb(int color_index, bool use_packed_color, - const FltPackedColor &packed_color) { - if (!use_packed_color) { - return get_rgb(color_index); - } - - LRGBColor color; - color[0] = packed_color._r / 255.0; - color[1] = packed_color._g / 255.0; - color[2] = packed_color._b / 255.0; - return color; -} - -/** - * Returns true if a material with the given index has been defined. - */ -bool FltHeader:: -has_material(int material_index) const { - return (_materials.count(material_index) != 0); -} - -/** - * Returns the material associated with the given index, or NULL if there is - * no such material. - */ -FltMaterial *FltHeader:: -get_material(int material_index) const { - Materials::const_iterator mi; - mi = _materials.find(material_index); - if (mi != _materials.end()) { - return (*mi).second; - } - return nullptr; -} - -/** - * Removes all materials from the palette. - */ -void FltHeader:: -clear_materials() { - _materials.clear(); -} - -/** - * Defines a new material. The material is added in the position indicated by - * the material's index number. If there is already a material defined for - * that index number, it is replaced. - */ -void FltHeader:: -add_material(FltMaterial *material) { - if (material->_material_index < 0) { - // We need to make up a new material index for the material. - material->_material_index = _next_material_index; - _next_material_index++; - - } else { - // Make sure our next generated material index will be different from any - // existing material indices. - _next_material_index = std::max(_next_material_index, material->_material_index + 1); - } - - _materials[material->_material_index] = material; -} - -/** - * Removes a particular material from the material palette, if it exists. - */ -void FltHeader:: -remove_material(int material_index) { - _materials.erase(material_index); -} - -/** - * Returns true if a texture with the given index has been defined. - */ -bool FltHeader:: -has_texture(int texture_index) const { - return (_textures.count(texture_index) != 0); -} - -/** - * Returns the texture associated with the given index, or NULL if there is no - * such texture. - */ -FltTexture *FltHeader:: -get_texture(int texture_index) const { - Textures::const_iterator mi; - mi = _textures.find(texture_index); - if (mi != _textures.end()) { - return (*mi).second; - } - return nullptr; -} - -/** - * Removes all textures from the palette. - */ -void FltHeader:: -clear_textures() { - _textures.clear(); -} - -/** - * Defines a new texture. The texture is added in the position indicated by - * the texture's index number. If there is already a texture defined for that - * index number, it is replaced. - */ -void FltHeader:: -add_texture(FltTexture *texture) { - if (texture->_pattern_index < 0) { - // We need to make up a new pattern index for the texture. - texture->_pattern_index = _next_pattern_index; - _next_pattern_index++; - - } else { - // Make sure our next generated pattern index will be different from any - // existing texture indices. - _next_pattern_index = std::max(_next_pattern_index, texture->_pattern_index + 1); - } - - _textures[texture->_pattern_index] = texture; -} - -/** - * Removes a particular texture from the texture palette, if it exists. - */ -void FltHeader:: -remove_texture(int texture_index) { - _textures.erase(texture_index); -} - -/** - * Returns true if a light source with the given index has been defined. - */ -bool FltHeader:: -has_light_source(int light_index) const { - return (_light_sources.count(light_index) != 0); -} - -/** - * Returns the light source associated with the given index, or NULL if there - * is no such light source. - */ -FltLightSourceDefinition *FltHeader:: -get_light_source(int light_index) const { - LightSources::const_iterator li; - li = _light_sources.find(light_index); - if (li != _light_sources.end()) { - return (*li).second; - } - return nullptr; -} - -/** - * Removes all light sources from the palette. - */ -void FltHeader:: -clear_light_sources() { - _light_sources.clear(); -} - -/** - * Defines a new light source. The light source is added in the position - * indicated by its light index number. If there is already a light source - * defined for that index number, it is replaced. - */ -void FltHeader:: -add_light_source(FltLightSourceDefinition *light_source) { - _light_sources[light_source->_light_index] = light_source; -} - -/** - * Removes a particular light source from the light source palette, if it - * exists. - */ -void FltHeader:: -remove_light_source(int light_index) { - _light_sources.erase(light_index); -} - -/** - * Returns true if we have read an eyepoint/trackplane palette, and at least - * some of the eyepoints and trackplanes are therefore expected to be - * meaningful. - */ -bool FltHeader:: -got_eyepoint_trackplane_palette() const { - return _got_eyepoint_trackplane_palette; -} - -/** - * Sets the state of the eyepoint/trackplane palette flag. When this is - * false, the palette is believed to be meaningless, and will not be written; - * when it is true, the palette is believed to contain at least some - * meaningful data, and will be written. - */ -void FltHeader:: -set_eyepoint_trackplane_palette(bool flag) { - _got_eyepoint_trackplane_palette = flag; -} - -/** - * Returns the number of eyepoints in the eyepoint/trackplane palette. This - * is presently fixed at 10, according to the MultiGen specs. - */ -int FltHeader:: -get_num_eyepoints() const { - return 10; -} - -/** - * Returns the nth eyepoint in the eyepoint/trackplane palette. - */ -FltEyepoint *FltHeader:: -get_eyepoint(int n) { - nassertr(n >= 0 && n < get_num_eyepoints(), nullptr); - return &_eyepoints[n]; -} - -/** - * Returns the number of trackplanes in the eyepoint/trackplane palette. This - * is presently fixed at 10, according to the MultiGen specs. - */ -int FltHeader:: -get_num_trackplanes() const { - return 10; -} - -/** - * Returns the nth trackplane in the eyepoint/trackplane palette. - */ -FltTrackplane *FltHeader:: -get_trackplane(int n) { - nassertr(n >= 0 && n < get_num_trackplanes(), nullptr); - return &_trackplanes[n]; -} - -/** - * Recomputes the offsets_by_vertex and vertices_by_offset tables. This - * reflects the flt file as it will be written out, but not necessarily as it - * was read in. - * - * The return value is the total length of the vertex palette, including the - * header record. - */ -int FltHeader:: -update_vertex_lookups() { - // We start with the length of the vertex palette record itself. - int offset = 8; - - Vertices::const_iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - FltVertex *vertex = (*vi); - - _offsets_by_vertex[vertex] = offset; - _vertices_by_offset[offset] = vertex; - offset += vertex->get_record_length(); - } - - _vertex_lookups_stale = false; - - return offset; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltHeader:: -extract_record(FltRecordReader &reader) { - if (!FltBeadID::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_header, false); - DatagramIterator &iterator = reader.get_iterator(); - - _format_revision_level = iterator.get_be_int32(); - _edit_revision_level = iterator.get_be_int32(); - _last_revision = iterator.get_fixed_string(32); - _next_group_id = iterator.get_be_int16(); - _next_lod_id = iterator.get_be_int16(); - _next_object_id = iterator.get_be_int16(); - _next_face_id = iterator.get_be_int16(); - _unit_multiplier = iterator.get_be_int16(); - _vertex_units = (Units)iterator.get_int8(); - _texwhite_new = (iterator.get_int8() != 0); - _flags = iterator.get_be_uint32(); - iterator.skip_bytes(24); - _projection_type = (ProjectionType)iterator.get_be_int32(); - iterator.skip_bytes(28); - _next_dof_id = iterator.get_be_int16(); - _vertex_storage_type = (VertexStorageType)iterator.get_be_int16(); - _database_origin = (DatabaseOrigin)iterator.get_be_int32(); - _sw_x = iterator.get_be_float64(); - _sw_y = iterator.get_be_float64(); - _delta_x = iterator.get_be_float64(); - _delta_y = iterator.get_be_float64(); - _next_sound_id = iterator.get_be_int16(); - _next_path_id = iterator.get_be_int16(); - iterator.skip_bytes(8); - _next_clip_id = iterator.get_be_int16(); - _next_text_id = iterator.get_be_int16(); - _next_bsp_id = iterator.get_be_int16(); - _next_switch_id = iterator.get_be_int16(); - iterator.skip_bytes(4); - _sw_lat = iterator.get_be_float64(); - _sw_long = iterator.get_be_float64(); - _ne_lat = iterator.get_be_float64(); - _ne_long = iterator.get_be_float64(); - _origin_lat = iterator.get_be_float64(); - _origin_long = iterator.get_be_float64(); - _lambert_upper_lat = iterator.get_be_float64(); - _lambert_lower_lat = iterator.get_be_float64(); - _next_light_id = iterator.get_be_int16(); - iterator.skip_bytes(2); - if (get_flt_version() >= 1420 && iterator.get_remaining_size() > 0) { - _next_road_id = iterator.get_be_int16(); - _next_cat_id = iterator.get_be_int16(); - - if (get_flt_version() >= 1520 && iterator.get_remaining_size() > 0) { - iterator.skip_bytes(2 + 2 + 2 + 2); - _earth_model = (EarthModel)iterator.get_be_int32(); - - // Undocumented padding. - iterator.skip_bytes(4); - - if (get_flt_version() >= 1560 && iterator.get_remaining_size() > 0) { - _next_adaptive_id = iterator.get_be_int16(); - _next_curve_id = iterator.get_be_int16(); - iterator.skip_bytes(4); - - if (get_flt_version() >= 1570 && iterator.get_remaining_size() > 0) { - _delta_z = iterator.get_be_float64(); - _radius = iterator.get_be_float64(); - _next_mesh_id = iterator.get_be_int16(); - iterator.skip_bytes(2); - - // Undocumented padding. - iterator.skip_bytes(4); - } - } - } - } - - check_remaining_size(iterator); - return true; -} - -/** - * Checks whether the given bead, which follows this bead sequentially in the - * file, is an ancillary record of this bead. If it is, extracts the relevant - * information and returns true; otherwise, leaves it alone and returns false. - */ -bool FltHeader:: -extract_ancillary(FltRecordReader &reader) { - switch (reader.get_opcode()) { - case FO_vertex_palette: - // We're about to begin the vertex palette! - clear_vertices(); - _current_vertex_offset = reader.get_record_length(); - return true; - - case FO_vertex_c: - case FO_vertex_cn: - case FO_vertex_cnu: - case FO_vertex_cu: - // Here's a new vertex for the palette. - return extract_vertex(reader); - - case FO_color_palette: - return extract_color_palette(reader); - - case FO_15_material: - return extract_material(reader); - - case FO_14_material_palette: - return extract_14_material_palette(reader); - - case FO_texture: - return extract_texture(reader); - - case FO_texture_map_palette: - return extract_texture_map(reader); - - case FO_light_definition: - return extract_light_source(reader); - - case FO_eyepoint_palette: - return extract_eyepoint_palette(reader); - - default: - return FltBeadID::extract_ancillary(reader); - } -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltHeader:: -build_record(FltRecordWriter &writer) const { - if (!FltBeadID::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_header); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int32(_format_revision_level); - datagram.add_be_int32(_edit_revision_level); - datagram.add_fixed_string(_last_revision, 32); - datagram.add_be_int16(_next_group_id); - datagram.add_be_int16(_next_lod_id); - datagram.add_be_int16(_next_object_id); - datagram.add_be_int16(_next_face_id); - datagram.add_be_int16(_unit_multiplier); - datagram.add_int8(_vertex_units); - datagram.add_int8(_texwhite_new); - datagram.add_be_uint32(_flags); - datagram.pad_bytes(24); - datagram.add_be_int32(_projection_type); - datagram.pad_bytes(28); - datagram.add_be_int16(_next_dof_id); - datagram.add_be_int16(_vertex_storage_type); - datagram.add_be_int32(_database_origin); - datagram.add_be_float64(_sw_x); - datagram.add_be_float64(_sw_y); - datagram.add_be_float64(_delta_x); - datagram.add_be_float64(_delta_y); - datagram.add_be_int16(_next_sound_id); - datagram.add_be_int16(_next_path_id); - datagram.pad_bytes(8); - datagram.add_be_int16(_next_clip_id); - datagram.add_be_int16(_next_text_id); - datagram.add_be_int16(_next_bsp_id); - datagram.add_be_int16(_next_switch_id); - datagram.pad_bytes(4); - datagram.add_be_float64(_sw_lat); - datagram.add_be_float64(_sw_long); - datagram.add_be_float64(_ne_lat); - datagram.add_be_float64(_ne_long); - datagram.add_be_float64(_origin_lat); - datagram.add_be_float64(_origin_long); - datagram.add_be_float64(_lambert_upper_lat); - datagram.add_be_float64(_lambert_lower_lat); - datagram.add_be_int16(_next_light_id); - datagram.pad_bytes(2); - datagram.add_be_int16(_next_road_id); - datagram.add_be_int16(_next_cat_id); - - if (get_flt_version() >= 1520) { - // New with 15.2 - datagram.pad_bytes(2 + 2 + 2 + 2); - datagram.add_be_int32(_earth_model); - - datagram.pad_bytes(4); - - if (get_flt_version() >= 1560) { - // New with 15.6 - datagram.add_be_int16(_next_adaptive_id); - datagram.add_be_int16(_next_curve_id); - datagram.pad_bytes(4); - - if (get_flt_version() >= 1570) { - // New with 15.7 - datagram.add_be_float64(_delta_z); - datagram.add_be_float64(_radius); - datagram.add_be_int16(_next_mesh_id); - datagram.pad_bytes(2); - datagram.pad_bytes(4); - } - } - } - - return true; -} - -/** - * Writes whatever ancillary records are required for this bead. Returns - * FE_ok on success, or something else on error. - */ -FltError FltHeader:: -write_ancillary(FltRecordWriter &writer) const { - FltError result; - - result = write_color_palette(writer); - if (result != FE_ok) { - return result; - } - - result = write_material_palette(writer); - if (result != FE_ok) { - return result; - } - - result = write_texture_palette(writer); - if (result != FE_ok) { - return result; - } - - result = write_light_source_palette(writer); - if (result != FE_ok) { - return result; - } - - result = write_eyepoint_palette(writer); - if (result != FE_ok) { - return result; - } - - result = write_vertex_palette(writer); - if (result != FE_ok) { - return result; - } - - return FltBeadID::write_ancillary(writer); -} - -/** - * Reads a single vertex ancillary record. It is assumed that all the vertex - * records will immediately follow the vertex palette record. - */ -bool FltHeader:: -extract_vertex(FltRecordReader &reader) { - FltVertex *vertex = new FltVertex(this); - if (!vertex->extract_record(reader)) { - return false; - } - _vertices.push_back(vertex); - _unique_vertices.insert(vertex); - _offsets_by_vertex[vertex] = _current_vertex_offset; - _vertices_by_offset[_current_vertex_offset] = vertex; - _current_vertex_offset += reader.get_record_length(); - - // _vertex_lookups_stale remains false. - - return true; -} - -/** - * Reads the color palette. - */ -bool FltHeader:: -extract_color_palette(FltRecordReader &reader) { - nassertr(reader.get_opcode() == FO_color_palette, false); - DatagramIterator &iterator = reader.get_iterator(); - - if (_got_color_palette) { - nout << "Warning: multiple color palettes found.\n"; - } - _got_color_palette = true; - - static const int expected_color_entries = 1024; - - iterator.skip_bytes(128); - _colors.clear(); - for (int i = 0; i < expected_color_entries; i++) { - if (iterator.get_remaining_size() == 0) { - // An early end to the palette is acceptable. - return true; - } - FltPackedColor color; - if (!color.extract_record(reader)) { - return false; - } - _colors.push_back(color); - } - - // Now pull out the color names. - while (iterator.get_remaining_size() > 0) { - int entry_length = iterator.get_be_uint16(); - iterator.skip_bytes(2); - if (iterator.get_remaining_size() > 0) { - int color_index = iterator.get_be_int16(); - iterator.skip_bytes(2); - - int name_length = entry_length - 8; - nassertr(color_index >= 0 && color_index < (int)_colors.size(), false); - _color_names[color_index] = iterator.get_fixed_string(name_length); - } - } - - check_remaining_size(iterator, "color palette"); - return true; -} - -/** - * Reads a single material ancillary record. - */ -bool FltHeader:: -extract_material(FltRecordReader &reader) { - PT(FltMaterial) material = new FltMaterial(this); - if (!material->extract_record(reader)) { - return false; - } - add_material(material); - - return true; -} - -/** - * Reads the v14.2 material palette. - */ -bool FltHeader:: -extract_14_material_palette(FltRecordReader &reader) { - nassertr(reader.get_opcode() == FO_14_material_palette, false); - DatagramIterator &iterator = reader.get_iterator(); - - if (_got_14_material_palette) { - nout << "Warning: multiple material palettes found.\n"; - } - _got_14_material_palette = true; - - static const int expected_material_entries = 64; - - _materials.clear(); - for (int i = 0; i < expected_material_entries; i++) { - if (iterator.get_remaining_size() == 0) { - // An early end to the palette is acceptable. - return true; - } - PT(FltMaterial) material = new FltMaterial(this); - if (!material->extract_14_record(i, iterator)) { - return false; - } - add_material(material); - } - - check_remaining_size(iterator, "material palette"); - return true; -} - -/** - * Reads a single texture ancillary record. - */ -bool FltHeader:: -extract_texture(FltRecordReader &reader) { - FltTexture *texture = new FltTexture(this); - if (!texture->extract_record(reader)) { - return false; - } - add_texture(texture); - - return true; -} - -/** - * Reads the a single texture mapping ancillary record. This describes a kind - * of texture mapping in the texture mapping palette. - */ -bool FltHeader:: -extract_texture_map(FltRecordReader &reader) { - // At the moment, we ignore this, since it's not needed for meaningful - // extraction of data: we can get this information from the UV's for a - // particular model. We just add an UnsupportedRecord for it. - FltUnsupportedRecord *rec = new FltUnsupportedRecord(this); - if (!rec->extract_record(reader)) { - return false; - } - add_ancillary(rec); - - return true; -} - -/** - * Reads a single light source ancillary record. - */ -bool FltHeader:: -extract_light_source(FltRecordReader &reader) { - FltLightSourceDefinition *light_source = new FltLightSourceDefinition(this); - if (!light_source->extract_record(reader)) { - return false; - } - add_light_source(light_source); - - return true; -} - -/** - * Reads the eyepoint/trackplane palette. - */ -bool FltHeader:: -extract_eyepoint_palette(FltRecordReader &reader) { - nassertr(reader.get_opcode() == FO_eyepoint_palette, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); - - int i; - int num_eyepoints = get_num_eyepoints(); - for (i = 0; i < num_eyepoints; i++) { - if (!_eyepoints[i].extract_record(reader)) { - return false; - } - } - - int num_trackplanes = get_num_trackplanes(); - for (i = 0; i < num_trackplanes; i++) { - if (!_trackplanes[i].extract_record(reader)) { - return false; - } - } - - _got_eyepoint_trackplane_palette = true; - - if (get_flt_version() >= 1420) { - // I have no idea what bytes are supposed to be here in earlier versions - // that 14.2, but who really cares? Don't bother reporting it if there - // are too many bytes in old versions. - check_remaining_size(iterator, "eyepoint palette"); - } - return true; -} - -/** - * Writes out the vertex palette with all of its vertices. - */ -FltError FltHeader:: -write_vertex_palette(FltRecordWriter &writer) const { - FltError result; - - int vertex_palette_length = - ((FltHeader *)this)->update_vertex_lookups(); - Datagram vertex_palette; - vertex_palette.add_be_int32(vertex_palette_length); - result = writer.write_record(FO_vertex_palette, vertex_palette); - if (result != FE_ok) { - return result; - } - // Now write out each vertex in the palette. - Vertices::const_iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - FltVertex *vertex = (*vi); - vertex->build_record(writer); - result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - return FE_ok; -} - - -/** - * Writes out the color palette. - */ -FltError FltHeader:: -write_color_palette(FltRecordWriter &writer) const { - writer.set_opcode(FO_color_palette); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(128); - - // How many colors should we write? - int num_colors = 1024; - - Colors::const_iterator ci; - for (ci = _colors.begin(); num_colors > 0 && ci != _colors.end(); ++ci) { - if (!(*ci).build_record(writer)) { - assert(!flt_error_abort); - return FE_invalid_record; - } - num_colors--; - } - - // Now we might need to pad the record to fill up the required number of - // colors. - if (num_colors > 0) { - FltPackedColor empty; - while (num_colors > 0) { - if (!empty.build_record(writer)) { - assert(!flt_error_abort); - return FE_invalid_record; - } - num_colors--; - } - } - - // Now append all the names at the end. - ColorNames::const_iterator ni; - for (ni = _color_names.begin(); ni != _color_names.end(); ++ni) { - std::string name = (*ni).second.substr(0, 80); - int entry_length = name.length() + 8; - datagram.add_be_uint16(entry_length); - datagram.pad_bytes(2); - datagram.add_be_uint16((*ni).first); - datagram.pad_bytes(2); - datagram.add_fixed_string(name, name.length()); - } - - return writer.advance(); -} - -/** - * Writes out the material palette. - */ -FltError FltHeader:: -write_material_palette(FltRecordWriter &writer) const { - FltError result; - - if (get_flt_version() >= 1520) { - // Write a version 15 material palette. - Materials::const_iterator mi; - for (mi = _materials.begin(); mi != _materials.end(); ++mi) { - FltMaterial *material = (*mi).second; - material->build_record(writer); - - result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - } else { - // Write a version 14 material palette. - if (_materials.empty()) { - // No palette is OK. - return FE_ok; - } - writer.set_opcode(FO_14_material_palette); - Datagram &datagram = writer.update_datagram(); - - PT(FltMaterial) dummy_material = new FltMaterial(_header); - - Materials::const_iterator mi = _materials.lower_bound(0); - int index; - static const int expected_material_entries = 64; - for (index = 0; index < expected_material_entries; index++) { - if (mi == _materials.end() || index < (*mi).first) { - dummy_material->build_14_record(datagram); - } else { - nassertr(index == (*mi).first, FE_internal); - FltMaterial *material = (*mi).second; - material->build_14_record(datagram); - ++mi; - } - } - - result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - return FE_ok; -} - -/** - * Writes out the texture palette. - */ -FltError FltHeader:: -write_texture_palette(FltRecordWriter &writer) const { - FltError result; - - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - FltTexture *texture = (*ti).second; - texture->build_record(writer); - result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - return FE_ok; -} - -/** - * Writes out the light source palette. - */ -FltError FltHeader:: -write_light_source_palette(FltRecordWriter &writer) const { - FltError result; - - LightSources::const_iterator li; - for (li = _light_sources.begin(); li != _light_sources.end(); ++li) { - FltLightSourceDefinition *light_source = (*li).second; - light_source->build_record(writer); - result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - return FE_ok; -} - -/** - * Writes out the eyepoint/trackplane palette, if we have one. - */ -FltError FltHeader:: -write_eyepoint_palette(FltRecordWriter &writer) const { - if (!_got_eyepoint_trackplane_palette) { - return FE_ok; - } - - writer.set_opcode(FO_eyepoint_palette); - Datagram &datagram = writer.update_datagram(); - datagram.pad_bytes(4); - - int i; - int num_eyepoints = get_num_eyepoints(); - for (i = 0; i < num_eyepoints; i++) { - if (!_eyepoints[i].build_record(writer)) { - assert(!flt_error_abort); - return FE_bad_data; - } - } - - int num_trackplanes = get_num_trackplanes(); - for (i = 0; i < num_trackplanes; i++) { - if (!_trackplanes[i].build_record(writer)) { - assert(!flt_error_abort); - return FE_bad_data; - } - } - - return writer.advance(); -} diff --git a/pandatool/src/flt/fltHeader.h b/pandatool/src/flt/fltHeader.h deleted file mode 100644 index 620e553a..00000000 --- a/pandatool/src/flt/fltHeader.h +++ /dev/null @@ -1,340 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltHeader.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTHEADER_H -#define FLTHEADER_H - -#include "pandatoolbase.h" - -#include "fltBeadID.h" -#include "fltVertex.h" -#include "fltMaterial.h" -#include "fltTexture.h" -#include "fltLightSourceDefinition.h" -#include "fltEyepoint.h" -#include "fltTrackplane.h" -#include "fltInstanceDefinition.h" - -#include "pathReplace.h" -#include "pointerTo.h" -#include "filename.h" -#include "dSearchPath.h" -#include "distanceUnit.h" -#include "pvector.h" -#include "pset.h" -#include "pmap.h" - -/** - * This is the first bead in the file, the top of the bead hierarchy, and the - * primary interface to reading and writing a Flt file. You always read a Flt - * file by creating a header and calling read_flt(), which fills in its - * children beads automatically; you write a Flt file by creating a header, - * adding its children, and calling write_flt(). - */ -class FltHeader : public FltBeadID { -public: - FltHeader(PathReplace *path_replace); - - virtual void apply_converted_filenames(); - - void set_path_replace(PathReplace *path_replace); - PathReplace *get_path_replace(); - const PathReplace *get_path_replace() const; - Filename convert_path(const Filename &orig_filename, - const DSearchPath &additional_path = DSearchPath()); - - void set_flt_filename(const Filename &flt_filename); - const Filename &get_flt_filename() const; - - FltError read_flt(Filename filename); - FltError read_flt(std::istream &in); - FltError write_flt(Filename filename); - FltError write_flt(std::ostream &out); - - enum AttrUpdate { - AU_none, - AU_if_missing, - AU_always - }; - - void set_auto_attr_update(AttrUpdate attr); - AttrUpdate get_auto_attr_update() const; - - enum Units { - U_meters = 0, - U_kilometers = 1, - U_feet = 4, - U_inches = 5, - U_nautical_miles = 8 - }; - - enum Flags { - F_save_vertex_normals = 0x80000000 - }; - - enum ProjectionType { - PT_flat_earth = 0, - PT_trapezoidal = 1, - PT_round_earth = 2, - PT_lambert = 3, - PT_utm = 4 - }; - - enum VertexStorageType { - VTS_double = 1 - }; - - enum DatabaseOrigin { - DO_open_flight = 100, - DO_dig = 200, - DO_es_ct6 = 300, - DO_psp = 400, - DO_ge_civ = 600, - DO_es_gdf = 700, - }; - - enum EarthModel { - EM_wgs84 = 0, - EM_wgs72 = 1, - EM_bessel = 2, - EM_clarke_1866 = 3, - EM_nad27 = 4 - }; - - int _format_revision_level; - int _edit_revision_level; - std::string _last_revision; - int _next_group_id; - int _next_lod_id; - int _next_object_id; - int _next_face_id; - int _unit_multiplier; - Units _vertex_units; - bool _texwhite_new; - unsigned int _flags; - ProjectionType _projection_type; - int _next_dof_id; - VertexStorageType _vertex_storage_type; - DatabaseOrigin _database_origin; - double _sw_x, _sw_y; - double _delta_x, _delta_y; - int _next_sound_id; - int _next_path_id; - int _next_clip_id; - int _next_text_id; - int _next_bsp_id; - int _next_switch_id; - double _sw_lat, _sw_long; - double _ne_lat, _ne_long; - double _origin_lat, _origin_long; - double _lambert_upper_lat, _lambert_lower_lat; - int _next_light_id; - int _next_road_id; - int _next_cat_id; - EarthModel _earth_model; - int _next_adaptive_id; - int _next_curve_id; - double _delta_z; - double _radius; - int _next_mesh_id; - -public: - int get_flt_version() const; - void set_flt_version(int version); - static int min_flt_version(); - static int max_flt_version(); - bool check_version() const; - - DistanceUnit get_units() const; - - // Accessors into the instance pool. - bool has_instance(int instance_index) const; - FltInstanceDefinition *get_instance(int instance_index) const; - void clear_instances(); - void add_instance(FltInstanceDefinition *instance); - void remove_instance(int instance_index); - - - // Accessors into the vertex palette. - int get_num_vertices() const; - FltVertex *get_vertex(int n) const; - void clear_vertices(); - void add_vertex(FltVertex *vertex); - - FltVertex *get_vertex_by_offset(int offset); - int get_offset_by_vertex(FltVertex *vertex); - - - // Accessors into the color palette. This is read-only; why would you want - // to mess with building a new color palette? - int get_num_colors() const; - LColor get_color(int color_index) const; - LRGBColor get_rgb(int color_index) const; - bool has_color_name(int color_index) const; - std::string get_color_name(int color_index) const; - - int get_closest_color(const LColor &color) const; - int get_closest_rgb(const LRGBColor &color) const; - - int get_num_color_entries() const; - int get_num_color_shades() const; - - // These functions are mainly used behind-the-scenes to decode the strange - // forest of color options defined for faces and vertices. - LColor get_color(int color_index, bool use_packed_color, - const FltPackedColor &packed_color, - int transparency); - LRGBColor get_rgb(int color_index, bool use_packed_color, - const FltPackedColor &packed_color); - - // Accessors into the material palette. - bool has_material(int material_index) const; - FltMaterial *get_material(int material_index) const; - void clear_materials(); - void add_material(FltMaterial *material); - void remove_material(int material_index); - - - // Accessors into the texture palette. - bool has_texture(int texture_index) const; - FltTexture *get_texture(int texture_index) const; - void clear_textures(); - void add_texture(FltTexture *texture); - void remove_texture(int texture_index); - - - // Accessors into the light source palette. - bool has_light_source(int light_index) const; - FltLightSourceDefinition *get_light_source(int light_index) const; - void clear_light_sources(); - void add_light_source(FltLightSourceDefinition *light_source); - void remove_light_source(int light_index); - - - // Accessors into the eyepointtrackplane palette. - bool got_eyepoint_trackplane_palette() const; - void set_eyepoint_trackplane_palette(bool flag); - - int get_num_eyepoints() const; - FltEyepoint *get_eyepoint(int n); - int get_num_trackplanes() const; - FltTrackplane *get_trackplane(int n); - -private: - // Instance subtrees. These are standalone subtrees, which may be - // referenced by various points in the hierarchy, stored by instance ID - // number. - typedef pmap Instances; - Instances _instances; - - - // Support for the vertex palette. - int update_vertex_lookups(); - - typedef pvector Vertices; - typedef pset UniqueVertices; - - typedef pmap VerticesByOffset; - typedef pmap OffsetsByVertex; - - Vertices _vertices; - UniqueVertices _unique_vertices; - VerticesByOffset _vertices_by_offset; - OffsetsByVertex _offsets_by_vertex; - - bool _vertex_lookups_stale; - - // This is maintained while the header is being read, to map the vertices to - // their corresponding offsets in the vertex palette. - int _current_vertex_offset; - - - // Support for the color palette. - bool _got_color_palette; - typedef pvector Colors; - typedef pmap ColorNames; - Colors _colors; - ColorNames _color_names; - - - // Support for the material palette. - bool _got_14_material_palette; - typedef pmap Materials; - Materials _materials; - int _next_material_index; - - - // Support for the texture palette. - AttrUpdate _auto_attr_update; - typedef pmap Textures; - Textures _textures; - int _next_pattern_index; - - - // Support for the light source palette. - typedef pmap LightSources; - LightSources _light_sources; - - - // Support for the eyepointtrackplane palette. - bool _got_eyepoint_trackplane_palette; - FltEyepoint _eyepoints[10]; - FltTrackplane _trackplanes[10]; - - // This pointer is used to resolve references in the flt file. - PT(PathReplace) _path_replace; - Filename _flt_filename; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool extract_ancillary(FltRecordReader &reader); - - virtual bool build_record(FltRecordWriter &writer) const; - virtual FltError write_ancillary(FltRecordWriter &writer) const; - -private: - bool extract_vertex(FltRecordReader &reader); - bool extract_color_palette(FltRecordReader &reader); - bool extract_material(FltRecordReader &reader); - bool extract_14_material_palette(FltRecordReader &reader); - bool extract_texture(FltRecordReader &reader); - bool extract_texture_map(FltRecordReader &reader); - bool extract_light_source(FltRecordReader &reader); - bool extract_eyepoint_palette(FltRecordReader &reader); - - FltError write_vertex_palette(FltRecordWriter &writer) const; - FltError write_color_palette(FltRecordWriter &writer) const; - FltError write_material_palette(FltRecordWriter &writer) const; - FltError write_texture_palette(FltRecordWriter &writer) const; - FltError write_light_source_palette(FltRecordWriter &writer) const; - FltError write_eyepoint_palette(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBeadID::init_type(); - register_type(_type_handle, "FltHeader", - FltBeadID::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltInstanceDefinition.cxx b/pandatool/src/flt/fltInstanceDefinition.cxx deleted file mode 100644 index 83cf3238..00000000 --- a/pandatool/src/flt/fltInstanceDefinition.cxx +++ /dev/null @@ -1,67 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltInstanceDefinition.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltInstanceDefinition.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltInstanceDefinition::_type_handle; - -/** - * - */ -FltInstanceDefinition:: -FltInstanceDefinition(FltHeader *header) : FltBead(header) { - _instance_index = 0; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltInstanceDefinition:: -extract_record(FltRecordReader &reader) { - if (!FltBead::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_instance, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(2); - _instance_index = iterator.get_be_int16(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltInstanceDefinition:: -build_record(FltRecordWriter &writer) const { - if (!FltBead::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_instance); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(2); - datagram.add_be_int16(_instance_index); - - return true; -} diff --git a/pandatool/src/flt/fltInstanceDefinition.h b/pandatool/src/flt/fltInstanceDefinition.h deleted file mode 100644 index 0a17f014..00000000 --- a/pandatool/src/flt/fltInstanceDefinition.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltInstanceDefinition.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTINSTANCEDEFINITION_H -#define FLTINSTANCEDEFINITION_H - -#include "pandatoolbase.h" - -#include "fltBead.h" - -/** - * This special kind of record marks the top node of an instance subtree. - * This subtree lives outside of the normal hierarchy, and is MultiGen's way - * of supporting instancing--each instance subtree has a unique index, which - * may be referenced in a FltInstanceRef object to make the instance appear in - * various places in the hierarchy. - */ -class FltInstanceDefinition : public FltBead { -public: - FltInstanceDefinition(FltHeader *header); - - int _instance_index; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBead::init_type(); - register_type(_type_handle, "FltInstanceDefinition", - FltBead::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltInstanceRef; - friend class FltRecordWriter; -}; - -#endif diff --git a/pandatool/src/flt/fltInstanceRef.cxx b/pandatool/src/flt/fltInstanceRef.cxx deleted file mode 100644 index f33ef3b1..00000000 --- a/pandatool/src/flt/fltInstanceRef.cxx +++ /dev/null @@ -1,112 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltInstanceRef.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltInstanceRef.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltInstanceDefinition.h" -#include "fltHeader.h" - -TypeHandle FltInstanceRef::_type_handle; - -/** - * - */ -FltInstanceRef:: -FltInstanceRef(FltHeader *header) : FltBead(header) { - _instance_index = 0; -} - -/** - * Returns the instance subtree referenced by this node, or NULL if the - * reference is invalid. - */ -FltInstanceDefinition *FltInstanceRef:: -get_instance() const { - return _header->get_instance(_instance_index); -} - -/** - * Writes a multiple-line description of the record and all of its children. - * This is a human-readable description, primarily for debugging; to write a - * flt file, use FltHeader::write_flt(). - */ -void FltInstanceRef:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) << "instance"; - FltInstanceDefinition *def = _header->get_instance(_instance_index); - if (def != nullptr) { - def->write_children(out, indent_level + 2); - indent(out, indent_level) << "}\n"; - } else { - out << "\n"; - } -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltInstanceRef:: -extract_record(FltRecordReader &reader) { - if (!FltBead::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_instance_ref, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(2); - _instance_index = iterator.get_be_int16(); - - check_remaining_size(iterator); - return true; -} - -/** - * Writes this record out to the flt file, along with all of its ancillary - * records and children records. Returns FE_ok on success, or something else - * on error. - */ -FltError FltInstanceRef:: -write_record_and_children(FltRecordWriter &writer) const { - // First, make sure our instance definition has already been written. - FltError result = writer.write_instance_def(_header, _instance_index); - if (result != FE_ok) { - return result; - } - - // Then write out our own record. - return FltBead::write_record_and_children(writer); -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltInstanceRef:: -build_record(FltRecordWriter &writer) const { - if (!FltBead::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_instance_ref); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(2); - datagram.add_be_int16(_instance_index); - - return true; -} diff --git a/pandatool/src/flt/fltInstanceRef.h b/pandatool/src/flt/fltInstanceRef.h deleted file mode 100644 index 2f8e281c..00000000 --- a/pandatool/src/flt/fltInstanceRef.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltInstanceRef.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTINSTANCEREF_H -#define FLTINSTANCEREF_H - -#include "pandatoolbase.h" - -#include "fltBead.h" - -class FltInstanceDefinition; - -/** - * This bead appears in the hierarchy to refer to a FltInstanceDefinition node - * defined elsewhere. It indicates that the subtree beginning at the - * FltInstanceDefinition should be considered to be instanced here. - */ -class FltInstanceRef : public FltBead { -public: - FltInstanceRef(FltHeader *header); - - int _instance_index; - - FltInstanceDefinition *get_instance() const; - - virtual void write(std::ostream &out, int indent_level = 0) const; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual FltError write_record_and_children(FltRecordWriter &writer) const; - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBead::init_type(); - register_type(_type_handle, "FltInstanceRef", - FltBead::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltLOD.cxx b/pandatool/src/flt/fltLOD.cxx deleted file mode 100644 index abe655ae..00000000 --- a/pandatool/src/flt/fltLOD.cxx +++ /dev/null @@ -1,91 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltLOD.cxx - * @author drose - * @date 2000-08-25 - */ - -#include "fltLOD.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltLOD::_type_handle; - -/** - * - */ -FltLOD:: -FltLOD(FltHeader *header) : FltBeadID(header) { - _switch_in = 0.0; - _switch_out = 0.0; - _special_id1 = 0; - _special_id2 = 0; - _flags = 0; - _center_x = 0.0; - _center_y = 0.0; - _center_z = 0.0; - _transition_range = 0.0; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltLOD:: -extract_record(FltRecordReader &reader) { - if (!FltBeadID::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_lod, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); - _switch_in = iterator.get_be_float64(); - _switch_out = iterator.get_be_float64(); - _special_id1 = iterator.get_be_int16(); - _special_id2 = iterator.get_be_int16(); - _flags = iterator.get_be_uint32(); - _center_x = iterator.get_be_float64(); - _center_y = iterator.get_be_float64(); - _center_z = iterator.get_be_float64(); - _transition_range = iterator.get_be_float64(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltLOD:: -build_record(FltRecordWriter &writer) const { - if (!FltBeadID::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_lod); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); - datagram.add_be_float64(_switch_in); - datagram.add_be_float64(_switch_out); - datagram.add_be_int16(_special_id1); - datagram.add_be_int16(_special_id2); - datagram.add_be_uint32(_flags); - datagram.add_be_float64(_center_x); - datagram.add_be_float64(_center_y); - datagram.add_be_float64(_center_z); - datagram.add_be_float64(_transition_range); - - return true; -} diff --git a/pandatool/src/flt/fltLOD.h b/pandatool/src/flt/fltLOD.h deleted file mode 100644 index 36e5ccb6..00000000 --- a/pandatool/src/flt/fltLOD.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltLOD.h - * @author drose - * @date 2000-08-25 - */ - -#ifndef FLTLOD_H -#define FLTLOD_H - -#include "pandatoolbase.h" - -#include "fltBeadID.h" - -/** - * A Level-of-Detail record. - */ -class FltLOD : public FltBeadID { -public: - FltLOD(FltHeader *header); - - enum Flags { - F_use_previous_slant = 0x80000000, - F_freeze_center = 0x20000000 - }; - - double _switch_in; - double _switch_out; - int _special_id1, _special_id2; - unsigned int _flags; - double _center_x; - double _center_y; - double _center_z; - double _transition_range; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBeadID::init_type(); - register_type(_type_handle, "FltLOD", - FltBeadID::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltLightSourceDefinition.cxx b/pandatool/src/flt/fltLightSourceDefinition.cxx deleted file mode 100644 index 52964251..00000000 --- a/pandatool/src/flt/fltLightSourceDefinition.cxx +++ /dev/null @@ -1,129 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltLightSourceDefinition.cxx - * @author drose - * @date 2000-08-26 - */ - -#include "fltLightSourceDefinition.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltLightSourceDefinition::_type_handle; - -/** - * - */ -FltLightSourceDefinition:: -FltLightSourceDefinition(FltHeader *header) : FltRecord(header) { - _light_index = 0; - _ambient.set(0.0, 0.0, 0.0, 1.0); - _diffuse.set(1.0, 1.0, 1.0, 1.0); - _specular.set(0.0, 0.0, 0.0, 1.0); - _light_type = LT_infinite; - _exponential_dropoff = 1.0; - _cutoff_angle = 180.0; - _yaw = 0.0; - _pitch = 0.0; - _constant_coefficient = 0.0; - _linear_coefficient = 0.0; - _quadratic_coefficient = 1.0; - _modeling_light = false; -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltLightSourceDefinition:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_light_definition, false); - DatagramIterator &iterator = reader.get_iterator(); - - _light_index = iterator.get_be_int32(); - iterator.skip_bytes(2*4); - _light_name = iterator.get_fixed_string(20); - iterator.skip_bytes(4); - _ambient[0] = iterator.get_be_float32(); - _ambient[1] = iterator.get_be_float32(); - _ambient[2] = iterator.get_be_float32(); - _ambient[3] = iterator.get_be_float32(); - _diffuse[0] = iterator.get_be_float32(); - _diffuse[1] = iterator.get_be_float32(); - _diffuse[2] = iterator.get_be_float32(); - _diffuse[3] = iterator.get_be_float32(); - _specular[0] = iterator.get_be_float32(); - _specular[1] = iterator.get_be_float32(); - _specular[2] = iterator.get_be_float32(); - _specular[3] = iterator.get_be_float32(); - _light_type = (LightType)iterator.get_be_int32(); - iterator.skip_bytes(4*10); - _exponential_dropoff = iterator.get_be_float32(); - _cutoff_angle = iterator.get_be_float32(); - _yaw = iterator.get_be_float32(); - _pitch = iterator.get_be_float32(); - _constant_coefficient = iterator.get_be_float32(); - _linear_coefficient = iterator.get_be_float32(); - _quadratic_coefficient = iterator.get_be_float32(); - _modeling_light = (iterator.get_be_int32() != 0); - iterator.skip_bytes(4*19); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltLightSourceDefinition:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_light_definition); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int32(_light_index); - datagram.pad_bytes(2*4); - datagram.add_fixed_string(_light_name, 20); - datagram.pad_bytes(4); - datagram.add_be_float32(_ambient[0]); - datagram.add_be_float32(_ambient[1]); - datagram.add_be_float32(_ambient[2]); - datagram.add_be_float32(_ambient[3]); - datagram.add_be_float32(_diffuse[0]); - datagram.add_be_float32(_diffuse[1]); - datagram.add_be_float32(_diffuse[2]); - datagram.add_be_float32(_diffuse[3]); - datagram.add_be_float32(_specular[0]); - datagram.add_be_float32(_specular[1]); - datagram.add_be_float32(_specular[2]); - datagram.add_be_float32(_specular[3]); - datagram.add_be_int32(_light_type); - datagram.pad_bytes(4*10); - datagram.add_be_float32(_exponential_dropoff); - datagram.add_be_float32(_cutoff_angle); - datagram.add_be_float32(_yaw); - datagram.add_be_float32(_pitch); - datagram.add_be_float32(_constant_coefficient); - datagram.add_be_float32(_linear_coefficient); - datagram.add_be_float32(_quadratic_coefficient); - datagram.add_be_int32(_modeling_light); - datagram.pad_bytes(4*19); - - return true; -} diff --git a/pandatool/src/flt/fltLightSourceDefinition.h b/pandatool/src/flt/fltLightSourceDefinition.h deleted file mode 100644 index e96d2752..00000000 --- a/pandatool/src/flt/fltLightSourceDefinition.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltLightSourceDefinition.h - * @author drose - * @date 2000-08-26 - */ - -#ifndef FLTLIGHTSOURCEDEFINITION_H -#define FLTLIGHTSOURCEDEFINITION_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" - -#include "luse.h" - -/** - * Represents a single entry in the light source palette. This completely - * defines the color, etc. of a single light source, which may be referenced - * later by a FltLightSource bead in the hierarchy. - */ -class FltLightSourceDefinition : public FltRecord { -public: - FltLightSourceDefinition(FltHeader *header); - - enum LightType { - LT_infinite = 0, - LT_local = 1, - LT_spot = 2 - }; - - int _light_index; - std::string _light_name; - LColor _ambient; - LColor _diffuse; - LColor _specular; - LightType _light_type; - PN_stdfloat _exponential_dropoff; - PN_stdfloat _cutoff_angle; // in degrees - - // yaw and pitch only for modeling lights, which are positioned at the - // eyepoint. - PN_stdfloat _yaw; - PN_stdfloat _pitch; - - PN_stdfloat _constant_coefficient; - PN_stdfloat _linear_coefficient; - PN_stdfloat _quadratic_coefficient; - bool _modeling_light; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltLightSourceDefinition", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltHeader; -}; - -#endif diff --git a/pandatool/src/flt/fltLocalVertexPool.I b/pandatool/src/flt/fltLocalVertexPool.I deleted file mode 100644 index d91696c8..00000000 --- a/pandatool/src/flt/fltLocalVertexPool.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltLocalVertexPool.I - * @author drose - * @date 2001-02-28 - */ diff --git a/pandatool/src/flt/fltLocalVertexPool.cxx b/pandatool/src/flt/fltLocalVertexPool.cxx deleted file mode 100644 index 96082ac7..00000000 --- a/pandatool/src/flt/fltLocalVertexPool.cxx +++ /dev/null @@ -1,234 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltLocalVertexPool.cxx - * @author drose - * @date 2001-02-28 - */ - -#include "fltLocalVertexPool.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "fltMaterial.h" - -TypeHandle FltLocalVertexPool::_type_handle; - -/** - * - */ -FltLocalVertexPool:: -FltLocalVertexPool(FltHeader *header) : FltRecord(header) { -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltLocalVertexPool:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_local_vertex_pool, false); - DatagramIterator &iterator = reader.get_iterator(); - - int num_vertices = iterator.get_be_int32(); - int attributes = iterator.get_be_int32(); - - for (int i = 0; i < num_vertices; i++) { - FltVertex *vertex = new FltVertex(_header); - _vertices.push_back(vertex); - - if ((attributes & AM_has_position) != 0) { - vertex->_pos[0] = iterator.get_be_float64(); - vertex->_pos[1] = iterator.get_be_float64(); - vertex->_pos[2] = iterator.get_be_float64(); - } - - if ((attributes & AM_has_color_index) != 0) { - vertex->_color_index = iterator.get_be_int32(); - - } else if ((attributes & AM_has_packed_color) != 0) { - if (!vertex->_packed_color.extract_record(reader)) { - return false; - } - vertex->_flags |= FltVertex::F_packed_color; - - } else { - vertex->_flags |= FltVertex::F_no_color; - } - - if ((attributes & AM_has_normal) != 0) { - vertex->_normal[0] = iterator.get_be_float32(); - vertex->_normal[1] = iterator.get_be_float32(); - vertex->_normal[2] = iterator.get_be_float32(); - vertex->_has_normal = true; - } - - if ((attributes & AM_has_base_uv) != 0) { - vertex->_uv[0] = iterator.get_be_float32(); - vertex->_uv[1] = iterator.get_be_float32(); - vertex->_has_uv = true; - } - - if ((attributes & AM_has_uv_1) != 0) { - iterator.get_be_float32(); - iterator.get_be_float32(); - } - - if ((attributes & AM_has_uv_2) != 0) { - iterator.get_be_float32(); - iterator.get_be_float32(); - } - - if ((attributes & AM_has_uv_3) != 0) { - iterator.get_be_float32(); - iterator.get_be_float32(); - } - - if ((attributes & AM_has_uv_4) != 0) { - iterator.get_be_float32(); - iterator.get_be_float32(); - } - - if ((attributes & AM_has_uv_5) != 0) { - iterator.get_be_float32(); - iterator.get_be_float32(); - } - - if ((attributes & AM_has_uv_6) != 0) { - iterator.get_be_float32(); - iterator.get_be_float32(); - } - - if ((attributes & AM_has_uv_7) != 0) { - iterator.get_be_float32(); - iterator.get_be_float32(); - } - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltLocalVertexPool:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_local_vertex_pool); - Datagram &datagram = writer.update_datagram(); - - // Determine what kind of vertices we have. - int attributes = AM_has_position; - - Vertices::const_iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - FltVertex *vertex = (*vi); - if ((vertex->_flags & FltVertex::F_no_color) != 0) { - // No color. - - } else if ((vertex->_flags & FltVertex::F_packed_color) != 0) { - // Packed color. - attributes |= AM_has_packed_color; - - } else { - // Indexed color. - attributes |= AM_has_color_index; - } - - if (vertex->_has_normal) { - attributes |= AM_has_normal; - } - - if (vertex->_has_uv) { - attributes |= AM_has_base_uv; - } - } - - if ((attributes & AM_has_packed_color) != 0 && - (attributes & AM_has_color_index) != 0) { - // We cannot have both a packed color and a color index. If we want both, - // used packed color. - attributes &= ~AM_has_color_index; - } - - datagram.add_be_int32(_vertices.size()); - datagram.add_be_int32(attributes); - - // Now write out each vertex. - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - FltVertex *vertex = (*vi); - - if ((attributes & AM_has_position) != 0) { - datagram.add_be_float64(vertex->_pos[0]); - datagram.add_be_float64(vertex->_pos[1]); - datagram.add_be_float64(vertex->_pos[2]); - } - - if ((attributes & AM_has_color_index) != 0) { - if ((vertex->_flags & (FltVertex::F_no_color | FltVertex::F_packed_color)) != 0) { - // This particular vertex does not have a color index. Make it white. - datagram.add_be_int32(_header->get_closest_rgb(LRGBColor(1.0, 1.0, 1.0))); - } else { - datagram.add_be_int32(vertex->_color_index); - } - - } else if ((attributes & AM_has_packed_color) != 0) { - // We extract our own FltPackedColor instead of writing out the vertex's - // _packed_color directly, just in case the vertex is actually index - // colored. This bit of code will work regardless of the kind of color - // the vertex has. - - FltPackedColor color; - if (vertex->has_color()) { - color.set_color(vertex->get_color()); - } else { - // An uncolored vertex. Make it white. - color.set_color(LColor(1.0, 1.0, 1.0, 1.0)); - } - - if (!color.build_record(writer)) { - return false; - } - } - - if ((attributes & AM_has_normal) != 0) { - if (!vertex->_has_normal) { - datagram.add_be_float32(0.0); - datagram.add_be_float32(0.0); - datagram.add_be_float32(0.0); - } else { - datagram.add_be_float32(vertex->_normal[0]); - datagram.add_be_float32(vertex->_normal[1]); - datagram.add_be_float32(vertex->_normal[2]); - } - } - - if ((attributes & AM_has_base_uv) != 0) { - if (!vertex->_has_uv) { - datagram.add_be_float32(0.0); - datagram.add_be_float32(0.0); - } else { - datagram.add_be_float32(vertex->_uv[0]); - datagram.add_be_float32(vertex->_uv[1]); - } - } - } - - return true; -} diff --git a/pandatool/src/flt/fltLocalVertexPool.h b/pandatool/src/flt/fltLocalVertexPool.h deleted file mode 100644 index f070dbc0..00000000 --- a/pandatool/src/flt/fltLocalVertexPool.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltLocalVertexPool.h - * @author drose - * @date 2001-02-28 - */ - -#ifndef FLTLOCALVERTEXPOOL_H -#define FLTLOCALVERTEXPOOL_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" -#include "fltHeader.h" -#include "fltVertex.h" - -#include "pointerTo.h" - -/** - * A local vertex pool, as might appear in the middle of the hierarchy, for - * instance for a mesh. - */ -class FltLocalVertexPool : public FltRecord { -public: - FltLocalVertexPool(FltHeader *header); - - // These bits are not stored in the vertex pool, but are read from the .flt - // file and used immediately. - enum AttributeMask { - AM_has_position = 0x80000000, - AM_has_color_index = 0x40000000, - AM_has_packed_color = 0x20000000, - AM_has_normal = 0x10000000, - AM_has_base_uv = 0x08000000, - AM_has_uv_1 = 0x04000000, - AM_has_uv_2 = 0x02000000, - AM_has_uv_3 = 0x01000000, - AM_has_uv_4 = 0x00800000, - AM_has_uv_5 = 0x00400000, - AM_has_uv_6 = 0x00200000, - AM_has_uv_7 = 0x00100000 - }; - - typedef pvector Vertices; - Vertices _vertices; - -public: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltLocalVertexPool", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "fltLocalVertexPool.I" - -#endif diff --git a/pandatool/src/flt/fltMaterial.cxx b/pandatool/src/flt/fltMaterial.cxx deleted file mode 100644 index 81411696..00000000 --- a/pandatool/src/flt/fltMaterial.cxx +++ /dev/null @@ -1,164 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMaterial.cxx - * @author drose - * @date 2000-08-25 - */ - -#include "fltMaterial.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltMaterial::_type_handle; - -/** - * - */ -FltMaterial:: -FltMaterial(FltHeader *header) : FltRecord(header) { - _material_index = -1; - _flags = 0; - _ambient.set(0.0, 0.0, 0.0); - _diffuse.set(0.0, 0.0, 0.0); - _specular.set(0.0, 0.0, 0.0); - _emissive.set(0.0, 0.0, 0.0); - _shininess = 0.0; - _alpha = 1.0; -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltMaterial:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_15_material, false); - DatagramIterator &iterator = reader.get_iterator(); - - _material_index = iterator.get_be_int32(); - _material_name = iterator.get_fixed_string(12); - _flags = iterator.get_be_uint32(); - _ambient[0] = iterator.get_be_float32(); - _ambient[1] = iterator.get_be_float32(); - _ambient[2] = iterator.get_be_float32(); - _diffuse[0] = iterator.get_be_float32(); - _diffuse[1] = iterator.get_be_float32(); - _diffuse[2] = iterator.get_be_float32(); - _specular[0] = iterator.get_be_float32(); - _specular[1] = iterator.get_be_float32(); - _specular[2] = iterator.get_be_float32(); - _emissive[0] = iterator.get_be_float32(); - _emissive[1] = iterator.get_be_float32(); - _emissive[2] = iterator.get_be_float32(); - _shininess = iterator.get_be_float32(); - _alpha = iterator.get_be_float32(); - iterator.skip_bytes(4); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltMaterial:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_15_material); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int32(_material_index); - datagram.add_fixed_string(_material_name, 12); - datagram.add_be_uint32(_flags); - datagram.add_be_float32(_ambient[0]); - datagram.add_be_float32(_ambient[1]); - datagram.add_be_float32(_ambient[2]); - datagram.add_be_float32(_diffuse[0]); - datagram.add_be_float32(_diffuse[1]); - datagram.add_be_float32(_diffuse[2]); - datagram.add_be_float32(_specular[0]); - datagram.add_be_float32(_specular[1]); - datagram.add_be_float32(_specular[2]); - datagram.add_be_float32(_emissive[0]); - datagram.add_be_float32(_emissive[1]); - datagram.add_be_float32(_emissive[2]); - datagram.add_be_float32(_shininess); - datagram.add_be_float32(_alpha); - datagram.pad_bytes(4); - - return true; -} - -/** - * Fills in the information in this record based on the information from the - * current position within the v14 material palette. Leaves the iterator at - * the beginning of the next material. - */ -bool FltMaterial:: -extract_14_record(int index, DatagramIterator &di) { - _material_index = index; - - _ambient[0] = di.get_be_float32(); - _ambient[1] = di.get_be_float32(); - _ambient[2] = di.get_be_float32(); - _diffuse[0] = di.get_be_float32(); - _diffuse[1] = di.get_be_float32(); - _diffuse[2] = di.get_be_float32(); - _specular[0] = di.get_be_float32(); - _specular[1] = di.get_be_float32(); - _specular[2] = di.get_be_float32(); - _emissive[0] = di.get_be_float32(); - _emissive[1] = di.get_be_float32(); - _emissive[2] = di.get_be_float32(); - _shininess = di.get_be_float32(); - _alpha = di.get_be_float32(); - _flags = di.get_be_uint32(); - _material_name = di.get_fixed_string(12); - di.skip_bytes(4 * 28); - - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, formatted as a part of a v14 material palette. Returns true on - * success, false if there is some error. - */ -bool FltMaterial:: -build_14_record(Datagram &datagram) { - datagram.add_be_float32(_ambient[0]); - datagram.add_be_float32(_ambient[1]); - datagram.add_be_float32(_ambient[2]); - datagram.add_be_float32(_diffuse[0]); - datagram.add_be_float32(_diffuse[1]); - datagram.add_be_float32(_diffuse[2]); - datagram.add_be_float32(_specular[0]); - datagram.add_be_float32(_specular[1]); - datagram.add_be_float32(_specular[2]); - datagram.add_be_float32(_emissive[0]); - datagram.add_be_float32(_emissive[1]); - datagram.add_be_float32(_emissive[2]); - datagram.add_be_float32(_shininess); - datagram.add_be_float32(_alpha); - datagram.add_be_uint32(_flags); - datagram.add_fixed_string(_material_name, 12); - datagram.pad_bytes(4 * 28); - - return true; -} diff --git a/pandatool/src/flt/fltMaterial.h b/pandatool/src/flt/fltMaterial.h deleted file mode 100644 index fadc3acc..00000000 --- a/pandatool/src/flt/fltMaterial.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMaterial.h - * @author drose - * @date 2000-08-25 - */ - -#ifndef FLTMATERIAL_H -#define FLTMATERIAL_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" - -#include "luse.h" - -class DatagramIterator; - -/** - * Represents a single material in the material palette. - */ -class FltMaterial : public FltRecord { -public: - FltMaterial(FltHeader *header); - - enum Flags { - F_materials_used = 0x80000000, - }; - - int _material_index; - std::string _material_name; - unsigned int _flags; - LRGBColor _ambient; - LRGBColor _diffuse; - LRGBColor _specular; - LRGBColor _emissive; - PN_stdfloat _shininess; - PN_stdfloat _alpha; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - bool extract_14_record(int index, DatagramIterator &di); - bool build_14_record(Datagram &datagram); - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltMaterial", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltHeader; -}; - -#endif diff --git a/pandatool/src/flt/fltMesh.I b/pandatool/src/flt/fltMesh.I deleted file mode 100644 index d1d9c0de..00000000 --- a/pandatool/src/flt/fltMesh.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMesh.I - * @author drose - * @date 2001-02-28 - */ diff --git a/pandatool/src/flt/fltMesh.cxx b/pandatool/src/flt/fltMesh.cxx deleted file mode 100644 index e77b8636..00000000 --- a/pandatool/src/flt/fltMesh.cxx +++ /dev/null @@ -1,110 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMesh.cxx - * @author drose - * @date 2001-02-28 - */ - -#include "fltMesh.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "fltMaterial.h" -#include "config_flt.h" - -TypeHandle FltMesh::_type_handle; - -/** - * - */ -FltMesh:: -FltMesh(FltHeader *header) : FltGeometry(header) { -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltMesh:: -extract_record(FltRecordReader &reader) { - if (!FltBeadID::extract_record(reader)) { - return false; - } - - DatagramIterator &iterator = reader.get_iterator(); - iterator.skip_bytes(4); // Undocumented padding. - - if (!FltGeometry::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_mesh, false); - - check_remaining_size(iterator); - return true; -} - -/** - * Checks whether the given bead, which follows this bead sequentially in the - * file, is an ancillary record of this bead. If it is, extracts the relevant - * information and returns true; otherwise, leaves it alone and returns false. - */ -bool FltMesh:: -extract_ancillary(FltRecordReader &reader) { - if (reader.get_opcode() == FO_local_vertex_pool) { - _vpool = new FltLocalVertexPool(_header); - return _vpool->extract_record(reader); - } - - return FltBeadID::extract_ancillary(reader); -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltMesh:: -build_record(FltRecordWriter &writer) const { - if (!FltBeadID::build_record(writer)) { - return false; - } - - Datagram &datagram = writer.update_datagram(); - datagram.pad_bytes(4); // Undocumented padding. - - if (!FltGeometry::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_mesh); - - return true; -} - -/** - * Writes whatever ancillary records are required for this record. Returns - * FE_ok on success, or something else if there is some error. - */ -FltError FltMesh:: -write_ancillary(FltRecordWriter &writer) const { - if (_vpool != nullptr) { - if (!_vpool->build_record(writer)) { - assert(!flt_error_abort); - return FE_bad_data; - } - FltError result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - return FltBeadID::write_ancillary(writer); -} diff --git a/pandatool/src/flt/fltMesh.h b/pandatool/src/flt/fltMesh.h deleted file mode 100644 index a66bdf62..00000000 --- a/pandatool/src/flt/fltMesh.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMesh.h - * @author drose - * @date 2001-02-28 - */ - -#ifndef FLTMESH_H -#define FLTMESH_H - -#include "pandatoolbase.h" - -#include "fltGeometry.h" -#include "fltLocalVertexPool.h" - -#include "pointerTo.h" - -/** - * A mesh of connected polygons and tristrips, etc., with a local vertex pool. - */ -class FltMesh : public FltGeometry { -public: - FltMesh(FltHeader *header); - - PT(FltLocalVertexPool) _vpool; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool extract_ancillary(FltRecordReader &reader); - - virtual bool build_record(FltRecordWriter &writer) const; - virtual FltError write_ancillary(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltGeometry::init_type(); - register_type(_type_handle, "FltMesh", - FltGeometry::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "fltMesh.I" - -#endif diff --git a/pandatool/src/flt/fltMeshPrimitive.I b/pandatool/src/flt/fltMeshPrimitive.I deleted file mode 100644 index 70923ab8..00000000 --- a/pandatool/src/flt/fltMeshPrimitive.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMeshPrimitive.I - * @author drose - * @date 2001-02-28 - */ diff --git a/pandatool/src/flt/fltMeshPrimitive.cxx b/pandatool/src/flt/fltMeshPrimitive.cxx deleted file mode 100644 index 6db78c80..00000000 --- a/pandatool/src/flt/fltMeshPrimitive.cxx +++ /dev/null @@ -1,126 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMeshPrimitive.cxx - * @author drose - * @date 2001-02-28 - */ - -#include "fltMeshPrimitive.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "fltMaterial.h" - -TypeHandle FltMeshPrimitive::_type_handle; - -/** - * - */ -FltMeshPrimitive:: -FltMeshPrimitive(FltHeader *header) : FltBead(header) { - _primitive_type = PT_tristrip; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltMeshPrimitive:: -extract_record(FltRecordReader &reader) { - if (!FltBead::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_mesh_primitive, false); - DatagramIterator &iterator = reader.get_iterator(); - - _primitive_type = (PrimitiveType)iterator.get_be_int16(); - - int vertex_width = iterator.get_be_int16(); - int num_vertices = iterator.get_be_int32(); - - if (vertex_width == 1) { - for (int i = 0; i < num_vertices; i++) { - _vertices.push_back(iterator.get_uint8()); - } - - } else if (vertex_width == 2) { - for (int i = 0; i < num_vertices; i++) { - _vertices.push_back(iterator.get_be_uint16()); - } - - } else if (vertex_width == 4) { - for (int i = 0; i < num_vertices; i++) { - _vertices.push_back(iterator.get_be_int32()); - } - - } else { - nout << "Invalid vertex width in mesh primitive: " << vertex_width - << "\n"; - return false; - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltMeshPrimitive:: -build_record(FltRecordWriter &writer) const { - if (!FltBead::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_mesh_primitive); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int16(_primitive_type); - - // Determine the optimum index width, based on the largest vertex index. - int max_index = 0; - Vertices::const_iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - max_index = std::max(max_index, (*vi)); - } - - int vertex_width; - if (max_index < 0x100) { - vertex_width = 1; - } else if (max_index < 0x10000) { - vertex_width = 2; - } else { - vertex_width = 4; - } - - datagram.add_be_int16(vertex_width); - datagram.add_be_int32(_vertices.size()); - - if (vertex_width == 1) { - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - datagram.add_uint8(*vi); - } - - } else if (vertex_width == 2) { - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - datagram.add_be_uint16(*vi); - } - - } else { - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - datagram.add_be_int32(*vi); - } - } - - return true; -} diff --git a/pandatool/src/flt/fltMeshPrimitive.h b/pandatool/src/flt/fltMeshPrimitive.h deleted file mode 100644 index bca21cc4..00000000 --- a/pandatool/src/flt/fltMeshPrimitive.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltMeshPrimitive.h - * @author drose - * @date 2001-02-28 - */ - -#ifndef FLTMESHPRIMITIVE_H -#define FLTMESHPRIMITIVE_H - -#include "pandatoolbase.h" - -#include "fltBead.h" -#include "fltHeader.h" - -#include "luse.h" -#include "vector_int.h" - -/** - * A single primitive of a mesh, like a triangle strip or fan. - */ -class FltMeshPrimitive : public FltBead { -public: - FltMeshPrimitive(FltHeader *header); - - enum PrimitiveType { - PT_tristrip = 1, - PT_trifan = 2, - PT_quadstrip = 3, - PT_polygon = 4, - }; - - typedef vector_int Vertices; - - PrimitiveType _primitive_type; - Vertices _vertices; - - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBead::init_type(); - register_type(_type_handle, "FltMeshPrimitive", - FltBead::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "fltMeshPrimitive.I" - -#endif diff --git a/pandatool/src/flt/fltObject.cxx b/pandatool/src/flt/fltObject.cxx deleted file mode 100644 index ce809741..00000000 --- a/pandatool/src/flt/fltObject.cxx +++ /dev/null @@ -1,76 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltObject.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltObject.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltObject::_type_handle; - -/** - * - */ -FltObject:: -FltObject(FltHeader *header) : FltBeadID(header) { -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltObject:: -extract_record(FltRecordReader &reader) { - if (!FltBeadID::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_object, false); - DatagramIterator &iterator = reader.get_iterator(); - - _flags = iterator.get_be_uint32(); - _relative_priority = iterator.get_be_int16(); - _transparency = iterator.get_be_int16(); - _special_id1 = iterator.get_be_int16(); - _special_id2 = iterator.get_be_int16(); - _significance = iterator.get_be_int16(); - iterator.skip_bytes(2); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltObject:: -build_record(FltRecordWriter &writer) const { - if (!FltBeadID::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_object); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_uint32(_flags); - datagram.add_be_int16(_relative_priority); - datagram.add_be_int16(_transparency); - datagram.add_be_int16(_special_id1); - datagram.add_be_int16(_special_id2); - datagram.add_be_int16(_significance); - datagram.pad_bytes(2); - - return true; -} diff --git a/pandatool/src/flt/fltObject.h b/pandatool/src/flt/fltObject.h deleted file mode 100644 index 35a77ce7..00000000 --- a/pandatool/src/flt/fltObject.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltObject.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTOBJECT_H -#define FLTOBJECT_H - -#include "pandatoolbase.h" - -#include "fltBeadID.h" - -/** - * The main objecting bead of the flt file. - */ -class FltObject : public FltBeadID { -public: - FltObject(FltHeader *header); - - enum Flags { - F_no_daylight = 0x80000000, - F_no_dusk = 0x40000000, - F_no_night = 0x20000000, - F_no_illuminate = 0x10000000, - F_flat_shaded = 0x08000000, - F_shadow_object = 0x04000000, - }; - - unsigned int _flags; - int _relative_priority; - int _transparency; - int _special_id1, _special_id2; - int _significance; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltBeadID::init_type(); - register_type(_type_handle, "FltObject", - FltBeadID::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltOpcode.cxx b/pandatool/src/flt/fltOpcode.cxx deleted file mode 100644 index 92fd64af..00000000 --- a/pandatool/src/flt/fltOpcode.cxx +++ /dev/null @@ -1,297 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltOpcode.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltOpcode.h" - -std::ostream & -operator << (std::ostream &out, FltOpcode opcode) { - switch (opcode) { - case FO_none: - return out << "null opcode"; - - case FO_header: - return out << "header"; - - case FO_group: - return out << "group"; - - case FO_OB_scale: - case FO_OB_scale2: - case FO_OB_scale3: - return out << "(obsolete) scale"; - - case FO_object: - return out << "object"; - - case FO_face: - return out << "face"; - - case FO_OB_vertex_i: - return out << "(obsolete) vertex with ID"; - - case FO_OB_short_vertex: - return out << "(obsolete) short vertex"; - - case FO_OB_vertex_c: - return out << "(obsolete) vertex with color"; - - case FO_OB_vertex_cn: - return out << "(obsolete) vertex with color and normal"; - - case FO_push: - return out << "push"; - - case FO_pop: - return out << "pop"; - - case FO_OB_translate: - case FO_OB_translate2: - case FO_OB_translate3: - return out << "(obsolete) translate"; - - case FO_OB_dof: - return out << "(obsolete) degree-of-freedom"; - - case FO_dof: - return out << "degree-of-freedom"; - - case FO_OB_instance_ref: - return out << "(obsolete) instance reference"; - - case FO_OB_instance: - return out << "(obsolete) instance definition"; - - case FO_push_face: - return out << "push subface"; - - case FO_pop_face: - return out << "pop subface"; - - case FO_push_extension: - return out << "push extension"; - - case FO_pop_extension: - return out << "pop extension"; - - case FO_continuation: - return out << "continuation"; - - case FO_comment: - return out << "comment"; - - case FO_color_palette: - return out << "color palette"; - - case FO_long_id: - return out << "long ID"; - - case FO_transform_matrix: - return out << "transformation matrix"; - - case FO_OB_rotate_point: - case FO_OB_rotate_point2: - return out << "(obsolete) rotate about point"; - - case FO_OB_rotate_edge: - return out << "(obsolete) rotate about edge"; - - case FO_OB_nu_scale: - return out << "(obsolete) non-uniform scale"; - - case FO_OB_rotate_to_point: - return out << "(obsolete) rotate to point"; - - case FO_OB_put: - return out << "(obsolete) put"; - - case FO_OB_bounding_box: - return out << "(obsolete) bounding box"; - - case FO_vector: - return out << "vector"; - - case FO_multitexture: - return out << "multitexture"; - - case FO_uv_list: - return out << "UV list"; - - case FO_bsp: - return out << "BSP"; - - case FO_replicate: - return out << "replicate"; - - case FO_instance_ref: - return out << "instance reference"; - - case FO_instance: - return out << "instance definition"; - - case FO_external_ref: - return out << "external reference"; - - case FO_texture: - return out << "texture"; - - case FO_OB_eyepoint_palette: - return out << "(obsolete) eyepoint palette"; - - case FO_14_material_palette: - return out << "v14 material palette"; - - case FO_vertex_palette: - return out << "vertex palette"; - - case FO_vertex_c: - return out << "vertex with color"; - - case FO_vertex_cn: - return out << "vertex with color and normal"; - - case FO_vertex_cnu: - return out << "vertex with color, normal, and uv"; - - case FO_vertex_cu: - return out << "vertex with color and uv"; - - case FO_vertex_list: - return out << "vertex list"; - - case FO_lod: - return out << "LOD"; - - case FO_bounding_box: - return out << "bounding box"; - - case FO_rotate_about_edge: - return out << "rotate about edge"; - - case FO_translate: - return out << "translate"; - - case FO_scale: - return out << "scale"; - - case FO_rotate_about_point: - return out << "rotate about point"; - - case FO_rotate_and_scale: - return out << "rotate and/or scale"; - - case FO_put: - return out << "put"; - - case FO_eyepoint_palette: - return out << "eyepoint palette"; - - case FO_mesh: - return out << "mesh"; - - case FO_local_vertex_pool: - return out << "local vertex pool"; - - case FO_mesh_primitive: - return out << "mesh primitive"; - - case FO_road_segment: - return out << "road segment"; - - case FO_road_zone: - return out << "road zone"; - - case FO_morph_list: - return out << "morph vertex list"; - - case FO_behavior_palette: - return out << "behavior palette"; - - case FO_sound: - return out << "sound"; - - case FO_road_path: - return out << "road path"; - - case FO_sound_palette: - return out << "sound palette"; - - case FO_general_matrix: - return out << "general matrix"; - - case FO_text: - return out << "text"; - - case FO_switch: - return out << "switch"; - - case FO_line_style: - return out << "line style"; - - case FO_clip_region: - return out << "clip region"; - - case FO_light_source: - return out << "light source"; - - case FO_light_definition: - return out << "light source definition"; - - case FO_bounding_sphere: - return out << "bounding sphere"; - - case FO_bounding_cylinder: - return out << "bounding cylinder"; - - case FO_bv_center: - return out << "bounding volume center"; - - case FO_bv_orientation: - return out << "bounding volume orientation"; - - case FO_light_point: - return out << "light point"; - - case FO_texture_map_palette: - return out << "texture mapping palette"; - - case FO_15_material: - return out << "material"; - - case FO_name_table: - return out << "name table"; - - case FO_cat: - return out << "continuously adaptive terrain"; - - case FO_cat_data: - return out << "CAT Data"; - - case FO_push_attribute: - return out << "push attribute"; - - case FO_pop_attribute: - return out << "pop attribute"; - - case FO_adaptive_attribute: - return out << "adaptive attribute"; - - case FO_curve: - return out << "curve"; - - case FO_road_construction: - return out << "road construction"; - - default: - return out << "unknown opcode " << (int)opcode; - } -} diff --git a/pandatool/src/flt/fltOpcode.h b/pandatool/src/flt/fltOpcode.h deleted file mode 100644 index f9bbeb9e..00000000 --- a/pandatool/src/flt/fltOpcode.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltOpcode.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTOPCODE_H -#define FLTOPCODE_H - -#include "pandatoolbase.h" - -// Known opcodes, as of the latest version of flt. -enum FltOpcode { - FO_none = 0, - FO_header = 1, - FO_group = 2, - FO_OB_scale = 3, // obsolete - FO_object = 4, - FO_face = 5, - FO_OB_vertex_i = 6, // obsolete - FO_OB_short_vertex = 7, // obsolete - FO_OB_vertex_c = 8, // obsolete - FO_OB_vertex_cn = 9, // obsolete - FO_push = 10, - FO_pop = 11, - FO_OB_translate = 12, // obsolete - FO_OB_dof = 13, // obsolete - FO_dof = 14, - FO_OB_instance_ref = 16, // obsolete - FO_OB_instance = 17, // obsolete - FO_push_face = 19, - FO_pop_face = 20, - FO_push_extension = 21, - FO_pop_extension = 22, - FO_continuation = 23, - - FO_comment = 31, - FO_color_palette = 32, - FO_long_id = 33, - FO_OB_translate2 = 40, // obsolete - FO_OB_rotate_point = 41, // obsolete - FO_OB_rotate_edge = 42, // obsolete - FO_OB_scale2 = 43, // obsolete - FO_OB_translate3 = 44, // obsolete - FO_OB_nu_scale = 45, // obsolete - FO_OB_rotate_point2 = 46, // obsolete - FO_OB_rotate_to_point = 47, // obsolete - FO_OB_put = 48, // obsolete - FO_transform_matrix = 49, - FO_vector = 50, - FO_OB_bounding_box = 51, // obsolete - FO_multitexture = 52, - FO_uv_list = 53, - FO_bsp = 55, - FO_replicate = 60, - FO_instance_ref = 61, - FO_instance = 62, - FO_external_ref = 63, - FO_texture = 64, - FO_OB_eyepoint_palette = 65, // obsolete - FO_14_material_palette = 66, - FO_vertex_palette = 67, - FO_vertex_c = 68, - FO_vertex_cn = 69, - FO_vertex_cnu = 70, - FO_vertex_cu = 71, - FO_vertex_list = 72, - FO_lod = 73, - FO_bounding_box = 74, - FO_rotate_about_edge = 76, - FO_OB_scale3 = 77, // obsolete - FO_translate = 78, - FO_scale = 79, - FO_rotate_about_point = 80, - FO_rotate_and_scale = 81, - FO_put = 82, - FO_eyepoint_palette = 83, - FO_mesh = 84, - FO_local_vertex_pool = 85, - FO_mesh_primitive = 86, - FO_road_segment = 87, - FO_road_zone = 88, - FO_morph_list = 89, - FO_behavior_palette = 90, - FO_sound = 91, - FO_road_path = 92, - FO_sound_palette = 93, - FO_general_matrix = 94, - FO_text = 95, - FO_switch = 96, - FO_line_style = 97, - FO_clip_region = 98, - FO_extension = 100, - FO_light_source = 101, - FO_light_definition = 102, - FO_bounding_sphere = 105, - FO_bounding_cylinder = 106, - FO_bv_center = 108, - FO_bv_orientation = 109, - FO_light_point = 111, - FO_texture_map_palette = 112, - FO_15_material = 113, - FO_name_table = 114, - FO_cat = 115, - FO_cat_data = 116, - FO_push_attribute = 122, - FO_pop_attribute = 123, - FO_adaptive_attribute = 125, - FO_curve = 126, - FO_road_construction = 127 -}; - -std::ostream &operator << (std::ostream &out, FltOpcode opcode); - -#endif diff --git a/pandatool/src/flt/fltPackedColor.I b/pandatool/src/flt/fltPackedColor.I deleted file mode 100644 index 50ae5906..00000000 --- a/pandatool/src/flt/fltPackedColor.I +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltPackedColor.I - * @author drose - * @date 2000-08-25 - */ - -INLINE std::ostream & -operator << (std::ostream &out, const FltPackedColor &color) { - color.output(out); - return out; -} - - -/** - * - */ -INLINE FltPackedColor:: -FltPackedColor() { - _a = 0; - _b = 0; - _g = 0; - _r = 0; -} - -/** - * Returns the four-component color as a LColor, where each component is in - * the range [0, 1]. - */ -INLINE LColor FltPackedColor:: -get_color() const { - return LColor(_r / 255.0, _g / 255.0, _b / 255.0, _a / 255.0); -} - -/** - * Returns the three-component color as an LRGBColor (ignoring the alpha - * component), where each component is in the range [0, 1]. - */ -INLINE LRGBColor FltPackedColor:: -get_rgb() const { - return LRGBColor(_r / 255.0, _g / 255.0, _b / 255.0); -} - -/** - * Sets the color according to the indicated four-component LColor value - * (including alpha). - */ -INLINE void FltPackedColor:: -set_color(const LColor &color) { - _r = (int)floor(color[0] * 255.0); - _g = (int)floor(color[1] * 255.0); - _b = (int)floor(color[2] * 255.0); - _a = (int)floor(color[3] * 255.0); -} - -/** - * Sets the color according to the indicated three-component LRGBColor value, - * and set the alpha to 1.0. - */ -INLINE void FltPackedColor:: -set_rgb(const LRGBColor &color) { - _r = (int)floor(color[0] * 255.0); - _g = (int)floor(color[1] * 255.0); - _b = (int)floor(color[2] * 255.0); - _a = 255; -} diff --git a/pandatool/src/flt/fltPackedColor.cxx b/pandatool/src/flt/fltPackedColor.cxx deleted file mode 100644 index 0faa4eb6..00000000 --- a/pandatool/src/flt/fltPackedColor.cxx +++ /dev/null @@ -1,54 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltPackedColor.cxx - * @author drose - * @date 2000-08-25 - */ - -#include "fltPackedColor.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -/** - * - */ -void FltPackedColor:: -output(std::ostream &out) const { - out << "(" << _r << " " << _g << " " << _b << " " << _a << ")"; -} - -/** - * - */ -bool FltPackedColor:: -extract_record(FltRecordReader &reader) { - DatagramIterator &iterator = reader.get_iterator(); - - _a = iterator.get_uint8(); - _b = iterator.get_uint8(); - _g = iterator.get_uint8(); - _r = iterator.get_uint8(); - - return true; -} - -/** - * - */ -bool FltPackedColor:: -build_record(FltRecordWriter &writer) const { - Datagram &datagram = writer.update_datagram(); - - datagram.add_uint8(_a); - datagram.add_uint8(_b); - datagram.add_uint8(_g); - datagram.add_uint8(_r); - - return true; -} diff --git a/pandatool/src/flt/fltPackedColor.h b/pandatool/src/flt/fltPackedColor.h deleted file mode 100644 index 1e38e02b..00000000 --- a/pandatool/src/flt/fltPackedColor.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltPackedColor.h - * @author drose - * @date 2000-08-25 - */ - -#ifndef FLTPACKEDCOLOR_H -#define FLTPACKEDCOLOR_H - -#include "pandatoolbase.h" - -#include "luse.h" -#include - -class FltRecordReader; -class FltRecordWriter; - -/** - * A packed color record, A, B, G, R. This appears, for instance, within a - * face bead. - */ -class FltPackedColor { -public: - INLINE FltPackedColor(); - - INLINE LColor get_color() const; - INLINE LRGBColor get_rgb() const; - INLINE void set_color(const LColor &color); - INLINE void set_rgb(const LRGBColor &rgb); - - void output(std::ostream &out) const; - bool extract_record(FltRecordReader &reader); - bool build_record(FltRecordWriter &writer) const; - -public: - int _a; - int _b; - int _g; - int _r; -}; - -INLINE std::ostream &operator << (std::ostream &out, const FltPackedColor &color); - -#include "fltPackedColor.I" - -#endif diff --git a/pandatool/src/flt/fltRecord.I b/pandatool/src/flt/fltRecord.I deleted file mode 100644 index add78f2d..00000000 --- a/pandatool/src/flt/fltRecord.I +++ /dev/null @@ -1,18 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltRecord.I - * @author drose - * @date 2000-08-24 - */ - -INLINE std::ostream & -operator << (std::ostream &out, const FltRecord &record) { - record.output(out); - return out; -} diff --git a/pandatool/src/flt/fltRecord.cxx b/pandatool/src/flt/fltRecord.cxx deleted file mode 100644 index 9fcc52fc..00000000 --- a/pandatool/src/flt/fltRecord.cxx +++ /dev/null @@ -1,746 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltRecord.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltRecord.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "fltGroup.h" -#include "fltObject.h" -#include "fltFace.h" -#include "fltCurve.h" -#include "fltMesh.h" -#include "fltLocalVertexPool.h" -#include "fltMeshPrimitive.h" -#include "fltVertexList.h" -#include "fltLOD.h" -#include "fltInstanceDefinition.h" -#include "fltInstanceRef.h" -#include "fltUnsupportedRecord.h" -#include "fltExternalReference.h" -#include "fltVectorRecord.h" -#include "config_flt.h" - -#include "dcast.h" -#include "indent.h" -#include "datagramIterator.h" - -#include - -TypeHandle FltRecord::_type_handle; - -/** - * - */ -FltRecord:: -FltRecord(FltHeader *header) : - _header(header) -{ -} - -/** - * - */ -FltRecord:: -~FltRecord() { -} - -/** - * Returns the number of child records of this record. This reflects the - * normal scene graph hierarchy. - */ -int FltRecord:: -get_num_children() const { - return _children.size(); -} - -/** - * Returns the nth child of this record. - */ -FltRecord *FltRecord:: -get_child(int n) const { - nassertr(n >= 0 && n < (int)_children.size(), nullptr); - return _children[n]; -} - -/** - * Removes all children from this record. - */ -void FltRecord:: -clear_children() { - _children.clear(); -} - -/** - * Adds a new child to the end of the list of children for this record. - */ -void FltRecord:: -add_child(FltRecord *child) { - _children.push_back(child); -} - -/** - * Returns the number of subface records of this record. Normally, subfaces - * will only be present on object records, although it is logically possible - * for them to appear anywhere. - */ -int FltRecord:: -get_num_subfaces() const { - return _subfaces.size(); -} - -/** - * Returns the nth subface of this record. - */ -FltRecord *FltRecord:: -get_subface(int n) const { - nassertr(n >= 0 && n < (int)_subfaces.size(), nullptr); - return _subfaces[n]; -} - -/** - * Removes all subfaces from this record. - */ -void FltRecord:: -clear_subfaces() { - _subfaces.clear(); -} - -/** - * Adds a new subface to the end of the list of subfaces for this record. - */ -void FltRecord:: -add_subface(FltRecord *subface) { - _subfaces.push_back(subface); -} - -/** - * Returns the number of extension attribute records for this object. These - * are auxiliary nodes, presumably of type FO_extension, that have some local - * meaning to the object. - */ -int FltRecord:: -get_num_extensions() const { - return _extensions.size(); -} - -/** - * Returns the nth extension of this record. - */ -FltRecord *FltRecord:: -get_extension(int n) const { - nassertr(n >= 0 && n < (int)_extensions.size(), nullptr); - return _extensions[n]; -} - -/** - * Removes all extensions from this record. - */ -void FltRecord:: -clear_extensions() { - _extensions.clear(); -} - -/** - * Adds a new extension to the end of the list of extensions for this record. - * This should be a record of type FO_extension. - */ -void FltRecord:: -add_extension(FltRecord *extension) { - _extensions.push_back(extension); -} - -/** - * Returns the number of unsupported ancillary records of this record. These - * are ancillary records that appeared following this record in the flt file - * but that aren't directly understood by the flt loader--normally, an - * ancillary record is examined and decoded on the spot, and no pointer to it - * is kept. - */ -int FltRecord:: -get_num_ancillary() const { - return _ancillary.size(); -} - -/** - * Returns the nth unsupported ancillary record of this record. See - * get_num_ancillary(). - */ -FltRecord *FltRecord:: -get_ancillary(int n) const { - nassertr(n >= 0 && n < (int)_ancillary.size(), nullptr); - return _ancillary[n]; -} - -/** - * Removes all unsupported ancillary records from this record. See - * get_num_ancillary(). - */ -void FltRecord:: -clear_ancillary() { - _ancillary.clear(); -} - -/** - * Adds a new unsupported ancillary record to the end of the list of ancillary - * records for this record. This record will be written to the flt file - * following this record, without attempting to understand what is in it. - * - * Normally, there is no reason to use this function; if the data stored in - * the FltRecord requires one or more ancillary record, the appropriate - * records will automatically be generated when the record is written. This - * function is only required to output a record whose type is not supported by - * the flt loader. But it would be better to extend the flt loader to know - * about this new kind of data record. - */ -void FltRecord:: -add_ancillary(FltRecord *ancillary) { - _ancillary.push_back(ancillary); -} - -/** - * Returns true if this record has a nonempty comment, false otherwise. - */ -bool FltRecord:: -has_comment() const { - return !_comment.empty(); -} - -/** - * Retrieves the comment for this record, or empty string if the record has no - * comment. - */ -const std::string &FltRecord:: -get_comment() const { - return _comment; -} - -/** - * Removes the comment for this record. - */ -void FltRecord:: -clear_comment() { - _comment = ""; -} - -/** - * Changes the comment for this record. - */ -void FltRecord:: -set_comment(const std::string &comment) { - _comment = comment; -} - -/** - * Checks that the iterator has no bytes left, as it should at the end of a - * successfully read record. If there *are* remaining bytes, print a warning - * message but otherwise don't worry about it. - * - * If we are attempting to read a flt file whose version is newer than the - * newest this program understands, don't even print a warning message, since - * this is exactly the sort of thing we expect. - */ -void FltRecord:: -check_remaining_size(const DatagramIterator &di, const std::string &name) const { - if (di.get_remaining_size() == 0) { - return; - } - - if (_header->get_flt_version() <= _header->max_flt_version()) { - nout << "Warning! Ignoring extra " << di.get_remaining_size() - << " bytes at the end of a "; - if (name.empty()) { - nout << get_type(); - } else { - nout << name; - } - nout << " record.\n"; - } -} - -/** - * Walks the hierarchy at this record and below and copies the - * _converted_filename record into the _orig_filename record, so the flt file - * will be written out with the converted filename instead of what was - * originally read in. - */ -void FltRecord:: -apply_converted_filenames() { - Records::const_iterator ci; - for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) { - (*ci)->apply_converted_filenames(); - } - for (ci = _children.begin(); ci != _children.end(); ++ci) { - (*ci)->apply_converted_filenames(); - } -} - -/** - * Writes a quick one-line description of the record, but not its children. - * This is a human-readable description, primarily for debugging; to write a - * flt file, use FltHeader::write_flt(). - */ -void FltRecord:: -output(std::ostream &out) const { - out << get_type(); -} - -/** - * Writes a multiple-line description of the record and all of its children. - * This is a human-readable description, primarily for debugging; to write a - * flt file, use FltHeader::write_flt(). - */ -void FltRecord:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) << *this; - write_children(out, indent_level); -} - -/** - * Assuming the current write position has been left at the end of the last - * line of the record description, writes out the list of children. - */ -void FltRecord:: -write_children(std::ostream &out, int indent_level) const { - if (!_ancillary.empty()) { - out << " + " << _ancillary.size() << " ancillary"; - } - if (!_extensions.empty()) { - out << " + " << _extensions.size() << " extensions"; - } - if (!_subfaces.empty()) { - out << " ["; - Records::const_iterator ci; - for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) { - out << " " << *(*ci); - } - out << " ]"; - } - if (!_children.empty()) { - out << " {\n"; - Records::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - (*ci)->write(out, indent_level + 2); - } - indent(out, indent_level) << "}\n"; - } else { - out << "\n"; - } -} - - /* - virtual void write(ostream &out) const; - virtual void build_record(Datagram &datagram) const; - */ - -/** - * Returns true if the indicated opcode corresponds to an ancillary record - * type, false otherwise. In general, this function is used to identify - * ancillary records that are not presently supported by the FltReader; these - * will be ignored. Normally, ancillary records will be detected and - * processed by extract_ancillary(). - */ -bool FltRecord:: -is_ancillary(FltOpcode opcode) { - switch (opcode) { - case FO_comment: - case FO_long_id: - case FO_multitexture: - case FO_uv_list: - case FO_replicate: - case FO_road_zone: - case FO_transform_matrix: - case FO_rotate_about_edge: - case FO_translate: - case FO_scale: - case FO_rotate_about_point: - case FO_rotate_and_scale: - case FO_put: - case FO_general_matrix: - case FO_vector: - case FO_bounding_box: - case FO_bounding_sphere: - case FO_bounding_cylinder: - case FO_bv_center: - case FO_bv_orientation: - case FO_local_vertex_pool: - case FO_cat_data: - - case FO_14_material_palette: - case FO_vertex_palette: - case FO_vertex_c: - case FO_vertex_cn: - case FO_vertex_cnu: - case FO_vertex_cu: - case FO_color_palette: - case FO_name_table: - case FO_15_material: - case FO_texture: - case FO_eyepoint_palette: - case FO_light_definition: - case FO_texture_map_palette: - return true; - - case FO_header: - case FO_mesh: - case FO_mesh_primitive: - case FO_group: - case FO_object: - case FO_face: - case FO_light_point: - case FO_dof: - case FO_vertex_list: - case FO_morph_list: - case FO_bsp: - case FO_external_ref: - case FO_lod: - case FO_sound: - case FO_light_source: - case FO_road_segment: - case FO_road_construction: - case FO_road_path: - case FO_clip_region: - case FO_text: - case FO_switch: - case FO_cat: - case FO_extension: - case FO_curve: - return false; - - case FO_push: - case FO_pop: - case FO_push_face: - case FO_pop_face: - case FO_push_attribute: - case FO_pop_attribute: - case FO_push_extension: - case FO_pop_extension: - case FO_instance: - case FO_instance_ref: - return false; - - default: - nout << "Don't know whether " << opcode << " is ancillary.\n"; - return false; - } -} - -/** - * Creates a new FltRecord corresponding to the opcode. If the opcode is - * unknown, creates a FltUnsupportedRecord. - */ -FltRecord *FltRecord:: -create_new_record(FltOpcode opcode) const { - switch (opcode) { - case FO_group: - return new FltGroup(_header); - - case FO_object: - return new FltObject(_header); - - case FO_face: - return new FltFace(_header); - - case FO_curve: - return new FltCurve(_header); - - case FO_mesh: - return new FltMesh(_header); - - case FO_local_vertex_pool: - return new FltLocalVertexPool(_header); - - case FO_mesh_primitive: - return new FltMeshPrimitive(_header); - - case FO_vertex_list: - return new FltVertexList(_header); - - case FO_lod: - return new FltLOD(_header); - - case FO_instance: - return new FltInstanceDefinition(_header); - - case FO_instance_ref: - return new FltInstanceRef(_header); - - case FO_external_ref: - return new FltExternalReference(_header); - - case FO_vector: - return new FltVectorRecord(_header); - - default: - nout << "Ignoring unsupported record " << opcode << "\n"; - return new FltUnsupportedRecord(_header); - } -} - -/** - * Extracts this record information from the current record presented in the - * reader, then advances the reader and continues to read any children, if - * present. On return, the reader is position on the next sibling record to - * this record. - * - * Returns FE_ok if successful, otherwise on error. - */ -FltError FltRecord:: -read_record_and_children(FltRecordReader &reader) { - if (!extract_record(reader)) { - nout << "Could not extract record for " << *this << "\n"; - assert(!flt_error_abort); - return FE_invalid_record; - } - FltError result = reader.advance(); - if (result == FE_end_of_file) { - return FE_ok; - } else if (result != FE_ok) { - return result; - } - - while (true) { - if (extract_ancillary(reader)) { - // Ok, a known ancillary record. Fine. - - } else if (reader.get_opcode() == FO_push) { - // A push begins a new list of children. - result = reader.advance(); - if (result != FE_ok) { - return result; - } - - while (reader.get_opcode() != FO_pop) { - PT(FltRecord) child = create_new_record(reader.get_opcode()); - FltError result = child->read_record_and_children(reader); - if (result != FE_ok) { - return result; - } - - if (child->is_of_type(FltInstanceDefinition::get_class_type())) { - // A special case for an instance definition. These shouldn't - // appear in the hierarchy, but should instead be added directly to - // the header. - _header->add_instance(DCAST(FltInstanceDefinition, child)); - - } else { - add_child(child); - } - - if (reader.eof() || reader.error()) { - assert(!flt_error_abort); - return FE_end_of_file; - } - } - - } else if (reader.get_opcode() == FO_push_face) { - // A push subface begins a new list of subfaces. - result = reader.advance(); - if (result != FE_ok) { - return result; - } - - while (reader.get_opcode() != FO_pop_face) { - PT(FltRecord) subface = create_new_record(reader.get_opcode()); - FltError result = subface->read_record_and_children(reader); - if (result != FE_ok) { - return result; - } - add_subface(subface); - if (reader.eof() || reader.error()) { - assert(!flt_error_abort); - return FE_end_of_file; - } - } - - } else if (reader.get_opcode() == FO_push_extension) { - // A push extension begins a new list of extensions. - result = reader.advance(); - if (result != FE_ok) { - return result; - } - - while (reader.get_opcode() != FO_pop_extension) { - PT(FltRecord) extension = create_new_record(reader.get_opcode()); - FltError result = extension->read_record_and_children(reader); - if (result != FE_ok) { - return result; - } - add_extension(extension); - if (reader.eof() || reader.error()) { - assert(!flt_error_abort); - return FE_end_of_file; - } - } - - } else if (is_ancillary(reader.get_opcode())) { - // An unsupported ancillary record. Skip it. - PT(FltRecord) ancillary = create_new_record(reader.get_opcode()); - ancillary->extract_record(reader); - _ancillary.push_back(ancillary); - - } else { - // None of the above: we're done. - return FE_ok; - } - - // Skip to the next record. If that's the end, fine. - result = reader.advance(true); - if (reader.eof() || result != FE_ok) { - return result; - } - } -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltRecord:: -extract_record(FltRecordReader &) { - return true; -} - -/** - * Checks whether the given record, which follows this record sequentially in - * the file, is an ancillary record of this record. If it is, extracts the - * relevant information and returns true; otherwise, leaves it alone and - * returns false. - */ -bool FltRecord:: -extract_ancillary(FltRecordReader &reader) { - if (reader.get_opcode() == FO_comment) { - DatagramIterator &di = reader.get_iterator(); - _comment = di.get_fixed_string(di.get_remaining_size()); - return true; - } - - return false; -} - -/** - * Writes this record out to the flt file, along with all of its ancillary - * records and children records. Returns FE_ok on success, or something else - * on error. - */ -FltError FltRecord:: -write_record_and_children(FltRecordWriter &writer) const { - // First, write the record. - if (!build_record(writer)) { - assert(!flt_error_abort); - return FE_bad_data; - } - - FltError result = writer.advance(); - if (result != FE_ok) { - return result; - } - - // Then the ancillary data. - result = write_ancillary(writer); - if (result != FE_ok) { - return result; - } - Records::const_iterator ci; - for (ci = _ancillary.begin(); ci != _ancillary.end(); ++ci) { - if (!(*ci)->build_record(writer)) { - assert(!flt_error_abort); - return FE_bad_data; - } - result = writer.advance(); - if (result != FE_ok) { - return result; - } - } - - // Any extensions? - if (!_extensions.empty()) { - result = writer.write_record(FO_push_face); - if (result != FE_ok) { - return result; - } - - for (ci = _extensions.begin(); ci != _extensions.end(); ++ci) { - (*ci)->write_record_and_children(writer); - } - - result = writer.write_record(FO_pop_face); - if (result != FE_ok) { - return result; - } - } - - // Finally, write all the children. - if (!_children.empty()) { - result = writer.write_record(FO_push); - if (result != FE_ok) { - return result; - } - - for (ci = _children.begin(); ci != _children.end(); ++ci) { - (*ci)->write_record_and_children(writer); - } - - result = writer.write_record(FO_pop); - if (result != FE_ok) { - return result; - } - } - - // We must write subfaces *after* the list of children, or Creator will - // crash trying to load the file. - if (!_subfaces.empty()) { - result = writer.write_record(FO_push_face); - if (result != FE_ok) { - return result; - } - - for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) { - (*ci)->write_record_and_children(writer); - } - - result = writer.write_record(FO_pop_face); - if (result != FE_ok) { - return result; - } - } - - return FE_ok; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltRecord:: -build_record(FltRecordWriter &) const { - return true; -} - -/** - * Writes whatever ancillary records are required for this record. Returns - * FE_ok on success, or something else if there is some error. - */ -FltError FltRecord:: -write_ancillary(FltRecordWriter &writer) const { - if (!_comment.empty()) { - Datagram dc(_comment.data(), _comment.size()); - FltError result = writer.write_record(FO_comment, dc); - if (result != FE_ok) { - return result; - } - } - return FE_ok; -} diff --git a/pandatool/src/flt/fltRecord.h b/pandatool/src/flt/fltRecord.h deleted file mode 100644 index 9fc8e3ad..00000000 --- a/pandatool/src/flt/fltRecord.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltRecord.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTRECORD_H -#define FLTRECORD_H - -#include "pandatoolbase.h" - -#include "fltOpcode.h" -#include "fltError.h" - -#include "typedObject.h" -#include "typedReferenceCount.h" -#include "pointerTo.h" - -class FltHeader; -class FltRecordReader; -class FltRecordWriter; -class DatagramIterator; - -/** - * The base class for all kinds of records in a MultiGen OpenFlight file. A - * flt file consists of a hierarchy of "beads" of various kinds, each of which - * may be followed by n ancillary records, written sequentially to the file. - */ -class FltRecord : public TypedReferenceCount { -public: - FltRecord(FltHeader *header); - virtual ~FltRecord(); - - int get_num_children() const; - FltRecord *get_child(int n) const; - void clear_children(); - void add_child(FltRecord *child); - - int get_num_subfaces() const; - FltRecord *get_subface(int n) const; - void clear_subfaces(); - void add_subface(FltRecord *subface); - - int get_num_extensions() const; - FltRecord *get_extension(int n) const; - void clear_extensions(); - void add_extension(FltRecord *extension); - - int get_num_ancillary() const; - FltRecord *get_ancillary(int n) const; - void clear_ancillary(); - void add_ancillary(FltRecord *ancillary); - - bool has_comment() const; - const std::string &get_comment() const; - void clear_comment(); - void set_comment(const std::string &comment); - - void check_remaining_size(const DatagramIterator &di, - const std::string &name = std::string()) const; - - virtual void apply_converted_filenames(); - - virtual void output(std::ostream &out) const; - virtual void write(std::ostream &out, int indent_level = 0) const; - -protected: - void write_children(std::ostream &out, int indent_level) const; - - static bool is_ancillary(FltOpcode opcode); - - FltRecord *create_new_record(FltOpcode opcode) const; - FltError read_record_and_children(FltRecordReader &reader); - virtual bool extract_record(FltRecordReader &reader); - virtual bool extract_ancillary(FltRecordReader &reader); - - virtual FltError write_record_and_children(FltRecordWriter &writer) const; - virtual bool build_record(FltRecordWriter &writer) const; - virtual FltError write_ancillary(FltRecordWriter &writer) const; - -protected: - FltHeader *_header; - -private: - typedef pvector Records; - Records _children; - Records _subfaces; - Records _extensions; - Records _ancillary; - - std::string _comment; - - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedReferenceCount::init_type(); - register_type(_type_handle, "FltRecord", - TypedReferenceCount::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -INLINE std::ostream &operator << (std::ostream &out, const FltRecord &record); - -#include "fltRecord.I" - -#endif diff --git a/pandatool/src/flt/fltRecordReader.cxx b/pandatool/src/flt/fltRecordReader.cxx deleted file mode 100644 index 8e1993c9..00000000 --- a/pandatool/src/flt/fltRecordReader.cxx +++ /dev/null @@ -1,242 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltRecordReader.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltRecordReader.h" -#include "config_flt.h" - -#include "datagramIterator.h" - -#include - -/** - * - */ -FltRecordReader:: -FltRecordReader(std::istream &in) : - _in(in) -{ - _opcode = FO_none; - _record_length = 0; - _iterator = nullptr; - _state = S_begin; - _next_error = FE_ok; - _next_opcode = FO_none; - _next_record_length = 0; - - // Read the first header to get us going. - read_next_header(); -} - -/** - * - */ -FltRecordReader:: -~FltRecordReader() { - delete _iterator; - _iterator = nullptr; -} - -/** - * Returns the opcode associated with the current record. - */ -FltOpcode FltRecordReader:: -get_opcode() const { - nassertr(_state == S_normal, FO_none); - return _opcode; -} - -/** - * Returns an iterator suitable for extracting data from the current record. - */ -DatagramIterator &FltRecordReader:: -get_iterator() { - nassertr(_state == S_normal, *_iterator); - return *_iterator; -} - -/** - * Returns the datagram representing the entire record, less the four-byte - * header. - */ -const Datagram &FltRecordReader:: -get_datagram() { -#ifndef NDEBUG - static Datagram bogus_datagram; - nassertr(_state == S_normal, bogus_datagram); -#endif - return _iterator->get_datagram(); -} - -/** - * Returns the entire length of the record, including the four-byte header. - */ -int FltRecordReader:: -get_record_length() const { - return _record_length; -} - -/** - * Extracts the next record from the file. Returns true if there is another - * record, or false if the end of file has been reached. - */ -FltError FltRecordReader:: -advance(bool ok_eof) { - if (_state == S_eof) { - assert(!flt_error_abort); - return FE_end_of_file; - } - if (_state == S_error) { - assert(!flt_error_abort); - return FE_read_error; - } - if (_iterator != nullptr) { - delete _iterator; - _iterator = nullptr; - } - - if (_next_error == FE_end_of_file) { - _state = S_eof; - if (ok_eof) { - return FE_ok; - } - assert(!flt_error_abort); - return FE_end_of_file; - - } else if (_next_error != FE_ok) { - _state = S_error; - assert(!flt_error_abort); - return _next_error; - } - - _opcode = _next_opcode; - _record_length = _next_record_length; - - if (flt_cat.is_debug()) { - flt_cat.debug() - << "Reading " << _opcode - << " of length " << _record_length << "\n"; - } - - // And now read the full record based on the length. - int length = _next_record_length - header_size; - if (length > 0) { - vector_uchar data((size_t)length); - _in.read((char *)&data[0], length); - _datagram = Datagram(std::move(data)); - } else { - _datagram = Datagram(); - } - - if (_in.fail()) { - if (_in.eof()) { - _state = S_eof; - assert(!flt_error_abort); - return FE_end_of_file; - } - - _state = S_error; - assert(!flt_error_abort); - return FE_read_error; - } - - // Check out the next header in case it's a continuation. - read_next_header(); - while (_next_error == FE_ok && _next_opcode == FO_continuation) { - if (flt_cat.is_debug()) { - flt_cat.debug() - << "Reading continuation of length " << _next_record_length << "\n"; - } - - // Read the continuation and tack it on. - _record_length += _next_record_length; - length = _next_record_length - header_size; - - if (length > 0) { - char *buffer = new char[length]; - _in.read(buffer, length); - _datagram.append_data(buffer, length); - delete[] buffer; - } - - if (_in.fail()) { - if (_in.eof()) { - _state = S_eof; - assert(!flt_error_abort); - return FE_end_of_file; - } - - _state = S_error; - assert(!flt_error_abort); - return FE_read_error; - } - - read_next_header(); - } - - // Finally, create a new iterator to read this record. - _iterator = new DatagramIterator(_datagram); - _state = S_normal; - - return FE_ok; -} - -/** - * Returns true if end-of-file has been reached without error. - */ -bool FltRecordReader:: -eof() const { - return _state == S_eof; -} - -/** - * Returns true if some error has been encountered while reading (for - * instance, a truncated file). - */ -bool FltRecordReader:: -error() const { - return _state == S_error; -} - -/** - * Reads the four-byte header for the next record, which contains the next - * opcode and record length. - * - * We need read the next header in advance so we can check to see if it - * happens to be a continuation record. If it is, we will need to concatenate - * the records together before returning. - */ -void FltRecordReader:: -read_next_header() { - char bytes[header_size]; - _in.read(bytes, header_size); - - if (_in.fail()) { - if (_in.eof()) { - _next_error = FE_end_of_file; - return; - } - _next_error = FE_read_error; - return; - } - - // Now extract out the opcode and length. - Datagram dg(bytes, header_size); - DatagramIterator dgi(dg); - _next_opcode = (FltOpcode)dgi.get_be_int16(); - _next_record_length = dgi.get_be_uint16(); - - if (_next_record_length < header_size) { - _next_error = FE_invalid_record; - return; - } -} diff --git a/pandatool/src/flt/fltRecordReader.h b/pandatool/src/flt/fltRecordReader.h deleted file mode 100644 index 8817e800..00000000 --- a/pandatool/src/flt/fltRecordReader.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltRecordReader.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTRECORDREADER_H -#define FLTRECORDREADER_H - -#include "pandatoolbase.h" - -#include "fltOpcode.h" -#include "fltError.h" - -#include "datagram.h" -#include "datagramIterator.h" - -/** - * This class turns an istream into a sequence of FltRecords by reading a - * sequence of Datagrams and extracting the opcode from each one. It - * remembers where it is in the file and what the current record is. - */ -class FltRecordReader { -public: - FltRecordReader(std::istream &in); - ~FltRecordReader(); - - FltOpcode get_opcode() const; - DatagramIterator &get_iterator(); - const Datagram &get_datagram(); - int get_record_length() const; - - FltError advance(bool ok_eof = false); - - bool eof() const; - bool error() const; - -private: - void read_next_header(); - - std::istream &_in; - Datagram _datagram; - FltOpcode _opcode; - int _record_length; - DatagramIterator *_iterator; - - FltError _next_error; - FltOpcode _next_opcode; - int _next_record_length; - - enum State { - S_begin, - S_normal, - S_eof, - S_error - }; - State _state; -}; - -#endif diff --git a/pandatool/src/flt/fltRecordWriter.cxx b/pandatool/src/flt/fltRecordWriter.cxx deleted file mode 100644 index 909e5ce2..00000000 --- a/pandatool/src/flt/fltRecordWriter.cxx +++ /dev/null @@ -1,151 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltRecordWriter.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltRecordWriter.h" -#include "fltInstanceDefinition.h" -#include "fltHeader.h" -#include "config_flt.h" - -#include "datagram.h" - -#include - -// Don't attempt to write more than this number of bytes in one record. If -// the record requires more than this, use continuation records. -static const int max_write_length = 65532; - -/** - * - */ -FltRecordWriter:: -FltRecordWriter(std::ostream &out) : - _out(out) -{ -} - -/** - * - */ -FltRecordWriter:: -~FltRecordWriter() { -} - -/** - * Sets the opcode associated with the current record. - */ -void FltRecordWriter:: -set_opcode(FltOpcode opcode) { - _opcode = opcode; -} - -/** - * Sets the datagram that will be written when advance() is called. - */ -void FltRecordWriter:: -set_datagram(const Datagram &datagram) { - _datagram = datagram; -} - -/** - * Returns a modifiable reference to the datagram associated with the current - * record. This datagram should then be stuffed with data corresponding to - * the data in the record, in preparation for calling advance() to write the - * data. - */ -Datagram &FltRecordWriter:: -update_datagram() { - return _datagram; -} - -/** - * Writes the current record to the flt file, and resets the current record to - * receive new data. Returns FE_ok on success, or something else on error. - */ -FltError FltRecordWriter:: -advance() { - int start_byte = 0; - int write_length = - std::min((int)_datagram.get_length() - start_byte, max_write_length - header_size); - FltOpcode opcode = _opcode; - - do { - if (flt_cat.is_debug()) { - flt_cat.debug() - << "Writing " << opcode << " of length " - << write_length + header_size << "\n"; - } - - // Build a mini-datagram to write the header. - Datagram dg; - dg.add_be_int16(opcode); - dg.add_be_int16(write_length + header_size); - - nassertr((int)dg.get_length() == header_size, FE_internal); - - _out.write((const char *)dg.get_data(), dg.get_length()); - if (_out.fail()) { - assert(!flt_error_abort); - return FE_write_error; - } - - // Now write the rest of the record. - _out.write((const char *)_datagram.get_data() + start_byte, write_length); - if (_out.fail()) { - assert(!flt_error_abort); - return FE_write_error; - } - - start_byte += write_length; - write_length = - std::min((int)_datagram.get_length() - start_byte, max_write_length - header_size); - opcode = FO_continuation; - } while (write_length > 0); - - _datagram.clear(); - _opcode = FO_none; - - return FE_ok; -} - -/** - * A convenience function to quickly write a simple record that consists of an - * opcode and possibly a datagram. - */ -FltError FltRecordWriter:: -write_record(FltOpcode opcode, const Datagram &datagram) { - _opcode = opcode; - _datagram = datagram; - return advance(); -} - -/** - * Ensures that the given instance definition has already been written to the - * file. If it has not, writes it now. - */ -FltError FltRecordWriter:: -write_instance_def(FltHeader *header, int instance_index) { - bool inserted = _instances_written.insert(instance_index).second; - - if (!inserted) { - // It's already been written. - return FE_ok; - } - - FltInstanceDefinition *instance = header->get_instance(instance_index); - if (instance == nullptr) { - assert(!flt_error_abort); - return FE_undefined_instance; - } - - return instance->write_record_and_children(*this); -} diff --git a/pandatool/src/flt/fltRecordWriter.h b/pandatool/src/flt/fltRecordWriter.h deleted file mode 100644 index 8cd4e4b6..00000000 --- a/pandatool/src/flt/fltRecordWriter.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltRecordWriter.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTRECORDWRITER_H -#define FLTRECORDWRITER_H - -#include "pandatoolbase.h" - -#include "fltOpcode.h" -#include "fltError.h" - -#include "datagram.h" -#include "pset.h" - -class FltHeader; - -/** - * This class writes a sequence of FltRecords to an ostream, handling opcode - * and size counts properly. - */ -class FltRecordWriter { -public: - FltRecordWriter(std::ostream &out); - ~FltRecordWriter(); - - void set_opcode(FltOpcode opcode); - const Datagram &get_datagram() const; - void set_datagram(const Datagram &datagram); - Datagram &update_datagram(); - - FltError advance(); - - FltError write_record(FltOpcode opcode, - const Datagram &datagram = Datagram()); - - FltError write_instance_def(FltHeader *header, int instance_index); - -private: - std::ostream &_out; - Datagram _datagram; - FltOpcode _opcode; - - typedef pset Instances; - Instances _instances_written; -}; - -#endif diff --git a/pandatool/src/flt/fltTexture.cxx b/pandatool/src/flt/fltTexture.cxx deleted file mode 100644 index c65f5a05..00000000 --- a/pandatool/src/flt/fltTexture.cxx +++ /dev/null @@ -1,475 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTexture.cxx - * @author drose - * @date 2000-08-25 - */ - -#include "fltTexture.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" -#include "pathReplace.h" -#include "config_putil.h" - -TypeHandle FltTexture::_type_handle; - -/** - * - */ -FltTexture:: -FltTexture(FltHeader *header) : FltRecord(header) { - _pattern_index = -1; - _x_location = 0; - _y_location = 0; - - _num_texels_u = 0; - _num_texels_v = 0; - _real_world_size_u = 0; - _real_world_size_v = 0; - _up_vector_x = 0; - _up_vector_y = 1; - _file_format = FF_none; - _min_filter = MN_point; - _mag_filter = MG_point; - _repeat = RT_repeat; - _repeat_u = RT_repeat; - _repeat_v = RT_repeat; - _modify_flag = 0; - _x_pivot_point = 0; - _y_pivot_point = 0; - _env_type = ET_modulate; - _intensity_is_alpha = false; - _float_real_world_size_u = 0.0; - _float_real_world_size_v = 0.0; - _imported_origin_code = 0; - _kernel_version = 1520; - _internal_format = IF_default; - _external_format = EF_default; - _use_mipmap_kernel = false; - memset(_mipmap_kernel, 0, sizeof(_mipmap_kernel)); - _use_lod_scale = false; - memset(_lod_scale, 0, sizeof(_lod_scale)); - _clamp = 0.0; - _mag_filter_alpha = MG_point; - _mag_filter_color = MG_point; - _lambert_conic_central_meridian = 0.0; - _lambert_conic_upper_latitude = 0.0; - _lambert_conic_lower_latitude = 0.0; - _use_detail = false; - _detail_j = 0; - _detail_k = 0; - _detail_m = 0; - _detail_n = 0; - _detail_scramble = 0; - _use_tile = false; - _tile_lower_left_u = 0.0; - _tile_lower_left_v = 0.0; - _tile_upper_right_u = 0.0; - _tile_upper_right_v = 0.0; - _projection = PT_flat_earth; - _earth_model = EM_wgs84; - _utm_zone = 0; - _image_origin = IO_lower_left; - _geospecific_points_units = PU_degrees; - _geospecific_hemisphere = H_southern; - _file_version = 1501; -} - -/** - * Walks the hierarchy at this record and below and copies the - * _converted_filename record into the _orig_filename record, so the flt file - * will be written out with the converted filename instead of what was - * originally read in. - */ -void FltTexture:: -apply_converted_filenames() { - _orig_filename = _converted_filename.to_os_generic(); - FltRecord::apply_converted_filenames(); -} - -/** - * Returns the name of the texture image file. - */ -Filename FltTexture:: -get_texture_filename() const { - return _converted_filename; -} - -/** - * Changes the name of the texture image file. - */ -void FltTexture:: -set_texture_filename(const Filename &filename) { - _converted_filename = filename; - _orig_filename = _converted_filename.to_os_generic(); -} - -/** - * Returns the name of the texture's associated .attr file. This contains - * some additional MultiGen information about the texture parameters. This - * is, of course, just the name of the texture with .attr appended. - * - * Normally, it won't be necessary to access this file directly; you can call - * read_attr_data() or write_attr_data() to get at the data stored in this - * file. (And read_attr_data() is called automatically when the Flt file is - * read in.) - */ -Filename FltTexture:: -get_attr_filename() const { - std::string texture_filename = get_texture_filename(); - return Filename::binary_filename(texture_filename + ".attr"); -} - -/** - * Opens up the texture's .attr file and reads its data into the extra - * FltTexture fields. This is normally performed automatically when the Flt - * file is read from disk. - */ -FltError FltTexture:: -read_attr_data() { - Filename attr_filename = get_attr_filename(); - - std::ifstream attr; - if (!attr_filename.open_read(attr)) { - return FE_could_not_open; - } - - // Determine the file's size so we can read it all into one big datagram. - attr.seekg(0, std::ios::end); - if (attr.fail()) { - return FE_read_error; - } - std::streampos length = attr.tellg(); - - char *buffer = new char[length]; - - attr.seekg(0, std::ios::beg); - attr.read(buffer, length); - if (attr.fail()) { - return FE_read_error; - } - - Datagram datagram(buffer, length); - delete[] buffer; - - return unpack_attr(datagram); -} - -/** - * Writes the texture's .attr file. This may or may not be performed - * automatically, according to the setting of - * FltHeader::set_auto_attr_update(). - */ -FltError FltTexture:: -write_attr_data() const { - return write_attr_data(get_attr_filename()); -} - -/** - * Writes the texture's .attr file to the named file. - */ -FltError FltTexture:: -write_attr_data(Filename attr_filename) const { - Datagram datagram; - FltError result = pack_attr(datagram); - if (result != FE_ok) { - return result; - } - - attr_filename.set_binary(); - std::ofstream attr; - if (!attr_filename.open_write(attr)) { - return FE_could_not_open; - } - - attr.write((const char *)datagram.get_data(), datagram.get_length()); - if (attr.fail()) { - return FE_write_error; - } - return FE_ok; -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTexture:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_texture, false); - DatagramIterator &iterator = reader.get_iterator(); - - if (_header->get_flt_version() < 1420) { - _orig_filename = iterator.get_fixed_string(80); - } else { - _orig_filename = iterator.get_fixed_string(200); - } - _converted_filename = _header->convert_path(Filename::from_os_specific(_orig_filename), get_model_path()); - _pattern_index = iterator.get_be_int32(); - _x_location = iterator.get_be_int32(); - _y_location = iterator.get_be_int32(); - - if (read_attr_data() != FE_ok) { - nout << "Unable to read attribute file " << get_attr_filename() << "\n"; - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTexture:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_texture); - Datagram &datagram = writer.update_datagram(); - - datagram.add_fixed_string(_orig_filename, 200); - datagram.add_be_int32(_pattern_index); - datagram.add_be_int32(_x_location); - datagram.add_be_int32(_y_location); - - if (_header->get_auto_attr_update() == FltHeader::AU_always || - (_header->get_auto_attr_update() == FltHeader::AU_if_missing && - !get_attr_filename().exists())) { - if (write_attr_data() != FE_ok) { - nout << "Unable to write attribute file " << get_attr_filename() << "\n"; - } - } - - return true; -} - -/** - * Reads the data from the attribute file. - */ -FltError FltTexture:: -unpack_attr(const Datagram &datagram) { - DatagramIterator iterator(datagram); - - _num_texels_u = iterator.get_be_int32(); - _num_texels_v = iterator.get_be_int32(); - _real_world_size_u = iterator.get_be_int32(); - _real_world_size_v = iterator.get_be_int32(); - _up_vector_x = iterator.get_be_int32(); - _up_vector_y = iterator.get_be_int32(); - _file_format = (FileFormat)iterator.get_be_int32(); - _min_filter = (Minification)iterator.get_be_int32(); - _mag_filter = (Magnification)iterator.get_be_int32(); - _repeat = (RepeatType)iterator.get_be_int32(); - _repeat_u = (RepeatType)iterator.get_be_int32(); - _repeat_v = (RepeatType)iterator.get_be_int32(); - _modify_flag = iterator.get_be_int32(); - _x_pivot_point = iterator.get_be_int32(); - _y_pivot_point = iterator.get_be_int32(); - _env_type = (EnvironmentType)iterator.get_be_int32(); - _intensity_is_alpha = (iterator.get_be_int32() != 0); - iterator.skip_bytes(4 * 8); - iterator.skip_bytes(4); // Undocumented padding. - _float_real_world_size_u = iterator.get_be_float64(); - _float_real_world_size_v = iterator.get_be_float64(); - _imported_origin_code = iterator.get_be_int32(); - _kernel_version = iterator.get_be_int32(); - _internal_format = (InternalFormat)iterator.get_be_int32(); - _external_format = (ExternalFormat)iterator.get_be_int32(); - _use_mipmap_kernel = (iterator.get_be_int32() != 0); - int i; - for (i = 0; i < 8; i++) { - _mipmap_kernel[i] = iterator.get_be_float32(); - } - _use_lod_scale = (iterator.get_be_int32() != 0); - for (i = 0; i < 8; i++) { - _lod_scale[i]._lod = iterator.get_be_float32(); - _lod_scale[i]._scale = iterator.get_be_float32(); - } - _clamp = iterator.get_be_float32(); - _mag_filter_alpha = (Magnification)iterator.get_be_int32(); - _mag_filter_color = (Magnification)iterator.get_be_int32(); - iterator.skip_bytes(4 + 4 * 8); - _lambert_conic_central_meridian = iterator.get_be_float64(); - _lambert_conic_upper_latitude = iterator.get_be_float64(); - _lambert_conic_lower_latitude = iterator.get_be_float64(); - iterator.skip_bytes(8 + 4 * 5); - _use_detail = (iterator.get_be_int32() != 0); - _detail_j = iterator.get_be_int32(); - _detail_k = iterator.get_be_int32(); - _detail_m = iterator.get_be_int32(); - _detail_n = iterator.get_be_int32(); - _detail_scramble = iterator.get_be_int32(); - _use_tile = (iterator.get_be_int32() != 0); - _tile_lower_left_u = iterator.get_be_float32(); - _tile_lower_left_v = iterator.get_be_float32(); - _tile_upper_right_u = iterator.get_be_float32(); - _tile_upper_right_v = iterator.get_be_float32(); - _projection = (ProjectionType)iterator.get_be_int32(); - _earth_model = (EarthModel)iterator.get_be_int32(); - iterator.skip_bytes(4); - _utm_zone = iterator.get_be_int32(); - _image_origin = (ImageOrigin)iterator.get_be_int32(); - _geospecific_points_units = (PointsUnits)iterator.get_be_int32(); - _geospecific_hemisphere = (Hemisphere)iterator.get_be_int32(); - iterator.skip_bytes(4 + 4 + 149 * 4); - iterator.skip_bytes(8); // Undocumented padding. - _comment = iterator.get_fixed_string(512); - - if (iterator.get_remaining_size() != 0) { - iterator.skip_bytes(13 * 4); - iterator.skip_bytes(4); // Undocumented padding. - _file_version = iterator.get_be_int32(); - - // Now read the geospecific control points. - _geospecific_control_points.clear(); - int num_points = iterator.get_be_int32(); - if (num_points > 0) { - iterator.skip_bytes(4); - - while (num_points > 0) { - GeospecificControlPoint gcp; - gcp._uv[0] = iterator.get_be_float64(); - gcp._uv[1] = iterator.get_be_float64(); - gcp._real_earth[0] = iterator.get_be_float64(); - gcp._real_earth[1] = iterator.get_be_float64(); - } - } - - if (iterator.get_remaining_size() != 0) { - int num_defs = iterator.get_be_int32(); - while (num_defs > 0) { - SubtextureDef def; - def._name = iterator.get_fixed_string(32); - def._left = iterator.get_be_int32(); - def._bottom = iterator.get_be_int32(); - def._right = iterator.get_be_int32(); - def._top = iterator.get_be_int32(); - } - } - } - - check_remaining_size(iterator); - return FE_ok; -} - -/** - * Packs the attribute data into a big datagram. - */ -FltError FltTexture:: -pack_attr(Datagram &datagram) const { - datagram.add_be_int32(_num_texels_u); - datagram.add_be_int32(_num_texels_v); - datagram.add_be_int32(_real_world_size_u); - datagram.add_be_int32(_real_world_size_v); - datagram.add_be_int32(_up_vector_x); - datagram.add_be_int32(_up_vector_y); - datagram.add_be_int32(_file_format); - datagram.add_be_int32(_min_filter); - datagram.add_be_int32(_mag_filter); - datagram.add_be_int32(_repeat); - datagram.add_be_int32(_repeat_u); - datagram.add_be_int32(_repeat_v); - datagram.add_be_int32(_modify_flag); - datagram.add_be_int32(_x_pivot_point); - datagram.add_be_int32(_y_pivot_point); - datagram.add_be_int32(_env_type); - datagram.add_be_int32(_intensity_is_alpha); - datagram.pad_bytes(4 * 8); - datagram.pad_bytes(4); // Undocumented padding. - datagram.add_be_float64(_float_real_world_size_u); - datagram.add_be_float64(_float_real_world_size_v); - datagram.add_be_int32(_imported_origin_code); - datagram.add_be_int32(_kernel_version); - datagram.add_be_int32(_internal_format); - datagram.add_be_int32(_external_format); - datagram.add_be_int32(_use_mipmap_kernel); - int i; - for (i = 0; i < 8; i++) { - datagram.add_be_float32(_mipmap_kernel[i]); - } - datagram.add_be_int32(_use_lod_scale); - for (i = 0; i < 8; i++) { - datagram.add_be_float32(_lod_scale[i]._lod); - datagram.add_be_float32(_lod_scale[i]._scale); - } - datagram.add_be_float32(_clamp); - datagram.add_be_int32(_mag_filter_alpha); - datagram.add_be_int32(_mag_filter_color); - datagram.pad_bytes(4 + 4 * 8); - datagram.add_be_float64(_lambert_conic_central_meridian); - datagram.add_be_float64(_lambert_conic_upper_latitude); - datagram.add_be_float64(_lambert_conic_lower_latitude); - datagram.pad_bytes(8 + 4 * 5); - datagram.add_be_int32(_use_detail); - datagram.add_be_int32(_detail_j); - datagram.add_be_int32(_detail_k); - datagram.add_be_int32(_detail_m); - datagram.add_be_int32(_detail_n); - datagram.add_be_int32(_detail_scramble); - datagram.add_be_int32(_use_tile); - datagram.add_be_float32(_tile_lower_left_u); - datagram.add_be_float32(_tile_lower_left_v); - datagram.add_be_float32(_tile_upper_right_u); - datagram.add_be_float32(_tile_upper_right_v); - datagram.add_be_int32(_projection); - datagram.add_be_int32(_earth_model); - datagram.pad_bytes(4); - datagram.add_be_int32(_utm_zone); - datagram.add_be_int32(_image_origin); - datagram.add_be_int32(_geospecific_points_units); - datagram.add_be_int32(_geospecific_hemisphere); - datagram.pad_bytes(4 + 4 + 149 * 4); - datagram.pad_bytes(8); // Undocumented padding. - datagram.add_fixed_string(_comment, 512); - datagram.pad_bytes(13 * 4); - datagram.pad_bytes(4); // Undocumented padding. - datagram.add_be_int32(_file_version); - - // Now write the geospecific control points. - datagram.add_be_int32(_geospecific_control_points.size()); - if (!_geospecific_control_points.empty()) { - datagram.pad_bytes(4); - GeospecificControlPoints::const_iterator pi; - for (pi = _geospecific_control_points.begin(); - pi != _geospecific_control_points.end(); - ++pi) { - const GeospecificControlPoint &gcp = (*pi); - datagram.add_be_float64(gcp._uv[0]); - datagram.add_be_float64(gcp._uv[1]); - datagram.add_be_float64(gcp._real_earth[0]); - datagram.add_be_float64(gcp._real_earth[1]); - } - } - - // Also write out the subtexture definitions. - datagram.add_be_int32(_subtexture_defs.size()); - SubtextureDefs::const_iterator di; - for (di = _subtexture_defs.begin(); - di != _subtexture_defs.end(); - ++di) { - const SubtextureDef &def = (*di); - datagram.add_fixed_string(def._name, 31); - datagram.add_int8(0); - datagram.add_be_int32(def._left); - datagram.add_be_int32(def._bottom); - datagram.add_be_int32(def._right); - datagram.add_be_int32(def._top); - } - - return FE_ok; -} diff --git a/pandatool/src/flt/fltTexture.h b/pandatool/src/flt/fltTexture.h deleted file mode 100644 index 34a487e1..00000000 --- a/pandatool/src/flt/fltTexture.h +++ /dev/null @@ -1,252 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTexture.h - * @author drose - * @date 2000-08-25 - */ - -#ifndef FLTTEXTURE_H -#define FLTTEXTURE_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" - -#include "filename.h" -#include "luse.h" - -/** - * Represents a single texture in the texture palette. - */ -class FltTexture : public FltRecord { -public: - FltTexture(FltHeader *header); - - virtual void apply_converted_filenames(); - - std::string _orig_filename; - Filename _converted_filename; - int _pattern_index; - int _x_location; - int _y_location; - - Filename get_texture_filename() const; - void set_texture_filename(const Filename &filename); - Filename get_attr_filename() const; - FltError read_attr_data(); - FltError write_attr_data() const; - FltError write_attr_data(Filename attr_filename) const; - - // The remaining fields are from the attr file. - enum FileFormat { - FF_none = -1, - FF_att_8_pattern = 0, - FF_att_8_template = 1, - FF_sgi_i = 2, - FF_sgi_ia = 3, - FF_sgi_rgb = 4, - FF_sgi_rgba = 5 - }; - - enum Minification { - MN_point = 0, - MN_bilinear = 1, - MN_OB_mipmap = 2, // obsolete - MN_mipmap_point = 3, - MN_mipmap_linear = 4, - MN_mipmap_bilinear = 5, - MN_mipmap_trilinear = 6, - MN_bicubic = 8, - MN_bilinear_gequal = 9, - MN_bilinear_lequal = 10, - MN_bicubic_gequal = 11, - MN_bicubic_lequal = 12 - }; - - enum Magnification { - MG_point = 0, - MG_bilinear = 1, - MG_bicubic = 3, - MG_sharpen = 4, - MG_add_detail = 5, - MG_modulate_detail = 6, - MG_bilinear_gequal = 7, - MG_bilinear_lequal = 8, - MG_bicubic_gequal = 9, - MG_bicubic_lequal = 10 - }; - - enum RepeatType { - RT_repeat = 0, - RT_clamp = 1 - }; - - enum EnvironmentType { - ET_modulate = 0, - ET_blend = 1, - ET_decal = 2, - ET_color = 3 - }; - - enum InternalFormat { - IF_default = 0, - IF_i_12a_4 = 1, - IF_ia_8 = 2, - IF_rgb_5 = 3, - IF_rgba_4 = 4, - IF_ia_12 = 5, - IF_rgba_8 = 6, - IF_rgba_12 = 7, - IF_i_16 = 8, // shadow mode only - IF_rgb_12 = 9 - }; - - enum ExternalFormat { - EF_default = 0, - EF_pack_8 = 1, - EF_pack_16 = 2 - }; - - enum ProjectionType { - PT_flat_earth = 0, - PT_lambert = 3, - PT_utm = 4, - PT_undefined = 7 - }; - - enum EarthModel { - EM_wgs84 = 0, - EM_wgs72 = 1, - EM_bessel = 2, - EM_clarke_1866 = 3, - EM_nad27 = 4 - }; - - enum ImageOrigin { - IO_lower_left = 0, - IO_upper_left = 1 - }; - - enum PointsUnits { - PU_degrees = 0, - PU_meters = 1, - PU_pixels = 2 - }; - - enum Hemisphere { - H_southern = 0, - H_northern = 1, - }; - - struct LODScale { - PN_stdfloat _lod; - PN_stdfloat _scale; - }; - - struct GeospecificControlPoint { - LPoint2d _uv; - LPoint2d _real_earth; - }; - - typedef pvector GeospecificControlPoints; - - struct SubtextureDef { - std::string _name; - int _left; - int _bottom; - int _right; - int _top; - }; - typedef pvector SubtextureDefs; - - int _num_texels_u; - int _num_texels_v; - int _real_world_size_u; - int _real_world_size_v; - int _up_vector_x; - int _up_vector_y; - FileFormat _file_format; - Minification _min_filter; - Magnification _mag_filter; - RepeatType _repeat; - RepeatType _repeat_u; - RepeatType _repeat_v; - int _modify_flag; - int _x_pivot_point; - int _y_pivot_point; - EnvironmentType _env_type; - bool _intensity_is_alpha; // if true, a one-channel image is actually - // an alpha image, not an intensity image. - double _float_real_world_size_u; - double _float_real_world_size_v; - int _imported_origin_code; - int _kernel_version; - InternalFormat _internal_format; - ExternalFormat _external_format; - bool _use_mipmap_kernel; - PN_stdfloat _mipmap_kernel[8]; - bool _use_lod_scale; - LODScale _lod_scale[8]; - PN_stdfloat _clamp; - Magnification _mag_filter_alpha; - Magnification _mag_filter_color; - double _lambert_conic_central_meridian; - double _lambert_conic_upper_latitude; - double _lambert_conic_lower_latitude; - bool _use_detail; - int _detail_j; - int _detail_k; - int _detail_m; - int _detail_n; - int _detail_scramble; - bool _use_tile; - PN_stdfloat _tile_lower_left_u; - PN_stdfloat _tile_lower_left_v; - PN_stdfloat _tile_upper_right_u; - PN_stdfloat _tile_upper_right_v; - ProjectionType _projection; - EarthModel _earth_model; - int _utm_zone; - ImageOrigin _image_origin; - PointsUnits _geospecific_points_units; - Hemisphere _geospecific_hemisphere; - std::string _comment; - int _file_version; - GeospecificControlPoints _geospecific_control_points; - SubtextureDefs _subtexture_defs; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -private: - FltError unpack_attr(const Datagram &datagram); - FltError pack_attr(Datagram &datagram) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltTexture", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltHeader; -}; - -#endif diff --git a/pandatool/src/flt/fltTrackplane.cxx b/pandatool/src/flt/fltTrackplane.cxx deleted file mode 100644 index 13f8a58c..00000000 --- a/pandatool/src/flt/fltTrackplane.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTrackplane.cxx - * @author drose - * @date 2000-08-26 - */ - -#include "fltTrackplane.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -/** - * - */ -FltTrackplane:: -FltTrackplane() { - _origin.set(0.0, 0.0, 0.0); - _alignment.set(0.0, 0.0, 0.0); - _plane.set(0.0, 0.0, 1.0); - _grid_state = false; - _grid_under = false; - _grid_angle = 0.0; - _grid_spacing_x = 1; - _grid_spacing_y = 1; - _snap_to_grid = false; - _grid_size = 10.0; - _grid_spacing_direction = 0; - _grid_mask = 0; -} - -/** - * - */ -bool FltTrackplane:: -extract_record(FltRecordReader &reader) { - DatagramIterator &iterator = reader.get_iterator(); - - _origin[0] = iterator.get_be_float64(); - _origin[1] = iterator.get_be_float64(); - _origin[2] = iterator.get_be_float64(); - _alignment[0] = iterator.get_be_float64(); - _alignment[1] = iterator.get_be_float64(); - _alignment[0] = iterator.get_be_float64(); - _plane[0] = iterator.get_be_float64(); - _plane[1] = iterator.get_be_float64(); - _plane[2] = iterator.get_be_float64(); - _grid_state = (iterator.get_be_int32() != 0); - _grid_under = (iterator.get_be_int32() != 0); - _grid_angle = iterator.get_be_float32(); - iterator.skip_bytes(4); - _grid_spacing_x = iterator.get_be_float64(); - _grid_spacing_y = iterator.get_be_float64(); - _snap_to_grid = (iterator.get_be_int32() != 0); - _grid_size = iterator.get_be_float64(); - _grid_spacing_direction = iterator.get_be_int32(); - _grid_mask = iterator.get_be_int32(); - iterator.skip_bytes(4); - - return true; -} - -/** - * - */ -bool FltTrackplane:: -build_record(FltRecordWriter &writer) const { - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_float64(_origin[0]); - datagram.add_be_float64(_origin[1]); - datagram.add_be_float64(_origin[2]); - datagram.add_be_float64(_alignment[0]); - datagram.add_be_float64(_alignment[1]); - datagram.add_be_float64(_alignment[2]); - datagram.add_be_float64(_plane[0]); - datagram.add_be_float64(_plane[1]); - datagram.add_be_float64(_plane[2]); - datagram.add_be_int32(_grid_state); - datagram.add_be_int32(_grid_under); - datagram.add_be_float32(_grid_angle); - datagram.pad_bytes(4); - datagram.add_be_float64(_grid_spacing_x); - datagram.add_be_float64(_grid_spacing_y); - datagram.add_be_int32(_snap_to_grid); - datagram.add_be_float64(_grid_size); - datagram.add_be_int32(_grid_spacing_direction); - datagram.add_be_int32(_grid_mask); - datagram.pad_bytes(4); - - return true; -} diff --git a/pandatool/src/flt/fltTrackplane.h b/pandatool/src/flt/fltTrackplane.h deleted file mode 100644 index 306f81e9..00000000 --- a/pandatool/src/flt/fltTrackplane.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTrackplane.h - * @author drose - * @date 2000-08-26 - */ - -#ifndef FLTTRACKPLANE_H -#define FLTTRACKPLANE_H - -#include "pandatoolbase.h" - -#include "luse.h" - -class FltRecordReader; -class FltRecordWriter; - -/** - * A single trackplane entry in the eyepoint/trackplane palette. - */ -class FltTrackplane { -public: - FltTrackplane(); - - bool extract_record(FltRecordReader &reader); - bool build_record(FltRecordWriter &writer) const; - -public: - LPoint3d _origin; - LPoint3d _alignment; - LVector3d _plane; - bool _grid_state; - bool _grid_under; - PN_stdfloat _grid_angle; - double _grid_spacing_x; - double _grid_spacing_y; - bool _snap_to_grid; - double _grid_size; - int _grid_spacing_direction; - int _grid_mask; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformGeneralMatrix.cxx b/pandatool/src/flt/fltTransformGeneralMatrix.cxx deleted file mode 100644 index 1c8adf4c..00000000 --- a/pandatool/src/flt/fltTransformGeneralMatrix.cxx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformGeneralMatrix.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltTransformGeneralMatrix.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltTransformGeneralMatrix::_type_handle; - -/** - * - */ -FltTransformGeneralMatrix:: -FltTransformGeneralMatrix(FltHeader *header) : FltTransformRecord(header) { -} - -/** - * Directly sets the general matrix. - */ -void FltTransformGeneralMatrix:: -set_matrix(const LMatrix4d &matrix) { - _matrix = matrix; -} - -/** - * Directly sets the general matrix. - */ -void FltTransformGeneralMatrix:: -set_matrix(const LMatrix4f &matrix) { - _matrix = LCAST(double, matrix); -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTransformGeneralMatrix:: -extract_record(FltRecordReader &reader) { - if (!FltTransformRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_general_matrix, false); - DatagramIterator &iterator = reader.get_iterator(); - - for (int r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - _matrix(r, c) = iterator.get_be_float32(); - } - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTransformGeneralMatrix:: -build_record(FltRecordWriter &writer) const { - if (!FltTransformRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_general_matrix); - Datagram &datagram = writer.update_datagram(); - - for (int r = 0; r < 4; r++) { - for (int c = 0; c < 4; c++) { - datagram.add_be_float32(_matrix(r, c)); - } - } - - return true; -} diff --git a/pandatool/src/flt/fltTransformGeneralMatrix.h b/pandatool/src/flt/fltTransformGeneralMatrix.h deleted file mode 100644 index e56fe94e..00000000 --- a/pandatool/src/flt/fltTransformGeneralMatrix.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformGeneralMatrix.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTTRANSFORMGENERALMATRIX_H -#define FLTTRANSFORMGENERALMATRIX_H - -#include "pandatoolbase.h" - -#include "fltTransformRecord.h" - -/** - * A general 4x4 matrix. This appears in the flt file when there is no record - * of the composition of the transform. - */ -class FltTransformGeneralMatrix : public FltTransformRecord { -public: - FltTransformGeneralMatrix(FltHeader *header); - - void set_matrix(const LMatrix4d &matrix); - void set_matrix(const LMatrix4f &matrix); - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltTransformRecord::init_type(); - register_type(_type_handle, "FltTransformGeneralMatrix", - FltTransformRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformPut.cxx b/pandatool/src/flt/fltTransformPut.cxx deleted file mode 100644 index 612c6b07..00000000 --- a/pandatool/src/flt/fltTransformPut.cxx +++ /dev/null @@ -1,195 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformPut.cxx - * @author drose - * @date 2000-08-29 - */ - -#include "fltTransformPut.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -#include "look_at.h" - -TypeHandle FltTransformPut::_type_handle; - -/** - * - */ -FltTransformPut:: -FltTransformPut(FltHeader *header) : FltTransformRecord(header) { - _from_origin.set(0.0, 0.0, 0.0); - _from_align.set(1.0, 0.0, 0.0); - _from_track.set(1.0, 0.0, 0.0); - _to_origin.set(0.0, 0.0, 0.0); - _to_align.set(1.0, 0.0, 0.0); - _to_track.set(1.0, 0.0, 0.0); -} - -/** - * Defines the put explicitly. The transformation will map the three "from" - * points to the corresponding three "to" points. - */ -void FltTransformPut:: -set(const LPoint3d &from_origin, const LPoint3d &from_align, - const LPoint3d &from_track, - const LPoint3d &to_origin, const LPoint3d &to_align, - const LPoint3d &to_track) { - _from_origin = from_origin; - _from_align = from_align; - _from_track = from_track; - _to_origin = to_origin; - _to_align = to_align; - _to_track = to_track; - - recompute_matrix(); -} - -/** - * - */ -const LPoint3d &FltTransformPut:: -get_from_origin() const { - return _from_origin; -} - -/** - * - */ -const LPoint3d &FltTransformPut:: -get_from_align() const { - return _from_align; -} - -/** - * - */ -const LPoint3d &FltTransformPut:: -get_from_track() const { - return _from_track; -} - -/** - * - */ -const LPoint3d &FltTransformPut:: -get_to_origin() const { - return _to_origin; -} - -/** - * - */ -const LPoint3d &FltTransformPut:: -get_to_align() const { - return _to_align; -} - -/** - * - */ -const LPoint3d &FltTransformPut:: -get_to_track() const { - return _to_track; -} - -/** - * - */ -void FltTransformPut:: -recompute_matrix() { - LMatrix4d r1, r2; - look_at(r1, _from_align - _from_origin, _from_track - _from_origin, CS_zup_right); - look_at(r2, _to_align - _to_origin, _to_track - _to_origin, CS_zup_right); - - _matrix = - LMatrix4d::translate_mat(-_from_origin) * - invert(r1) * - r2 * - LMatrix4d::translate_mat(_to_origin); -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTransformPut:: -extract_record(FltRecordReader &reader) { - if (!FltTransformRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_put, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - _from_origin[0] = iterator.get_be_float64(); - _from_origin[1] = iterator.get_be_float64(); - _from_origin[2] = iterator.get_be_float64(); - _from_align[0] = iterator.get_be_float64(); - _from_align[1] = iterator.get_be_float64(); - _from_align[2] = iterator.get_be_float64(); - _from_track[0] = iterator.get_be_float64(); - _from_track[1] = iterator.get_be_float64(); - _from_track[2] = iterator.get_be_float64(); - _to_origin[0] = iterator.get_be_float64(); - _to_origin[1] = iterator.get_be_float64(); - _to_origin[2] = iterator.get_be_float64(); - _to_align[0] = iterator.get_be_float64(); - _to_align[1] = iterator.get_be_float64(); - _to_align[2] = iterator.get_be_float64(); - _to_track[0] = iterator.get_be_float64(); - _to_track[1] = iterator.get_be_float64(); - _to_track[2] = iterator.get_be_float64(); - - recompute_matrix(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTransformPut:: -build_record(FltRecordWriter &writer) const { - if (!FltTransformRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_put); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); // Undocumented additional padding. - - datagram.add_be_float64(_from_origin[0]); - datagram.add_be_float64(_from_origin[1]); - datagram.add_be_float64(_from_origin[2]); - datagram.add_be_float64(_from_align[0]); - datagram.add_be_float64(_from_align[1]); - datagram.add_be_float64(_from_align[2]); - datagram.add_be_float64(_from_track[0]); - datagram.add_be_float64(_from_track[1]); - datagram.add_be_float64(_from_track[2]); - datagram.add_be_float64(_to_origin[0]); - datagram.add_be_float64(_to_origin[1]); - datagram.add_be_float64(_to_origin[2]); - datagram.add_be_float64(_to_align[0]); - datagram.add_be_float64(_to_align[1]); - datagram.add_be_float64(_to_align[2]); - datagram.add_be_float64(_to_track[0]); - datagram.add_be_float64(_to_track[1]); - datagram.add_be_float64(_to_track[2]); - - return true; -} diff --git a/pandatool/src/flt/fltTransformPut.h b/pandatool/src/flt/fltTransformPut.h deleted file mode 100644 index fdfab778..00000000 --- a/pandatool/src/flt/fltTransformPut.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformPut.h - * @author drose - * @date 2000-08-29 - */ - -#ifndef FLTTRANSFORMPUT_H -#define FLTTRANSFORMPUT_H - -#include "pandatoolbase.h" - -#include "fltTransformRecord.h" - -/** - * A "put", which is a MultiGen concept of defining a transformation by - * mapping three arbitrary points to three new arbitrary points. - */ -class FltTransformPut : public FltTransformRecord { -public: - FltTransformPut(FltHeader *header); - - void set(const LPoint3d &from_origin, - const LPoint3d &from_align, - const LPoint3d &from_track, - const LPoint3d &to_origin, - const LPoint3d &to_align, - const LPoint3d &to_track); - - const LPoint3d &get_from_origin() const; - const LPoint3d &get_from_align() const; - const LPoint3d &get_from_track() const; - const LPoint3d &get_to_origin() const; - const LPoint3d &get_to_align() const; - const LPoint3d &get_to_track() const; - -private: - void recompute_matrix(); - - LPoint3d _from_origin; - LPoint3d _from_align; - LPoint3d _from_track; - LPoint3d _to_origin; - LPoint3d _to_align; - LPoint3d _to_track; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltTransformRecord::init_type(); - register_type(_type_handle, "FltTransformPut", - FltTransformRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformRecord.cxx b/pandatool/src/flt/fltTransformRecord.cxx deleted file mode 100644 index bc1275bc..00000000 --- a/pandatool/src/flt/fltTransformRecord.cxx +++ /dev/null @@ -1,33 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRecord.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltTransformRecord.h" - -TypeHandle FltTransformRecord::_type_handle; - -/** - * - */ -FltTransformRecord:: -FltTransformRecord(FltHeader *header) : FltRecord(header) { - _matrix = LMatrix4d::ident_mat(); -} - -/** - * Returns the transform matrix represented by this particular component of - * the transform. - */ -const LMatrix4d &FltTransformRecord:: -get_matrix() const { - return _matrix; -} diff --git a/pandatool/src/flt/fltTransformRecord.h b/pandatool/src/flt/fltTransformRecord.h deleted file mode 100644 index b2679b84..00000000 --- a/pandatool/src/flt/fltTransformRecord.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRecord.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTTRANSFORMRECORD_H -#define FLTTRANSFORMRECORD_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" - -#include "luse.h" - -/** - * A base class for a number of types of ancillary records that follow beads - * and indicate some kind of a transformation. Pointers of this type are - * collected in the FltTransformation class. - */ -class FltTransformRecord : public FltRecord { -public: - FltTransformRecord(FltHeader *header); - - const LMatrix4d &get_matrix() const; - -protected: - LMatrix4d _matrix; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltTransformRecord", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltBead; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformRotateAboutEdge.cxx b/pandatool/src/flt/fltTransformRotateAboutEdge.cxx deleted file mode 100644 index ec4bbf95..00000000 --- a/pandatool/src/flt/fltTransformRotateAboutEdge.cxx +++ /dev/null @@ -1,144 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRotateAboutEdge.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltTransformRotateAboutEdge.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltTransformRotateAboutEdge::_type_handle; - -/** - * - */ -FltTransformRotateAboutEdge:: -FltTransformRotateAboutEdge(FltHeader *header) : FltTransformRecord(header) { - _point_a.set(0.0, 0.0, 0.0); - _point_b.set(1.0, 0.0, 0.0); - _angle = 0.0; -} - -/** - * Defines the rotation. The angle is given in degrees, counterclockwise - * about the axis as seen from point a. - */ -void FltTransformRotateAboutEdge:: -set(const LPoint3d &point_a, const LPoint3d &point_b, PN_stdfloat angle) { - _point_a = point_a; - _point_b = point_b; - _angle = angle; - - recompute_matrix(); -} - -/** - * - */ -const LPoint3d &FltTransformRotateAboutEdge:: -get_point_a() const { - return _point_a; -} - -/** - * - */ -const LPoint3d &FltTransformRotateAboutEdge:: -get_point_b() const { - return _point_b; -} - -/** - * Returns the angle of rotation, in degrees counterclockwise about the axis - * as seen from point a. - */ -PN_stdfloat FltTransformRotateAboutEdge:: -get_angle() const { - return _angle; -} - -/** - * - */ -void FltTransformRotateAboutEdge:: -recompute_matrix() { - if (_point_a == _point_b) { - // Degenerate case. - _matrix = LMatrix4d::ident_mat(); - } else { - LVector3d axis = _point_b - _point_a; - _matrix = - LMatrix4d::translate_mat(-_point_a) * - LMatrix4d::rotate_mat(_angle, normalize(axis), CS_zup_right) * - LMatrix4d::translate_mat(_point_a); - } -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTransformRotateAboutEdge:: -extract_record(FltRecordReader &reader) { - if (!FltTransformRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_rotate_about_edge, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - _point_a[0] = iterator.get_be_float64(); - _point_a[1] = iterator.get_be_float64(); - _point_a[2] = iterator.get_be_float64(); - _point_b[0] = iterator.get_be_float64(); - _point_b[1] = iterator.get_be_float64(); - _point_b[2] = iterator.get_be_float64(); - _angle = iterator.get_be_float32(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - recompute_matrix(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTransformRotateAboutEdge:: -build_record(FltRecordWriter &writer) const { - if (!FltTransformRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_rotate_about_edge); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); // Undocumented additional padding. - - datagram.add_be_float64(_point_a[0]); - datagram.add_be_float64(_point_a[1]); - datagram.add_be_float64(_point_a[2]); - datagram.add_be_float64(_point_b[0]); - datagram.add_be_float64(_point_b[1]); - datagram.add_be_float64(_point_b[2]); - datagram.add_be_float32(_angle); - - datagram.pad_bytes(4); // Undocumented additional padding. - - return true; -} diff --git a/pandatool/src/flt/fltTransformRotateAboutEdge.h b/pandatool/src/flt/fltTransformRotateAboutEdge.h deleted file mode 100644 index 34ce5854..00000000 --- a/pandatool/src/flt/fltTransformRotateAboutEdge.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRotateAboutEdge.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTTRANSFORMROTATEABOUTEDGE_H -#define FLTTRANSFORMROTATEABOUTEDGE_H - -#include "pandatoolbase.h" - -#include "fltTransformRecord.h" - -/** - * A transformation that rotates about a particular axis in space, defined by - * two endpoints. - */ -class FltTransformRotateAboutEdge : public FltTransformRecord { -public: - FltTransformRotateAboutEdge(FltHeader *header); - - void set(const LPoint3d &point_a, const LPoint3d &point_b, PN_stdfloat angle); - - const LPoint3d &get_point_a() const; - const LPoint3d &get_point_b() const; - PN_stdfloat get_angle() const; - -private: - void recompute_matrix(); - - LPoint3d _point_a; - LPoint3d _point_b; - PN_stdfloat _angle; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltTransformRecord::init_type(); - register_type(_type_handle, "FltTransformRotateAboutEdge", - FltTransformRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformRotateAboutPoint.cxx b/pandatool/src/flt/fltTransformRotateAboutPoint.cxx deleted file mode 100644 index 1c6db879..00000000 --- a/pandatool/src/flt/fltTransformRotateAboutPoint.cxx +++ /dev/null @@ -1,140 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRotateAboutPoint.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltTransformRotateAboutPoint.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltTransformRotateAboutPoint::_type_handle; - -/** - * - */ -FltTransformRotateAboutPoint:: -FltTransformRotateAboutPoint(FltHeader *header) : FltTransformRecord(header) { - _center.set(0.0, 0.0, 0.0); - _axis.set(1.0, 0.0, 0.0); - _angle = 0.0; -} - -/** - * Defines the rotation. The angle is given in degrees, counterclockwise - * about the axis as seen from point a. - */ -void FltTransformRotateAboutPoint:: -set(const LPoint3d ¢er, const LVector3 &axis, PN_stdfloat angle) { - _center = center; - _axis = axis; - _angle = angle; - - recompute_matrix(); -} - -/** - * - */ -const LPoint3d &FltTransformRotateAboutPoint:: -get_center() const { - return _center; -} - -/** - * - */ -const LVector3 &FltTransformRotateAboutPoint:: -get_axis() const { - return _axis; -} - -/** - * Returns the angle of rotation, in degrees counterclockwise about the axis. - */ -PN_stdfloat FltTransformRotateAboutPoint:: -get_angle() const { - return _angle; -} - -/** - * - */ -void FltTransformRotateAboutPoint:: -recompute_matrix() { - if (_axis == LVector3::zero()) { - // Degenerate case. - _matrix = LMatrix4d::ident_mat(); - } else { - LVector3d axis = LCAST(double, _axis); - - _matrix = - LMatrix4d::translate_mat(-_center) * - LMatrix4d::rotate_mat(_angle, axis, CS_zup_right) * - LMatrix4d::translate_mat(_center); - } -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTransformRotateAboutPoint:: -extract_record(FltRecordReader &reader) { - if (!FltTransformRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_rotate_about_point, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - _center[0] = iterator.get_be_float64(); - _center[1] = iterator.get_be_float64(); - _center[2] = iterator.get_be_float64(); - _axis[0] = iterator.get_be_float32(); - _axis[1] = iterator.get_be_float32(); - _axis[2] = iterator.get_be_float32(); - _angle = iterator.get_be_float32(); - - recompute_matrix(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTransformRotateAboutPoint:: -build_record(FltRecordWriter &writer) const { - if (!FltTransformRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_rotate_about_point); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); // Undocumented additional padding. - - datagram.add_be_float64(_center[0]); - datagram.add_be_float64(_center[1]); - datagram.add_be_float64(_center[2]); - datagram.add_be_float32(_axis[0]); - datagram.add_be_float32(_axis[1]); - datagram.add_be_float32(_axis[2]); - datagram.add_be_float32(_angle); - - return true; -} diff --git a/pandatool/src/flt/fltTransformRotateAboutPoint.h b/pandatool/src/flt/fltTransformRotateAboutPoint.h deleted file mode 100644 index 716bb56c..00000000 --- a/pandatool/src/flt/fltTransformRotateAboutPoint.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRotateAboutPoint.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTTRANSFORMROTATEABOUTPOINT_H -#define FLTTRANSFORMROTATEABOUTPOINT_H - -#include "pandatoolbase.h" - -#include "fltTransformRecord.h" - -/** - * A transformation that rotates about a particular axis in space, defined by - * a point and vector. - */ -class FltTransformRotateAboutPoint : public FltTransformRecord { -public: - FltTransformRotateAboutPoint(FltHeader *header); - - void set(const LPoint3d ¢er, const LVector3 &axis, PN_stdfloat angle); - - const LPoint3d &get_center() const; - const LVector3 &get_axis() const; - PN_stdfloat get_angle() const; - -private: - void recompute_matrix(); - - LPoint3d _center; - LVector3 _axis; - PN_stdfloat _angle; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltTransformRecord::init_type(); - register_type(_type_handle, "FltTransformRotateAboutPoint", - FltTransformRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformRotateScale.cxx b/pandatool/src/flt/fltTransformRotateScale.cxx deleted file mode 100644 index e81dbb47..00000000 --- a/pandatool/src/flt/fltTransformRotateScale.cxx +++ /dev/null @@ -1,208 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRotateScale.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltTransformRotateScale.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -#include "mathNumbers.h" -#include "look_at.h" - -TypeHandle FltTransformRotateScale::_type_handle; - -/** - * - */ -FltTransformRotateScale:: -FltTransformRotateScale(FltHeader *header) : FltTransformRecord(header) { - _center.set(0.0, 0.0, 0.0); - _reference_point.set(0.0, 0.0, 0.0); - _to_point.set(0.0, 0.0, 0.0); - _overall_scale = 1.0; - _axis_scale = 1.0; - _angle = 0.0; -} - -/** - * Defines the transform explicitly. The angle of rotation is determined by - * the angle between the reference point and the to point (relative to the - * center), and the scale factor is determined by the distance between the - * reference point and the center point. If axis_scale is true, the scale is - * along reference point axis only; otherwise, it is a uniform scale. - */ -void FltTransformRotateScale:: -set(const LPoint3d ¢er, const LPoint3d &reference_point, - const LPoint3d &to_point, bool axis_scale) { - _center = center; - _reference_point = reference_point; - _to_point = to_point; - - LVector3d v1 = _reference_point - _center; - LVector3d v2 = _to_point - _center; - - _angle = - acos(dot(normalize(v1), normalize(v2))) * 180.0 / MathNumbers::pi; - - if (axis_scale) { - _axis_scale = length(v1); - _overall_scale = 1.0; - } else { - _overall_scale = length(v1); - _axis_scale = 1.0; - } - - recompute_matrix(); -} - -/** - * - */ -const LPoint3d &FltTransformRotateScale:: -get_center() const { - return _center; -} - -/** - * - */ -const LPoint3d &FltTransformRotateScale:: -get_reference_point() const { - return _reference_point; -} - -/** - * - */ -const LPoint3d &FltTransformRotateScale:: -get_to_point() const { - return _to_point; -} - -/** - * Returns the overall scale factor. - */ -PN_stdfloat FltTransformRotateScale:: -get_overall_scale() const { - return _overall_scale; -} - -/** - * Returns the scale factor in the direction of the axis. - */ -PN_stdfloat FltTransformRotateScale:: -get_axis_scale() const { - return _axis_scale; -} - -/** - * Returns the angle of rotation in degrees. - */ -PN_stdfloat FltTransformRotateScale:: -get_angle() const { - return _angle; -} - -/** - * - */ -void FltTransformRotateScale:: -recompute_matrix() { - LVector3d v1 = _reference_point - _center; - LVector3d v2 = _to_point - _center; - LVector3d rotate_axis = normalize(cross(v1, v2)); - - // To scale along an axis, we have to do a bit of work. First determine the - // matrices to rotate and unrotate the rotate axis to the y-forward axis. - LMatrix4d r1; - look_at(r1, v1, rotate_axis, CS_zup_right); - - _matrix = - LMatrix4d::translate_mat(-_center) * - r1 * - LMatrix4d::scale_mat(1.0, _axis_scale, 1.0) * - LMatrix4d::scale_mat(_overall_scale) * - invert(r1) * - LMatrix4d::rotate_mat(_angle, rotate_axis, CS_zup_right) * - LMatrix4d::translate_mat(_center); -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTransformRotateScale:: -extract_record(FltRecordReader &reader) { - if (!FltTransformRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_rotate_and_scale, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - _center[0] = iterator.get_be_float64(); - _center[1] = iterator.get_be_float64(); - _center[2] = iterator.get_be_float64(); - _reference_point[0] = iterator.get_be_float64(); - _reference_point[1] = iterator.get_be_float64(); - _reference_point[2] = iterator.get_be_float64(); - _to_point[0] = iterator.get_be_float64(); - _to_point[1] = iterator.get_be_float64(); - _to_point[2] = iterator.get_be_float64(); - _overall_scale = iterator.get_be_float32(); - _axis_scale = iterator.get_be_float32(); - _angle = iterator.get_be_float32(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - recompute_matrix(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTransformRotateScale:: -build_record(FltRecordWriter &writer) const { - if (!FltTransformRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_put); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); // Undocumented additional padding. - - datagram.add_be_float64(_center[0]); - datagram.add_be_float64(_center[1]); - datagram.add_be_float64(_center[2]); - datagram.add_be_float64(_reference_point[0]); - datagram.add_be_float64(_reference_point[1]); - datagram.add_be_float64(_reference_point[2]); - datagram.add_be_float64(_to_point[0]); - datagram.add_be_float64(_to_point[1]); - datagram.add_be_float64(_to_point[2]); - datagram.add_be_float32(_overall_scale); - datagram.add_be_float32(_axis_scale); - datagram.add_be_float32(_angle); - - datagram.pad_bytes(4); // Undocumented additional padding. - - return true; -} diff --git a/pandatool/src/flt/fltTransformRotateScale.h b/pandatool/src/flt/fltTransformRotateScale.h deleted file mode 100644 index 29b72ddd..00000000 --- a/pandatool/src/flt/fltTransformRotateScale.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformRotateScale.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTTRANSFORMROTATESCALE_H -#define FLTTRANSFORMROTATESCALE_H - -#include "pandatoolbase.h" - -#include "fltTransformRecord.h" - -/** - * A combination rotation and scale. This is sometimes called "Rotate To - * Point" within MultiGen. - */ -class FltTransformRotateScale : public FltTransformRecord { -public: - FltTransformRotateScale(FltHeader *header); - - void set(const LPoint3d ¢er, const LPoint3d &reference_point, - const LPoint3d &to_point, bool axis_scale); - - const LPoint3d &get_center() const; - const LPoint3d &get_reference_point() const; - const LPoint3d &get_to_point() const; - PN_stdfloat get_overall_scale() const; - PN_stdfloat get_axis_scale() const; - PN_stdfloat get_angle() const; - -private: - void recompute_matrix(); - - LPoint3d _center; - LPoint3d _reference_point; - LPoint3d _to_point; - PN_stdfloat _overall_scale; - PN_stdfloat _axis_scale; - PN_stdfloat _angle; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltTransformRecord::init_type(); - register_type(_type_handle, "FltTransformRotateScale", - FltTransformRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformScale.cxx b/pandatool/src/flt/fltTransformScale.cxx deleted file mode 100644 index 69ae6f4c..00000000 --- a/pandatool/src/flt/fltTransformScale.cxx +++ /dev/null @@ -1,142 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformScale.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltTransformScale.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltTransformScale::_type_handle; - -/** - * - */ -FltTransformScale:: -FltTransformScale(FltHeader *header) : FltTransformRecord(header) { - _center.set(0.0, 0.0, 0.0); - _scale.set(1.0, 1.0, 1.0); -} - -/** - * Defines the scale. - */ -void FltTransformScale:: -set(const LPoint3d ¢er, const LVecBase3 &scale) { - _center = center; - _scale = scale; - - recompute_matrix(); -} - -/** - * Returns true if the center is specified, false if it is not. For some - * reason, MultiGen stores large negative numbers in for the center if it is - * not specified. It is unclear what the purpose of this is. - */ -bool FltTransformScale:: -has_center() const { - return - _center[0] > -1e+08 && - _center[1] > -1e+08 && - _center[2] > -1e+08; -} - -/** - * - */ -const LPoint3d &FltTransformScale:: -get_center() const { - return _center; -} - -/** - * - */ -const LVecBase3 &FltTransformScale:: -get_scale() const { - return _scale; -} - -/** - * - */ -void FltTransformScale:: -recompute_matrix() { - if (has_center()) { - _matrix = - LMatrix4d::translate_mat(-_center) * - LMatrix4d::scale_mat(LCAST(double, _scale)) * - LMatrix4d::translate_mat(_center); - } else { - _matrix = - LMatrix4d::scale_mat(LCAST(double, _scale)); - } -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTransformScale:: -extract_record(FltRecordReader &reader) { - if (!FltTransformRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_scale, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); - - _center[0] = iterator.get_be_float64(); - _center[1] = iterator.get_be_float64(); - _center[2] = iterator.get_be_float64(); - _scale[0] = iterator.get_be_float32(); - _scale[1] = iterator.get_be_float32(); - _scale[2] = iterator.get_be_float32(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - recompute_matrix(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTransformScale:: -build_record(FltRecordWriter &writer) const { - if (!FltTransformRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_scale); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); // Undocumented additional padding. - - datagram.add_be_float64(_center[0]); - datagram.add_be_float64(_center[1]); - datagram.add_be_float64(_center[2]); - datagram.add_be_float32(_scale[0]); - datagram.add_be_float32(_scale[1]); - datagram.add_be_float32(_scale[2]); - - datagram.pad_bytes(4); // Undocumented additional padding. - - return true; -} diff --git a/pandatool/src/flt/fltTransformScale.h b/pandatool/src/flt/fltTransformScale.h deleted file mode 100644 index 01bc6296..00000000 --- a/pandatool/src/flt/fltTransformScale.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformScale.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTTRANSFORMSCALE_H -#define FLTTRANSFORMSCALE_H - -#include "pandatoolbase.h" - -#include "fltTransformRecord.h" - -/** - * A transformation that applies a (possibly nonuniform) scale. - */ -class FltTransformScale : public FltTransformRecord { -public: - FltTransformScale(FltHeader *header); - - void set(const LPoint3d ¢er, const LVecBase3 &scale); - - bool has_center() const; - const LPoint3d &get_center() const; - const LVecBase3 &get_scale() const; - -private: - void recompute_matrix(); - - LPoint3d _center; - LVecBase3 _scale; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltTransformRecord::init_type(); - register_type(_type_handle, "FltTransformScale", - FltTransformRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltTransformTranslate.cxx b/pandatool/src/flt/fltTransformTranslate.cxx deleted file mode 100644 index 1a06d761..00000000 --- a/pandatool/src/flt/fltTransformTranslate.cxx +++ /dev/null @@ -1,122 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformTranslate.cxx - * @author drose - * @date 2000-08-30 - */ - -#include "fltTransformTranslate.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltTransformTranslate::_type_handle; - -/** - * - */ -FltTransformTranslate:: -FltTransformTranslate(FltHeader *header) : FltTransformRecord(header) { - _from.set(0.0, 0.0, 0.0); - _delta.set(0.0, 0.0, 0.0); -} - -/** - * Defines the translation. The "from" point seems to be pretty much ignored. - */ -void FltTransformTranslate:: -set(const LPoint3d &from, const LVector3d &delta) { - _from = from; - _delta = delta; - - recompute_matrix(); -} - -/** - * Returns the reference point of the translation. This is largely - * meaningless. - */ -const LPoint3d &FltTransformTranslate:: -get_from() const { - return _from; -} - -/** - * - */ -const LVector3d &FltTransformTranslate:: -get_delta() const { - return _delta; -} - -/** - * - */ -void FltTransformTranslate:: -recompute_matrix() { - _matrix = LMatrix4d::translate_mat(_delta); -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltTransformTranslate:: -extract_record(FltRecordReader &reader) { - if (!FltTransformRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_translate, false); - DatagramIterator &iterator = reader.get_iterator(); - - iterator.skip_bytes(4); // Undocumented additional padding. - - _from[0] = iterator.get_be_float64(); - _from[1] = iterator.get_be_float64(); - _from[2] = iterator.get_be_float64(); - _delta[0] = iterator.get_be_float64(); - _delta[1] = iterator.get_be_float64(); - _delta[2] = iterator.get_be_float64(); - - // iterator.skip_bytes(4); Undocumented additional padding. - - recompute_matrix(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltTransformTranslate:: -build_record(FltRecordWriter &writer) const { - if (!FltTransformRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_translate); - Datagram &datagram = writer.update_datagram(); - - datagram.pad_bytes(4); // Undocumented additional padding. - - datagram.add_be_float64(_from[0]); - datagram.add_be_float64(_from[1]); - datagram.add_be_float64(_from[2]); - datagram.add_be_float64(_delta[0]); - datagram.add_be_float64(_delta[1]); - datagram.add_be_float64(_delta[2]); - - // datagram.pad_bytes(4); Undocumented additional padding. - - return true; -} diff --git a/pandatool/src/flt/fltTransformTranslate.h b/pandatool/src/flt/fltTransformTranslate.h deleted file mode 100644 index c9a0c879..00000000 --- a/pandatool/src/flt/fltTransformTranslate.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTransformTranslate.h - * @author drose - * @date 2000-08-30 - */ - -#ifndef FLTTRANSFORMTRANSLATE_H -#define FLTTRANSFORMTRANSLATE_H - -#include "pandatoolbase.h" - -#include "fltTransformRecord.h" - -/** - * A transformation that applies a translation. - */ -class FltTransformTranslate : public FltTransformRecord { -public: - FltTransformTranslate(FltHeader *header); - - void set(const LPoint3d &from, const LVector3d &delta); - - const LPoint3d &get_from() const; - const LVector3d &get_delta() const; - -private: - void recompute_matrix(); - - LPoint3d _from; - LVector3d _delta; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltTransformRecord::init_type(); - register_type(_type_handle, "FltTransformTranslate", - FltTransformRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/fltUnsupportedRecord.cxx b/pandatool/src/flt/fltUnsupportedRecord.cxx deleted file mode 100644 index 7a6e67aa..00000000 --- a/pandatool/src/flt/fltUnsupportedRecord.cxx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltUnsupportedRecord.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "fltUnsupportedRecord.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltUnsupportedRecord::_type_handle; - -/** - * - */ -FltUnsupportedRecord:: -FltUnsupportedRecord(FltHeader *header) : FltRecord(header) { - _opcode = FO_none; -} - -/** - * Writes a quick one-line description of the bead, but not its children. - * This is a human-readable description, primarily for debugging; to write a - * flt file, use FltHeader::write_flt(). - */ -void FltUnsupportedRecord:: -output(std::ostream &out) const { - out << "Unsupported(" << _opcode << ")"; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltUnsupportedRecord:: -extract_record(FltRecordReader &reader) { - _opcode = reader.get_opcode(); - _datagram = reader.get_datagram(); - - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltUnsupportedRecord:: -build_record(FltRecordWriter &writer) const { - writer.set_opcode(_opcode); - writer.set_datagram(_datagram); - return true; -} diff --git a/pandatool/src/flt/fltUnsupportedRecord.h b/pandatool/src/flt/fltUnsupportedRecord.h deleted file mode 100644 index a358577d..00000000 --- a/pandatool/src/flt/fltUnsupportedRecord.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltUnsupportedRecord.h - * @author drose - * @date 2000-08-24 - */ - -#ifndef FLTUNSUPPORTEDRECORD_H -#define FLTUNSUPPORTEDRECORD_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" - -#include "datagram.h" - -/** - * - */ -class FltUnsupportedRecord : public FltRecord { -public: - FltUnsupportedRecord(FltHeader *header); - - virtual void output(std::ostream &out) const; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -private: - FltOpcode _opcode; - Datagram _datagram; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltUnsupportedRecord", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltHeader; -}; - -#endif diff --git a/pandatool/src/flt/fltVectorRecord.cxx b/pandatool/src/flt/fltVectorRecord.cxx deleted file mode 100644 index dbe23a63..00000000 --- a/pandatool/src/flt/fltVectorRecord.cxx +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltVectorRecord.cxx - * @author drose - * @date 2002-08-30 - */ - -#include "fltVectorRecord.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" - -TypeHandle FltVectorRecord::_type_handle; - -/** - * - */ -FltVectorRecord:: -FltVectorRecord(FltHeader *header) : FltRecord(header) { - _vector.set(0.0f, 0.0f, 0.0f); -} - -/** - * Returns the vector value. - */ -const LVector3 &FltVectorRecord:: -get_vector() const { - return _vector; -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltVectorRecord:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_vector, false); - DatagramIterator &iterator = reader.get_iterator(); - - _vector[0] = iterator.get_be_float32(); - _vector[1] = iterator.get_be_float32(); - _vector[2] = iterator.get_be_float32(); - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltVectorRecord:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_vector); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_float32(_vector[0]); - datagram.add_be_float32(_vector[1]); - datagram.add_be_float32(_vector[2]); - - return true; -} diff --git a/pandatool/src/flt/fltVectorRecord.h b/pandatool/src/flt/fltVectorRecord.h deleted file mode 100644 index e099652e..00000000 --- a/pandatool/src/flt/fltVectorRecord.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltVectorRecord.h - * @author drose - * @date 2002-08-30 - */ - -#ifndef FLTVECTORRECORD_H -#define FLTVECTORRECORD_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" - -#include "luse.h" - -/** - * This is an ancillary record of the old (pre-15.4) face node. Its only use - * is to provide the direction vector for unidirectional and bidirectional - * light point faces. - */ -class FltVectorRecord : public FltRecord { -public: - FltVectorRecord(FltHeader *header); - - const LVector3 &get_vector() const; - -protected: - LVector3 _vector; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltVectorRecord", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltBead; -}; - -#endif diff --git a/pandatool/src/flt/fltVertex.I b/pandatool/src/flt/fltVertex.I deleted file mode 100644 index 2f7717af..00000000 --- a/pandatool/src/flt/fltVertex.I +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltVertex.I - * @author drose - * @date 2000-08-30 - */ - -/** - * Returns true if the vertex has a primary color indicated, false otherwise. - */ -INLINE bool FltVertex:: -has_color() const { - // Even if the no_color bit is not set, if the color_index is -1, the vertex - // doesn't have a color (unless we've got packed color). - return ((_flags & F_no_color) == 0 && - (_color_index != -1 || ((_flags & F_packed_color) != 0))); -} - -/** - * Sets the color of the vertex, using the packed color convention. The alpha - * component is ignored. - */ -INLINE void FltVertex:: -set_color(const LColor &color) { - set_rgb(LRGBColor(color[0], color[1], color[2])); -} diff --git a/pandatool/src/flt/fltVertex.cxx b/pandatool/src/flt/fltVertex.cxx deleted file mode 100644 index 77cac997..00000000 --- a/pandatool/src/flt/fltVertex.cxx +++ /dev/null @@ -1,259 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltVertex.cxx - * @author drose - * @date 2000-08-25 - */ - -#include "fltVertex.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" - -TypeHandle FltVertex::_type_handle; - -/** - * - */ -FltVertex:: -FltVertex(FltHeader *header) : FltRecord(header) { - _color_name_index = 0; - _flags = F_no_color; - _pos.set(0.0, 0.0, 0.0); - _normal.set(0.0, 0.0, 0.0); - _uv.set(0.0, 0.0); - _color_index = 0; - - _has_normal = false; - _has_uv = false; -} - -/** - * Returns the opcode that this record will be written as. - */ -FltOpcode FltVertex:: -get_opcode() const { - if (_has_normal) { - if (_has_uv) { - return FO_vertex_cnu; - } else { - return FO_vertex_cn; - } - } else { - if (_has_uv) { - return FO_vertex_cu; - } else { - return FO_vertex_c; - } - } -} - -/** - * Returns the length of this record in bytes as it will be written to the flt - * file. - */ -int FltVertex:: -get_record_length() const { - if (_header->get_flt_version() < 1520) { - // Version 14.2 - switch (get_opcode()) { - case FO_vertex_c: - return 36; - - case FO_vertex_cn: - return 48; - - case FO_vertex_cnu: - return 56; - - case FO_vertex_cu: - return 44; - - default: - nassertr(false, 0); - } - - } else { - // Version 15.2 and higher - switch (get_opcode()) { - case FO_vertex_c: - return 40; - - case FO_vertex_cn: - return 56; - - case FO_vertex_cnu: - return 64; - - case FO_vertex_cu: - return 48; - - default: - nassertr(false, 0); - } - } - - return 0; -} - -/** - * If has_color() indicates true, returns the color of the vertex, as a four- - * component value. In the case of a vertex, the alpha channel will always be - * 1.0, as MultiGen does not store transparency per-vertex. - */ -LColor FltVertex:: -get_color() const { - nassertr(has_color(), LColor(0.0, 0.0, 0.0, 0.0)); - - return _header->get_color(_color_index, (_flags & F_packed_color) != 0, - _packed_color, 0); -} - -/** - * If has_color() indicates true, returns the color of the vertex, as a three- - * component value. - */ -LRGBColor FltVertex:: -get_rgb() const { - nassertr(has_color(), LRGBColor(0.0, 0.0, 0.0)); - - return _header->get_rgb(_color_index, (_flags & F_packed_color) != 0, - _packed_color); -} - -/** - * Sets the color of the vertex, using the packed color convention. - */ -void FltVertex:: -set_rgb(const LRGBColor &rgb) { - _packed_color.set_rgb(rgb); - _flags = ((_flags & ~F_no_color) | F_packed_color); -} - -/** - * Fills in the information in this record based on the information given in - * the indicated datagram, whose opcode has already been read. Returns true - * on success, false if the datagram is invalid. - */ -bool FltVertex:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - - switch (reader.get_opcode()) { - case FO_vertex_c: - _has_normal = false; - _has_uv = false; - break; - - case FO_vertex_cn: - _has_normal = true; - _has_uv = false; - break; - - case FO_vertex_cnu: - _has_normal = true; - _has_uv = true; - break; - - case FO_vertex_cu: - _has_normal = false; - _has_uv = true; - break; - - default: - nassertr(false, false); - } - - DatagramIterator &iterator = reader.get_iterator(); - - _color_name_index = iterator.get_be_int16(); - _flags = iterator.get_be_uint16(); - _pos[0] = iterator.get_be_float64(); - _pos[1] = iterator.get_be_float64(); - _pos[2] = iterator.get_be_float64(); - - if (_has_normal) { - _normal[0] = iterator.get_be_float32(); - _normal[1] = iterator.get_be_float32(); - _normal[2] = iterator.get_be_float32(); - } - if (_has_uv) { - _uv[0] = iterator.get_be_float32(); - _uv[1] = iterator.get_be_float32(); - } - - if (iterator.get_remaining_size() > 0) { - if (!_packed_color.extract_record(reader)) { - return false; - } - if (_header->get_flt_version() >= 1520) { - _color_index = iterator.get_be_int32(); - - if (_has_normal && iterator.get_remaining_size() > 0) { - // If we extracted a normal, our double-word alignment is off; now we - // have a few extra bytes to ignore. - iterator.skip_bytes(4); - } - } - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltVertex:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(get_opcode()); - Datagram &datagram = writer.update_datagram(); - - datagram.add_be_int16(_color_name_index); - datagram.add_be_uint16(_flags); - datagram.add_be_float64(_pos[0]); - datagram.add_be_float64(_pos[1]); - datagram.add_be_float64(_pos[2]); - - if (_has_normal) { - datagram.add_be_float32(_normal[0]); - datagram.add_be_float32(_normal[1]); - datagram.add_be_float32(_normal[2]); - } - if (_has_uv) { - datagram.add_be_float32(_uv[0]); - datagram.add_be_float32(_uv[1]); - } - - if (!_packed_color.build_record(writer)) { - return false; - } - - if (_header->get_flt_version() >= 1520) { - // New with 15.2 - datagram.add_be_uint32(_color_index); - - if (_has_normal) { - // If we added a normal, our double-word alignment is off; now we have a - // few extra bytes to add. - datagram.pad_bytes(4); - } - } - - nassertr((int)datagram.get_length() == get_record_length() - 4, true); - return true; -} diff --git a/pandatool/src/flt/fltVertex.h b/pandatool/src/flt/fltVertex.h deleted file mode 100644 index 9c02c372..00000000 --- a/pandatool/src/flt/fltVertex.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltVertex.h - * @author drose - * @date 2000-08-25 - */ - -#ifndef FLTVERTEX_H -#define FLTVERTEX_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" -#include "fltPackedColor.h" - -#include "luse.h" - -/** - * Represents a single vertex in the vertex palette. Flt files index vertices - * by their byte offset in the vertex palette; within this library, we map - * those byte offsets to pointers automatically. - * - * This may represent a vertex with or without a normal or texture - * coordinates. - */ -class FltVertex : public FltRecord { -public: - FltVertex(FltHeader *header); - - FltOpcode get_opcode() const; - int get_record_length() const; - - enum Flags { - F_hard_edge = 0x8000, - F_normal_frozen = 0x4000, - F_no_color = 0x2000, - F_packed_color = 0x1000 - }; - - int _color_name_index; - unsigned int _flags; - LPoint3d _pos; - LPoint3 _normal; - LPoint2 _uv; - FltPackedColor _packed_color; - int _color_index; - - bool _has_normal; - bool _has_uv; - -public: - INLINE bool has_color() const; - LColor get_color() const; - INLINE void set_color(const LColor &color); - LRGBColor get_rgb() const; - void set_rgb(const LRGBColor &rgb); - - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltVertex", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class FltHeader; -}; - -#include "fltVertex.I" - -#endif diff --git a/pandatool/src/flt/fltVertexList.cxx b/pandatool/src/flt/fltVertexList.cxx deleted file mode 100644 index 65da9b59..00000000 --- a/pandatool/src/flt/fltVertexList.cxx +++ /dev/null @@ -1,116 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltVertexList.cxx - * @author drose - * @date 2000-08-25 - */ - -#include "fltVertexList.h" -#include "fltRecordReader.h" -#include "fltRecordWriter.h" -#include "fltHeader.h" - -TypeHandle FltVertexList::_type_handle; - -/** - * - */ -FltVertexList:: -FltVertexList(FltHeader *header) : FltRecord(header) { -} - -/** - * Returns the number of vertices in this vertex list. - */ -int FltVertexList:: -get_num_vertices() const { - return _vertices.size(); -} - -/** - * Returns the nth vertex of this vertex list. - */ -FltVertex *FltVertexList:: -get_vertex(int n) const { - nassertr(n >= 0 && n < (int)_vertices.size(), nullptr); - return _vertices[n]; -} - -/** - * Removes all vertices from this vertex list. - */ -void FltVertexList:: -clear_vertices() { - _vertices.clear(); -} - -/** - * Adds a new vertex to the end of the vertex list. - */ -void FltVertexList:: -add_vertex(FltVertex *vertex) { - _header->add_vertex(vertex); - _vertices.push_back(vertex); -} - -/** - * Writes a quick one-line description of the record, but not its children. - * This is a human-readable description, primarily for debugging; to write a - * flt file, use FltHeader::write_flt(). - */ -void FltVertexList:: -output(std::ostream &out) const { - out << _vertices.size() << " vertices"; -} - -/** - * Fills in the information in this bead based on the information given in the - * indicated datagram, whose opcode has already been read. Returns true on - * success, false if the datagram is invalid. - */ -bool FltVertexList:: -extract_record(FltRecordReader &reader) { - if (!FltRecord::extract_record(reader)) { - return false; - } - - nassertr(reader.get_opcode() == FO_vertex_list, false); - DatagramIterator &iterator = reader.get_iterator(); - - _vertices.clear(); - while (iterator.get_remaining_size() >= 4) { - int vertex_offset = iterator.get_be_int32(); - _vertices.push_back(_header->get_vertex_by_offset(vertex_offset)); - } - - check_remaining_size(iterator); - return true; -} - -/** - * Fills up the current record on the FltRecordWriter with data for this - * record, but does not advance the writer. Returns true on success, false if - * there is some error. - */ -bool FltVertexList:: -build_record(FltRecordWriter &writer) const { - if (!FltRecord::build_record(writer)) { - return false; - } - - writer.set_opcode(FO_vertex_list); - Datagram &datagram = writer.update_datagram(); - - Vertices::const_iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - datagram.add_be_uint32(_header->get_offset_by_vertex(*vi)); - } - - return true; -} diff --git a/pandatool/src/flt/fltVertexList.h b/pandatool/src/flt/fltVertexList.h deleted file mode 100644 index 5fd53ad8..00000000 --- a/pandatool/src/flt/fltVertexList.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltVertexList.h - * @author drose - * @date 2000-08-25 - */ - -#ifndef FLTVERTEXLIST_H -#define FLTVERTEXLIST_H - -#include "pandatoolbase.h" - -#include "fltRecord.h" -#include "fltPackedColor.h" -#include "fltVertex.h" - -#include "pointerTo.h" - -/** - * A list of vertices, typically added as a child of a face bead. - */ -class FltVertexList : public FltRecord { -public: - FltVertexList(FltHeader *header); - - int get_num_vertices() const; - FltVertex *get_vertex(int n) const; - void clear_vertices(); - void add_vertex(FltVertex *vertex); - - virtual void output(std::ostream &out) const; - -protected: - virtual bool extract_record(FltRecordReader &reader); - virtual bool build_record(FltRecordWriter &writer) const; - -private: - typedef pvector Vertices; - Vertices _vertices; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - FltRecord::init_type(); - register_type(_type_handle, "FltVertexList", - FltRecord::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/flt/p3flt_composite1.cxx b/pandatool/src/flt/p3flt_composite1.cxx deleted file mode 100644 index 8c9f9fd2..00000000 --- a/pandatool/src/flt/p3flt_composite1.cxx +++ /dev/null @@ -1,41 +0,0 @@ - -#include "config_flt.cxx" -#include "fltBead.cxx" -#include "fltBeadID.cxx" -#include "fltCurve.cxx" -#include "fltError.cxx" -#include "fltExternalReference.cxx" -#include "fltEyepoint.cxx" -#include "fltFace.cxx" -#include "fltGeometry.cxx" -#include "fltGroup.cxx" -#include "fltHeader.cxx" -#include "fltInstanceDefinition.cxx" -#include "fltInstanceRef.cxx" -#include "fltLOD.cxx" -#include "fltLightSourceDefinition.cxx" -#include "fltLocalVertexPool.cxx" -#include "fltMaterial.cxx" -#include "fltMesh.cxx" -#include "fltMeshPrimitive.cxx" -#include "fltObject.cxx" -#include "fltOpcode.cxx" -#include "fltPackedColor.cxx" -#include "fltRecord.cxx" -#include "fltRecordReader.cxx" -#include "fltRecordWriter.cxx" -#include "fltTexture.cxx" -#include "fltTrackplane.cxx" -#include "fltTransformGeneralMatrix.cxx" -#include "fltTransformPut.cxx" -#include "fltTransformRecord.cxx" -#include "fltTransformRotateAboutEdge.cxx" -#include "fltTransformRotateAboutPoint.cxx" -#include "fltTransformRotateScale.cxx" -#include "fltTransformScale.cxx" -#include "fltTransformTranslate.cxx" -#include "fltUnsupportedRecord.cxx" -#include "fltVectorRecord.cxx" -#include "fltVertex.cxx" -#include "fltVertexList.cxx" - diff --git a/pandatool/src/fltegg/CMakeLists.txt b/pandatool/src/fltegg/CMakeLists.txt deleted file mode 100644 index 5a61e47a..00000000 --- a/pandatool/src/fltegg/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3FLTEGG_HEADERS - fltToEggConverter.h fltToEggConverter.I - fltToEggLevelState.h fltToEggLevelState.I -) - -set(P3FLTEGG_SOURCES - fltToEggConverter.cxx - fltToEggLevelState.cxx -) - -add_library(p3fltegg STATIC ${P3FLTEGG_HEADERS} ${P3FLTEGG_SOURCES}) -target_link_libraries(p3fltegg p3flt p3eggbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/fltegg/fltToEggConverter.I b/pandatool/src/fltegg/fltToEggConverter.I deleted file mode 100644 index 1168eb64..00000000 --- a/pandatool/src/fltegg/fltToEggConverter.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEggConverter.I - * @author drose - * @date 2001-04-17 - */ diff --git a/pandatool/src/fltegg/fltToEggConverter.cxx b/pandatool/src/fltegg/fltToEggConverter.cxx deleted file mode 100644 index 98b01938..00000000 --- a/pandatool/src/fltegg/fltToEggConverter.cxx +++ /dev/null @@ -1,839 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEggConverter.cxx - * @author drose - * @date 2001-04-17 - */ - -#include "fltToEggConverter.h" - -#include "fltRecord.h" -#include "fltLOD.h" -#include "fltGroup.h" -#include "fltObject.h" -#include "fltBeadID.h" -#include "fltBead.h" -#include "fltFace.h" -#include "fltVertex.h" -#include "fltVertexList.h" -#include "fltExternalReference.h" -#include "dcast.h" -#include "eggData.h" -#include "eggGroup.h" -#include "eggSwitchCondition.h" -#include "eggPrimitive.h" -#include "eggPolygon.h" -#include "eggPoint.h" -#include "eggVertex.h" -#include "eggVertexPool.h" -#include "eggExternalReference.h" -#include "string_utils.h" - -using std::string; - - -/** - * - */ -FltToEggConverter:: -FltToEggConverter() { - _compose_transforms = false; - _flt_units = DU_invalid; -} - -/** - * - */ -FltToEggConverter:: -FltToEggConverter(const FltToEggConverter ©) : - SomethingToEggConverter(copy), - _compose_transforms(copy._compose_transforms) -{ -} - -/** - * - */ -FltToEggConverter:: -~FltToEggConverter() { - cleanup(); -} - -/** - * Allocates and returns a new copy of the converter. - */ -SomethingToEggConverter *FltToEggConverter:: -make_copy() { - return new FltToEggConverter(*this); -} - - -/** - * Returns the English name of the file type this converter supports. - */ -string FltToEggConverter:: -get_name() const { - return "MultiGen"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -string FltToEggConverter:: -get_extension() const { - return "flt"; -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. - */ -bool FltToEggConverter:: -supports_compressed() const { - return true; -} - -/** - * Handles the reading of the input file and converting it to egg. Returns - * true if successful, false otherwise. - * - * This is designed to be as generic as possible, generally in support of run- - * time loading. Command-line converters may choose to use convert_flt() - * instead, as it provides more control. - */ -bool FltToEggConverter:: -convert_file(const Filename &filename) { - PT(FltHeader) header = new FltHeader(_path_replace); - - nout << "Reading " << filename << "\n"; - FltError result = header->read_flt(filename); - if (result != FE_ok) { - nout << "Unable to read: " << result << "\n"; - return false; - } - - header->check_version(); - - _flt_units = header->get_units(); - - return convert_flt(header); -} - -/** - * This may be called after convert_file() has been called and returned true, - * indicating a successful conversion. It will return the distance units - * represented by the converted egg file, if known, or DU_invalid if not - * known. - */ -DistanceUnit FltToEggConverter:: -get_input_units() { - return _flt_units; -} - -/** - * Fills up the egg_data structure according to the indicated lwo structure. - */ -bool FltToEggConverter:: -convert_flt(const FltHeader *flt_header) { - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_zup_right); - } - - clear_error(); - _flt_header = flt_header; - - // Generate a default vertex pool. - _main_egg_vpool = new EggVertexPool("vpool"); - _egg_data->add_child(_main_egg_vpool.p()); - - // We could populate the vertex pool right away, but it's better to defer - // each vertex until we encounter it, since some of the vertices may need to - // be adjusted to match the particular polygon they're assigned to (for - // instance, to apply a transparency or something). - - FltToEggLevelState state(this); - state._egg_parent = _egg_data; - convert_record(_flt_header, state); - - if (_main_egg_vpool->empty()) { - // If we didn't get any global vertices, remove the vertex pool just for - // cleanliness. - _egg_data->remove_child(_main_egg_vpool.p()); - } - - cleanup(); - - return !had_error(); -} - -/** - * Frees all the internal data structures after we're done converting, and - * resets the converter to its initial state. - */ -void FltToEggConverter:: -cleanup() { - _flt_header.clear(); - _main_egg_vpool.clear(); - _textures.clear(); -} - -/** - * Converts the record and all of its children. - */ -void FltToEggConverter:: -convert_record(const FltRecord *flt_record, FltToEggLevelState &state) { - int num_children = flt_record->get_num_children(); - - for (int i = 0; i < num_children; i++) { - const FltRecord *child = flt_record->get_child(i); - dispatch_record(child, state); - } -} - -/** - * Determines what kind of record this is and calls the appropriate convert - * function. - */ -void FltToEggConverter:: -dispatch_record(const FltRecord *flt_record, FltToEggLevelState &state) { - if (flt_record->is_of_type(FltLOD::get_class_type())) { - convert_lod(DCAST(FltLOD, flt_record), state); - - } else if (flt_record->is_of_type(FltGroup::get_class_type())) { - convert_group(DCAST(FltGroup, flt_record), state); - - } else if (flt_record->is_of_type(FltObject::get_class_type())) { - convert_object(DCAST(FltObject, flt_record), state); - - } else if (flt_record->is_of_type(FltFace::get_class_type())) { - convert_face(DCAST(FltFace, flt_record), state); - - } else if (flt_record->is_of_type(FltExternalReference::get_class_type())) { - convert_ext_ref(DCAST(FltExternalReference, flt_record), state); - - // Fallbacks. - } else if (flt_record->is_of_type(FltBeadID::get_class_type())) { - convert_bead_id(DCAST(FltBeadID, flt_record), state); - - } else if (flt_record->is_of_type(FltBead::get_class_type())) { - convert_bead(DCAST(FltBead, flt_record), state); - - } else { - convert_record(flt_record, state); - } -} - -/** - * Converts the LOD bead and all of its children. - */ -void FltToEggConverter:: -convert_lod(const FltLOD *flt_lod, FltToEggLevelState &state) { - EggGroup *egg_group = new EggGroup(flt_lod->get_id()); - state._egg_parent->add_child(egg_group); - - EggSwitchConditionDistance lod - (flt_lod->_switch_in, flt_lod->_switch_out, - LPoint3d(flt_lod->_center_x, flt_lod->_center_y, flt_lod->_center_z), - flt_lod->_transition_range); - egg_group->set_lod(lod); - - state.set_transform(flt_lod, egg_group); - parse_comment(flt_lod, egg_group); - - FltToEggLevelState next_state(state); - next_state._egg_parent = egg_group; - convert_record(flt_lod, next_state); -} - -/** - * Converts the group and all of its children. - */ -void FltToEggConverter:: -convert_group(const FltGroup *flt_group, FltToEggLevelState &state) { - EggGroup *egg_group = new EggGroup(flt_group->get_id()); - state._egg_parent->add_child(egg_group); - - if ((flt_group->_flags & FltGroup::F_forward_animation) != 0) { - // It's a sequence animation. - egg_group->set_switch_flag(true); - egg_group->set_switch_fps(24.0); - } - - state.set_transform(flt_group, egg_group); - parse_comment(flt_group, egg_group); - - // *** replicate count. - - FltToEggLevelState next_state(state); - next_state._egg_parent = egg_group; - convert_record(flt_group, next_state); -} - -/** - * Converts the object and all of its children. - */ -void FltToEggConverter:: -convert_object(const FltObject *flt_object, FltToEggLevelState &state) { - EggGroup *egg_group = new EggGroup(flt_object->get_id()); - state._egg_parent->add_child(egg_group); - - state.set_transform(flt_object, egg_group); - parse_comment(flt_object, egg_group); - - FltToEggLevelState next_state(state); - next_state._flt_object = flt_object; - next_state._egg_parent = egg_group; - convert_record(flt_object, next_state); -} - -/** - * Converts the generic bead (with ID) and all of its children. - */ -void FltToEggConverter:: -convert_bead_id(const FltBeadID *flt_bead, FltToEggLevelState &state) { - nout << "Don't know how to convert beads of type " << flt_bead->get_type() - << "\n"; - EggGroup *egg_group = new EggGroup(flt_bead->get_id()); - state._egg_parent->add_child(egg_group); - - state.set_transform(flt_bead, egg_group); - parse_comment(flt_bead, egg_group); - - FltToEggLevelState next_state(state); - next_state._egg_parent = egg_group; - convert_record(flt_bead, next_state); -} - -/** - * Converts the generic bead (without ID) and all of its children. - */ -void FltToEggConverter:: -convert_bead(const FltBead *flt_bead, FltToEggLevelState &state) { - nout << "Don't know how to convert beads of type " << flt_bead->get_type() - << "\n"; - EggGroup *egg_group = new EggGroup; - state._egg_parent->add_child(egg_group); - - state.set_transform(flt_bead, egg_group); - parse_comment(flt_bead, egg_group); - - FltToEggLevelState next_state(state); - next_state._egg_parent = egg_group; - convert_record(flt_bead, next_state); -} - -/** - * Converts the face and all of its children. - */ -void FltToEggConverter:: -convert_face(const FltFace *flt_face, FltToEggLevelState &state) { - bool is_light; - switch (flt_face->_draw_type) { - case FltGeometry::DT_omni_light: - case FltGeometry::DT_uni_light: - case FltGeometry::DT_bi_light: - is_light = true; - break; - - default: - is_light = false; - } - - PT(EggPrimitive) egg_prim; - if (is_light) { - egg_prim = new EggPoint; - } else { - egg_prim = new EggPolygon; - } - - // Collect the vertices for this primitive. - pvector< PT_EggVertex > vertices; - - const FltVertexList *vlist = nullptr; - int num_children = flt_face->get_num_children(); - for (int i = 0; i < num_children && vlist == nullptr; i++) { - const FltRecord *child = flt_face->get_child(i); - if (child->is_of_type(FltVertexList::get_class_type())) { - vlist = DCAST(FltVertexList, child); - } - } - - if (vlist != nullptr) { - int num_vertices = vlist->get_num_vertices(); - for (int i = 0; i < num_vertices; i++) { - FltVertex *flt_vertex = vlist->get_vertex(i); - vertices.push_back(make_egg_vertex(flt_vertex)); - } - } - - setup_geometry(flt_face, state, egg_prim, _main_egg_vpool, vertices); -} - -/** - * Converts the external reference node. - */ -void FltToEggConverter:: -convert_ext_ref(const FltExternalReference *flt_ext, FltToEggLevelState &state) { - // Get a group node to put the reference into. - EggGroupNode *egg_parent = - state.get_synthetic_group("", flt_ext); - - handle_external_reference(egg_parent, flt_ext->get_ref_filename()); -} - -/** - * Applies the state indicated in the FltGeometry record to the indicated - * EggPrimitive and all of its indicated vertices, and then officially adds - * the vertices to the vertex pool and to the primitive, and adds the - * primitive to its appropriate parent. - */ -void FltToEggConverter:: -setup_geometry(const FltGeometry *flt_geom, FltToEggLevelState &state, - EggPrimitive *egg_prim, EggVertexPool *egg_vpool, - const FltToEggConverter::EggVertices &vertices) { - - // Determine what the appropriate parent will be. - EggGroupNode *egg_parent = - state.get_synthetic_group(flt_geom->get_id(), flt_geom, - flt_geom->_billboard_type); - - // Create a new state to reflect the new parent. - FltToEggLevelState next_state(state); - next_state._egg_parent = egg_parent; - - // Check for decals onto the primitive. - convert_subfaces(flt_geom, next_state); - - // Add the primitive to its new home. - next_state._egg_parent->add_child(egg_prim); - - // Now examine the vertices. - EggVertices::const_iterator vi; - - bool use_vertex_color = true; - bool keep_normals = true; - switch (flt_geom->_light_mode) { - case FltGeometry::LM_face_no_normal: - use_vertex_color = false; - keep_normals = false; - break; - - case FltGeometry::LM_vertex_no_normal: - use_vertex_color = true; - keep_normals = false; - break; - - case FltGeometry::LM_face_with_normal: - use_vertex_color = false; - keep_normals = true; - break; - - case FltGeometry::LM_vertex_with_normal: - use_vertex_color = true; - keep_normals = true; - break; - } - - LColor face_color = flt_geom->get_color(); - - if (state._flt_object != nullptr) { - // If we have a FltObject above us, it might also specify a transparency. - // This combines with our existing transparency. - PN_stdfloat alpha = 1.0 - (state._flt_object->_transparency / 65535.0); - face_color[3] *= alpha; - } - - egg_prim->set_color(face_color); - - if (flt_geom->has_texture()) { - // If the geometry has a texture, apply it. - egg_prim->set_texture(make_egg_texture(flt_geom->get_texture())); - - if (flt_geom->_texwhite) { - // If the geometry should be colored white under the texture, then - // eliminate vertex colors. - use_vertex_color = false; - } - } - - if (use_vertex_color) { - // If we're to use vertex color instead of the face color, remove the face - // color to eliminate any ambiguity. - egg_prim->clear_color(); - - // Also, make sure the transparency is set correctly across all vertices. - for (vi = vertices.begin(); vi != vertices.end(); ++vi) { - EggVertex *vertex = (*vi); - if (vertex->has_color()) { - LColor vertex_color = vertex->get_color(); - vertex_color[3] = face_color[3]; - vertex->set_color(vertex_color); - } else { - if (flt_geom->has_color()) { - // If a vertex doesn't have a color but the face does, set the - // vertex to use the face color. - vertex->set_color(face_color); - } - } - } - - } else { - // If we're to use face color instead of vertex color, remove the vertex - // color to eliminate any ambiguity. - for (vi = vertices.begin(); vi != vertices.end(); ++vi) { - (*vi)->clear_color(); - } - } - - if (!keep_normals) { - // If we're not to use the normals, then eliminate them. - for (vi = vertices.begin(); vi != vertices.end(); ++vi) { - (*vi)->clear_normal(); - } - } - - if (flt_geom->_draw_type == FltGeometry::DT_solid_no_cull) { - // A double-sided polygon. - egg_prim->set_bface_flag(true); - } - - for (vi = vertices.begin(); vi != vertices.end(); ++vi) { - EggVertex *egg_vertex = egg_vpool->create_unique_vertex(*(*vi)); - egg_prim->add_vertex(egg_vertex); - } - - parse_comment(flt_geom, egg_prim); -} - -/** - * Records all of the subfaces of the indicated group as coplanar polygons - * (i.e. decals) of the group. - * - * If coplanar polygons exist, the state is modified so that _egg_parent is - * the new group to which the base polygons should be added. Therefore, - * subfaces should be defined before the ordinary children are processed. - */ -void FltToEggConverter:: -convert_subfaces(const FltRecord *flt_record, FltToEggLevelState &state) { - int num_subfaces = flt_record->get_num_subfaces(); - if (num_subfaces == 0) { - // No subfaces. - return; - } - - // Create a new group to contain the base polygons. - EggGroup *egg_group = new EggGroup("decal_base"); - state._egg_parent->add_child(egg_group); - state._egg_parent = egg_group; - - egg_group->set_decal_flag(true); - - // Now create a nested group to hold the decals. - EggGroup *decal_group = new EggGroup("decals"); - egg_group->add_child(decal_group); - egg_group = decal_group; - - FltToEggLevelState next_state(state); - next_state._egg_parent = decal_group; - - for (int i = 0; i < num_subfaces; i++) { - const FltRecord *subface = flt_record->get_subface(i); - dispatch_record(subface, next_state); - } -} - -/** - * Scans the comment on this record for " { ... }" and parses the - * enclosed string as if it appeared in the egg file. Returns true on - * success, false on syntax error (in which case _error is also set to true). - */ -bool FltToEggConverter:: -parse_comment(const FltBeadID *flt_bead, EggNode *egg_node) { - return parse_comment(flt_bead->get_comment(), flt_bead->get_id(), egg_node); -} - -/** - * Scans the comment on this record for " { ... }" and parses the - * enclosed string as if it appeared in the egg file. Returns true on - * success, false on syntax error (in which case _error is also set to true). - */ -bool FltToEggConverter:: -parse_comment(const FltBead *flt_bead, EggNode *egg_node) { - return parse_comment(flt_bead->get_comment(), "anonymous", egg_node); -} - -/** - * Scans the comment on this record for " { ... }" and parses the - * enclosed string as if it appeared in the egg file. Returns true on - * success, false on syntax error (in which case _error is also set to true). - */ -bool FltToEggConverter:: -parse_comment(const FltTexture *flt_texture, EggNode *egg_node) { - return parse_comment(flt_texture->get_comment(), - flt_texture->get_texture_filename(), egg_node); -} - -/** - * Scans the comment on this record for " { ... }" and parses the - * enclosed string as if it appeared in the egg file. Returns true on - * success, false on syntax error (in which case _error is also set to true). - */ -bool FltToEggConverter:: -parse_comment(const string &comment, const string &name, - EggNode *egg_node) { - if (comment.empty()) { - // No comment. - return true; - } - - // Scan for . - static const string egg_str = ""; - - size_t p; - p = 0; - while (p < comment.length() && - cmp_nocase(comment.substr(p, 5), egg_str) != 0) { - p++; - } - - if (p >= comment.length()) { - // No "" in the comment. - return true; - } - - p += 5; - // Now scan past whitespace for the open curly brace. - while (p < comment.length() && isspace(comment[p])) { - ++p; - } - if (p >= comment.length() || comment[p] != '{') { - nout << "No opening brace in comment for " - << name << "\n\n"; - _error = true; - return false; - } - - // Here's the beginning of the string after " {". Now lop off the - // closing brace at the end. - ++p; - size_t q = comment.length() - 1; - while (q > p && comment[q] != '}') { - --q; - } - if (q == p) { - nout << "No closing brace in comment for " - << name << "\n\n"; - _error = true; - return false; - } - - string egg_syntax = comment.substr(p, q - p); - - if (!egg_node->parse_egg(egg_syntax)) { - nout << "Syntax error in comment for " - << name << "\n\n"; - _error = true; - return false; - } - - // Correctly parsed! - return true; -} - -/** - * Makes a new EggVertex for the indicated FltVertex. The vertex is not - * automatically added to the vertex pool. - */ -PT_EggVertex FltToEggConverter:: -make_egg_vertex(const FltVertex *flt_vertex) { - PT_EggVertex egg_vertex = new EggVertex; - egg_vertex->set_pos(flt_vertex->_pos); - - if (flt_vertex->_has_normal) { - egg_vertex->set_normal(LCAST(double, flt_vertex->_normal)); - } - - if (flt_vertex->_has_uv) { - egg_vertex->set_uv(LCAST(double, flt_vertex->_uv)); - } - - if (flt_vertex->has_color()) { - egg_vertex->set_color(flt_vertex->get_color()); - } - - return egg_vertex; -} - -/** - * Makes a new EggTexture for the indicated FltTexture, or returns a pointer - * to one previously made for the same FltTexture. - */ -PT_EggTexture FltToEggConverter:: -make_egg_texture(const FltTexture *flt_texture) { - Textures::const_iterator ti; - ti = _textures.find(flt_texture); - if (ti != _textures.end()) { - // There's one previously created. - return (*ti).second; - } - - // Create a new one. - string tref_name = format_string(flt_texture->_pattern_index); - Filename filename = flt_texture->get_texture_filename(); - - PT_EggTexture egg_texture = new EggTexture(tref_name, filename); - - _textures.insert(Textures::value_type(flt_texture, egg_texture)); - - // Set up the texture properties. - - switch (flt_texture->_min_filter) { - case FltTexture::MN_point: - egg_texture->set_minfilter(EggTexture::FT_nearest); - break; - - case FltTexture::MN_bilinear: - egg_texture->set_minfilter(EggTexture::FT_linear); - break; - - case FltTexture::MN_mipmap_point: - egg_texture->set_minfilter(EggTexture::FT_nearest_mipmap_nearest); - break; - - case FltTexture::MN_mipmap_linear: - egg_texture->set_minfilter(EggTexture::FT_nearest_mipmap_linear); - break; - - case FltTexture::MN_mipmap_bilinear: - egg_texture->set_minfilter(EggTexture::FT_linear_mipmap_nearest); - break; - - case FltTexture::MN_mipmap_trilinear: - case FltTexture::MN_OB_mipmap: - egg_texture->set_minfilter(EggTexture::FT_linear_mipmap_linear); - break; - - case FltTexture::MN_bicubic: - case FltTexture::MN_bilinear_gequal: - case FltTexture::MN_bilinear_lequal: - case FltTexture::MN_bicubic_gequal: - case FltTexture::MN_bicubic_lequal: - // Not supported. - break; - } - - switch (flt_texture->_mag_filter) { - case FltTexture::MG_point: - egg_texture->set_magfilter(EggTexture::FT_nearest); - break; - - case FltTexture::MG_bilinear: - egg_texture->set_magfilter(EggTexture::FT_linear); - break; - - case FltTexture::MG_bicubic: - case FltTexture::MG_sharpen: - case FltTexture::MG_add_detail: - case FltTexture::MG_modulate_detail: - case FltTexture::MG_bilinear_gequal: - case FltTexture::MG_bilinear_lequal: - case FltTexture::MG_bicubic_gequal: - case FltTexture::MG_bicubic_lequal: - // Not supported. - break; - } - - switch (flt_texture->_repeat) { - case FltTexture::RT_repeat: - egg_texture->set_wrap_mode(EggTexture::WM_repeat); - break; - - case FltTexture::RT_clamp: - egg_texture->set_wrap_mode(EggTexture::WM_clamp); - break; - } - - switch (flt_texture->_repeat_u) { - case FltTexture::RT_repeat: - egg_texture->set_wrap_u(EggTexture::WM_repeat); - break; - - case FltTexture::RT_clamp: - egg_texture->set_wrap_u(EggTexture::WM_clamp); - break; - } - - switch (flt_texture->_repeat_v) { - case FltTexture::RT_repeat: - egg_texture->set_wrap_v(EggTexture::WM_repeat); - break; - - case FltTexture::RT_clamp: - egg_texture->set_wrap_v(EggTexture::WM_clamp); - break; - } - - switch (flt_texture->_env_type) { - case FltTexture::ET_modulate: - egg_texture->set_env_type(EggTexture::ET_modulate); - break; - - case FltTexture::ET_decal: - egg_texture->set_env_type(EggTexture::ET_decal); - break; - - case FltTexture::ET_blend: - case FltTexture::ET_color: - // Not supported. - break; - } - - switch (flt_texture->_internal_format) { - case FltTexture::IF_default: - break; - - case FltTexture::IF_i_12a_4: - case FltTexture::IF_ia_12: - case FltTexture::IF_ia_8: - egg_texture->set_format(EggTexture::F_luminance_alpha); - break; - - case FltTexture::IF_rgb_5: - egg_texture->set_format(EggTexture::F_rgb5); - break; - - case FltTexture::IF_rgba_4: - egg_texture->set_format(EggTexture::F_rgba4); - break; - - - case FltTexture::IF_rgba_8: - egg_texture->set_format(EggTexture::F_rgba8); - break; - - case FltTexture::IF_rgba_12: - egg_texture->set_format(EggTexture::F_rgba12); - break; - - case FltTexture::IF_i_16: - if (flt_texture->_intensity_is_alpha) { - egg_texture->set_format(EggTexture::F_alpha); - } else { - egg_texture->set_format(EggTexture::F_luminance); - } - break; - - case FltTexture::IF_rgb_12: - egg_texture->set_format(EggTexture::F_rgb12); - break; - } - - parse_comment(flt_texture, egg_texture); - return egg_texture; -} diff --git a/pandatool/src/fltegg/fltToEggConverter.h b/pandatool/src/fltegg/fltToEggConverter.h deleted file mode 100644 index c9e8cc61..00000000 --- a/pandatool/src/fltegg/fltToEggConverter.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEggConverter.h - * @author drose - * @date 2001-04-17 - */ - -#ifndef FLTTOEGGCONVERTER_H -#define FLTTOEGGCONVERTER_H - -#include "pandatoolbase.h" - -#include "fltToEggLevelState.h" -#include "somethingToEggConverter.h" -#include "fltHeader.h" -#include "eggVertex.h" -#include "eggVertexPool.h" -#include "eggTexture.h" -#include "pt_EggTexture.h" -#include "pt_EggVertex.h" -#include "pointerTo.h" -#include "distanceUnit.h" - -class FltRecord; -class FltLOD; -class FltGroup; -class FltObject; -class FltBeadID; -class FltBead; -class FltVertex; -class FltGeometry; -class FltFace; -class FltExternalReference; -class FltTexture; -class EggGroupNode; -class EggPrimitive; - -/** - * This class supervises the construction of an EggData structure from the - * data represented by the FltHeader. Reading and writing the egg and flt - * structures is left to the user. - */ -class FltToEggConverter : public SomethingToEggConverter { -public: - FltToEggConverter(); - FltToEggConverter(const FltToEggConverter ©); - ~FltToEggConverter(); - - virtual SomethingToEggConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual bool supports_compressed() const; - - virtual bool convert_file(const Filename &filename); - virtual DistanceUnit get_input_units(); - bool convert_flt(const FltHeader *flt_header); - - // Set this true to store transforms in egg files as the fully composed - // matrix, or false (the default) to keep them decomposed into elemental - // operations. - bool _compose_transforms; - -private: - void cleanup(); - - typedef pvector< PT_EggVertex > EggVertices; - - void convert_record(const FltRecord *flt_record, FltToEggLevelState &state); - void dispatch_record(const FltRecord *flt_record, FltToEggLevelState &state); - void convert_lod(const FltLOD *flt_lod, FltToEggLevelState &state); - void convert_group(const FltGroup *flt_group, FltToEggLevelState &state); - void convert_object(const FltObject *flt_object, FltToEggLevelState &state); - void convert_bead_id(const FltBeadID *flt_bead, FltToEggLevelState &state); - void convert_bead(const FltBead *flt_bead, FltToEggLevelState &state); - void convert_face(const FltFace *flt_face, FltToEggLevelState &state); - void convert_ext_ref(const FltExternalReference *flt_ext, FltToEggLevelState &state); - - void setup_geometry(const FltGeometry *flt_geom, FltToEggLevelState &state, - EggPrimitive *egg_prim, EggVertexPool *egg_vpool, - const EggVertices &vertices); - - void convert_subfaces(const FltRecord *flt_record, FltToEggLevelState &state); - - bool parse_comment(const FltBeadID *flt_bead, EggNode *egg_node); - bool parse_comment(const FltBead *flt_bead, EggNode *egg_node); - bool parse_comment(const FltTexture *flt_texture, EggNode *egg_node); - bool parse_comment(const std::string &comment, const std::string &name, - EggNode *egg_node); - - PT_EggVertex make_egg_vertex(const FltVertex *flt_vertex); - PT_EggTexture make_egg_texture(const FltTexture *flt_texture); - - CPT(FltHeader) _flt_header; - DistanceUnit _flt_units; - - PT(EggVertexPool) _main_egg_vpool; - - typedef pmap Textures; - Textures _textures; -}; - -#include "fltToEggConverter.I" - -#endif diff --git a/pandatool/src/fltegg/fltToEggLevelState.I b/pandatool/src/fltegg/fltToEggLevelState.I deleted file mode 100644 index e5460717..00000000 --- a/pandatool/src/fltegg/fltToEggLevelState.I +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEggLevelState.I - * @author drose - * @date 2001-04-18 - */ - -/** - * - */ -INLINE FltToEggLevelState:: -FltToEggLevelState(FltToEggConverter *converter) : - _converter(converter) -{ - _flt_object = nullptr; - _egg_parent = nullptr; -} - -/** - * - */ -INLINE FltToEggLevelState:: -FltToEggLevelState(const FltToEggLevelState ©) : - _flt_object(copy._flt_object), - _egg_parent(copy._egg_parent), - _converter(copy._converter) -{ - // We don't bother to copy the _parents map. -} - -/** - * - */ -INLINE void FltToEggLevelState:: -operator = (const FltToEggLevelState ©) { - _flt_object = copy._flt_object; - _egg_parent = copy._egg_parent; - _converter = copy._converter; - // We don't bother to copy the _parents map. -} diff --git a/pandatool/src/fltegg/fltToEggLevelState.cxx b/pandatool/src/fltegg/fltToEggLevelState.cxx deleted file mode 100644 index ef396fd8..00000000 --- a/pandatool/src/fltegg/fltToEggLevelState.cxx +++ /dev/null @@ -1,229 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEggLevelState.cxx - * @author drose - * @date 2001-04-18 - */ - -#include "fltToEggLevelState.h" -#include "fltToEggConverter.h" -#include "fltTransformTranslate.h" -#include "fltTransformRotateAboutPoint.h" -#include "fltTransformRotateAboutEdge.h" -#include "fltTransformScale.h" -#include "fltTransformPut.h" -#include "eggGroup.h" -#include "dcast.h" -#include "look_at.h" - - -/** - * - */ -FltToEggLevelState:: -~FltToEggLevelState() { - Parents::iterator pi; - for (pi = _parents.begin(); pi != _parents.end(); ++pi) { - delete (*pi).second; - } -} - -/** - * - */ -FltToEggLevelState::ParentNodes:: -ParentNodes() { - _axial_billboard = nullptr; - _point_billboard = nullptr; - _plain = nullptr; -} - -/** - * Sometimes it is necessary to synthesize a group within a particular - * EggGroup, for instance to insert a transform or billboard flag. This - * function will synthesize a group as needed, or return an existing group (if - * the group need not be synthesized, or if a matching group was previously - * synthesized). - * - * This collects together polygons that share the same billboard axis and/or - * transform space into the same group, rather than wastefully creating a - * group per polygon. - */ -EggGroupNode *FltToEggLevelState:: -get_synthetic_group(const std::string &name, - const FltBead *transform_bead, - FltGeometry::BillboardType type) { - LMatrix4d transform = transform_bead->get_transform(); - bool is_identity = transform.almost_equal(LMatrix4d::ident_mat()); - if (is_identity && - (type != FltGeometry::BT_axial && - type != FltGeometry::BT_point)) { - // Trivial case: the primitive belongs directly in its parent group node. - return _egg_parent; - } - - // For other cases, we may have to create a subgroup to put the primitive - // into. - Parents::iterator pi; - pi = _parents.find(transform); - ParentNodes *nodes; - if (pi != _parents.end()) { - nodes = (*pi).second; - } else { - nodes = new ParentNodes; - _parents.insert(Parents::value_type(transform, nodes)); - } - - switch (type) { - case FltGeometry::BT_axial: - if (nodes->_axial_billboard == nullptr) { - nodes->_axial_billboard = new EggGroup(name); - _egg_parent->add_child(nodes->_axial_billboard); - nodes->_axial_billboard->set_billboard_type(EggGroup::BT_axis); - if (!is_identity) { - set_transform(transform_bead, nodes->_axial_billboard); - nodes->_axial_billboard->set_group_type(EggGroup::GT_instance); - } - } - return nodes->_axial_billboard; - - case FltGeometry::BT_point: - if (nodes->_point_billboard == nullptr) { - nodes->_point_billboard = new EggGroup(name); - _egg_parent->add_child(nodes->_point_billboard); - nodes->_point_billboard->set_billboard_type(EggGroup::BT_point_world_relative); - if (!is_identity) { - set_transform(transform_bead, nodes->_point_billboard); - nodes->_point_billboard->set_group_type(EggGroup::GT_instance); - } - } - return nodes->_point_billboard; - - default: // Normally, BT_none, although we've occasionally seen a - // value of 3 come in here, whatever that's supposed to mean. - if (nodes->_plain == nullptr) { - nodes->_plain = new EggGroup(name); - _egg_parent->add_child(nodes->_plain); - if (!is_identity) { - set_transform(transform_bead, nodes->_plain); - nodes->_plain->set_group_type(EggGroup::GT_instance); - } - } - return nodes->_plain; - } -} - -/** - * Sets up the group to reflect the transform indicated by the given record, - * if any. - */ -void FltToEggLevelState:: -set_transform(const FltBead *flt_bead, EggGroup *egg_group) { - if (flt_bead->has_transform()) { - egg_group->set_group_type(EggGroup::GT_instance); - - int num_steps = flt_bead->get_num_transform_steps(); - bool componentwise_ok = !_converter->_compose_transforms; - - if (num_steps == 0) { - componentwise_ok = false; - } else { - // Walk through each transform step and store the individual components - // in the egg file. If we come across a step we don't know how to - // interpret, just store the whole transform matrix in the egg file. - egg_group->clear_transform(); - for (int i = num_steps -1; i >= 0 && componentwise_ok; i--) { - const FltTransformRecord *step = flt_bead->get_transform_step(i); - if (step->is_exact_type(FltTransformTranslate::get_class_type())) { - const FltTransformTranslate *trans; - DCAST_INTO_V(trans, step); - if (!trans->get_delta().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(trans->get_delta()); - } - - } else if (step->is_exact_type(FltTransformRotateAboutPoint::get_class_type())) { - const FltTransformRotateAboutPoint *rap; - DCAST_INTO_V(rap, step); - if (!IS_NEARLY_ZERO(rap->get_angle())) { - if (!rap->get_center().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(-rap->get_center()); - } - LVector3d axis = LCAST(double, rap->get_axis()); - egg_group->add_rotate3d(rap->get_angle(), axis); - if (!rap->get_center().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(rap->get_center()); - } - } - - } else if (step->is_exact_type(FltTransformRotateAboutEdge::get_class_type())) { - const FltTransformRotateAboutEdge *rae; - DCAST_INTO_V(rae, step); - if (!IS_NEARLY_ZERO(rae->get_angle())) { - if (!rae->get_point_a().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(-rae->get_point_a()); - } - LVector3d axis = rae->get_point_b() - rae->get_point_a(); - egg_group->add_rotate3d(rae->get_angle(), axis); - if (!rae->get_point_a().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(rae->get_point_a()); - } - } - - } else if (step->is_exact_type(FltTransformScale::get_class_type())) { - const FltTransformScale *scale; - DCAST_INTO_V(scale, step); - if (!scale->get_scale().almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) { - if (scale->has_center() && - !scale->get_center().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(-scale->get_center()); - } - egg_group->add_scale3d(LCAST(double, scale->get_scale())); - if (scale->has_center() && - !scale->get_center().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(scale->get_center()); - } - } - - } else if (step->is_exact_type(FltTransformPut::get_class_type())) { - const FltTransformPut *put; - DCAST_INTO_V(put, step); - - if (!put->get_from_origin().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(-put->get_from_origin()); - } - LQuaterniond q1, q2; - look_at(q1, put->get_from_align() - put->get_from_origin(), - put->get_from_track() - put->get_from_origin(), - CS_zup_right); - look_at(q2, put->get_to_align() - put->get_to_origin(), - put->get_to_track() - put->get_to_origin(), - CS_zup_right); - - LQuaterniond q = invert(q1) * q2; - - if (!q.is_identity()) { - egg_group->add_rotate3d(q); - } - if (!put->get_to_origin().almost_equal(LVector3d::zero())) { - egg_group->add_translate3d(put->get_to_origin()); - } - - } else { - // Here's a transform component we haven't implemented here. Give - // up on storing the componentwise transform. - componentwise_ok = false; - } - } - } - - if (!componentwise_ok) { - egg_group->set_transform3d(flt_bead->get_transform()); - } - } -} diff --git a/pandatool/src/fltegg/fltToEggLevelState.h b/pandatool/src/fltegg/fltToEggLevelState.h deleted file mode 100644 index 91877e23..00000000 --- a/pandatool/src/fltegg/fltToEggLevelState.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEggLevelState.h - * @author drose - * @date 2001-04-18 - */ - -#ifndef FLTTOEGGLEVELSTATE_H -#define FLTTOEGGLEVELSTATE_H - -#include "pandatoolbase.h" -#include "fltGeometry.h" - -class FltObject; -class FltBead; -class EggGroupNode; -class EggGroup; -class FltToEggConverter; - -/** - * This keeps track of relevant things about the traversal as we walk through - * the flt hierarchy. - */ -class FltToEggLevelState { -public: - INLINE FltToEggLevelState(FltToEggConverter *converter); - INLINE FltToEggLevelState(const FltToEggLevelState ©); - INLINE void operator = (const FltToEggLevelState ©); - ~FltToEggLevelState(); - - EggGroupNode *get_synthetic_group(const std::string &name, - const FltBead *transform_bead, - FltGeometry::BillboardType type = FltGeometry::BT_none); - - void set_transform(const FltBead *flt_bead, EggGroup *egg_group); - - const FltObject *_flt_object; - EggGroupNode *_egg_parent; - -private: - class ParentNodes { - public: - ParentNodes(); - - EggGroup *_axial_billboard; - EggGroup *_point_billboard; - EggGroup *_plain; - }; - - typedef pmap Parents; - Parents _parents; - - FltToEggConverter *_converter; -}; - -#include "fltToEggLevelState.I" - -#endif diff --git a/pandatool/src/fltprogs/CMakeLists.txt b/pandatool/src/fltprogs/CMakeLists.txt deleted file mode 100644 index 0ceebcf6..00000000 --- a/pandatool/src/fltprogs/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(flt-info fltInfo.cxx fltInfo.h) -target_link_libraries(flt-info p3progbase p3flt) -install(TARGETS flt-info EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(flt-trans fltTrans.cxx fltTrans.h) -target_link_libraries(flt-trans p3progbase p3flt) -install(TARGETS flt-trans EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -if(HAVE_EGG) - - add_executable(egg2flt eggToFlt.cxx eggToFlt.h) - target_link_libraries(egg2flt p3fltegg p3eggbase p3progbase) - install(TARGETS egg2flt EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - - add_executable(flt2egg fltToEgg.cxx fltToEgg.h) - target_link_libraries(flt2egg p3fltegg p3eggbase p3progbase) - install(TARGETS flt2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -endif() diff --git a/pandatool/src/fltprogs/eggToFlt.cxx b/pandatool/src/fltprogs/eggToFlt.cxx deleted file mode 100644 index f6cbc9d2..00000000 --- a/pandatool/src/fltprogs/eggToFlt.cxx +++ /dev/null @@ -1,672 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToFlt.cxx - * @author drose - * @date 2003-10-01 - */ - -#include "eggToFlt.h" -#include "fltHeader.h" -#include "fltBead.h" -#include "fltGroup.h" -#include "fltFace.h" -#include "fltVertexList.h" -#include "fltVertex.h" -#include "fltTexture.h" -#include "fltTransformTranslate.h" -#include "fltTransformRotateAboutEdge.h" -#include "fltTransformScale.h" -#include "fltTransformGeneralMatrix.h" -#include "eggPolygon.h" -#include "eggPoint.h" -#include "eggPrimitive.h" -#include "eggExternalReference.h" -#include "eggGroup.h" -#include "eggGroupNode.h" -#include "eggTexture.h" -#include "eggTransform.h" -#include "dcast.h" -#include "string_utils.h" -#include "vector_string.h" - -/** - * - */ -EggToFlt:: -EggToFlt() : - EggToSomething("MultiGen", ".flt", true, false) -{ - set_binary_output(true); - set_program_brief("convert files from .egg format to MultiGen .flt"); - set_program_description - ("egg2lt converts files from egg format to MultiGen .flt " - "format. It attempts to be as robust as possible, and matches " - "the capabilities of flt2egg. Generally, converting a model " - "from egg2lt and then back via flt2egg will result in essentially " - "the same egg file, within the limitations of what can be " - "represented in flt."); - - add_option - ("attr", "none/new/all", 0, - "Specifies whether to write (or rewrite) .attr files for each " - "texture image. MultiGen stores texture properties like mipmapping " - "in a separate .attr file for each different texture image. " - "If this parameter is \"none\", these files will not be generated; " - "if this is \"new\", these files will only be generated if they " - "do not already exist (even if the properties have changed). " - "Specifying \"all\" causes these to be rewritten every time.", - &EggToFlt::dispatch_attr, nullptr, &_auto_attr_update); - - // Flt files are always in the z-up coordinate system. Don't confuse the - // user with this meaningless option. - remove_option("cs"); - _coordinate_system = CS_zup_right; - _got_coordinate_system = true; - _auto_attr_update = FltHeader::AU_if_missing; -} - -/** - * - */ -void EggToFlt:: -run() { - _flt_header = new FltHeader(_path_replace); - _flt_header->set_auto_attr_update(_auto_attr_update); - - traverse(_data, _flt_header, FltGeometry::BT_none); - - // Finally, write the resulting file out. - FltError result = _flt_header->write_flt(get_output()); - if (result != FE_ok) { - nout << "Cannot write " << get_output_filename() << "\n"; - exit(1); - } -} - -/** - * Dispatch function for the -attr parameter. - */ -bool EggToFlt:: -dispatch_attr(const std::string &opt, const std::string &arg, void *var) { - FltHeader::AttrUpdate *ip = (FltHeader::AttrUpdate *)var; - - if (cmp_nocase(arg, "none") == 0) { - *ip = FltHeader::AU_none; - - } else if (cmp_nocase(arg, "new") == 0) { - *ip = FltHeader::AU_if_missing; - - } else if (cmp_nocase(arg, "all") == 0) { - *ip = FltHeader::AU_always; - - } else { - nout << "-" << opt - << " requires either \"none\", \"new\", or \"all\".\n"; - return false; - } - - return true; -} - -/** - * - */ -void EggToFlt:: -traverse(EggNode *egg_node, FltBead *flt_node, - FltGeometry::BillboardType billboard) { - if (egg_node->is_of_type(EggPolygon::get_class_type()) || - egg_node->is_of_type(EggPoint::get_class_type())) { - // It's a polygon or point light. - EggPrimitive *egg_primitive = DCAST(EggPrimitive, egg_node); - convert_primitive(egg_primitive, flt_node, billboard); - - } else if (egg_node->is_of_type(EggExternalReference::get_class_type())) { - // Convert external references. - - } else if (egg_node->is_of_type(EggGroup::get_class_type())) { - // An EggGroup creates a fltBead, and recurses. - EggGroup *egg_group = DCAST(EggGroup, egg_node); - - if (egg_group->get_group_type() == EggGroup::GT_joint) { - // Ignore joints and their children. - return; - } - - convert_group(egg_group, flt_node, billboard); - - } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - // Some kind of grouping node other than an EggGroup. Just recurse. - EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); - EggGroupNode::iterator ci; - for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { - traverse(*ci, flt_node, billboard); - } - } -} - -/** - * Converts an egg polygon or series of light points to the corresponding Flt - * geometry, and adds it to the indicated flt_node. - */ -void EggToFlt:: -convert_primitive(EggPrimitive *egg_primitive, FltBead *flt_node, - FltGeometry::BillboardType billboard) { - FltFace *flt_face = new FltFace(_flt_header); - flt_node->add_child(flt_face); - - flt_face->_billboard_type = billboard; - - if (egg_primitive->has_color()) { - flt_face->set_color(egg_primitive->get_color()); - } - - if (egg_primitive->is_of_type(EggPoint::get_class_type())) { - // A series of points, instead of a polygon. - flt_face->_draw_type = FltFace::DT_omni_light; - - } else if (egg_primitive->get_bface_flag()) { - // A polygon whose backface is visible. - flt_face->_draw_type = FltFace::DT_solid_no_cull; - - } else { - // A normal polygon. - flt_face->_draw_type = FltFace::DT_solid_cull_backface; - } - - if (egg_primitive->has_texture()) { - EggTexture *egg_texture = egg_primitive->get_texture(); - FltTexture *flt_texture = get_flt_texture(egg_texture); - flt_face->set_texture(flt_texture); - } - - // Create a vertex list representing the vertices in the primitive, and add - // it as a child of the face bead. This is how Flt files associate vertices - // with faces. - FltVertexList *flt_vertices = new FltVertexList(_flt_header); - flt_face->add_child(flt_vertices); - - EggPrimitive::iterator vi; - bool all_verts_have_color = true; - bool all_verts_have_normal = true; - for (vi = egg_primitive->begin(); vi != egg_primitive->end(); ++vi) { - EggVertex *egg_vertex = (*vi); - FltVertex *flt_vertex = get_flt_vertex(egg_vertex, egg_primitive); - flt_vertices->add_vertex(flt_vertex); - - if (!egg_vertex->has_color()) { - all_verts_have_color = false; - } - if (!egg_vertex->has_normal()) { - all_verts_have_normal = false; - } - } - if (all_verts_have_color) { - // If all the vertices of the face have a color specification, then we - // specify per-vertex color on the face. - if (all_verts_have_normal) { - // And similarly with the normals. - flt_face->_light_mode = FltFace::LM_vertex_with_normal; - } else { - flt_face->_light_mode = FltFace::LM_vertex_no_normal; - } - } else { - if (all_verts_have_normal) { - flt_face->_light_mode = FltFace::LM_face_with_normal; - } else { - flt_face->_light_mode = FltFace::LM_face_no_normal; - } - } -} - -/** - * Converts an egg group to the corresponding flt group, and adds it to the - * indicated parent node. Also recurses on the children of the egg group. - */ -void EggToFlt:: -convert_group(EggGroup *egg_group, FltBead *flt_node, - FltGeometry::BillboardType billboard) { - std::ostringstream egg_syntax; - - FltGroup *flt_group = new FltGroup(_flt_header); - flt_node->add_child(flt_group); - - flt_group->set_id(egg_group->get_name()); - - switch (egg_group->get_billboard_type()) { - // MultiGen represents billboarding at the polygon level, so we have to - // remember this flag for later. - case EggGroup::BT_axis: - billboard = FltGeometry::BT_axial; - break; - - case EggGroup::BT_point_world_relative: - billboard = FltGeometry::BT_point; - break; - - case EggGroup::BT_point_camera_relative: - // Not sure if this is the right flag for MultiGen. - billboard = FltGeometry::BT_fixed; - break; - - default: - break; - } - - if (egg_group->has_transform()) { - apply_transform(egg_group, flt_group); - } - - if (egg_group->get_switch_flag()) { - if (egg_group->get_switch_fps() != 0.0) { - // A sequence animation. - flt_group->_flags |= FltGroup::F_forward_animation; - egg_syntax - << " fps { " << egg_group->get_switch_fps() << " }\n"; - } else { - // Just a switch node. - egg_group->write_switch_flags(egg_syntax, 2); - } - } - - // Pick up any additional egg attributes that MultiGen doesn't support; - // these will get written to the comment field where flt2egg will find it. - egg_group->write_collide_flags(egg_syntax, 2); - egg_group->write_model_flags(egg_syntax, 2); - egg_group->write_object_types(egg_syntax, 2); - egg_group->write_decal_flags(egg_syntax, 2); - egg_group->write_tags(egg_syntax, 2); - egg_group->write_render_mode(egg_syntax, 2); - - apply_egg_syntax(egg_syntax.str(), flt_group); - - EggGroup::iterator ci; - for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { - traverse(*ci, flt_group, billboard); - } -} - -/** - * Applies the indicated egg transform to the indicated flt bead. - */ -void EggToFlt:: -apply_transform(EggTransform *egg_transform, FltBead *flt_node) { - flt_node->clear_transform(); - - bool components_ok = true; - int num_components = egg_transform->get_num_components(); - for (int i = num_components - 1; i >= 0 && components_ok; i--) { - switch (egg_transform->get_component_type(i)) { - case EggTransform::CT_translate2d: - { - FltTransformTranslate *translate = - new FltTransformTranslate(_flt_header); - LVector2d v2 = egg_transform->get_component_vec2(i); - translate->set(LPoint3d::zero(), LVector3d(v2[0], v2[1], 0.0)); - flt_node->add_transform_step(translate); - } - break; - - case EggTransform::CT_translate3d: - { - FltTransformTranslate *translate = - new FltTransformTranslate(_flt_header); - translate->set(LPoint3d::zero(), egg_transform->get_component_vec3(i)); - flt_node->add_transform_step(translate); - } - break; - - case EggTransform::CT_rotate2d: - { - FltTransformRotateAboutEdge *rotate = - new FltTransformRotateAboutEdge(_flt_header); - rotate->set(LPoint3d::zero(), LPoint3d(0.0, 0.0, 1.0), - egg_transform->get_component_number(i)); - flt_node->add_transform_step(rotate); - } - break; - - case EggTransform::CT_rotx: - { - FltTransformRotateAboutEdge *rotate = - new FltTransformRotateAboutEdge(_flt_header); - rotate->set(LPoint3d::zero(), LPoint3d(1.0, 0.0, 0.0), - egg_transform->get_component_number(i)); - flt_node->add_transform_step(rotate); - } - break; - - case EggTransform::CT_roty: - { - FltTransformRotateAboutEdge *rotate = - new FltTransformRotateAboutEdge(_flt_header); - rotate->set(LPoint3d::zero(), LPoint3d(0.0, 1.0, 0.0), - egg_transform->get_component_number(i)); - flt_node->add_transform_step(rotate); - } - break; - - case EggTransform::CT_rotz: - { - FltTransformRotateAboutEdge *rotate = - new FltTransformRotateAboutEdge(_flt_header); - rotate->set(LPoint3d::zero(), LPoint3d(0.0, 0.0, 1.0), - egg_transform->get_component_number(i)); - flt_node->add_transform_step(rotate); - } - break; - - case EggTransform::CT_rotate3d: - { - FltTransformRotateAboutEdge *rotate = - new FltTransformRotateAboutEdge(_flt_header); - rotate->set(LPoint3d::zero(), egg_transform->get_component_vec3(i), - egg_transform->get_component_number(i)); - flt_node->add_transform_step(rotate); - } - break; - - case EggTransform::CT_scale2d: - { - FltTransformScale *scale = new FltTransformScale(_flt_header); - LVector2d v2 = egg_transform->get_component_vec2(i); - scale->set(LPoint3d::zero(), LVector3(v2[0], v2[1], 1.0f)); - flt_node->add_transform_step(scale); - } - break; - - case EggTransform::CT_scale3d: - { - FltTransformScale *scale = new FltTransformScale(_flt_header); - scale->set(LPoint3d::zero(), LCAST(PN_stdfloat, egg_transform->get_component_vec3(i))); - flt_node->add_transform_step(scale); - } - break; - - case EggTransform::CT_uniform_scale: - { - FltTransformScale *scale = new FltTransformScale(_flt_header); - PN_stdfloat factor = (PN_stdfloat)egg_transform->get_component_number(i); - scale->set(LPoint3d::zero(), LVecBase3(factor, factor, factor)); - flt_node->add_transform_step(scale); - } - break; - - case EggTransform::CT_matrix3: - { - FltTransformGeneralMatrix *matrix = - new FltTransformGeneralMatrix(_flt_header); - const LMatrix3d &m = egg_transform->get_component_mat3(i); - LMatrix4d mat4(m(0, 0), m(0, 1), 0.0, m(0, 2), - m(1, 0), m(1, 1), 0.0, m(1, 2), - 0.0, 0.0, 1.0, 0.0, - m(2, 0), m(2, 1), 0.0, m(2, 2)); - matrix->set_matrix(mat4); - flt_node->add_transform_step(matrix); - } - break; - - case EggTransform::CT_matrix4: - { - FltTransformGeneralMatrix *matrix = - new FltTransformGeneralMatrix(_flt_header); - matrix->set_matrix(egg_transform->get_component_mat4(i)); - flt_node->add_transform_step(matrix); - } - break; - - default: - // Don't know how to convert this component. - components_ok = false; - } - } - - if (components_ok) { - // Verify that the transform was computed correctly. - if (!flt_node->get_transform().almost_equal(egg_transform->get_transform3d())) { - nout << "Incorrect transform! Expected:\n"; - egg_transform->get_transform3d().write(nout, 2); - nout << "Computed:\n"; - flt_node->get_transform().write(nout, 2); - nout << "\n"; - components_ok = false; - } - } - - if (!components_ok) { - // Just store the overall transform. - flt_node->set_transform(egg_transform->get_transform3d()); - } -} - -/** - * Adds the indicated sequence of egg syntax lines (presumably representing - * egg features not directly supported by MultiGen) to the flt record as a - * comment, so that flt2egg will reapply it to the egg groups. - */ -void EggToFlt:: -apply_egg_syntax(const std::string &egg_syntax, FltRecord *flt_record) { - if (!egg_syntax.empty()) { - std::ostringstream out; - out << " {\n" - << egg_syntax - << "}"; - flt_record->set_comment(out.str()); - } -} - -/** - * Returns a FltVertex corresponding to the indicated EggVertex. If the - * vertex has not been seen before (in this particular vertex frame), creates - * a new one. - */ -FltVertex *EggToFlt:: -get_flt_vertex(EggVertex *egg_vertex, EggNode *context) { - const LMatrix4d *frame = context->get_vertex_to_node_ptr(); - VertexMap &vertex_map = _vertex_map_per_frame[frame]; - - VertexMap::iterator vi = vertex_map.find(egg_vertex); - if (vi != vertex_map.end()) { - return (*vi).second; - } - FltVertex *flt_vertex = new FltVertex(_flt_header); - flt_vertex->_pos = egg_vertex->get_pos3(); - - if (egg_vertex->has_color()) { - flt_vertex->set_color(egg_vertex->get_color()); - } - if (egg_vertex->has_normal()) { - flt_vertex->_normal = LCAST(PN_stdfloat, egg_vertex->get_normal()); - flt_vertex->_has_normal = true; - } - if (egg_vertex->has_uv()) { - flt_vertex->_uv = LCAST(PN_stdfloat, egg_vertex->get_uv()); - flt_vertex->_has_uv = true; - } - - if (frame != nullptr) { - flt_vertex->_pos = flt_vertex->_pos * (*frame); - flt_vertex->_normal = flt_vertex->_normal * LCAST(PN_stdfloat, (*frame)); - } - - _flt_header->add_vertex(flt_vertex); - vertex_map[egg_vertex] = flt_vertex; - - return flt_vertex; -} - -/** - * Returns a FltTexture corresponding to the indicated EggTexture. If the - * texture has not been seen before, creates a new one. - */ -FltTexture *EggToFlt:: -get_flt_texture(EggTexture *egg_texture) { - // We have to maintain this map based on the filename, not the egg pointer, - // because there may be multiple EggTextures with the same filename, and we - // have to collapse them together. - Filename filename = egg_texture->get_filename(); - TextureMap::iterator vi = _texture_map.find(filename); - if (vi != _texture_map.end()) { - return (*vi).second; - } - FltTexture *flt_texture = new FltTexture(_flt_header); - flt_texture->set_texture_filename(filename); - - switch (egg_texture->get_minfilter()) { - case EggTexture::FT_nearest: - flt_texture->_min_filter = FltTexture::MN_point; - break; - - case EggTexture::FT_linear: - flt_texture->_min_filter = FltTexture::MN_bilinear; - break; - - case EggTexture::FT_nearest_mipmap_nearest: - flt_texture->_min_filter = FltTexture::MN_mipmap_point; - break; - - case EggTexture::FT_nearest_mipmap_linear: - flt_texture->_min_filter = FltTexture::MN_mipmap_linear; - break; - - case EggTexture::FT_linear_mipmap_nearest: - flt_texture->_min_filter = FltTexture::MN_mipmap_bilinear; - break; - - case EggTexture::FT_linear_mipmap_linear: - flt_texture->_min_filter = FltTexture::MN_mipmap_trilinear; - break; - - default: - break; - } - - switch (egg_texture->get_magfilter()) { - case EggTexture::FT_nearest: - flt_texture->_mag_filter = FltTexture::MG_point; - break; - - case EggTexture::FT_linear: - flt_texture->_mag_filter = FltTexture::MG_bilinear; - break; - - default: - break; - } - - switch (egg_texture->get_wrap_mode()) { - case EggTexture::WM_repeat: - flt_texture->_repeat = FltTexture::RT_repeat; - break; - - case EggTexture::WM_clamp: - flt_texture->_repeat = FltTexture::RT_clamp; - break; - - default: - break; - } - - switch (egg_texture->get_wrap_u()) { - case EggTexture::WM_repeat: - flt_texture->_repeat_u = FltTexture::RT_repeat; - break; - - case EggTexture::WM_clamp: - flt_texture->_repeat_u = FltTexture::RT_clamp; - break; - - default: - break; - } - - switch (egg_texture->get_wrap_v()) { - case EggTexture::WM_repeat: - flt_texture->_repeat_v = FltTexture::RT_repeat; - break; - - case EggTexture::WM_clamp: - flt_texture->_repeat_v = FltTexture::RT_clamp; - break; - - default: - break; - } - - switch (egg_texture->get_env_type()) { - case EggTexture::ET_modulate: - flt_texture->_env_type = FltTexture::ET_modulate; - break; - - case EggTexture::ET_decal: - flt_texture->_env_type = FltTexture::ET_decal; - break; - - default: - break; - } - - switch (egg_texture->get_format()) { - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - flt_texture->_internal_format = FltTexture::IF_ia_8; - break; - - case EggTexture::F_rgb5: - case EggTexture::F_rgb332: - flt_texture->_internal_format = FltTexture::IF_rgb_5; - break; - - case EggTexture::F_rgba4: - case EggTexture::F_rgba5: - flt_texture->_internal_format = FltTexture::IF_rgba_4; - break; - - case EggTexture::F_rgba8: - case EggTexture::F_rgba: - case EggTexture::F_rgbm: - case EggTexture::F_rgb: - case EggTexture::F_rgb8: - flt_texture->_internal_format = FltTexture::IF_rgba_8; - break; - - case EggTexture::F_rgba12: - flt_texture->_internal_format = FltTexture::IF_rgba_12; - break; - - case EggTexture::F_alpha: - flt_texture->_internal_format = FltTexture::IF_i_16; - flt_texture->_intensity_is_alpha = true; - break; - - case EggTexture::F_luminance: - flt_texture->_internal_format = FltTexture::IF_i_16; - break; - - case EggTexture::F_rgb12: - flt_texture->_internal_format = FltTexture::IF_rgb_12; - break; - - default: - break; - } - - _flt_header->add_texture(flt_texture); - _texture_map[filename] = flt_texture; - - return flt_texture; -} - - - -int main(int argc, char *argv[]) { - EggToFlt prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/fltprogs/eggToFlt.h b/pandatool/src/fltprogs/eggToFlt.h deleted file mode 100644 index 0cbcb212..00000000 --- a/pandatool/src/fltprogs/eggToFlt.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToFlt.h - * @author drose - * @date 2003-10-01 - */ - -#ifndef EGGTOFLT_H -#define EGGTOFLT_H - -#include "pandatoolbase.h" - -#include "eggToSomething.h" -#include "fltHeader.h" -#include "fltGeometry.h" -#include "pointerTo.h" -#include "pmap.h" -#include "vector_string.h" - -class EggGroup; -class EggVertex; -class EggPrimitive; -class EggTexture; -class EggTransform; -class FltVertex; -class FltBead; -class FltTexture; - -/** - * A program to read an egg file and write a flt file. - */ -class EggToFlt : public EggToSomething { -public: - EggToFlt(); - - void run(); - -private: - static bool dispatch_attr(const std::string &opt, const std::string &arg, void *var); - - void traverse(EggNode *egg_node, FltBead *flt_node, - FltGeometry::BillboardType billboard); - void convert_primitive(EggPrimitive *egg_primitive, FltBead *flt_node, - FltGeometry::BillboardType billboard); - void convert_group(EggGroup *egg_group, FltBead *flt_node, - FltGeometry::BillboardType billboard); - void apply_transform(EggTransform *egg_transform, FltBead *flt_node); - void apply_egg_syntax(const std::string &egg_syntax, FltRecord *flt_record); - FltVertex *get_flt_vertex(EggVertex *egg_vertex, EggNode *context); - FltTexture *get_flt_texture(EggTexture *egg_texture); - - FltHeader::AttrUpdate _auto_attr_update; - - PT(FltHeader) _flt_header; - - typedef pmap VertexMap; - typedef pmap VertexMapPerFrame; - VertexMapPerFrame _vertex_map_per_frame; - - typedef pmap TextureMap; - TextureMap _texture_map; -}; - -#endif diff --git a/pandatool/src/fltprogs/fltInfo.cxx b/pandatool/src/fltprogs/fltInfo.cxx deleted file mode 100644 index bd0e9d8a..00000000 --- a/pandatool/src/fltprogs/fltInfo.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltInfo.cxx - * @author drose - * @date 2001-09-05 - */ - -#include "fltInfo.h" - -#include "fltHeader.h" -#include "indent.h" - -/** - * - */ -FltInfo:: -FltInfo() { - set_program_brief("describe the contents of a MultiGen .flt file"); - set_program_description - ("This program reads a MultiGen OpenFlight (.flt) file and reports " - "some interesting things about its contents."); - - clear_runlines(); - add_runline("[opts] input.flt"); - - add_option - ("ls", "", 0, - "List the hierarchy in the flt file.", - &FltInfo::dispatch_none, &_list_hierarchy); -} - - -/** - * - */ -void FltInfo:: -run() { - PT(FltHeader) header = new FltHeader(_path_replace); - - nout << "Reading " << _input_filename << "\n"; - FltError result = header->read_flt(_input_filename); - if (result != FE_ok) { - nout << "Unable to read: " << result << "\n"; - exit(1); - } - - if (header->check_version()) { - nout << "Version is " << header->get_flt_version() / 100.0 << "\n"; - } - - if (_list_hierarchy) { - list_hierarchy(header, 0); - } -} - -/** - * Recursively lists the flt file's hierarchy in a meaningful way. - */ -void FltInfo:: -list_hierarchy(FltRecord *record, int indent_level) { - // Maybe in the future we can do something fancier here. - record->write(std::cout, indent_level); -} - - -/** - * - */ -bool FltInfo:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the .flt file to read on the command line.\n"; - return false; - - } else if (args.size() != 1) { - nout << "You must specify only one .flt file to read on the command line.\n"; - return false; - } - - _input_filename = args[0]; - - return true; -} - - -int main(int argc, char *argv[]) { - FltInfo prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/fltprogs/fltInfo.h b/pandatool/src/fltprogs/fltInfo.h deleted file mode 100644 index 1dc87953..00000000 --- a/pandatool/src/fltprogs/fltInfo.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltInfo.h - * @author drose - * @date 2001-09-05 - */ - -#ifndef FLTINFO_H -#define FLTINFO_H - -#include "pandatoolbase.h" - -#include "programBase.h" - -class FltRecord; - -/** - * A program to read a flt file and report interesting things about it. - */ -class FltInfo : public ProgramBase { -public: - FltInfo(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - - void list_hierarchy(FltRecord *record, int indent_level); - - Filename _input_filename; - bool _list_hierarchy; -}; - -#endif diff --git a/pandatool/src/fltprogs/fltToEgg.cxx b/pandatool/src/fltprogs/fltToEgg.cxx deleted file mode 100644 index c08a8381..00000000 --- a/pandatool/src/fltprogs/fltToEgg.cxx +++ /dev/null @@ -1,106 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEgg.cxx - * @author drose - * @date 2001-04-17 - */ - -#include "fltToEgg.h" - -#include "fltToEggConverter.h" -#include "config_flt.h" - -/** - * - */ -FltToEgg:: -FltToEgg() : - SomethingToEgg("MultiGen", ".flt") -{ - add_path_replace_options(); - add_path_store_options(); - add_units_options(); - add_normals_options(); - add_transform_options(); - add_merge_externals_options(); - - set_program_brief("convert a MultiGen .flt file to .egg"); - set_program_description - ("This program converts MultiGen OpenFlight (.flt) files to egg. Most " - "features of MultiGen that are also recognized by egg are supported."); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. Normally, this is z-up."); - - // Does anyone really care about this option? It's mainly useful for - // debugging the flt2egg logic. - /* - add_option - ("C", "", 0, - "Compose node transforms into a single matrix before writing them to " - "the egg file, instead of writing them as individual scale, rotate, and " - "translate operations.", - &FltToEgg::dispatch_none, &_compose_transforms); - */ - _compose_transforms = false; - - _coordinate_system = CS_zup_right; -} - -/** - * - */ -void FltToEgg:: -run() { - _data->set_coordinate_system(_coordinate_system); - - FltToEggConverter converter; - converter.set_merge_externals(_merge_externals); - converter.set_egg_data(_data); - converter._compose_transforms = _compose_transforms; - converter._allow_errors = _allow_errors; - - apply_parameters(converter); - - - PT(FltHeader) header = new FltHeader(_path_replace); - - nout << "Reading " << _input_filename << "\n"; - FltError result = header->read_flt(_input_filename); - if (result != FE_ok) { - nout << "Unable to read: " << result << "\n"; - exit(1); - } - - header->check_version(); - - - if (!converter.convert_flt(header)) { - nout << "Errors in conversion.\n"; - exit(1); - } - - if (_input_units == DU_invalid) { - _input_units = converter.get_input_units(); - } - - write_egg_file(); - nout << "\n"; -} - - -int main(int argc, char *argv[]) { - init_libflt(); - FltToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/fltprogs/fltToEgg.h b/pandatool/src/fltprogs/fltToEgg.h deleted file mode 100644 index 6a756fe6..00000000 --- a/pandatool/src/fltprogs/fltToEgg.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltToEgg.h - * @author drose - * @date 2001-04-17 - */ - -#ifndef FLTTOEGG_H -#define FLTTOEGG_H - -#include "pandatoolbase.h" - -#include "somethingToEgg.h" -#include "fltToEggConverter.h" - -#include "dSearchPath.h" - -/** - * A program to read a flt file and generate an egg file. - */ -class FltToEgg : public SomethingToEgg { -public: - FltToEgg(); - - void run(); - - bool _compose_transforms; -}; - -#endif diff --git a/pandatool/src/fltprogs/fltTrans.cxx b/pandatool/src/fltprogs/fltTrans.cxx deleted file mode 100644 index 692f8e37..00000000 --- a/pandatool/src/fltprogs/fltTrans.cxx +++ /dev/null @@ -1,133 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTrans.cxx - * @author drose - * @date 2001-04-11 - */ - -#include "fltTrans.h" - -#include "fltHeader.h" - -/** - * - */ -FltTrans:: -FltTrans() : - WithOutputFile(true, false, true) -{ - // Indicate the extension name we expect the user to supply for output - // files. - _preferred_extension = ".flt"; - - set_program_brief("apply various operations to a MultiGen .flt file"); - set_program_description - ("This program reads a MultiGen OpenFlight (.flt) file and writes an " - "essentially equivalent .flt file, to the file specified with -o (or " - "as the second parameter). Some simple operations may be performed."); - - clear_runlines(); - add_runline("[opts] input.flt output.flt"); - add_runline("[opts] -o output.flt input.flt"); - - add_path_replace_options(); - add_path_store_options(); - - add_option - ("v", "version", 0, - "Upgrade (or downgrade) the flt file to the indicated version. This " - "may not be completely correct for all version-to-version combinations.", - &FltTrans::dispatch_double, &_got_new_version, &_new_version); - - add_option - ("o", "filename", 0, - "Specify the filename to which the resulting .flt file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file.", - &FltTrans::dispatch_filename, &_got_output_filename, &_output_filename); -} - - -/** - * - */ -void FltTrans:: -run() { - if (_got_new_version) { - int new_version = (int)floor(_new_version * 100.0 + 0.5); - if (new_version < FltHeader::min_flt_version() || - new_version > FltHeader::max_flt_version()) { - nout << "Cannot write flt files of version " << new_version / 100.0 - << ". This program only understands how to write flt files between version " - << FltHeader::min_flt_version() / 100.0 << " and " - << FltHeader::max_flt_version() / 100.0 << ".\n"; - exit(1); - } - } - - PT(FltHeader) header = new FltHeader(_path_replace); - - nout << "Reading " << _input_filename << "\n"; - FltError result = header->read_flt(_input_filename); - if (result != FE_ok) { - nout << "Unable to read: " << result << "\n"; - exit(1); - } - - if (header->check_version()) { - nout << "Version is " << header->get_flt_version() / 100.0 << "\n"; - } - - if (_got_new_version) { - int new_version = (int)floor(_new_version * 100.0 + 0.5); - header->set_flt_version(new_version); - } - - header->apply_converted_filenames(); - - result = header->write_flt(get_output()); - if (result != FE_ok) { - nout << "Unable to write: " << result << "\n"; - exit(1); - } - - nout << "Successfully written.\n"; -} - - -/** - * - */ -bool FltTrans:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 1)) { - return false; - } - - if (args.empty()) { - nout << "You must specify the .flt file to read on the command line.\n"; - return false; - - } else if (args.size() != 1) { - nout << "You must specify only one .flt file to read on the command line.\n"; - return false; - } - - _input_filename = args[0]; - - return true; -} - - -int main(int argc, char *argv[]) { - FltTrans prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/fltprogs/fltTrans.h b/pandatool/src/fltprogs/fltTrans.h deleted file mode 100644 index 042418f6..00000000 --- a/pandatool/src/fltprogs/fltTrans.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file fltTrans.h - * @author drose - * @date 2001-04-11 - */ - -#ifndef FLTTRANS_H -#define FLTTRANS_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "withOutputFile.h" - -/** - * A program to read a flt file and write an equivalent flt file, possibly - * performing some minor operations along the way. - */ -class FltTrans : public ProgramBase, public WithOutputFile { -public: - FltTrans(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - - Filename _input_filename; - bool _got_new_version; - double _new_version; -}; - -#endif diff --git a/pandatool/src/gtk-stats/CMakeLists.txt b/pandatool/src/gtk-stats/CMakeLists.txt deleted file mode 100644 index dca2f914..00000000 --- a/pandatool/src/gtk-stats/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_GTK3 OR NOT HAVE_NET) - return() -endif() - -set(GTKSTATS_HEADERS - gtkStatsChartMenu.h - gtkStatsFlameGraph.h - gtkStatsGraph.h - gtkStatsLabel.h - gtkStatsLabelStack.h - gtkStatsMonitor.h gtkStatsMonitor.I - gtkStatsPianoRoll.h - gtkStatsServer.h - gtkStatsStripChart.h -) - -set(GTKSTATS_SOURCES - gtkStats.cxx - gtkStatsChartMenu.cxx - gtkStatsFlameGraph.cxx - gtkStatsGraph.cxx - gtkStatsLabel.cxx - gtkStatsLabelStack.cxx - gtkStatsMonitor.cxx - gtkStatsPianoRoll.cxx - gtkStatsServer.cxx - gtkStatsStripChart.cxx - gtkStatsTimeline.cxx -) - -composite_sources(gtk-stats GTKSTATS_SOURCES) -add_executable(gtk-stats ${GTKSTATS_HEADERS} ${GTKSTATS_SOURCES}) -target_link_libraries(gtk-stats p3progbase p3pstatserver PKG::GTK3) - -# This program is NOT actually called gtk-stats. It's pstats-gtk on Win32 and -# pstats everywhere else (as the Win32 GUI is not built). -if(WIN32 OR APPLE) - set_target_properties(gtk-stats PROPERTIES OUTPUT_NAME "pstats-gtk") -else() - set_target_properties(gtk-stats PROPERTIES OUTPUT_NAME "pstats") -endif() - -install(TARGETS gtk-stats EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/gtk-stats/gtkStats.cxx b/pandatool/src/gtk-stats/gtkStats.cxx deleted file mode 100644 index 344af201..00000000 --- a/pandatool/src/gtk-stats/gtkStats.cxx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStats.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "pandatoolbase.h" -#include "gtkStats.h" -#include "gtkStatsServer.h" -#include "config_pstatclient.h" - -int -main(int argc, char *argv[]) { - gtk_init(&argc, &argv); - - // Create the server window. - GtkStatsServer *server = new GtkStatsServer; - server->parse_command_line(argc, argv); - - // Now get lost in the message loop. - gtk_main(); - - return (0); -} diff --git a/pandatool/src/gtk-stats/gtkStats.h b/pandatool/src/gtk-stats/gtkStats.h deleted file mode 100644 index a8cd1cb0..00000000 --- a/pandatool/src/gtk-stats/gtkStats.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStats.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATS_H -#define GTKSTATS_H - -#include "pStatServer.h" - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx deleted file mode 100644 index 7f0ad0a4..00000000 --- a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx +++ /dev/null @@ -1,328 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsChartMenu.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsChartMenu.h" -#include "gtkStatsMonitor.h" - -/** - * - */ -GtkStatsChartMenu:: -GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index) : - _monitor(monitor), - _thread_index(thread_index) -{ - _menu = gtk_menu_new(); - - if (thread_index == 0) { - // Timeline goes first. - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), - make_menu_item("Timeline", -1, GtkStatsMonitor::CT_timeline, false)); - - // Then the piano roll (even though it's not very useful nowadays) - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), - make_menu_item("Piano Roll", -1, GtkStatsMonitor::CT_piano_roll, false)); - } - else { - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), - make_menu_item("Open Strip Chart", 0, GtkStatsMonitor::CT_strip_chart, false)); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), - make_menu_item("Open Flame Graph", -1, GtkStatsMonitor::CT_flame_graph, false)); - } - - { - GtkWidget *sep = gtk_separator_menu_item_new(); - gtk_widget_show(sep); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), sep); - } - _time_items_end = 3; - - // Put a separator between time items and level items. - { - GtkWidget *sep = gtk_separator_menu_item_new(); - gtk_widget_show(sep); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), sep); - _level_items_end = _time_items_end + 1; - } - - // For the main thread menu, also some options relating to all graph windows. - if (thread_index == 0) { - GtkWidget *sep = gtk_separator_menu_item_new(); - gtk_widget_show(sep); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), sep); - - { - GtkWidget *menu_item = gtk_menu_item_new_with_label("Close All Graphs"); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), menu_item); - - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(activate_close_all), - (void *)_monitor); - } - - { - GtkWidget *menu_item = gtk_menu_item_new_with_label("Reopen Default Graphs"); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), menu_item); - - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(activate_reopen_default), - (void *)_monitor); - } - - { - GtkWidget *menu_item = gtk_menu_item_new_with_label("Save Current Layout as Default"); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu), menu_item); - - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(activate_save_default), - (void *)_monitor); - } - } - - do_update(); - gtk_widget_show(_menu); -} - -/** - * - */ -GtkStatsChartMenu:: -~GtkStatsChartMenu() { -} - -/** - * Returns the gtk widget for this particular menu. - */ -GtkWidget *GtkStatsChartMenu:: -get_menu_widget() { - return _menu; -} - -/** - * Adds the menu to the end of the indicated menu bar. - */ -void GtkStatsChartMenu:: -add_to_menu_bar(GtkWidget *menu_bar, int position) { - const PStatClientData *client_data = _monitor->get_client_data(); - std::string thread_name; - if (_thread_index == 0) { - // A special case for the main thread. - thread_name = "Graphs"; - } else { - thread_name = client_data->get_thread_name(_thread_index); - } - - _menu_item = gtk_menu_item_new_with_label(thread_name.c_str()); - gtk_widget_show(_menu_item); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(_menu_item), _menu); - - gtk_menu_shell_insert(GTK_MENU_SHELL(menu_bar), _menu_item, position); -} - -/** - * Removes the menu from the menu bar. - */ -void GtkStatsChartMenu:: -remove_from_menu_bar(GtkWidget *menu_bar) { - gtk_container_remove(GTK_CONTAINER(menu_bar), _menu_item); -} - -/** - * Checks to see if the menu needs to be updated (e.g. because of new data - * from the client), and updates it if necessary. - */ -void GtkStatsChartMenu:: -check_update() { - PStatView &view = _monitor->get_view(_thread_index); - if (view.get_level_index() != _last_level_index) { - do_update(); - } -} - -/** - * Unconditionally updates the menu with the latest data from the client. - */ -void GtkStatsChartMenu:: -do_update() { - PStatView &view = _monitor->get_view(_thread_index); - _last_level_index = view.get_level_index(); - - const PStatClientData *client_data = _monitor->get_client_data(); - if ((size_t)client_data->get_num_collectors() > _collector_items.size()) { - _collector_items.resize(client_data->get_num_collectors(), std::make_pair(nullptr, nullptr)); - } - - // The menu item(s) for the thread's frame time goes second. - const PStatViewLevel *view_level = view.get_top_level(); - if (_thread_index == 0) { - if (add_view(_menu, view_level, false, _time_items_end)) { - ++_time_items_end; - ++_level_items_end; - } - } else { - for (int c = 0; c < view_level->get_num_children(); ++c) { - if (add_view(_menu, view_level->get_child(c), false, _time_items_end)) { - ++_time_items_end; - ++_level_items_end; - } - } - } - - // And then the menu item(s) for each of the level values. - int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); - for (int tc = 0; tc < num_toplevel_collectors; tc++) { - int collector = client_data->get_toplevel_collector(tc); - if (client_data->has_collector(collector) && - client_data->get_collector_has_level(collector, _thread_index)) { - - PStatView &level_view = _monitor->get_level_view(collector, _thread_index); - add_view(_menu, level_view.get_top_level(), true, _level_items_end); - } - } -} - -/** - * Adds a new entry or entries to the menu for the indicated view and its - * children. Returns true if an item was added, false if not. - */ -bool GtkStatsChartMenu:: -add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level, - bool show_level, int insert_at) { - int collector = view_level->get_collector(); - - GtkWidget *&menu_item = _collector_items[collector].first; - GtkWidget *&menu = _collector_items[collector].second; - - const PStatClientData *client_data = _monitor->get_client_data(); - - int num_children = view_level->get_num_children(); - if (menu == nullptr && num_children == 0) { - // For a collector without children, no point in making a submenu. We just - // have the item open a strip chart directly (no point in creating a flame - // graph if there are no children). - if (menu_item != nullptr) { - // Already exists. - return false; - } - - std::string collector_name = client_data->get_collector_name(collector); - menu_item = make_menu_item( - collector_name.c_str(), collector, GtkStatsMonitor::CT_strip_chart, show_level); - gtk_menu_shell_insert(GTK_MENU_SHELL(parent_menu), menu_item, insert_at); - return true; - } - else if (menu_item != nullptr && menu == nullptr) { - // Unhook the signal handler, we are creating a submenu. - GtkStatsMonitor::MenuDef smd(GtkStatsMonitor::CT_strip_chart, _thread_index, collector, -1, show_level); - const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd); - - g_signal_handlers_disconnect_by_data(G_OBJECT(menu_item), (void *)menu_def); - } - - // Create a submenu. - bool added_item = false; - if (menu_item == nullptr) { - std::string collector_name = client_data->get_collector_name(collector); - menu_item = gtk_menu_item_new_with_label(collector_name.c_str()); - gtk_widget_show(menu_item); - gtk_menu_shell_insert(GTK_MENU_SHELL(parent_menu), menu_item, insert_at); - added_item = true; - } - - if (menu == nullptr) { - menu = gtk_menu_new(); - gtk_widget_show(menu); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu); - - gtk_menu_shell_append(GTK_MENU_SHELL(menu), - make_menu_item("Open Strip Chart", collector, GtkStatsMonitor::CT_strip_chart, show_level)); - - if (!show_level) { - if (collector == 0) { - collector = -1; - } - - gtk_menu_shell_append(GTK_MENU_SHELL(menu), - make_menu_item("Open Flame Graph", collector, GtkStatsMonitor::CT_flame_graph)); - } - - GtkWidget *sep = gtk_separator_menu_item_new(); - gtk_widget_show(sep); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep); - } - - for (int c = 0; c < num_children; ++c) { - add_view(menu, view_level->get_child(c), show_level, 3 + !show_level); - } - - return added_item; -} - -/** - * - */ -GtkWidget *GtkStatsChartMenu:: -make_menu_item(const char *label, int collector_index, ChartType chart_type, - bool show_level) { - GtkStatsMonitor::MenuDef smd(chart_type, _thread_index, collector_index, -1, show_level); - const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd); - - GtkWidget *menu_item = gtk_menu_item_new_with_label(label); - gtk_widget_show(menu_item); - - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - - return menu_item; -} - -/** - * Removes a previous menu child from the menu. - */ -void GtkStatsChartMenu:: -remove_menu_child(GtkWidget *widget, gpointer data) { - GtkWidget *menu = (GtkWidget *)data; - gtk_container_remove(GTK_CONTAINER(menu), widget); -} - -/** - * Callback for Close All Graphs. - */ -void GtkStatsChartMenu:: -activate_close_all(GtkWidget *widget, gpointer data) { - GtkStatsMonitor *monitor = (GtkStatsMonitor *)data; - monitor->remove_all_graphs(); -} - -/** - * Callback for Reopen Default Graphs. - */ -void GtkStatsChartMenu:: -activate_reopen_default(GtkWidget *widget, gpointer data) { - GtkStatsMonitor *monitor = (GtkStatsMonitor *)data; - monitor->remove_all_graphs(); - monitor->open_default_graphs(); -} - -/** - * Callback for Save Current Layout as Default. - */ -void GtkStatsChartMenu:: -activate_save_default(GtkWidget *widget, gpointer data) { - GtkStatsMonitor *monitor = (GtkStatsMonitor *)data; - monitor->save_default_graphs(); -} diff --git a/pandatool/src/gtk-stats/gtkStatsChartMenu.h b/pandatool/src/gtk-stats/gtkStatsChartMenu.h deleted file mode 100644 index f2dfb6da..00000000 --- a/pandatool/src/gtk-stats/gtkStatsChartMenu.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsChartMenu.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSCHARTMENU_H -#define GTKSTATSCHARTMENU_H - -#include "pandatoolbase.h" -#include "gtkStatsMonitor.h" - -#include - -class PStatView; -class PStatViewLevel; - -/** - * A pulldown menu of charts available for a particular thread. - */ -class GtkStatsChartMenu { -public: - typedef GtkStatsMonitor::ChartType ChartType; - - GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index); - ~GtkStatsChartMenu(); - - int get_thread_index() const { return _thread_index; } - - GtkWidget *get_menu_widget(); - void add_to_menu_bar(GtkWidget *menu_bar, int position); - void remove_from_menu_bar(GtkWidget *menu_bar); - - void check_update(); - void do_update(); - -private: - bool add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level, - bool show_level, int insert_at); - GtkWidget *make_menu_item(const char *label, int collector_index, - ChartType chart_type, bool show_level = false); - - static void remove_menu_child(GtkWidget *widget, gpointer data); - static void activate_close_all(GtkWidget *widget, gpointer data); - static void activate_reopen_default(GtkWidget *widget, gpointer data); - static void activate_save_default(GtkWidget *widget, gpointer data); - - GtkStatsMonitor *_monitor; - int _thread_index; - - int _last_level_index; - GtkWidget *_menu; - GtkWidget *_menu_item = nullptr; - - // Pair of menu item, submenu - std::vector > _collector_items; - int _time_items_end = 0; - int _level_items_end = 0; -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsFlameGraph.cxx b/pandatool/src/gtk-stats/gtkStatsFlameGraph.cxx deleted file mode 100644 index ea20558b..00000000 --- a/pandatool/src/gtk-stats/gtkStatsFlameGraph.cxx +++ /dev/null @@ -1,814 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsFlameGraph.cxx - * @author rdb - * @date 2022-02-02 - */ - -#include "gtkStatsFlameGraph.h" -#include "gtkStatsLabel.h" -#include "gtkStatsMonitor.h" -#include "pStatCollectorDef.h" - -static const int default_flame_graph_width = 800; -static const int default_flame_graph_height = 150; - -/** - * - */ -GtkStatsFlameGraph:: -GtkStatsFlameGraph(GtkStatsMonitor *monitor, int thread_index, - int collector_index, int frame_number) : - PStatFlameGraph(monitor, thread_index, collector_index, frame_number, 0, 0), - GtkStatsGraph(monitor, false) -{ - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - std::string window_title = get_title_text(); - gtk_window_set_title(GTK_WINDOW(_window), window_title.c_str()); - - // Put some stuff on top of the graph. - _top_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_box_pack_start(GTK_BOX(_graph_vbox), _top_hbox, - FALSE, FALSE, 0); - - _average_check_box = gtk_check_button_new_with_label("Average"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_average_check_box), TRUE); - g_signal_connect(G_OBJECT(_average_check_box), "toggled", - G_CALLBACK(toggled_callback), this); - - // Add a DrawingArea widget on top of the graph, to display all of the scale - // units. - _scale_area = gtk_drawing_area_new(); - g_signal_connect(G_OBJECT(_scale_area), "draw", G_CALLBACK(draw_callback), this); - - _total_label = gtk_label_new(""); - gtk_box_pack_start(GTK_BOX(_top_hbox), _average_check_box, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(_top_hbox), _scale_area, TRUE, TRUE, 0); - gtk_box_pack_end(GTK_BOX(_top_hbox), _total_label, FALSE, FALSE, 0); - - // Listen for mouse scroll and keyboard events. - gtk_widget_add_events(_window, GDK_SCROLL_MASK | GDK_KEY_PRESS_MASK); - g_signal_connect(G_OBJECT(_window), "scroll_event", - G_CALLBACK(scroll_callback), this); - g_signal_connect(G_OBJECT(_window), "key_press_event", - G_CALLBACK(key_press_callback), this); - - gtk_widget_set_size_request(_graph_window, - default_flame_graph_width * monitor->get_resolution() / 96, - default_flame_graph_height * monitor->get_resolution() / 96); - - gtk_widget_show_all(_window); - gtk_widget_show(_window); - - // Allow the window to be resized as small as the user likes. We have to do - // this after the window has been shown; otherwise, it will affect the - // window's initial size. - gtk_widget_set_size_request(_window, 0, 0); - - clear_region(); - - if (get_average_mode()) { - start_animation(); - } -} - -/** - * - */ -GtkStatsFlameGraph:: -~GtkStatsFlameGraph() { -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void GtkStatsFlameGraph:: -new_collector(int collector_index) { - GtkStatsGraph::new_collector(collector_index); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void GtkStatsFlameGraph:: -new_data(int thread_index, int frame_number) { - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - gtk_window_set_title(GTK_WINDOW(_window), window_title.c_str()); - } - } - - if (!_pause) { - update(); - - std::string text = format_number(get_horizontal_scale(), get_guide_bar_units(), get_guide_bar_unit_name()); - if (_net_value_text != text) { - _net_value_text = text; - gtk_label_set_text(GTK_LABEL(_total_label), _net_value_text.c_str()); - } - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void GtkStatsFlameGraph:: -force_redraw() { - if (_cr) { - PStatFlameGraph::force_redraw(); - } -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void GtkStatsFlameGraph:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatFlameGraph::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void GtkStatsFlameGraph:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - gtk_widget_queue_draw(_scale_area); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void GtkStatsFlameGraph:: -on_click_label(int collector_index) { - push_collector_index(collector_index); -} - -/** - * Called when the user hovers the mouse over a label. - */ -void GtkStatsFlameGraph:: -on_enter_label(int collector_index) { - if (collector_index != _highlighted_index) { - _highlighted_index = collector_index; - - if (!get_average_mode()) { - PStatFlameGraph::force_redraw(); - } - } -} - -/** - * Called when the user's mouse cursor leaves a label. - */ -void GtkStatsFlameGraph:: -on_leave_label(int collector_index) { - if (collector_index == _highlighted_index && collector_index != -1) { - _highlighted_index = -1; - - if (!get_average_mode()) { - PStatFlameGraph::force_redraw(); - } - } -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void GtkStatsFlameGraph:: -normal_guide_bars() { - // We want vaguely 100 pixels between guide bars. - int num_bars = get_xsize() / (_pixel_scale * 25); - - _guide_bars.clear(); - - double dist = get_horizontal_scale() / num_bars; - - for (int i = 1; i < num_bars; ++i) { - _guide_bars.push_back(make_guide_bar(i * dist)); - } - - _guide_bars_changed = true; - - nassertv_always(_scale_area != nullptr); - gtk_widget_queue_draw(_scale_area); -} - -/** - * Erases the chart area. - */ -void GtkStatsFlameGraph:: -clear_region() { - cairo_set_source_rgb(_cr, 1.0, 1.0, 1.0); - cairo_paint(_cr); -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void GtkStatsFlameGraph:: -begin_draw() { - clear_region(); - - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_bar(_cr, get_guide_bar(i)); - } -} - -/** - * Should be overridden by the user class. Should draw a single bar at the - * indicated location. - */ -void GtkStatsFlameGraph:: -draw_bar(int depth, int from_x, int to_x, int collector_index, int parent_index) { - double bottom = get_ysize() - depth * _pixel_scale * 5; - double top = bottom - _pixel_scale * 5; - - bool is_highlighted = collector_index == _highlighted_index; - cairo_set_source(_cr, get_collector_pattern(collector_index, is_highlighted)); - - if (to_x < from_x + 3) { - // It's just a tiny sliver. This is a more reliable way to draw it. - cairo_rectangle(_cr, from_x, top, to_x - from_x, bottom - top); - cairo_fill(_cr); - } - else { - double radius = std::min((double)_pixel_scale, (to_x - from_x) / 2.0); - cairo_new_sub_path(_cr); - cairo_arc(_cr, to_x - radius, top + radius, radius, -0.5 * M_PI, 0.0); - cairo_arc(_cr, to_x - radius, bottom - radius, radius, 0.0, 0.5 * M_PI); - cairo_arc(_cr, from_x + radius, bottom - radius, radius, 0.5 * M_PI, M_PI); - cairo_arc(_cr, from_x + radius, top + radius, radius, M_PI, 1.5 * M_PI); - cairo_close_path(_cr); - cairo_fill(_cr); - - if ((to_x - from_x) >= _pixel_scale * 4) { - // Only bother drawing the text if we've got some space to draw on. - int left = std::max(from_x, 0) + _pixel_scale / 2; - int right = std::min(to_x, get_xsize()) - _pixel_scale / 2; - - const PStatClientData *client_data = GtkStatsGraph::_monitor->get_client_data(); - const PStatCollectorDef &def = client_data->get_collector_def(collector_index); - - // Choose a suitable foreground color. - LRGBColor fg = get_collector_text_color(collector_index, is_highlighted); - cairo_set_source_rgb(_cr, fg[0], fg[1], fg[2]); - - PangoLayout *layout = gtk_widget_create_pango_layout(_graph_window, def._name.c_str()); - pango_layout_set_attributes(layout, _pango_attrs); - pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); - pango_layout_set_width(layout, (right - left) * PANGO_SCALE); - pango_layout_set_height(layout, -1); - - if (!pango_layout_is_ellipsized(layout)) { - // We have room for more. Show the collector's actual parent, if it's - // different than the block it's shown above. - if (def._parent_index > 0 && def._parent_index != parent_index) { - const PStatCollectorDef &parent_def = client_data->get_collector_def(def._parent_index); - std::string long_name = parent_def._name + ":" + def._name; - pango_layout_set_text(layout, long_name.c_str(), long_name.size()); - if (pango_layout_is_ellipsized(layout)) { - // Nope, it's too long, go back. - pango_layout_set_text(layout, def._name.c_str(), def._name.size()); - } - } - else if (collector_index == 0 && get_frame_number() >= 0) { - char text[32]; - sprintf(text, "Frame %d", get_frame_number()); - pango_layout_set_text(layout, text, -1); - if (pango_layout_is_ellipsized(layout)) { - // Nope, it's too long, go back. - pango_layout_set_text(layout, def._name.c_str(), def._name.size()); - } - } - } - - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - - // Center the text vertically in the bar. - cairo_move_to(_cr, left, top + (bottom - top - height) / 2); - pango_cairo_show_layout(_cr, layout); - - g_object_unref(layout); - } - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void GtkStatsFlameGraph:: -end_draw() { - gtk_widget_queue_draw(_graph_window); -} - -/** - * Called at the end of the draw cycle. - */ -void GtkStatsFlameGraph:: -idle() { -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool GtkStatsFlameGraph:: -animate(double time, double dt) { - return PStatFlameGraph::animate(time, dt); -} - -/** - * Returns the current window dimensions. - */ -bool GtkStatsFlameGraph:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - GtkStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void GtkStatsFlameGraph:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - GtkStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * This is called during the servicing of the draw event; it gives a derived - * class opportunity to do some further painting into the graph window. - */ -void GtkStatsFlameGraph:: -additional_graph_window_paint(cairo_t *cr) { - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_bar(cr, get_user_guide_bar(i)); - } -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsFlameGraph:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return get_bar_tooltip(pixel_to_depth(mouse_y), mouse_x); -} - -/** - * Based on the mouse position within the window's client area, look for - * draggable things the mouse might be hovering over and return the - * apprioprate DragMode enum or DM_none if nothing is indicated. - */ -GtkStatsGraph::DragMode GtkStatsFlameGraph:: -consider_drag_start(int graph_x, int graph_y) { - if (graph_y >= 0 && graph_y < get_ysize()) { - if (graph_x >= 0 && graph_x < get_xsize()) { - // See if the mouse is over a user-defined guide bar. - int x = graph_x; - double from_height = pixel_to_height(x - 2); - double to_height = pixel_to_height(x + 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else { - // The mouse is left or right of the graph; maybe create a new guide - // bar. - return DM_new_guide_bar; - } - } - - return DM_none; -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -gboolean GtkStatsFlameGraph:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - int depth = pixel_to_depth(graph_y); - int collector_index = get_bar_collector(depth, graph_x); - if (button == 3) { - if (collector_index >= 0) { - GtkWidget *menu = gtk_menu_new(); - _popup_index = collector_index; - - std::string label = get_bar_tooltip(depth, graph_x); - if (!label.empty()) { - GtkWidget *menu_item = gtk_menu_item_new_with_label(label.c_str()); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - gtk_widget_set_sensitive(menu_item, FALSE); - } - - { - GtkWidget *menu_item = gtk_menu_item_new_with_label("Set as Focus"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - - if (collector_index == 0 && get_collector_index() == 0) { - gtk_widget_set_sensitive(menu_item, FALSE); - } else { - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(+[] (GtkWidget *widget, gpointer data) { - GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; - self->push_collector_index(self->_popup_index); - }), - this); - } - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_strip_chart, get_thread_index(), collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_flame_graph, get_thread_index(), collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - GtkWidget *menu_item = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_choose_color, -1, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_reset_color, -1, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - gtk_widget_show_all(menu); - gtk_menu_popup_at_pointer(GTK_MENU(menu), nullptr); - return TRUE; - } - return FALSE; - } - else if (double_click && button == 1) { - // Double-clicking on a color bar in the graph will zoom the graph into - // that collector. - if (collector_index >= 0) { - push_collector_index(collector_index); - } else { - // Double-clicking the background goes to the top. - clear_history(); - set_collector_index(-1); - } - return TRUE; - } - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - _drag_scale_start = pixel_to_height(graph_x); - // SetCapture(_graph_window); - return TRUE; - - } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - _drag_start_x = graph_x; - // SetCapture(_graph_window); - return TRUE; - } - - return GtkStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -gboolean GtkStatsFlameGraph:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_x < 0 || graph_x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return GtkStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -gboolean GtkStatsFlameGraph:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none && - graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - // When the mouse is over a color bar, highlight it. - int depth = pixel_to_depth(graph_y); - int collector_index = get_bar_collector(depth, graph_x); - on_enter_label(collector_index); - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - if (graph_x >= 0 && graph_x < get_xsize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_x)); - return TRUE; - } - } - else if (_drag_mode == DM_guide_bar) { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - return TRUE; - } - - return GtkStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -gboolean GtkStatsFlameGraph:: -handle_leave() { - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - return TRUE; -} - -/** - * Converts a pixel to a depth index. - */ -int GtkStatsFlameGraph:: -pixel_to_depth(int y) const { - return (get_ysize() - 1 - y) / (_pixel_scale * 5); -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void GtkStatsFlameGraph:: -draw_guide_bar(cairo_t *cr, const PStatGraph::GuideBar &bar) { - int x = height_to_pixel(bar._height); - - if (x > 0 && x < get_xsize() - 1) { - // Only draw it if it's not too close to the top. - switch (bar._style) { - case GBS_target: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_user: - cairo_set_source_rgb(cr, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2]); - break; - - default: - cairo_set_source_rgb(cr, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2]); - break; - } - cairo_move_to(cr, x, 0); - cairo_line_to(cr, x, get_ysize()); - cairo_stroke(cr); - } -} - -/** - * This is called during the servicing of the draw event. - */ -void GtkStatsFlameGraph:: -draw_guide_labels(cairo_t *cr) { - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; i++) { - draw_guide_label(cr, get_guide_bar(i)); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; i++) { - draw_guide_label(cr, get_user_guide_bar(i)); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void GtkStatsFlameGraph:: -draw_guide_label(cairo_t *cr, const PStatGraph::GuideBar &bar) { - switch (bar._style) { - case GBS_target: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_user: - cairo_set_source_rgb(cr, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2]); - break; - - default: - cairo_set_source_rgb(cr, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2]); - break; - } - - int x = height_to_pixel(bar._height); - const std::string &label = bar._label; - - PangoLayout *layout = gtk_widget_create_pango_layout(_scale_area, label.c_str()); - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(x - width * _cr_scale); - double to_height = pixel_to_height(x + width * _cr_scale); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - g_object_unref(layout); - return; - } - } - - if (x >= 0 && x < get_xsize()) { - // Now convert our x to a coordinate within our drawing area. - int junk_y; - - x /= _cr_scale; - - // The x coordinate comes from the graph_window. - gtk_widget_translate_coordinates(_graph_window, _scale_area, - x, 0, - &x, &junk_y); - - GtkAllocation allocation; - gtk_widget_get_allocation(_scale_area, &allocation); - - int this_x = x - width / 2; - if (this_x >= 0 && this_x + width < allocation.width) { - cairo_move_to(cr, this_x, allocation.height - height); - pango_cairo_show_layout(cr, layout); - } - } - - g_object_unref(layout); -} - -/** - * Called when the average check box is toggled. - */ -void GtkStatsFlameGraph:: -toggled_callback(GtkToggleButton *button, gpointer data) { - GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; - - bool active = gtk_toggle_button_get_active(button); - self->set_average_mode(active); - if (active) { - self->start_animation(); - } -} - -/** - * Draws in the scale labels. - */ -gboolean GtkStatsFlameGraph:: -draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { - GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; - self->draw_guide_labels(cr); - - return TRUE; -} - -/** - * - */ -gboolean GtkStatsFlameGraph:: -scroll_callback(GtkWidget *widget, GdkEventScroll *event, gpointer data) { - GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; - bool changed = false; - switch (event->direction) { - case GDK_SCROLL_LEFT: - changed = self->prev_frame(); - break; - - case GDK_SCROLL_RIGHT: - changed = self->next_frame(); - break; - } - - if (changed) { - std::string window_title = self->get_title_text(); - gtk_window_set_title(GTK_WINDOW(self->_window), window_title.c_str()); - return TRUE; - } else { - return FALSE; - } -} - -/** - * - */ -gboolean GtkStatsFlameGraph:: -key_press_callback(GtkWidget *widget, GdkEventKey *event, gpointer data) { - GtkStatsFlameGraph *self = (GtkStatsFlameGraph *)data; - bool changed = false; - switch (event->keyval) { - case GDK_KEY_Left: - if (event->state & GDK_MOD1_MASK) { - changed = self->pop_collector_index(); - } else { - changed = self->prev_frame(); - } - break; - - case GDK_KEY_Right: - if ((event->state & GDK_MOD1_MASK) == 0) { - changed = self->next_frame(); - } - break; - - case GDK_KEY_Home: - if ((event->state & GDK_MOD1_MASK) == 0) { - changed = self->first_frame(); - } - break; - - case GDK_KEY_End: - if ((event->state & GDK_MOD1_MASK) == 0) { - changed = self->last_frame(); - } - break; - } - - if (changed) { - std::string window_title = self->get_title_text(); - gtk_window_set_title(GTK_WINDOW(self->_window), window_title.c_str()); - return TRUE; - } else { - return FALSE; - } -} diff --git a/pandatool/src/gtk-stats/gtkStatsFlameGraph.h b/pandatool/src/gtk-stats/gtkStatsFlameGraph.h deleted file mode 100644 index 1381ca80..00000000 --- a/pandatool/src/gtk-stats/gtkStatsFlameGraph.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsFlameGraph.h - * @author rdb - * @date 2022-02-02 - */ - -#ifndef GTKSTATSFLAMEGRAPH_H -#define GTKSTATSFLAMEGRAPH_H - -#include "pandatoolbase.h" - -#include "gtkStatsGraph.h" -#include "pStatFlameGraph.h" - -class GtkStatsLabel; - -/** - * A window that draws a flame chart, which shows the collectors explicitly - * stopping and starting, one frame at a time. - */ -class GtkStatsFlameGraph final : public PStatFlameGraph, public GtkStatsGraph { -public: - GtkStatsFlameGraph(GtkStatsMonitor *monitor, int thread_index, - int collector_index=-1, int frame_number=-1); - virtual ~GtkStatsFlameGraph(); - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void on_click_label(int collector_index); - virtual void on_enter_label(int collector_index); - virtual void on_leave_label(int collector_index); - -protected: - virtual void normal_guide_bars(); - - void clear_region(); - virtual void begin_draw(); - virtual void draw_bar(int depth, int from_x, int to_x, - int collector_index, int parent_index); - virtual void end_draw(); - virtual void idle(); - - virtual bool animate(double time, double dt); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual void additional_graph_window_paint(cairo_t *cr); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - - virtual gboolean handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual gboolean handle_button_release(int graph_x, int graph_y); - virtual gboolean handle_motion(int graph_x, int graph_y); - virtual gboolean handle_leave(); - -private: - int pixel_to_depth(int y) const; - void draw_guide_bar(cairo_t *cr, const PStatGraph::GuideBar &bar); - void draw_guide_labels(cairo_t *cr); - void draw_guide_label(cairo_t *cr, const PStatGraph::GuideBar &bar); - - static void toggled_callback(GtkToggleButton *button, gpointer data); - static gboolean draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data); - static gboolean scroll_callback(GtkWidget *widget, GdkEventScroll *event, gpointer data); - static gboolean key_press_callback(GtkWidget *widget, GdkEventKey *event, gpointer data); - -private: - std::string _net_value_text; - - GtkWidget *_top_hbox; - GtkWidget *_average_check_box; - GtkWidget *_total_label; - - int _popup_index = -1; -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsGraph.cxx b/pandatool/src/gtk-stats/gtkStatsGraph.cxx deleted file mode 100644 index 794f4cea..00000000 --- a/pandatool/src/gtk-stats/gtkStatsGraph.cxx +++ /dev/null @@ -1,702 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsGraph.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsGraph.h" -#include "gtkStatsMonitor.h" -#include "gtkStatsLabelStack.h" -#include "convert_srgb.h" - -const double GtkStatsGraph::rgb_light_gray[3] = { - 0x9a / (double)0xff, 0x9a / (double)0xff, 0x9a / (double)0xff, -}; -const double GtkStatsGraph::rgb_dark_gray[3] = { - 0x33 / (double)0xff, 0x33 / (double)0xff, 0x33 / (double)0xff, -}; -const double GtkStatsGraph::rgb_user_guide_bar[3] = { - 0x82 / (double)0xff, 0x96 / (double)0xff, 0xff / (double)0xff, -}; - -/** - * - */ -GtkStatsGraph:: -GtkStatsGraph(GtkStatsMonitor *monitor, bool has_label_stack) : - _monitor(monitor) -{ - GtkWidget *parent_window = monitor->get_window(); - - GdkWindow *window = gtk_widget_get_window(parent_window); - GdkDisplay *display = gdk_window_get_display(window); - _hand_cursor = gdk_cursor_new_for_display(display, GDK_HAND2); - - int scale = gdk_window_get_scale_factor(window); - _pixel_scale = scale * monitor->get_resolution() * 4 / 96; - - _cr_surface = nullptr; - _cr = nullptr; - _cr_scale = scale; - _pango_attrs = nullptr; - - _surface_xsize = 0; - _surface_ysize = 0; - - _window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_type_hint(GTK_WINDOW(_window), GDK_WINDOW_TYPE_HINT_UTILITY); - //gtk_window_set_transient_for(GTK_WINDOW(_window), GTK_WINDOW(parent_window)); - //gtk_window_set_position(GTK_WINDOW(_window), GTK_WIN_POS_CENTER_ON_PARENT); - - gtk_window_add_accel_group(GTK_WINDOW(_window), monitor->get_accel_group()); - - gtk_widget_add_events(_window, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK); - g_signal_connect(G_OBJECT(_window), "delete_event", - G_CALLBACK(window_delete_event), this); - g_signal_connect(G_OBJECT(_window), "destroy", - G_CALLBACK(window_destroy), this); - //g_signal_connect(G_OBJECT(_window), "button_press_event", - // G_CALLBACK(button_press_event_callback), this); - //g_signal_connect(G_OBJECT(_window), "button_release_event", - // G_CALLBACK(button_release_event_callback), this); - //g_signal_connect(G_OBJECT(_window), "motion_notify_event", - // G_CALLBACK(motion_notify_event_callback), this); - - _graph_window = gtk_drawing_area_new(); - gtk_widget_add_events(_graph_window, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); - g_signal_connect(G_OBJECT(_graph_window), "draw", - G_CALLBACK(graph_draw_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "configure_event", - G_CALLBACK(configure_graph_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "button_press_event", - G_CALLBACK(button_press_event_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "button_release_event", - G_CALLBACK(button_release_event_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "motion_notify_event", - G_CALLBACK(motion_notify_event_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "leave_notify_event", - G_CALLBACK(leave_notify_event_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "query-tooltip", - G_CALLBACK(query_tooltip_callback), this); - - gtk_widget_set_has_tooltip(_graph_window, TRUE); - - // A Frame to hold the graph. - _graph_frame = gtk_frame_new(nullptr); - gtk_frame_set_shadow_type(GTK_FRAME(_graph_frame), GTK_SHADOW_IN); - gtk_container_add(GTK_CONTAINER(_graph_frame), _graph_window); - - // A VBox to hold the graph's frame, and any numbers (scale legend? total?) - // above it. - _graph_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - gtk_box_pack_end(GTK_BOX(_graph_vbox), _graph_frame, TRUE, TRUE, 0); - - // An HBox to hold the graph's frame, and the scale legend to the right of - // it. - _graph_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_box_pack_start(GTK_BOX(_graph_hbox), _graph_vbox, TRUE, TRUE, 0); - - // An HPaned to hold the label stack and the graph hbox. - if (has_label_stack) { - _hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); - gtk_paned_set_wide_handle(GTK_PANED(_hpaned), TRUE); - gtk_container_add(GTK_CONTAINER(_window), _hpaned); - gtk_container_set_border_width(GTK_CONTAINER(_window), 8); - - gtk_paned_pack1(GTK_PANED(_hpaned), _label_stack.get_widget(), FALSE, FALSE); - gtk_paned_pack2(GTK_PANED(_hpaned), _graph_hbox, TRUE, TRUE); - } - else { - gtk_container_add(GTK_CONTAINER(_window), _graph_hbox); - } - - _drag_mode = DM_none; - _potential_drag_mode = DM_none; - _drag_scale_start = 0.0f; - - _pause = false; -} - -/** - * - */ -GtkStatsGraph:: -~GtkStatsGraph() { - if (_timer_id != 0) { - gtk_widget_remove_tick_callback(_graph_window, _timer_id); - _timer_id = 0; - } - - _monitor = nullptr; - release_surface(); - - for (auto &item : _brushes) { - cairo_pattern_destroy(item.second.first); - cairo_pattern_destroy(item.second.second); - } - _brushes.clear(); - _text_colors.clear(); - - _label_stack.clear_labels(); - - if (_pango_attrs != nullptr) { - pango_attr_list_unref(_pango_attrs); - _pango_attrs = nullptr; - } - - if (_window != nullptr) { - GtkWidget *window = _window; - _window = nullptr; - gtk_widget_destroy(window); - } -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void GtkStatsGraph:: -new_collector(int new_collector) { -} - -/** - * Called whenever new data arrives. - */ -void GtkStatsGraph:: -new_data(int thread_index, int frame_number) { -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void GtkStatsGraph:: -changed_graph_size(int graph_xsize, int graph_ysize) { -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void GtkStatsGraph:: -set_time_units(int unit_mask) { -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speed for the graph to the indicated value. - */ -void GtkStatsGraph:: -set_scroll_speed(double scroll_speed) { -} - -/** - * Changes the pause flag for the graph. When this flag is true, the graph - * does not update in response to new data. - */ -void GtkStatsGraph:: -set_pause(bool pause) { - _pause = pause; -} - -/** - * Called when the user guide bars have been changed. - */ -void GtkStatsGraph:: -user_guide_bars_changed() { - if (_scale_area != nullptr) { - gtk_widget_queue_draw(_scale_area); - } - gtk_widget_queue_draw(_graph_window); -} - -/** - * Called when the user single-clicks on a label. - */ -void GtkStatsGraph:: -on_click_label(int collector_index) { -} - -/** - * Called when a pop-up menu should be shown for the label. - */ -void GtkStatsGraph:: -on_popup_label(int collector_index) { -} - -/** - * Called when the user hovers the mouse over a label. - */ -void GtkStatsGraph:: -on_enter_label(int collector_index) { - if (collector_index != _highlighted_index) { - _highlighted_index = collector_index; - force_redraw(); - } -} - -/** - * Called when the user's mouse cursor leaves a label. - */ -void GtkStatsGraph:: -on_leave_label(int collector_index) { - if (collector_index == _highlighted_index && collector_index != -1) { - _highlighted_index = -1; - force_redraw(); - } -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsGraph:: -get_label_tooltip(int collector_index) const { - return std::string(); -} - -/** - * Should be called when the user closes the associated window. This tells - * the monitor to remove the graph. - */ -void GtkStatsGraph:: -close() { - _label_stack.clear_labels(false); - if (_window != nullptr) { - _window = nullptr; - - GtkStatsMonitor *monitor = _monitor; - _monitor = nullptr; - if (monitor != nullptr) { - monitor->remove_graph(this); - } - } -} - -/** - * Turns on the animation timer, if it hasn't already been turned on. - */ -void GtkStatsGraph:: -start_animation() { - if (_timer_id != 0) { - return; - } - - _time = 0; - _timer_id = gtk_widget_add_tick_callback(_graph_window, tick_callback, - this, nullptr); -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool GtkStatsGraph:: -animate(double time, double dt) { - return false; -} - -/** - * Returns the current window dimensions. - */ -void GtkStatsGraph:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - GtkWindow *window = GTK_WINDOW(_window); - gtk_window_get_position(window, &x, &y); - gtk_window_get_size(window, &width, &height); - maximized = gtk_window_is_maximized(window); - minimized = false; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void GtkStatsGraph:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - GtkWindow *window = GTK_WINDOW(_window); - gtk_window_move(window, x, y); - gtk_window_resize(window, width, height); - if (maximized) { - gtk_window_maximize(window); - } - if (minimized) { - gtk_window_iconify(window); - } -} - -/** - * Returns a pattern suitable for drawing in the indicated collector's color. - */ -cairo_pattern_t *GtkStatsGraph:: -get_collector_pattern(int collector_index, bool highlight) { - Brushes::iterator bi; - bi = _brushes.find(collector_index); - if (bi != _brushes.end()) { - return highlight ? (*bi).second.second : (*bi).second.first; - } - - // Ask the monitor what color this guy should be. - LRGBColor rgb = _monitor->get_collector_color(collector_index); - cairo_pattern_t *pattern = cairo_pattern_create_rgb( - encode_sRGB_float((float)rgb[0]), - encode_sRGB_float((float)rgb[1]), - encode_sRGB_float((float)rgb[2])); - cairo_pattern_t *hpattern = cairo_pattern_create_rgb( - encode_sRGB_float((float)rgb[0] * 0.75f), - encode_sRGB_float((float)rgb[1] * 0.75f), - encode_sRGB_float((float)rgb[2] * 0.75f)); - - _brushes[collector_index] = std::make_pair(pattern, hpattern); - return highlight ? hpattern : pattern; -} - -/** - * Returns a text color suitable for the given collector. - */ -LRGBColor GtkStatsGraph:: -get_collector_text_color(int collector_index, bool highlight) { - TextColors::iterator tci; - tci = _text_colors.find(collector_index); - if (tci != _text_colors.end()) { - return highlight ? (*tci).second.second : (*tci).second.first; - } - - LRGBColor rgb = _monitor->get_collector_color(collector_index); - double bright = - rgb[0] * 0.2126 + - rgb[1] * 0.7152 + - rgb[2] * 0.0722; - LRGBColor color = bright >= 0.5 ? LRGBColor(0) : LRGBColor(1); - LRGBColor hcolor = bright * 0.75 >= 0.5 ? LRGBColor(0) : LRGBColor(1); - - _text_colors[collector_index] = std::make_pair(color, hcolor); - return highlight ? hcolor : color; -} - -/** - * Called when the given collector has changed colors. - */ -void GtkStatsGraph:: -reset_collector_color(int collector_index) { - _brushes.erase(collector_index); - _text_colors.erase(collector_index); - force_redraw(); - _label_stack.update_label_color(collector_index); -} - -/** - * This is called during the servicing of the draw event; it gives a derived - * class opportunity to do some further painting into the graph window. - */ -void GtkStatsGraph:: -additional_graph_window_paint(cairo_t *cr) { -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsGraph:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return std::string(); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -GtkStatsGraph::DragMode GtkStatsGraph:: -consider_drag_start(int graph_x, int graph_y) { - return DM_none; -} - -/** - * This should be called whenever the drag mode needs to change state. It - * provides hooks for a derived class to do something special. - */ -void GtkStatsGraph:: -set_drag_mode(GtkStatsGraph::DragMode drag_mode) { - _drag_mode = drag_mode; -} - -/** - * Called when the mouse button is depressed within the window, or any nested - * window. - */ -gboolean GtkStatsGraph:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (_potential_drag_mode != DM_none && button == 1) { - set_drag_mode(_potential_drag_mode); - _drag_start_x = graph_x; - _drag_start_y = graph_y; - // SetCapture(_window); - } - return TRUE; -} - -/** - * Called when the mouse button is released within the window, or any nested - * window. - */ -gboolean GtkStatsGraph:: -handle_button_release(int graph_x, int graph_y) { - set_drag_mode(DM_none); - // ReleaseCapture(); - - return handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the window, or any nested window. - */ -gboolean GtkStatsGraph:: -handle_motion(int graph_x, int graph_y) { - _potential_drag_mode = consider_drag_start(graph_x, graph_y); - - GdkWindow *window = gtk_widget_get_window(_window); - - if (_potential_drag_mode == DM_guide_bar || - _drag_mode == DM_guide_bar) { - gdk_window_set_cursor(window, _hand_cursor); - } - else { - gdk_window_set_cursor(window, nullptr); - } - - return TRUE; -} - -/** - * Called when the mouse has left the graph window. - */ -gboolean GtkStatsGraph:: -handle_leave() { - return FALSE; -} - -/** - * Sets up a backing-store bitmap of the indicated size. - */ -void GtkStatsGraph:: -setup_surface(int xsize, int ysize, int scale) { - release_surface(); - - _surface_xsize = xsize; - _surface_ysize = ysize; - _pixel_scale = scale * _monitor->get_resolution() * 4 / 96; - - GdkWindow *window = gtk_widget_get_window(_graph_window); - _cr_surface = gdk_window_create_similar_image_surface(window, CAIRO_FORMAT_RGB24, _surface_xsize, _surface_ysize, 1); - _cr = cairo_create(_cr_surface); - _cr_scale = scale; - - cairo_set_source_rgb(_cr, 1.0, 1.0, 1.0); - cairo_paint(_cr); - - // Cache the font scale attribute. - _pango_attrs = pango_attr_list_new(); - PangoAttribute *attr = pango_attr_scale_new(scale * 0.9); - attr->start_index = 0; - attr->end_index = -1; - pango_attr_list_insert(_pango_attrs, attr); -} - -/** - * Frees the backing-store bitmap created by setup_surface(). - */ -void GtkStatsGraph:: -release_surface() { - if (_cr_surface != nullptr) { - cairo_surface_destroy(_cr_surface); - cairo_destroy(_cr); - _cr_surface = nullptr; - _cr = nullptr; - } - - if (_pango_attrs != nullptr) { - pango_attr_list_unref(_pango_attrs); - _pango_attrs = nullptr; - } -} - -/** - * Callback when the window is closed by the user. - */ -gboolean GtkStatsGraph:: -window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { - // Returning FALSE to indicate we should destroy the window when the user - // selects "close". - return FALSE; -} - -/** - * Callback when the window is destroyed by the system (or by delete_event). - */ -void GtkStatsGraph:: -window_destroy(GtkWidget *widget, gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - self->close(); -} - -/** - * Fills in the graph window. - */ -gboolean GtkStatsGraph:: -graph_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - - if (self->_cr_surface != nullptr) { - double scale = 1.0 / self->_cr_scale; - cairo_scale(cr, scale, scale); - cairo_set_source_surface(cr, self->_cr_surface, 0, 0); - cairo_paint(cr); - } - - self->additional_graph_window_paint(cr); - - return TRUE; -} - -/** - * Changes the size of the graph window - */ -gboolean GtkStatsGraph:: -configure_graph_callback(GtkWidget *widget, GdkEventConfigure *event, - gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - - GdkWindow *window = gtk_widget_get_window(widget); - int scale = gdk_window_get_scale_factor(window); - int scaled_xsize = std::max(event->width * scale, 0); - int scaled_ysize = std::max(event->height * scale, 0); - - if (self->_cr == nullptr || - self->_cr_scale != scale || - self->_surface_xsize != scaled_xsize || - self->_surface_ysize != scaled_ysize) { - self->setup_surface(scaled_xsize, scaled_ysize, scale); - self->changed_graph_size(scaled_xsize, scaled_ysize); - } - - return TRUE; -} - -/** - * Called when the mouse button is depressed within the graph window or main - * window. - */ -gboolean GtkStatsGraph:: -button_press_event_callback(GtkWidget *widget, GdkEventButton *event, - gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - int graph_x, graph_y; - gtk_widget_translate_coordinates(widget, self->_graph_window, - (int)event->x, (int)event->y, - &graph_x, &graph_y); - graph_x *= self->_cr_scale; - graph_y *= self->_cr_scale; - - bool double_click = (event->type == GDK_2BUTTON_PRESS); - - return self->handle_button_press(graph_x, graph_y, - double_click, event->button); -} - -/** - * Called when the mouse button is released within the graph window or main - * window. - */ -gboolean GtkStatsGraph:: -button_release_event_callback(GtkWidget *widget, GdkEventButton *event, - gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - int graph_x, graph_y; - gtk_widget_translate_coordinates(widget, self->_graph_window, - (int)event->x, (int)event->y, - &graph_x, &graph_y); - graph_x *= self->_cr_scale; - graph_y *= self->_cr_scale; - - return self->handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window or main window. - */ -gboolean GtkStatsGraph:: -motion_notify_event_callback(GtkWidget *widget, GdkEventMotion *event, - gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - int graph_x, graph_y; - gtk_widget_translate_coordinates(widget, self->_graph_window, - (int)event->x, (int)event->y, - &graph_x, &graph_y); - graph_x *= self->_cr_scale; - graph_y *= self->_cr_scale; - - return self->handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -gboolean GtkStatsGraph:: -leave_notify_event_callback(GtkWidget *widget, GdkEventCrossing *event, - gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - return self->handle_leave(); -} - -/** - * Called when a tooltip should be displayed. - */ -gboolean GtkStatsGraph:: -query_tooltip_callback(GtkWidget *widget, gint x, gint y, - gboolean keyboard_tip, GtkTooltip *tooltip, - gpointer data) { - GtkStatsGraph *self = (GtkStatsGraph *)data; - x *= self->_cr_scale; - y *= self->_cr_scale; - - std::string text = self->get_graph_tooltip(x, y); - gtk_tooltip_set_text(tooltip, text.c_str()); - return !text.empty(); -} - -/** - * Called to update the animations. - */ -gboolean GtkStatsGraph:: -tick_callback(GtkWidget *widget, GdkFrameClock *clock, gpointer data) { - GtkStatsGraph *graph = (GtkStatsGraph *)data; - gint64 new_time = gdk_frame_clock_get_frame_time(clock); - if (graph->_time == 0) { - // First frame, so we don't have a dt yet. - graph->_time = new_time; - return TRUE; - } - gint64 delta = new_time - graph->_time; - if (delta == 0) { - return TRUE; - } - if (graph->animate(new_time / 1000000.0, delta / 1000000.0)) { - graph->_time = new_time; - return TRUE; - } else { - graph->_timer_id = 0; - return FALSE; - } -} diff --git a/pandatool/src/gtk-stats/gtkStatsGraph.h b/pandatool/src/gtk-stats/gtkStatsGraph.h deleted file mode 100644 index bd2f3339..00000000 --- a/pandatool/src/gtk-stats/gtkStatsGraph.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsGraph.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSGRAPH_H -#define GTKSTATSGRAPH_H - -#include "pandatoolbase.h" -#include "gtkStatsLabelStack.h" -#include "pmap.h" -#include "luse.h" - -#include -#include - -class GtkStatsMonitor; - -/** - * This is just an abstract base class to provide a common pointer type for - * the various kinds of graphs that may be created for a GtkStatsMonitor. - */ -class GtkStatsGraph { -public: - // What is the user adjusting by dragging the mouse in a window? - enum DragMode { - DM_none, - DM_scale, - DM_guide_bar, - DM_new_guide_bar, - DM_sizing, - DM_pan, - }; - -public: - GtkStatsGraph(GtkStatsMonitor *monitor, bool has_label_stack); - virtual ~GtkStatsGraph(); - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw()=0; - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void set_scroll_speed(double scroll_speed); - void set_pause(bool pause); - - void user_guide_bars_changed(); - virtual void on_click_label(int collector_index); - virtual void on_popup_label(int collector_index); - virtual void on_enter_label(int collector_index); - virtual void on_leave_label(int collector_index); - virtual std::string get_label_tooltip(int collector_index) const; - - void reset_collector_color(int collector_index); - -protected: - void close(); - - void start_animation(); - virtual bool animate(double time, double dt); - - void get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - cairo_pattern_t *get_collector_pattern(int collector_index, bool highlight = false); - LRGBColor get_collector_text_color(int collector_index, bool highlight = false); - - virtual void additional_graph_window_paint(cairo_t *cr); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - virtual void set_drag_mode(DragMode drag_mode); - - virtual gboolean handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual gboolean handle_button_release(int graph_x, int graph_y); - virtual gboolean handle_motion(int graph_x, int graph_y); - virtual gboolean handle_leave(); - -protected: - // Table of patterns for our various collectors. - typedef pmap > Brushes; - Brushes _brushes; - - typedef pmap > TextColors; - TextColors _text_colors; - - GtkStatsMonitor *_monitor; - GtkWidget *_parent_window = nullptr; - GtkWidget *_window = nullptr; - GtkWidget *_graph_frame; - GtkWidget *_graph_window = nullptr; - GtkWidget *_graph_hbox; - GtkWidget *_graph_vbox; - GtkWidget *_hpaned; - GtkWidget *_scale_area = nullptr; - GtkStatsLabelStack _label_stack; - - GdkCursor *_hand_cursor; - - cairo_surface_t *_cr_surface; - cairo_t *_cr; - int _surface_xsize, _surface_ysize; - PangoAttrList *_pango_attrs; - int _cr_scale; - int _pixel_scale; - - DragMode _drag_mode; - DragMode _potential_drag_mode; - int _drag_start_x, _drag_start_y; - double _drag_scale_start; - int _drag_guide_bar; - - int _highlighted_index = -1; - - bool _pause; - - guint _timer_id = 0; - gint64 _time = 0; - - static const double rgb_white[3]; - static const double rgb_light_gray[3]; - static const double rgb_dark_gray[3]; - static const double rgb_black[3]; - static const double rgb_user_guide_bar[3]; - -private: - void setup_surface(int xsize, int ysize, int scale); - void release_surface(); - - static gboolean window_delete_event(GtkWidget *widget, GdkEvent *event, - gpointer data); - static void window_destroy(GtkWidget *widget, gpointer data); - static gboolean graph_draw_callback(GtkWidget *widget, - cairo_t *cr, gpointer data); - static gboolean configure_graph_callback(GtkWidget *widget, - GdkEventConfigure *event, - gpointer data); - -protected: - static gboolean button_press_event_callback(GtkWidget *widget, - GdkEventButton *event, - gpointer data); - static gboolean button_release_event_callback(GtkWidget *widget, - GdkEventButton *event, - gpointer data); - static gboolean motion_notify_event_callback(GtkWidget *widget, - GdkEventMotion *event, - gpointer data); - static gboolean leave_notify_event_callback(GtkWidget *widget, - GdkEventCrossing *event, - gpointer data); - static gboolean query_tooltip_callback(GtkWidget *widget, gint x, gint y, - gboolean keyboard_tip, - GtkTooltip *tooltip, gpointer data); - static gboolean tick_callback(GtkWidget *widget, GdkFrameClock *clock, - gpointer data); -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsLabel.cxx b/pandatool/src/gtk-stats/gtkStatsLabel.cxx deleted file mode 100644 index bb766038..00000000 --- a/pandatool/src/gtk-stats/gtkStatsLabel.cxx +++ /dev/null @@ -1,283 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsLabel.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsLabel.h" -#include "gtkStatsMonitor.h" -#include "gtkStatsGraph.h" -#include "convert_srgb.h" - -int GtkStatsLabel::_left_margin = 6; -int GtkStatsLabel::_right_margin = 2; -int GtkStatsLabel::_top_margin = 1; -int GtkStatsLabel::_bottom_margin = 1; - -/** - * - */ -GtkStatsLabel:: -GtkStatsLabel(GtkStatsMonitor *monitor, GtkStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname, - bool align_right) : - _monitor(monitor), - _graph(graph), - _thread_index(thread_index), - _collector_index(collector_index), - _align_right(align_right) -{ - _widget = gtk_drawing_area_new(); - gtk_widget_add_events(_widget, - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | - GDK_BUTTON_PRESS_MASK); - g_signal_connect(G_OBJECT(_widget), "draw", - G_CALLBACK(draw_callback), this); - g_signal_connect(G_OBJECT(_widget), "enter_notify_event", - G_CALLBACK(enter_notify_event_callback), this); - g_signal_connect(G_OBJECT(_widget), "leave_notify_event", - G_CALLBACK(leave_notify_event_callback), this); - g_signal_connect(G_OBJECT(_widget), "button_press_event", - G_CALLBACK(button_press_event_callback), this); - g_signal_connect(G_OBJECT(_widget), "query-tooltip", - G_CALLBACK(query_tooltip_callback), this); - - gtk_widget_set_has_tooltip(_widget, TRUE); - - _highlight = false; - _mouse_within = false; - - update_color(); - update_text(use_fullname); - gtk_widget_show_all(_widget); -} - -/** - * - */ -GtkStatsLabel:: -~GtkStatsLabel() { - if (_layout) { - g_object_unref(_layout); - _layout = nullptr; - } -} - -/** - * Returns the widget for this label. - */ -GtkWidget *GtkStatsLabel:: -get_widget() const { - return _widget; -} - -/** - * Returns the height of the label as we requested it. - */ -int GtkStatsLabel:: -get_height() const { - return _height; -} - -/** - * Returns the collector this label represents. - */ -int GtkStatsLabel:: -get_collector_index() const { - return _collector_index; -} - -/** - * Returns the thread index. - */ -int GtkStatsLabel:: -get_thread_index() const { - return _thread_index; -} - -/** - * Enables or disables the visual highlight for this label. - */ -void GtkStatsLabel:: -set_highlight(bool highlight) { - if (_highlight != highlight) { - _highlight = highlight; - gtk_widget_queue_draw(_widget); - } -} - -/** - * Returns true if the visual highlight for this label is enabled. - */ -bool GtkStatsLabel:: -get_highlight() const { - return _highlight; -} - -/** - * Updates the colors. - */ -void GtkStatsLabel:: -update_color() { - // Set the fg and bg colors on the label. - LRGBColor rgb = _monitor->get_collector_color(_collector_index); - _bg_color = LRGBColor( - encode_sRGB_float((float)rgb[0]), - encode_sRGB_float((float)rgb[1]), - encode_sRGB_float((float)rgb[2])); - - _highlight_bg_color = LRGBColor( - encode_sRGB_float((float)rgb[0] * 0.75f), - encode_sRGB_float((float)rgb[1] * 0.75f), - encode_sRGB_float((float)rgb[2] * 0.75f)); - - // Should our foreground be black or white? - PN_stdfloat bright = _bg_color.dot(LRGBColor(0.2126, 0.7152, 0.0722)); - if (bright >= 0.5) { - _fg_color = LRGBColor(0); - } else { - _fg_color = LRGBColor(1); - } - if (bright * 0.75 >= 0.5) { - _highlight_fg_color = LRGBColor(0); - } else { - _highlight_fg_color = LRGBColor(1); - } - - gtk_widget_queue_draw(_widget); -} - -/** - * Set to true if the full name of the collector should be shown. - */ -void GtkStatsLabel:: -update_text(bool use_fullname) { - const PStatClientData *client_data = _monitor->get_client_data(); - if (use_fullname) { - _text = client_data->get_collector_fullname(_collector_index); - } else { - _text = client_data->get_collector_name(_collector_index); - } - - // Make up a PangoLayout to represent the text. - if (_layout) { - g_object_unref(_layout); - } - _layout = gtk_widget_create_pango_layout(_widget, _text.c_str()); - - // What are the extents of the text? This determines the minimum size of - // our widget. - int width, height; - pango_layout_get_pixel_size(_layout, &width, &height); - _ideal_width = width + _left_margin + _right_margin; - _height = height + _top_margin + _bottom_margin; - gtk_widget_set_size_request(_widget, _ideal_width, _height); -} - -/** - * Used internally to indicate whether the mouse is within the label's widget. - */ -void GtkStatsLabel:: -set_mouse_within(bool mouse_within) { - if (_mouse_within != mouse_within) { - _mouse_within = mouse_within; - gtk_widget_queue_draw(_widget); - } -} - -/** - * Draws the background color of the label. - */ -gboolean GtkStatsLabel:: -draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { - GtkStatsLabel *self = (GtkStatsLabel *)data; - - LRGBColor bg, fg; - if (self->_highlight || self->_mouse_within) { - bg = self->_highlight_bg_color; - fg = self->_highlight_fg_color; - } else { - bg = self->_bg_color; - fg = self->_fg_color; - - } - cairo_set_source_rgb(cr, bg[0], bg[1], bg[2]); - - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - - cairo_rectangle(cr, 0, 0, allocation.width, allocation.height); - cairo_fill(cr); - - int width, height; - pango_layout_get_pixel_size(self->_layout, &width, &height); - - cairo_set_source_rgb(cr, fg[0], fg[1], fg[2]); - if (self->_align_right) { - cairo_move_to(cr, allocation.width - width - _right_margin, _top_margin); - } else { - cairo_move_to(cr, _left_margin, _top_margin); - } - pango_cairo_show_layout(cr, self->_layout); - - return TRUE; -} - -/** - * Called when the mouse enters the label region - */ -gboolean GtkStatsLabel:: -enter_notify_event_callback(GtkWidget *widget, GdkEventCrossing *event, - gpointer data) { - GtkStatsLabel *self = (GtkStatsLabel *)data; - self->set_mouse_within(true); - return TRUE; -} - -/** - * Called when the mouse leaves the label region - */ -gboolean GtkStatsLabel:: -leave_notify_event_callback(GtkWidget *widget, GdkEventCrossing *event, - gpointer data) { - GtkStatsLabel *self = (GtkStatsLabel *)data; - self->set_mouse_within(false); - return TRUE; -} - -/** - * Called when the mouse button is depressed within the label. - */ -gboolean GtkStatsLabel:: -button_press_event_callback(GtkWidget *widget, GdkEventButton *event, - gpointer data) { - GtkStatsLabel *self = (GtkStatsLabel *)data; - if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { - self->_graph->on_click_label(self->_collector_index); - } - else if (event->type == GDK_BUTTON_PRESS && event->button == 3) { - self->_graph->on_popup_label(self->_collector_index); - } - return TRUE; -} - -/** - * Called when a tooltip should be displayed. - */ -gboolean GtkStatsLabel:: -query_tooltip_callback(GtkWidget *widget, gint x, gint y, - gboolean keyboard_tip, GtkTooltip *tooltip, - gpointer data) { - GtkStatsLabel *self = (GtkStatsLabel *)data; - - std::string text = self->_graph->get_label_tooltip(self->_collector_index); - gtk_tooltip_set_text(tooltip, text.c_str()); - return !text.empty(); -} diff --git a/pandatool/src/gtk-stats/gtkStatsLabel.h b/pandatool/src/gtk-stats/gtkStatsLabel.h deleted file mode 100644 index 3f07a4e9..00000000 --- a/pandatool/src/gtk-stats/gtkStatsLabel.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsLabel.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSLABEL_H -#define GTKSTATSLABEL_H - -#include "pandatoolbase.h" -#include "luse.h" - -#include -#include - -class GtkStatsMonitor; -class GtkStatsGraph; - -/** - * A text label that will draw in color appropriate for a particular - * collector. It also responds when the user double-clicks on it. This is - * handy for putting colored labels on strip charts. - */ -class GtkStatsLabel { -public: - GtkStatsLabel(GtkStatsMonitor *monitor, GtkStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname, - bool align_right = true); - ~GtkStatsLabel(); - - GtkWidget *get_widget() const; - int get_height() const; - - int get_collector_index() const; - int get_thread_index() const; - - void set_highlight(bool highlight); - bool get_highlight() const; - - void update_color(); - void update_text(bool use_fullname); - -private: - void set_mouse_within(bool mouse_within); - static gboolean draw_callback(GtkWidget *widget, - cairo_t *cr, gpointer data); - static gboolean enter_notify_event_callback(GtkWidget *widget, - GdkEventCrossing *event, - gpointer data); - static gboolean leave_notify_event_callback(GtkWidget *widget, - GdkEventCrossing *event, - gpointer data); - static gboolean button_press_event_callback(GtkWidget *widget, - GdkEventButton *event, - gpointer data); - static gboolean query_tooltip_callback(GtkWidget *widget, gint x, gint y, - gboolean keyboard_tip, GtkTooltip *tooltip, - gpointer data); - - GtkStatsMonitor *_monitor; - GtkStatsGraph *_graph; - int _thread_index; - int _collector_index; - std::string _text; - GtkWidget *_widget; - LRGBColor _fg_color; - LRGBColor _highlight_fg_color; - LRGBColor _bg_color; - LRGBColor _highlight_bg_color; - PangoLayout *_layout = nullptr; - - int _height; - int _ideal_width; - bool _highlight; - bool _mouse_within; - bool _align_right; - - static int _left_margin, _right_margin; - static int _top_margin, _bottom_margin; -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx b/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx deleted file mode 100644 index cc887081..00000000 --- a/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx +++ /dev/null @@ -1,143 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsLabelStack.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsLabelStack.h" -#include "gtkStatsLabel.h" -#include "pnotify.h" - -/** - * - */ -GtkStatsLabelStack:: -GtkStatsLabelStack() { - _widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - _highlight_label = -1; -} - -/** - * - */ -GtkStatsLabelStack:: -~GtkStatsLabelStack() { - clear_labels(); -} - -/** - * Returns the widget for this stack. - */ -GtkWidget *GtkStatsLabelStack:: -get_widget() const { - return _widget; -} - -/** - * Returns the y position of the indicated label's bottom edge, relative to - * the indicated target widget. - */ -int GtkStatsLabelStack:: -get_label_y(int label_index, GtkWidget *target_widget) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0); - - GtkStatsLabel *label = _labels[label_index]; - - int x, y; - gtk_widget_translate_coordinates(label->get_widget(), target_widget, - 0, 0, &x, &y); - y += label->get_height(); - return y; -} - -/** - * Returns the height of the indicated label. - */ -int GtkStatsLabelStack:: -get_label_height(int label_index) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0); - return _labels[label_index]->get_height(); -} - -/** - * Returns the collector index associated with the indicated label. - */ -int GtkStatsLabelStack:: -get_label_collector_index(int label_index) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), -1); - return _labels[label_index]->get_collector_index(); -} - -/** - * Removes the set of labels and starts a new set. - */ -void GtkStatsLabelStack:: -clear_labels(bool delete_widgets) { - for (GtkStatsLabel *label : _labels) { - if (delete_widgets) { - gtk_container_remove(GTK_CONTAINER(_widget), label->get_widget()); - } - delete label; - } - _labels.clear(); -} - -/** - * Adds a new label to the top of the stack; returns the new label index. - */ -int GtkStatsLabelStack:: -add_label(GtkStatsMonitor *monitor, GtkStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname) { - GtkStatsLabel *label = - new GtkStatsLabel(monitor, graph, thread_index, collector_index, use_fullname); - - gtk_box_pack_end(GTK_BOX(_widget), label->get_widget(), - FALSE, FALSE, 0); - - int label_index = (int)_labels.size(); - _labels.push_back(label); - - return label_index; -} - -/** - * Returns the number of labels in the stack. - */ -int GtkStatsLabelStack:: -get_num_labels() const { - return _labels.size(); -} - -/** - * Draws a highlight around the label representing the indicated collector, - * and removes the highlight from any other label. Specify -1 to remove the - * highlight from all labels. - */ -void GtkStatsLabelStack:: -highlight_label(int collector_index) { - if (_highlight_label != collector_index) { - _highlight_label = collector_index; - for (GtkStatsLabel *label : _labels) { - label->set_highlight(label->get_collector_index() == _highlight_label); - } - } -} - -/** - * Refreshes the color of the label with the given index. - */ -void GtkStatsLabelStack:: -update_label_color(int collector_index) { - for (GtkStatsLabel *label : _labels) { - if (label->get_collector_index() == collector_index) { - label->update_color(); - } - } -} diff --git a/pandatool/src/gtk-stats/gtkStatsLabelStack.h b/pandatool/src/gtk-stats/gtkStatsLabelStack.h deleted file mode 100644 index 42247239..00000000 --- a/pandatool/src/gtk-stats/gtkStatsLabelStack.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsLabelStack.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSLABELSTACK_H -#define GTKSTATSLABELSTACK_H - -#include "pandatoolbase.h" -#include "pvector.h" - -#include - -class GtkStatsLabel; -class GtkStatsMonitor; -class GtkStatsGraph; - -/** - * A widget that contains a stack of labels from bottom to top. - */ -class GtkStatsLabelStack { -public: - GtkStatsLabelStack(); - ~GtkStatsLabelStack(); - - GtkWidget *get_widget() const; - - int get_label_y(int label_index, GtkWidget *target_widget) const; - int get_label_height(int label_index) const; - int get_label_collector_index(int label_index) const; - - void clear_labels(bool delete_widgets = true); - int add_label(GtkStatsMonitor *monitor, GtkStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname); - int get_num_labels() const; - - void highlight_label(int collector_index); - void update_label_color(int collector_index); - -private: - GtkWidget *_widget; - int _highlight_label; - - typedef pvector Labels; - Labels _labels; -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.I b/pandatool/src/gtk-stats/gtkStatsMonitor.I deleted file mode 100644 index 867c4349..00000000 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.I +++ /dev/null @@ -1,47 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsMonitor.I - * @author drose - * @date 2006-01-16 - */ - -/** - * - */ -INLINE GtkStatsMonitor::MenuDef:: -MenuDef(ChartType chart_type, int thread_index, int collector_index, - int frame_number, bool show_level) : - _chart_type(chart_type), - _thread_index(thread_index), - _collector_index(collector_index), - _frame_number(frame_number), - _show_level(show_level), - _monitor(nullptr) -{ -} - -/** - * - */ -INLINE bool GtkStatsMonitor::MenuDef:: -operator < (const MenuDef &other) const { - if (_chart_type != other._chart_type) { - return _chart_type < other._chart_type; - } - if (_thread_index != other._thread_index) { - return _thread_index < other._thread_index; - } - if (_collector_index != other._collector_index) { - return _collector_index < other._collector_index; - } - if (_frame_number != other._frame_number) { - return _frame_number < other._frame_number; - } - return (int)_show_level < (int)other._show_level; -} diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx deleted file mode 100644 index 2be16d94..00000000 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx +++ /dev/null @@ -1,882 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsMonitor.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsMonitor.h" -#include "gtkStats.h" -#include "gtkStatsServer.h" -#include "gtkStatsStripChart.h" -#include "gtkStatsChartMenu.h" -#include "gtkStatsPianoRoll.h" -#include "gtkStatsFlameGraph.h" -#include "gtkStatsTimeline.h" -#include "pStatGraph.h" -#include "pStatCollectorDef.h" - -#include "convert_srgb.h" - -/** - * - */ -GtkStatsMonitor:: -GtkStatsMonitor(GtkStatsServer *server) : PStatMonitor(server) { - _window = server->get_window(); - _menu_bar = server->get_menu_bar(); - _status_bar = server->get_status_bar(); - - // These will be filled in later when the menu is created. - _scroll_speed = 0.0; - _pause = false; - _next_chart_index = 2; - - _resolution = gdk_screen_get_resolution(gdk_screen_get_default()); - setup_speed_menu(); - setup_frame_rate_label(); -} - -/** - * - */ -GtkStatsMonitor:: -~GtkStatsMonitor() { - close(); -} - -/** - * Closes all the graphs associated with this monitor. - */ -void GtkStatsMonitor:: -close() { - PStatMonitor::close(); - - remove_all_graphs(); - - for (GtkWidget *flow_box_child : _status_bar_labels) { - gtk_container_remove(GTK_CONTAINER(_status_bar), flow_box_child); - g_object_unref(flow_box_child); - } - _status_bar_collectors.clear(); - _status_bar_labels.clear(); - - if (_speed_menu_item != nullptr) { - gtk_container_remove(GTK_CONTAINER(_menu_bar), _speed_menu_item); - _speed_menu_item = nullptr; - } - - for (GtkStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->remove_from_menu_bar(_menu_bar); - delete chart_menu; - } - _chart_menus.clear(); - - if (_frame_rate_menu_item != nullptr) { - gtk_container_remove(GTK_CONTAINER(_menu_bar), _frame_rate_menu_item); - _frame_rate_menu_item = nullptr; - } - - _next_chart_index = 2; -} - -/** - * Should be redefined to return a descriptive name for the type of - * PStatsMonitor this is. - */ -std::string GtkStatsMonitor:: -get_monitor_name() { - return "GtkStats"; -} - -/** - * Called after the monitor has been fully set up. At this time, it will have - * a valid _client_data pointer, and things like is_alive() and close() will - * be meaningful. However, we may not yet know who we're connected to - * (is_client_known() may return false), and we may not know anything about - * the threads or collectors we're about to get data on. - */ -void GtkStatsMonitor:: -initialized() { -} - -/** - * Called when the "hello" message has been received from the client. At this - * time, the client's hostname and program name will be known. - */ -void GtkStatsMonitor:: -got_hello() { -} - -/** - * Like got_hello(), this is called when the "hello" message has been received - * from the client. At this time, the client's hostname and program name will - * be known. However, the client appears to be an incompatible version and - * the connection will be terminated; the monitor should issue a message to - * that effect. - */ -void GtkStatsMonitor:: -got_bad_version(int client_major, int client_minor, - int server_major, int server_minor) { - std::ostringstream str; - str << "Unable to honor connection attempt from " - << get_client_progname() << " on " << get_client_hostname() - << ": unsupported PStats version " - << client_major << "." << client_minor; - - if (server_minor == 0) { - str << " (server understands version " << server_major - << "." << server_minor << " only)."; - } else { - str << " (server understands versions " << server_major - << ".0 through " << server_major << "." << server_minor << ")."; - } - - std::string message = str.str(); - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "%s", message.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); -} - -/** - * Called whenever a new Collector definition is received from the client. - * Generally, the client will send all of its collectors over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Collector definitions midstream. - */ -void GtkStatsMonitor:: -new_collector(int collector_index) { - for (GtkStatsGraph *graph : _graphs) { - graph->new_collector(collector_index); - } -} - -/** - * Called whenever a new Thread definition is received from the client. - * Generally, the client will send all of its threads over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Thread definitions midstream. - */ -void GtkStatsMonitor:: -new_thread(int thread_index) { - GtkStatsChartMenu *chart_menu = new GtkStatsChartMenu(this, thread_index); - chart_menu->add_to_menu_bar(_menu_bar, _next_chart_index); - ++_next_chart_index; - _chart_menus.push_back(chart_menu); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void GtkStatsMonitor:: -new_data(int thread_index, int frame_number) { - PStatMonitor::new_data(thread_index, frame_number); - - for (GtkStatsGraph *graph : _graphs) { - graph->new_data(thread_index, frame_number); - } - - if (thread_index == 0) { - update_status_bar(); - } - - if (!_have_data) { - open_default_graphs(); - _have_data = true; - - // Flash the window. - gtk_window_set_urgency_hint(GTK_WINDOW(_window), TRUE); - } -} - -/** - * Called when a thread should be removed from the list of threads. - */ -void GtkStatsMonitor:: -remove_thread(int thread_index) { - for (ChartMenus::iterator it = _chart_menus.begin(); it != _chart_menus.end(); ++it) { - GtkStatsChartMenu *chart_menu = *it; - if (chart_menu->get_thread_index() == thread_index) { - chart_menu->remove_from_menu_bar(_menu_bar); - delete chart_menu; - _chart_menus.erase(it); - --_next_chart_index; - return; - } - } -} - -/** - * Called whenever the connection to the client has been lost. This is a - * permanent state change. The monitor should update its display to represent - * this, and may choose to close down automatically. - */ -void GtkStatsMonitor:: -lost_connection() { - nout << "Lost connection to " << get_client_hostname() << "\n"; -} - -/** - * If has_idle() returns true, this will be called periodically to allow the - * monitor to update its display or whatever it needs to do. - */ -void GtkStatsMonitor:: -idle() { - // Check if any of our chart menus need updating. - for (GtkStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->check_update(); - } - - // Update the frame rate label from the main thread (thread 0). - const PStatThreadData *thread_data = get_client_data()->get_thread_data(0); - double frame_rate = thread_data->get_frame_rate(); - if (frame_rate != 0.0f) { - char buffer[128]; - sprintf(buffer, "%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate); - - gtk_label_set_text(GTK_LABEL(_frame_rate_label), buffer); - - if (!_status_bar_labels.empty()) { - GtkWidget *label = gtk_bin_get_child(GTK_BIN(_status_bar_labels[0])); - gtk_label_set_text(GTK_LABEL(label), buffer); - } - } -} - -/** - * Should be redefined to return true if you want to redefine idle() and - * expect it to be called. - */ -bool GtkStatsMonitor:: -has_idle() { - return true; -} - -/** - * Called when the user guide bars have been changed. - */ -void GtkStatsMonitor:: -user_guide_bars_changed() { - for (GtkStatsGraph *graph : _graphs) { - graph->user_guide_bars_changed(); - } -} - -/** - * Returns the window handle to the monitor's window. - */ -GtkWidget *GtkStatsMonitor:: -get_window() const { - return _window; -} - -/** - * - */ -GtkAccelGroup *GtkStatsMonitor:: -get_accel_group() const { - return ((GtkStatsServer *)_server)->get_accel_group(); -} - -/** - * Returns the screen DPI. - */ -double GtkStatsMonitor:: -get_resolution() const { - return _resolution; -} - -/** - * Opens a new timeline. - */ -PStatGraph *GtkStatsMonitor:: -open_timeline() { - GtkStatsTimeline *graph = new GtkStatsTimeline(this); - add_graph(graph); - return graph; -} - -/** - * Opens a new flame graph showing the indicated data. - */ -PStatGraph *GtkStatsMonitor:: -open_flame_graph(int thread_index, int collector_index, int frame_number) { - GtkStatsFlameGraph *graph = new GtkStatsFlameGraph(this, thread_index, collector_index, frame_number); - add_graph(graph); - return graph; -} - -/** - * Opens a new strip chart showing the indicated data. - */ -PStatGraph *GtkStatsMonitor:: -open_strip_chart(int thread_index, int collector_index, bool show_level) { - GtkStatsStripChart *graph = - new GtkStatsStripChart(this, thread_index, collector_index, show_level); - add_graph(graph); - return graph; -} - -/** - * Opens a new piano roll showing the indicated data. - */ -PStatGraph *GtkStatsMonitor:: -open_piano_roll(int thread_index) { - GtkStatsPianoRoll *graph = new GtkStatsPianoRoll(this, thread_index); - add_graph(graph); - return graph; -} - -/** - * Opens a dialog to change the given collector color. - */ -void GtkStatsMonitor:: -choose_collector_color(int collector_index) { - const LRGBColor ¤t = get_collector_color(collector_index); - - GtkWidget *chooser = gtk_color_chooser_dialog_new(nullptr, GTK_WINDOW(_window)); - gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(chooser), FALSE); - - GdkRGBA rgba; - rgba.red = encode_sRGB_float((float)current[0]); - rgba.green = encode_sRGB_float((float)current[1]); - rgba.blue = encode_sRGB_float((float)current[2]); - rgba.alpha = 1.0; - gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(chooser), &rgba); - - if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK) { - gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(chooser), &rgba); - LRGBColor result( - decode_sRGB_float((float)rgba.red), - decode_sRGB_float((float)rgba.green), - decode_sRGB_float((float)rgba.blue)); - - set_collector_color(collector_index, result); - - for (GtkStatsGraph *graph : _graphs) { - graph->reset_collector_color(collector_index); - } - } - - gtk_widget_destroy(chooser); -} - -/** - * Resets the color of the given collector to the default. - */ -void GtkStatsMonitor:: -reset_collector_color(int collector_index) { - clear_collector_color(collector_index); - - for (GtkStatsGraph *graph : _graphs) { - graph->reset_collector_color(collector_index); - } -} - -/** - * Adds a new MenuDef to the monitor, or returns an existing one if there is - * already one just like it. - */ -const GtkStatsMonitor::MenuDef *GtkStatsMonitor:: -add_menu(const MenuDef &menu_def) { - std::pair result = _menus.insert(menu_def); - Menus::iterator mi = result.first; - const GtkStatsMonitor::MenuDef &new_menu_def = (*mi); - if (result.second) { - // A new MenuDef was inserted. - ((GtkStatsMonitor::MenuDef &)new_menu_def)._monitor = this; - } - return &new_menu_def; -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for all graphs to the indicated mask if - * it is a time-based graph. - */ -void GtkStatsMonitor:: -set_time_units(int unit_mask) { - for (GtkStatsGraph *graph : _graphs) { - graph->set_time_units(unit_mask); - } -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speeds for all graphs to the indicated value. - */ -void GtkStatsMonitor:: -set_scroll_speed(double scroll_speed) { - _scroll_speed = scroll_speed; - - // First, change all of the open graphs appropriately. - for (GtkStatsGraph *graph : _graphs) { - graph->set_scroll_speed(_scroll_speed); - } -} - -/** - * Called when the user selects a pause on or pause off option from the menu. - */ -void GtkStatsMonitor:: -set_pause(bool pause) { - _pause = pause; - - // First, change all of the open graphs appropriately. - for (GtkStatsGraph *graph : _graphs) { - graph->set_pause(_pause); - } -} - -/** - * Adds the newly-created graph to the list of managed graphs. - */ -void GtkStatsMonitor:: -add_graph(GtkStatsGraph *graph) { - _graphs.insert(graph); - - graph->set_time_units(((GtkStatsServer *)_server)->get_time_units()); - graph->set_scroll_speed(_scroll_speed); - graph->set_pause(_pause); -} - -/** - * Deletes the indicated graph. - */ -void GtkStatsMonitor:: -remove_graph(GtkStatsGraph *graph) { - Graphs::iterator gi = _graphs.find(graph); - if (gi != _graphs.end()) { - _graphs.erase(gi); - delete graph; - } -} - -/** - * Deletes all open graphs. - */ -void GtkStatsMonitor:: -remove_all_graphs() { - for (GtkStatsGraph *graph : _graphs) { - delete graph; - } - _graphs.clear(); -} - -/** - * Creates the "Speed" pulldown menu. - */ -void GtkStatsMonitor:: -setup_speed_menu() { - GtkWidget *menu = gtk_menu_new(); - - _speed_menu_item = gtk_menu_item_new_with_label("Speed"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(_speed_menu_item), menu); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu_bar), _speed_menu_item); - - GSList *group = nullptr; - GtkWidget *item; - item = gtk_radio_menu_item_new_with_label(group, "1"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "toggled", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))) { - GtkStatsMonitor *self = (GtkStatsMonitor *)data; - self->set_scroll_speed(1); - } - }), this); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); - - item = gtk_radio_menu_item_new_with_label(group, "2"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "toggled", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))) { - GtkStatsMonitor *self = (GtkStatsMonitor *)data; - self->set_scroll_speed(2); - } - }), this); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); - - item = gtk_radio_menu_item_new_with_label(group, "3"); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "toggled", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))) { - GtkStatsMonitor *self = (GtkStatsMonitor *)data; - self->set_scroll_speed(3); - } - }), this); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); - - item = gtk_radio_menu_item_new_with_label(group, "6"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "toggled", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))) { - GtkStatsMonitor *self = (GtkStatsMonitor *)data; - self->set_scroll_speed(6); - } - }), this); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); - - item = gtk_radio_menu_item_new_with_label(group, "12"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "toggled", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))) { - GtkStatsMonitor *self = (GtkStatsMonitor *)data; - self->set_scroll_speed(12); - } - }), this); - //group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); - - item = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - - item = gtk_check_menu_item_new_with_label("pause"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - g_signal_connect(G_OBJECT(item), "toggled", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsMonitor *self = (GtkStatsMonitor *)data; - self->set_pause(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); - }), this); - - set_scroll_speed(3); - set_pause(false); - - gtk_widget_show_all(_speed_menu_item); - ++_next_chart_index; -} - -/** - * Creates the frame rate label on the right end of the menu bar. This is - * used as a text label to display the main thread's frame rate to the user, - * although it is implemented as a right-justified toplevel menu item that - * doesn't open to anything. - */ -void GtkStatsMonitor:: -setup_frame_rate_label() { - _frame_rate_menu_item = gtk_menu_item_new(); - _frame_rate_label = gtk_label_new(""); - gtk_container_add(GTK_CONTAINER(_frame_rate_menu_item), _frame_rate_label); - gtk_widget_set_sensitive(_frame_rate_menu_item, FALSE); - - gtk_widget_show(_frame_rate_menu_item); - gtk_widget_show(_frame_rate_label); - gtk_menu_item_set_right_justified(GTK_MENU_ITEM(_frame_rate_menu_item), TRUE); - - gtk_menu_shell_append(GTK_MENU_SHELL(_menu_bar), _frame_rate_menu_item); -} - -/** - * Updates the status bar. - */ -void GtkStatsMonitor:: -update_status_bar() { - const PStatClientData *client_data = get_client_data(); - if (client_data == nullptr) { - return; - } - - const PStatThreadData *thread_data = get_client_data()->get_thread_data(0); - if (thread_data == nullptr || thread_data->is_empty()) { - return; - } - int frame_number = thread_data->get_latest_frame_number(); - const PStatFrameData &frame_data = thread_data->get_latest_frame(); - - pvector collectors; - - // The first label displays the frame rate. - size_t li = 1; - collectors.push_back(0); - if (_status_bar_labels.empty()) { - // As workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2029 - // We manually create a GtkFlowBoxChild instance and attach the label to it - // and increase its reference count so it it not prematurely destroyed when - // removed from the GtkFlowBox, causing the app to segfault. - GtkWidget *label = gtk_label_new(""); - GtkWidget *flow_box_child = gtk_flow_box_child_new(); - gtk_container_add(GTK_CONTAINER(flow_box_child), label); - gtk_container_add(GTK_CONTAINER(_status_bar), flow_box_child); - _status_bar_labels.push_back(flow_box_child); - g_object_ref(flow_box_child); - } - - // Gather the top-level collector list. - int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); - for (int tc = 0; tc < num_toplevel_collectors; tc++) { - int collector = client_data->get_toplevel_collector(tc); - if (client_data->has_collector(collector) && - client_data->get_collector_has_level(collector, 0)) { - PStatView &view = get_level_view(collector, 0); - view.set_to_frame(frame_data); - double value = view.get_net_value(); - if (value == 0.0) { - // Don't include it unless we've included it before. - if (std::find(_status_bar_collectors.begin(), _status_bar_collectors.end(), collector) == _status_bar_collectors.end()) { - continue; - } - } - - // Add the value for other threads that have this collector. - for (int thread_index = 1; thread_index < client_data->get_num_threads(); ++thread_index) { - PStatView &view = get_level_view(collector, thread_index); - view.set_to_frame(frame_number); - value += view.get_net_value(); - } - - const PStatCollectorDef &def = client_data->get_collector_def(collector); - std::string text = def._name; - text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units); - - GtkWidget *flow_box_child; - GtkWidget *label; - if (li < _status_bar_labels.size()) { - flow_box_child = _status_bar_labels[li++]; - label = gtk_bin_get_child(GTK_BIN(flow_box_child)); - gtk_label_set_text(GTK_LABEL(label), text.c_str()); - } - else { - label = gtk_label_new(text.c_str()); - // See comment above - flow_box_child = gtk_flow_box_child_new(); - gtk_container_add(GTK_CONTAINER(flow_box_child), label); - gtk_container_add(GTK_CONTAINER(_status_bar), flow_box_child); - _status_bar_labels.push_back(flow_box_child); - g_object_ref(flow_box_child); - } - - collectors.push_back(collector); - } - } - - _status_bar_collectors = std::move(collectors); - - gtk_widget_show_all(_status_bar); -} - -/** - * Handles clicks on a partion of the status bar. - */ -gboolean GtkStatsMonitor:: -status_bar_button_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - GtkStatsMonitor *monitor = (GtkStatsMonitor *)data; - - GtkFlowBoxChild *child = gtk_flow_box_get_child_at_pos( - GTK_FLOW_BOX(monitor->_status_bar), event->x, event->y); - if (child == nullptr) { - return FALSE; - } - - // Which child is this? - GList *children = gtk_container_get_children(GTK_CONTAINER(monitor->_status_bar)); - int index = g_list_index(children, child); - g_list_free(children); - if (index < 0 || (size_t)index >= monitor->_status_bar_labels.size()) { - return FALSE; - } - - const PStatClientData *client_data = monitor->get_client_data(); - if (client_data == nullptr) { - return FALSE; - } - - int collector = monitor->_status_bar_collectors[index]; - - if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { - monitor->open_strip_chart(0, collector, collector != 0); - - // Also open a strip chart for other threads with data for this - // collector. - if (collector != 0) { - for (int thread_index = 1; thread_index < client_data->get_num_threads(); ++thread_index) { - PStatView &view = monitor->get_level_view(collector, thread_index); - if (view.get_net_value() > 0.0) { - monitor->open_strip_chart(thread_index, collector, true); - } - } - } - return TRUE; - } - else if (event->type == GDK_BUTTON_PRESS && event->button == 3 && index > 0) { - PStatView &level_view = monitor->get_level_view(collector, 0); - const PStatViewLevel *view_level = level_view.get_top_level(); - int num_children = view_level->get_num_children(); - if (num_children == 0) { - return FALSE; - } - - GtkWidget *menu = gtk_menu_new(); - - // Reverse the order since the menus are listed from the top down; we want - // to be visually consistent with the graphs, which list these labels from - // the bottom up. - for (int c = num_children - 1; c >= 0; c--) { - const PStatViewLevel *child_level = view_level->get_child(c); - - int child_collector = child_level->get_collector(); - const MenuDef *menu_def = monitor->add_menu({CT_strip_chart, 0, child_collector, -1, true}); - - double value = child_level->get_net_value(); - - const PStatCollectorDef &def = client_data->get_collector_def(child_collector); - std::string text = def._name; - text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units); - - GtkWidget *menu_item = gtk_menu_item_new_with_label(text.c_str()); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(menu_activate), - (void *)menu_def); - } - - gtk_widget_show_all(menu); - - GtkWidget *flow_box_child = monitor->_status_bar_labels[index]; - GtkWidget *label = gtk_bin_get_child(GTK_BIN(flow_box_child)); - gtk_menu_popup_at_widget(GTK_MENU(menu), label, - GDK_GRAVITY_NORTH_WEST, - GDK_GRAVITY_SOUTH_WEST, nullptr); - return TRUE; - } - return FALSE; -} - -/** - * Callback when a menu item is selected. - */ -void GtkStatsMonitor:: -menu_activate(GtkWidget *widget, gpointer data) { - const MenuDef &menu_def = *(const MenuDef *)data; - GtkStatsMonitor *monitor = menu_def._monitor; - - if (monitor == nullptr) { - return; - } - - switch (menu_def._chart_type) { - case CT_timeline: - monitor->open_timeline(); - break; - - case CT_strip_chart: - monitor->open_strip_chart(menu_def._thread_index, - menu_def._collector_index, - menu_def._show_level); - break; - - case CT_flame_graph: - monitor->open_flame_graph(menu_def._thread_index, - menu_def._collector_index, - menu_def._frame_number); - break; - - case CT_piano_roll: - monitor->open_piano_roll(menu_def._thread_index); - break; - - case CT_choose_color: - monitor->choose_collector_color(menu_def._collector_index); - break; - - case CT_reset_color: - monitor->reset_collector_color(menu_def._collector_index); - break; - } -} - -/** - * Called when a status bar item is double-clicked. - */ -void GtkStatsMonitor:: -handle_status_bar_click(int item) { - if (item == 0) { - open_strip_chart(0, 0, false); - } - else if (item >= 1 && (size_t)item < _status_bar_collectors.size()) { - int collector = _status_bar_collectors[item]; - open_strip_chart(0, collector, true); - - // Also open a strip chart for other threads with data for this - // collector. - const PStatClientData *client_data = get_client_data(); - for (int thread_index = 1; thread_index < client_data->get_num_threads(); ++thread_index) { - PStatView &view = get_level_view(collector, thread_index); - if (view.get_net_value() > 0.0) { - open_strip_chart(thread_index, collector, true); - } - } - } -} - -/** - * Called when a status bar item is right-clicked. - */ -void GtkStatsMonitor:: -handle_status_bar_popup(int item) { - if (item >= 0 && (size_t)item < _status_bar_collectors.size()) { - int collector = _status_bar_collectors[item]; - - PStatView &level_view = get_level_view(collector, 0); - const PStatViewLevel *view_level = level_view.get_top_level(); - int num_children = view_level->get_num_children(); - if (num_children == 0) { - return; - } - - GtkWidget *menu = gtk_menu_new(); - - // Reverse the order since the menus are listed from the top down; we want - // to be visually consistent with the graphs, which list these labels from - // the bottom up. - const PStatClientData *client_data = get_client_data(); - for (int c = num_children - 1; c >= 0; c--) { - const PStatViewLevel *child_level = view_level->get_child(c); - - int child_collector = child_level->get_collector(); - const MenuDef *menu_def = add_menu({CT_strip_chart, 0, child_collector, -1, true}); - - double value = child_level->get_net_value(); - - const PStatCollectorDef &def = client_data->get_collector_def(child_collector); - std::string text = def._name; - text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units); - - GtkWidget *menu_item = gtk_menu_item_new_with_label(text.c_str()); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(menu_activate), - (void *)menu_def); - } - - gtk_widget_show_all(menu); - - GtkWidget *flow_box_child = _status_bar_labels[item]; - GtkWidget *label = gtk_bin_get_child(GTK_BIN(flow_box_child)); - gtk_menu_popup_at_widget(GTK_MENU(menu), label, - GDK_GRAVITY_NORTH_WEST, - GDK_GRAVITY_SOUTH_WEST, nullptr); - - } -} diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.h b/pandatool/src/gtk-stats/gtkStatsMonitor.h deleted file mode 100644 index 3ac15aba..00000000 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.h +++ /dev/null @@ -1,148 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsMonitor.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSMONITOR_H -#define GTKSTATSMONITOR_H - -#include "pandatoolbase.h" - -#include "pStatMonitor.h" -#include "pointerTo.h" -#include "pset.h" -#include "pvector.h" -#include "pmap.h" - -#include - -class GtkStatsGraph; -class GtkStatsServer; -class GtkStatsChartMenu; - -/** - * This class represents a connection to a PStatsClient and manages the data - * exchange with the client. - */ -class GtkStatsMonitor : public PStatMonitor { -public: - enum ChartType { - CT_timeline, - CT_strip_chart, - CT_flame_graph, - CT_piano_roll, - - CT_choose_color, - CT_reset_color, - }; - - class MenuDef { - public: - INLINE MenuDef(ChartType chart_type, int thread_index, int collector_index, - int frame_number = -1, bool show_level = false); - INLINE bool operator < (const MenuDef &other) const; - - ChartType _chart_type; - int _thread_index; - int _collector_index; - int _frame_number; - bool _show_level; - GtkStatsMonitor *_monitor; - }; - - GtkStatsMonitor(GtkStatsServer *server); - virtual ~GtkStatsMonitor(); - - void close(); - - virtual std::string get_monitor_name(); - - virtual void initialized(); - virtual void got_hello(); - virtual void got_bad_version(int client_major, int client_minor, - int server_major, int server_minor); - virtual void new_collector(int collector_index); - virtual void new_thread(int thread_index); - virtual void new_data(int thread_index, int frame_number); - virtual void remove_thread(int thread_index); - virtual void lost_connection(); - virtual void idle(); - virtual bool has_idle(); - - virtual void user_guide_bars_changed(); - - GtkWidget *get_window() const; - GtkAccelGroup *get_accel_group() const; - double get_resolution() const; - - PStatGraph *open_timeline(); - PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); - PStatGraph *open_piano_roll(int thread_index); - - void choose_collector_color(int collector_index); - void reset_collector_color(int collector_index); - - const MenuDef *add_menu(const MenuDef &menu_def); - - void set_time_units(int unit_mask); - void set_scroll_speed(double scroll_speed); - void set_pause(bool pause); - - void add_graph(GtkStatsGraph *graph); - void remove_graph(GtkStatsGraph *graph); - void remove_all_graphs(); - -private: - void setup_speed_menu(); - void setup_frame_rate_label(); - void update_status_bar(); - - static gboolean status_bar_button_event(GtkWidget *widget, - GdkEventButton *event, - gpointer data); -public: - static void menu_activate(GtkWidget *widget, gpointer data); - void handle_status_bar_click(int item); - void handle_status_bar_popup(int item); - -private: - typedef pset Graphs; - Graphs _graphs; - - typedef pvector ChartMenus; - ChartMenus _chart_menus; - - typedef pset Menus; - Menus _menus; - - GtkWidget *_window; - GtkWidget *_menu_bar; - GtkWidget *_speed_menu_item = nullptr; - int _next_chart_index; - GtkWidget *_frame_rate_menu_item = nullptr; - GtkWidget *_frame_rate_label; - GtkWidget *_status_bar; - pvector _status_bar_collectors; - pvector _status_bar_labels; - std::string _window_title; - double _scroll_speed; - bool _pause; - bool _have_data = false; - double _resolution; - - friend class GtkStatsGraph; - friend class GtkStatsServer; -}; - -#include "gtkStatsMonitor.I" - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx b/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx deleted file mode 100644 index da5e6b36..00000000 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx +++ /dev/null @@ -1,642 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsPianoRoll.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsPianoRoll.h" -#include "gtkStatsMonitor.h" -#include "numeric_types.h" -#include "gtkStatsLabelStack.h" - -static const int default_piano_roll_width = 800; -static const int default_piano_roll_height = 400; - -/** - * - */ -GtkStatsPianoRoll:: -GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index) : - PStatPianoRoll(monitor, thread_index, 0, 0), - GtkStatsGraph(monitor, true) -{ - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - // Add a DrawingArea widget on top of the graph, to display all of the scale - // units. - _scale_area = gtk_drawing_area_new(); - g_signal_connect(G_OBJECT(_scale_area), "draw", - G_CALLBACK(draw_callback), this); - gtk_box_pack_start(GTK_BOX(_graph_vbox), _scale_area, FALSE, FALSE, 0); - - // It should be large enough to display the labels. - { - PangoLayout *layout = gtk_widget_create_pango_layout(_scale_area, "0123456789 ms"); - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - gtk_widget_set_size_request(_scale_area, 0, height + 1); - g_object_unref(layout); - } - - gtk_widget_set_size_request(_graph_window, - default_piano_roll_width * monitor->get_resolution() / 96, - default_piano_roll_height * monitor->get_resolution() / 96); - - const PStatClientData *client_data = - GtkStatsGraph::_monitor->get_client_data(); - std::string thread_name = client_data->get_thread_name(_thread_index); - std::string window_title = thread_name + " thread piano roll"; - gtk_window_set_title(GTK_WINDOW(_window), window_title.c_str()); - - gtk_widget_show_all(_window); - gtk_widget_show(_window); - - // Allow the window to be resized as small as the user likes. We have to do - // this after the window has been shown; otherwise, it will affect the - // window's initial size. - gtk_widget_set_size_request(_window, 0, 0); - - force_redraw(); - idle(); -} - -/** - * - */ -GtkStatsPianoRoll:: -~GtkStatsPianoRoll() { -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void GtkStatsPianoRoll:: -new_data(int thread_index, int frame_number) { - if (!_pause) { - update(); - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void GtkStatsPianoRoll:: -force_redraw() { - if (_cr) { - PStatPianoRoll::force_redraw(); - } -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void GtkStatsPianoRoll:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatPianoRoll::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void GtkStatsPianoRoll:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - gtk_widget_queue_draw(_scale_area); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void GtkStatsPianoRoll:: -on_click_label(int collector_index) { - if (collector_index >= 0) { - GtkStatsGraph::_monitor->open_strip_chart(_thread_index, collector_index, false); - } -} - -/** - * Called when the user right-clicks on a label. - */ -void GtkStatsPianoRoll:: -on_popup_label(int collector_index) { - GtkWidget *menu = gtk_menu_new(); - - std::string label = get_label_tooltip(collector_index); - if (!label.empty()) { - GtkWidget *menu_item = gtk_menu_item_new_with_label(label.c_str()); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - gtk_widget_set_sensitive(menu_item, FALSE); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_strip_chart, _thread_index, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_flame_graph, _thread_index, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - GtkWidget *menu_item = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_choose_color, -1, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_reset_color, -1, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - gtk_widget_show_all(menu); - gtk_menu_popup_at_pointer(GTK_MENU(menu), nullptr); -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsPianoRoll:: -get_label_tooltip(int collector_index) const { - return PStatPianoRoll::get_label_tooltip(collector_index); -} - -/** - * Changes the amount of time the width of the horizontal axis represents. - * This may force a redraw. - */ -void GtkStatsPianoRoll:: -set_horizontal_scale(double time_width) { - PStatPianoRoll::set_horizontal_scale(time_width); - - gtk_widget_queue_draw(_graph_window); - gtk_widget_queue_draw(_scale_area); -} - -/** - * Erases the chart area. - */ -void GtkStatsPianoRoll:: -clear_region() { - cairo_set_source_rgb(_cr, 1.0, 1.0, 1.0); - cairo_paint(_cr); -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void GtkStatsPianoRoll:: -begin_draw() { - clear_region(); - - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_bar(_cr, get_guide_bar(i)); - } -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any one row of bars. These bars correspond to the collector whose - * index is get_row_collector(row), and in the color get_row_color(row). - */ -void GtkStatsPianoRoll:: -begin_row(int row) { - int collector_index = get_label_collector(row); - cairo_set_source(_cr, get_collector_pattern(collector_index, - _highlighted_index == collector_index)); -} - -/** - * Draws a single bar on the chart. - */ -void GtkStatsPianoRoll:: -draw_bar(int row, int from_x, int to_x) { - if (row >= 0 && row < _label_stack.get_num_labels()) { - int y = _label_stack.get_label_y(row, _graph_window); - int height = _label_stack.get_label_height(row); - - cairo_rectangle(_cr, from_x, (y - height + 2) * _cr_scale, to_x - from_x, (height - 4) * _cr_scale); - cairo_fill(_cr); - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void GtkStatsPianoRoll:: -end_draw() { - gtk_widget_queue_draw(_graph_window); -} - -/** - * Called at the end of the draw cycle. - */ -void GtkStatsPianoRoll:: -idle() { - if (_labels_changed) { - update_labels(); - } -} - -/** - * Returns the current window dimensions. - */ -bool GtkStatsPianoRoll:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - GtkStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void GtkStatsPianoRoll:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - GtkStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * This is called during the servicing of the draw event; it gives a derived - * class opportunity to do some further painting into the graph window. - */ -void GtkStatsPianoRoll:: -additional_graph_window_paint(cairo_t *cr) { - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_bar(cr, get_user_guide_bar(i)); - } -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsPianoRoll:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - int collector_index = get_collector_under_pixel(mouse_x, mouse_y); - if (collector_index >= 0) { - return get_label_tooltip(collector_index); - } - return std::string(); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -GtkStatsGraph::DragMode GtkStatsPianoRoll:: -consider_drag_start(int graph_x, int graph_y) { - if (graph_y >= 0 && graph_y < get_ysize()) { - if (graph_x >= 0 && graph_x < get_xsize()) { - // See if the mouse is over a user-defined guide bar. - int x = graph_x; - double from_height = pixel_to_height(x - 2); - double to_height = pixel_to_height(x + 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else { - // The mouse is left or right of the graph; maybe create a new guide - // bar. - return DM_new_guide_bar; - } - } - - return GtkStatsGraph::consider_drag_start(graph_x, graph_y); -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -gboolean GtkStatsPianoRoll:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - int collector_index = get_collector_under_pixel(graph_x, graph_y); - if (button == 3) { - // Right-clicking on a color bar in the graph is the same as right- - // clicking on the corresponding label. - if (collector_index >= 0) { - on_popup_label(collector_index); - return TRUE; - } - return FALSE; - } - else if (double_click && button == 1) { - // Double-clicking on a color bar in the graph is the same as double- - // clicking on the corresponding label. - on_click_label(get_collector_under_pixel(graph_x, graph_y)); - return TRUE; - } - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - _drag_scale_start = pixel_to_height(graph_x); - // SetCapture(_graph_window); - return TRUE; - - } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - _drag_start_x = graph_x; - // SetCapture(_graph_window); - return TRUE; - } - - return GtkStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -gboolean GtkStatsPianoRoll:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_x < 0 || graph_x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return GtkStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -gboolean GtkStatsPianoRoll:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { - // When the mouse is over a color bar, highlight it. - int collector_index = get_collector_under_pixel(graph_x, graph_y); - _label_stack.highlight_label(collector_index); - on_enter_label(collector_index); - - /* - // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph - // window. - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - _graph_window, - 0 - }; - TrackMouseEvent(&tme); - */ - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_scale) { - double ratio = (double)graph_x / (double)get_xsize(); - if (ratio > 0.0f) { - set_horizontal_scale(_drag_scale_start / ratio); - } - return TRUE; - } - else if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - if (graph_x >= 0 && graph_x < get_xsize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_x)); - return TRUE; - } - - } else if (_drag_mode == DM_guide_bar) { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - return TRUE; - } - - return GtkStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -gboolean GtkStatsPianoRoll:: -handle_leave() { - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - return TRUE; -} - -/** - * Returns the collector index associated with the indicated vertical row, or - * -1. - */ -int GtkStatsPianoRoll:: -get_collector_under_pixel(int xpoint, int ypoint) const { - if (_label_stack.get_num_labels() == 0) { - return -1; - } - - // Assume all of the labels are the same height. - int height = _label_stack.get_label_height(0); - int row = (get_ysize() - ypoint) / (height * _cr_scale); - if (row >= 0 && row < _label_stack.get_num_labels()) { - return _label_stack.get_label_collector_index(row); - } else { - return -1; - } -} - -/** - * Resets the list of labels. - */ -void GtkStatsPianoRoll:: -update_labels() { - _label_stack.clear_labels(); - for (int i = 0; i < get_num_labels(); i++) { - _label_stack.add_label(GtkStatsGraph::_monitor, this, - _thread_index, - get_label_collector(i), true); - } - _labels_changed = false; -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void GtkStatsPianoRoll:: -draw_guide_bar(cairo_t *cr, const PStatGraph::GuideBar &bar) { - int x = height_to_pixel(bar._height); - - if (x > 0 && x < get_xsize() - 1) { - // Only draw it if it's not too close to the top. - switch (bar._style) { - case GBS_target: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_user: - cairo_set_source_rgb(cr, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2]); - break; - - default: - cairo_set_source_rgb(cr, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2]); - break; - } - cairo_move_to(cr, x, 0); - cairo_line_to(cr, x, get_ysize()); - cairo_stroke(cr); - } -} - -/** - * This is called during the servicing of the draw event. - */ -void GtkStatsPianoRoll:: -draw_guide_labels(cairo_t *cr) { - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; i++) { - draw_guide_label(cr, get_guide_bar(i)); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; i++) { - draw_guide_label(cr, get_user_guide_bar(i)); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void GtkStatsPianoRoll:: -draw_guide_label(cairo_t *cr, const PStatGraph::GuideBar &bar) { - switch (bar._style) { - case GBS_target: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_user: - cairo_set_source_rgb(cr, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2]); - break; - - default: - cairo_set_source_rgb(cr, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2]); - break; - } - - int x = height_to_pixel(bar._height); - const std::string &label = bar._label; - - PangoLayout *layout = gtk_widget_create_pango_layout(_scale_area, label.c_str()); - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(x - width * _cr_scale); - double to_height = pixel_to_height(x + width * _cr_scale); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - g_object_unref(layout); - return; - } - } - - if (x >= 0 && x < get_xsize()) { - // Now convert our x to a coordinate within our drawing area. - int junk_y; - - x /= _cr_scale; - - // The x coordinate comes from the graph_window. - gtk_widget_translate_coordinates(_graph_window, _scale_area, - x, 0, - &x, &junk_y); - - GtkAllocation allocation; - gtk_widget_get_allocation(_scale_area, &allocation); - - int this_x = x - width / 2; - cairo_move_to(cr, this_x, allocation.height - height); - pango_cairo_show_layout(cr, layout); - } - - g_object_unref(layout); -} - -/** - * Draws in the scale labels. - */ -gboolean GtkStatsPianoRoll:: -draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { - GtkStatsPianoRoll *self = (GtkStatsPianoRoll *)data; - self->draw_guide_labels(cr); - - return TRUE; -} diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.h b/pandatool/src/gtk-stats/gtkStatsPianoRoll.h deleted file mode 100644 index e3dd892d..00000000 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsPianoRoll.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSPIANOROLL_H -#define GTKSTATSPIANOROLL_H - -#include "pandatoolbase.h" - -#include "gtkStatsGraph.h" -#include "pStatPianoRoll.h" -#include "pointerTo.h" - -#include - -class GtkStatsMonitor; - -/** - * A window that draws a piano-roll style chart, which shows the collectors - * explicitly stopping and starting, one frame at a time. - */ -class GtkStatsPianoRoll final : public PStatPianoRoll, public GtkStatsGraph { -public: - GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index); - virtual ~GtkStatsPianoRoll(); - - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void on_click_label(int collector_index); - virtual void on_popup_label(int collector_index); - virtual std::string get_label_tooltip(int collector_index) const; - void set_horizontal_scale(double time_width); - -protected: - void clear_region(); - virtual void begin_draw(); - virtual void begin_row(int row); - virtual void draw_bar(int row, int from_x, int to_x); - virtual void end_draw(); - virtual void idle(); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual void additional_graph_window_paint(cairo_t *cr); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - - virtual gboolean handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual gboolean handle_button_release(int graph_x, int graph_y); - virtual gboolean handle_motion(int graph_x, int graph_y); - virtual gboolean handle_leave(); - -private: - int get_collector_under_pixel(int xpoint, int ypoint) const; - void update_labels(); - void draw_guide_bar(cairo_t *cr, const PStatGraph::GuideBar &bar); - void draw_guide_labels(cairo_t *cr); - void draw_guide_label(cairo_t *cr, const PStatGraph::GuideBar &bar); - - static gboolean draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data); -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsServer.cxx b/pandatool/src/gtk-stats/gtkStatsServer.cxx deleted file mode 100644 index 25fdba2e..00000000 --- a/pandatool/src/gtk-stats/gtkStatsServer.cxx +++ /dev/null @@ -1,766 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsServer.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsServer.h" -#include "gtkStatsMonitor.h" -#include "pandaVersion.h" -#include "pStatGraph.h" -#include "config_pstatclient.h" - -#include - -/** - * - */ -GtkStatsServer:: -GtkStatsServer() : _port(pstats_port) { - set_program_brief("GTK+3-based PStats client"); - set_program_description - ("This is a GUI-based PStats server that listens on a TCP port for a " - "connection from a PStatClient in a Panda3D application. It offers " - "various graphs for showing the timing information sent by the client." - "\n\n" - "The full documentation is available online:\n " -#ifdef HAVE_PYTHON - "https://docs.panda3d.org/" PANDA_ABI_VERSION_STR "/python/optimization/pstats" -#else - "https://docs.panda3d.org/" PANDA_ABI_VERSION_STR "/cpp/optimization/pstats" -#endif - ""); - - add_option - ("p", "port", 0, - "Specify the TCP port to listen for connections on. By default, this " - "is taken from the pstats-port Config variable.", - &ProgramBase::dispatch_int, nullptr, &_port); - - add_runline("[-p 5185]"); - add_runline("session.pstats"); - -#ifdef __APPLE__ - _last_session = Filename::expand_from( - "$HOME/Library/Caches/Panda3D-" PANDA_ABI_VERSION_STR "/last-session.pstats"); -#else - _last_session = Filename::expand_from("$XDG_STATE_HOME/panda3d/last-session.pstats"); -#endif - _last_session.set_binary(); - - create_window(); -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool GtkStatsServer:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - new_session(); - return true; - } - else if (args.size() == 1) { - Filename fn = Filename::from_os_specific(args[0]); - fn.set_binary(); - GtkStatsMonitor *monitor = new GtkStatsMonitor(this); - if (!monitor->read(fn)) { - delete monitor; - - // If we're not running from the terminal, show a GUI message box. - if (!isatty(STDERR_FILENO)) { - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Failed to load session file: %s", fn.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - } - return false; - } - _save_filename = fn; - - gtk_widget_set_sensitive(_new_session_menu_item, TRUE); - gtk_widget_set_sensitive(_save_session_menu_item, TRUE); - gtk_widget_set_sensitive(_close_session_menu_item, TRUE); - gtk_widget_set_sensitive(_export_session_menu_item, TRUE); - - _monitor = monitor; - return true; - } - else { - nout << "At most one filename may be specified on the command-line.\n"; - return false; - } -} - -/** - * - */ -PStatMonitor *GtkStatsServer:: -make_monitor(const NetAddress &address) { - // Enable the "New Session", "Save Session" and "Close Session" menu items. - gtk_widget_set_sensitive(_new_session_menu_item, TRUE); - gtk_widget_set_sensitive(_save_session_menu_item, TRUE); - gtk_widget_set_sensitive(_close_session_menu_item, TRUE); - gtk_widget_set_sensitive(_export_session_menu_item, TRUE); - - std::ostringstream strm; - strm << "PStats Server (connected to " << address << ")"; - std::string title = strm.str(); - gtk_window_set_title(GTK_WINDOW(_window), title.c_str()); - - if (_status_bar_label != nullptr) { - gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label); - g_object_unref(_status_bar_label); - _status_bar_label = nullptr; - } - - _monitor = new GtkStatsMonitor(this); - return _monitor; -} - -/** - * Called when connection has been lost. - */ -void GtkStatsServer:: -lost_connection(PStatMonitor *monitor) { - if (_monitor != nullptr && !_monitor->_have_data) { - // We didn't have any data yet. Just silently restart the session. - _monitor->close(); - _monitor = nullptr; - if (new_session()) { - return; - } - } else { - // Store a backup now, in case PStats crashes or something. - _last_session.make_dir(); - if (monitor->write(_last_session)) { - nout << "Wrote to " << _last_session << "\n"; - } else { - nout << "Failed to write to " << _last_session << "\n"; - } - } - - stop_listening(); - - gtk_window_set_title(GTK_WINDOW(_window), "PStats Server (disconnected)"); -} - -/** - * Starts a new session. - */ -bool GtkStatsServer:: -new_session() { - if (!close_session()) { - return false; - } - - if (listen(_port)) { - { - std::ostringstream strm; - strm << "PStats Server (listening on port " << _port << ")"; - std::string title = strm.str(); - gtk_window_set_title(GTK_WINDOW(_window), title.c_str()); - } - { - std::ostringstream strm; - strm << "Waiting for client to connect on port " << _port << "..."; - std::string title = strm.str(); - // As workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2029 - // We manually create a GtkFlowBoxChild instance and attach the label to it - // and increase its reference count so it it not prematurely destroyed when - // removed from the GtkFlowBox, causing the app to segfault. - GtkWidget * label = gtk_label_new(title.c_str()); - _status_bar_label = gtk_flow_box_child_new(); - gtk_container_add(GTK_CONTAINER(_status_bar_label), label); - gtk_container_add(GTK_CONTAINER(_status_bar), _status_bar_label); - gtk_widget_show(_status_bar_label); - g_object_ref(_status_bar_label); - } - - gtk_widget_set_sensitive(_new_session_menu_item, FALSE); - gtk_widget_set_sensitive(_save_session_menu_item, FALSE); - gtk_widget_set_sensitive(_close_session_menu_item, TRUE); - gtk_widget_set_sensitive(_export_session_menu_item, FALSE); - - return true; - } - - gtk_window_set_title(GTK_WINDOW(_window), "PStats Server"); - - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Unable to open port %d. Try specifying a different port number " - "using pstats-port in your Config file or the -p option on the " - "command-line.", _port); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - - return false; -} - -/** - * Offers to open an existing session. - */ -bool GtkStatsServer:: -open_session() { - if (!close_session()) { - return false; - } - - GtkFileChooserNative *native = gtk_file_chooser_native_new( - "Open Session", - GTK_WINDOW(_window), - GTK_FILE_CHOOSER_ACTION_SAVE, - "_Open", "Cancel"); - GtkFileChooser *chooser = GTK_FILE_CHOOSER(native); - - GtkFileFilter *filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, "PStats Session Files"); - gtk_file_filter_add_pattern(filter, "*.pstats"); - gtk_file_chooser_add_filter(chooser, filter); - - gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)); - if (res == GTK_RESPONSE_ACCEPT) { - char *buffer = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser)); - Filename fn = Filename::from_os_specific(buffer); - fn.set_binary(); - g_free(buffer); - g_object_unref(native); - - GtkStatsMonitor *monitor = new GtkStatsMonitor(this); - if (!monitor->read(fn)) { - delete monitor; - - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Failed to load session file: %s", fn.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - return false; - } - _save_filename = fn; - - gtk_widget_set_sensitive(_new_session_menu_item, TRUE); - gtk_widget_set_sensitive(_save_session_menu_item, TRUE); - gtk_widget_set_sensitive(_close_session_menu_item, TRUE); - gtk_widget_set_sensitive(_export_session_menu_item, TRUE); - - _monitor = monitor; - return true; - } - - g_object_unref(native); - return false; -} - -/** - * Opens the last session, if any. - */ -bool GtkStatsServer:: -open_last_session() { - if (!close_session()) { - return false; - } - - Filename fn = _last_session; - GtkStatsMonitor *monitor = new GtkStatsMonitor(this); - if (!monitor->read(fn)) { - delete monitor; - - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Failed to load session file: %s", fn.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - - return false; - } - _monitor = monitor; - - // Enable the "New Session", "Save Session" and "Close Session" menu items. - gtk_widget_set_sensitive(_new_session_menu_item, TRUE); - gtk_widget_set_sensitive(_save_session_menu_item, TRUE); - gtk_widget_set_sensitive(_close_session_menu_item, TRUE); - gtk_widget_set_sensitive(_export_session_menu_item, TRUE); - - // If the file contained no graphs, open the default graphs. - if (monitor->_graphs.empty()) { - monitor->open_default_graphs(); - } - - return true; -} - -/** - * Offers to save the current session. - */ -bool GtkStatsServer:: -save_session() { - nassertr_always(_monitor != nullptr, true); - - GtkFileChooserNative *native = gtk_file_chooser_native_new( - "Save Session", - GTK_WINDOW(_window), - GTK_FILE_CHOOSER_ACTION_SAVE, - "_Save", "Cancel"); - GtkFileChooser *chooser = GTK_FILE_CHOOSER(native); - - gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); - - GtkFileFilter *filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, "PStats Session Files"); - gtk_file_filter_add_pattern(filter, "*.pstats"); - gtk_file_chooser_add_filter(chooser, filter); - - if (_save_filename.empty()) { - gtk_file_chooser_set_current_name(chooser, "session.pstats"); - } - else { - gtk_file_chooser_set_filename(chooser, _save_filename.c_str()); - } - - gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)); - if (res == GTK_RESPONSE_ACCEPT) { - char *buffer = gtk_file_chooser_get_filename(chooser); - Filename fn = Filename::from_os_specific(buffer); - fn.set_binary(); - g_free(buffer); - g_object_unref(native); - - if (!_monitor->write(fn)) { - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Failed to save session file: %s", fn.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - return false; - } - _save_filename = fn; - _monitor->get_client_data()->clear_dirty(); - return true; - } - - g_object_unref(native); - return false; -} - -/** - * Offers to export the current session as a JSON file. - */ -bool GtkStatsServer:: -export_session() { - nassertr_always(_monitor != nullptr, true); - - GtkFileChooserNative *native = gtk_file_chooser_native_new( - "Export Session", - GTK_WINDOW(_window), - GTK_FILE_CHOOSER_ACTION_SAVE, - "_Export", "Cancel"); - GtkFileChooser *chooser = GTK_FILE_CHOOSER(native); - - gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE); - - GtkFileFilter *filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, "JSON files"); - gtk_file_filter_add_pattern(filter, "*.json"); - gtk_file_chooser_add_filter(chooser, filter); - - gtk_file_chooser_set_current_name(chooser, "session.json"); - - gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)); - if (res == GTK_RESPONSE_ACCEPT) { - char *buffer = gtk_file_chooser_get_filename(chooser); - Filename fn = Filename::from_os_specific(buffer); - fn.set_text(); - g_free(buffer); - g_object_unref(native); - - std::ofstream stream; - if (!fn.open_write(stream)) { - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Failed to open file for export: %s", fn.c_str()); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - return false; - } - - int pid = _monitor->get_client_pid(); - _monitor->get_client_data()->write_json(stream, std::max(0, pid)); - stream.close(); - return true; - } - - g_object_unref(native); - return false; -} - -/** - * Closes the current session. - */ -bool GtkStatsServer:: -close_session() { - bool wrote_last_session = false; - - if (_monitor != nullptr) { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data != nullptr && client_data->is_dirty()) { - if (!_monitor->has_read_filename()) { - _last_session.make_dir(); - if (_monitor->write(_last_session)) { - nout << "Wrote to " << _last_session << "\n"; - wrote_last_session = true; - } - else { - nout << "Failed to write to " << _last_session << "\n"; - } - } - - GtkWidget *dialog = - gtk_message_dialog_new(GTK_WINDOW(_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - "Would you like to save the currently open session?"); - gint response = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - - if (response == GTK_RESPONSE_CANCEL || - (response == GTK_RESPONSE_YES && !save_session())) { - return false; - } - } - - _monitor->close(); - _monitor = nullptr; - } - - _save_filename = Filename(); - stop_listening(); - - gtk_window_set_title(GTK_WINDOW(_window), "PStats Server"); - - if (_status_bar_label != nullptr) { - gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label); - g_object_unref(_status_bar_label); - _status_bar_label = nullptr; - } - - gtk_widget_set_sensitive(_new_session_menu_item, TRUE); - if (wrote_last_session) { - gtk_widget_set_sensitive(_open_last_session_menu_item, TRUE); - } - gtk_widget_set_sensitive(_save_session_menu_item, FALSE); - gtk_widget_set_sensitive(_close_session_menu_item, FALSE); - gtk_widget_set_sensitive(_export_session_menu_item, FALSE); - return true; -} - -/** - * Returns the window handle to the server's window. - */ -GtkWidget *GtkStatsServer:: -get_window() const { - return _window; -} - -/** - * Returns the server window's accelerator group. - */ -GtkAccelGroup *GtkStatsServer:: -get_accel_group() const { - return _accel_group; -} - -/** - * Returns the menu handle to the server's menu bar. - */ -GtkWidget *GtkStatsServer:: -get_menu_bar() const { - return _menu_bar; -} - -/** - * Returns the window handle to the server's status bar. - */ -GtkWidget *GtkStatsServer:: -get_status_bar() const { - return _status_bar; -} - -/** - * - */ -int GtkStatsServer:: -get_time_units() const { - return _time_units; -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for all graphs to the indicated mask if - * it is a time-based graph. - */ -void GtkStatsServer:: -set_time_units(int unit_mask) { - _time_units = unit_mask; - - if (_monitor != nullptr) { - _monitor->set_time_units(unit_mask); - } -} - -/** - * Creates the window for this monitor. - */ -void GtkStatsServer:: -create_window() { - _window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(_window), "PStats Server"); - gtk_window_set_default_size(GTK_WINDOW(_window), 500, 360); - - // Connect the delete and destroy events, so the user can exit the - // application by closing the main window. - g_signal_connect(G_OBJECT(_window), "delete_event", - G_CALLBACK(+[](GtkWidget *widget, GdkEvent *event, gpointer data) -> gboolean { - GtkStatsServer *self = (GtkStatsServer *)data; - return self->close_session() ? FALSE : TRUE; - }), this); - - g_signal_connect(G_OBJECT(_window), "destroy", - G_CALLBACK(+[](GtkWidget *widget, GdkEvent *event, gpointer data) -> gboolean { - gtk_main_quit(); - return FALSE; - }), this); - - // Set up the menu. - _accel_group = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(_window), _accel_group); - _menu_bar = gtk_menu_bar_new(); - - setup_session_menu(); - setup_options_menu(); - - // Pack the menu into the window. - GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1); - gtk_container_add(GTK_CONTAINER(_window), main_vbox); - gtk_box_pack_start(GTK_BOX(main_vbox), _menu_bar, FALSE, TRUE, 0); - - // Create the status bar. - _status_bar = gtk_flow_box_new(); - gtk_flow_box_set_activate_on_single_click(GTK_FLOW_BOX(_status_bar), FALSE); - gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(_status_bar), GTK_SELECTION_NONE); - g_signal_connect(G_OBJECT(_status_bar), "button_press_event", - G_CALLBACK(status_bar_button_event), this); - gtk_box_pack_end(GTK_BOX(main_vbox), _status_bar, FALSE, FALSE, 0); - - GtkWidget *sep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); - gtk_box_pack_end(GTK_BOX(main_vbox), sep, FALSE, FALSE, 0); - - gtk_widget_show_all(_window); - gtk_widget_show(_window); - gtk_widget_realize(_window); - - // Set up a timer to poll the pstats every so often. - g_timeout_add(200, +[](gpointer data) -> gboolean { - GtkStatsServer *self = (GtkStatsServer *)data; - self->poll(); - return TRUE; - }, this); -} - -/** - * Creates the "Session" pulldown menu. - */ -void GtkStatsServer:: -setup_session_menu() { - _session_menu = gtk_menu_new(); - - GtkWidget *item = gtk_menu_item_new_with_mnemonic("_Session"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), _session_menu); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu_bar), item); - - item = gtk_menu_item_new_with_mnemonic("_New Session"); - _new_session_menu_item = item; - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->new_session(); - }), this); - gtk_widget_add_accelerator(item, "activate", _accel_group, - GDK_KEY_n, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - - item = gtk_menu_item_new_with_mnemonic("_Open Session..."); - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->open_session(); - }), this); - gtk_widget_add_accelerator(item, "activate", _accel_group, - GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - - item = gtk_menu_item_new_with_mnemonic("Open _Last Session"); - _open_last_session_menu_item = item; - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->open_last_session(); - }), this); - - if (!_last_session.exists()) { - gtk_widget_set_sensitive(item, FALSE); - } - - item = gtk_menu_item_new_with_mnemonic("_Save Session..."); - _save_session_menu_item = item; - gtk_widget_set_sensitive(item, FALSE); - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->save_session(); - }), this); - gtk_widget_add_accelerator(item, "activate", _accel_group, - GDK_KEY_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - - item = gtk_menu_item_new_with_mnemonic("_Close Session"); - _close_session_menu_item = item; - gtk_widget_set_sensitive(item, FALSE); - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->close_session(); - }), this); - gtk_widget_add_accelerator(item, "activate", _accel_group, - GDK_KEY_w, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - - GtkWidget *sep = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), sep); - - item = gtk_menu_item_new_with_mnemonic("_Export as JSON..."); - _export_session_menu_item = item; - gtk_widget_set_sensitive(item, FALSE); - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->export_session(); - }), this); - - sep = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), sep); - - item = gtk_menu_item_new_with_mnemonic("E_xit"); - gtk_menu_shell_append(GTK_MENU_SHELL(_session_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - if (self->close_session()) { - gtk_main_quit(); - } - }), this); - gtk_widget_add_accelerator(item, "activate", _accel_group, - GDK_KEY_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - - gtk_widget_show_all(_session_menu); -} - -/** - * Creates the "Options" pulldown menu. - */ -void GtkStatsServer:: -setup_options_menu() { - _options_menu = gtk_menu_new(); - - GtkWidget *item = gtk_menu_item_new_with_label("Options"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), _options_menu); - gtk_menu_shell_append(GTK_MENU_SHELL(_menu_bar), item); - - GtkWidget *units_menu = gtk_menu_new(); - item = gtk_menu_item_new_with_label("Units"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), units_menu); - gtk_menu_shell_append(GTK_MENU_SHELL(_options_menu), item); - - item = gtk_radio_menu_item_new_with_label(nullptr, "ms"); - gtk_menu_shell_append(GTK_MENU_SHELL(units_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->set_time_units(PStatGraph::GBU_ms); - }), this); - - item = gtk_radio_menu_item_new_with_label( - gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)), "Hz"); - gtk_menu_shell_append(GTK_MENU_SHELL(units_menu), item); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(+[](GtkMenuItem *item, gpointer data) { - GtkStatsServer *self = (GtkStatsServer *)data; - self->set_time_units(PStatGraph::GBU_hz); - }), this); - - set_time_units(PStatGraph::GBU_ms); -} - -/** - * Handles clicks on a partion of the status bar. - */ -gboolean GtkStatsServer:: -status_bar_button_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - GtkStatsServer *server = (GtkStatsServer *)data; - - GtkFlowBoxChild *child = gtk_flow_box_get_child_at_pos( - GTK_FLOW_BOX(server->_status_bar), event->x, event->y); - if (child == nullptr) { - return FALSE; - } - - // Which child is this? - GList *children = gtk_container_get_children(GTK_CONTAINER(server->_status_bar)); - int index = g_list_index(children, child); - g_list_free(children); - if (index < 0) { - return FALSE; - } - - if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { - server->_monitor->handle_status_bar_click(index); - return TRUE; - } - else if (event->type == GDK_BUTTON_PRESS && event->button == 3 && index > 0) { - server->_monitor->handle_status_bar_popup(index); - return TRUE; - } - return FALSE; -} diff --git a/pandatool/src/gtk-stats/gtkStatsServer.h b/pandatool/src/gtk-stats/gtkStatsServer.h deleted file mode 100644 index 9aa3507a..00000000 --- a/pandatool/src/gtk-stats/gtkStatsServer.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsServer.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSSERVER_H -#define GTKSTATSSERVER_H - -#include "pandatoolbase.h" -#include "programBase.h" -#include "pStatServer.h" -#include "gtkStatsMonitor.h" - -/** - * The class that owns the main loop, waiting for client connections. - */ -class GtkStatsServer : public PStatServer, public ProgramBase { -public: - GtkStatsServer(); - - virtual bool handle_args(Args &args) override; - - virtual PStatMonitor *make_monitor(const NetAddress &address) override; - virtual void lost_connection(PStatMonitor *monitor) override; - - bool new_session(); - bool open_session(); - bool open_last_session(); - bool save_session(); - bool export_session(); - bool close_session(); - - GtkWidget *get_window() const; - GtkAccelGroup *get_accel_group() const; - GtkWidget *get_menu_bar() const; - GtkWidget *get_status_bar() const; - - int get_time_units() const; - void set_time_units(int unit_mask); - -private: - void create_window(); - void setup_session_menu(); - void setup_options_menu(); - - static gboolean status_bar_button_event(GtkWidget *widget, - GdkEventButton *event, - gpointer data); - -private: - PT(GtkStatsMonitor) _monitor; - - Filename _last_session; - Filename _save_filename; - - int _port = -1; - GtkWidget *_window = nullptr; - GtkAccelGroup *_accel_group = nullptr; - GtkWidget *_menu_bar = nullptr; - GtkWidget *_session_menu = nullptr; - GtkWidget *_options_menu = nullptr; - GtkWidget *_status_bar; - GtkWidget *_status_bar_label = nullptr; - GtkWidget *_new_session_menu_item; - GtkWidget *_open_last_session_menu_item; - GtkWidget *_save_session_menu_item; - GtkWidget *_close_session_menu_item; - GtkWidget *_export_session_menu_item; - int _time_units = 0; -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx b/pandatool/src/gtk-stats/gtkStatsStripChart.cxx deleted file mode 100644 index 0be191da..00000000 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx +++ /dev/null @@ -1,796 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsStripChart.cxx - * @author drose - * @date 2006-01-16 - */ - -#include "gtkStatsStripChart.h" -#include "gtkStatsMonitor.h" -#include "pStatCollectorDef.h" -#include "numeric_types.h" -#include "string_utils.h" - -static const int default_strip_chart_width = 400; -static const int default_strip_chart_height = 100; - -/** - * - */ -GtkStatsStripChart:: -GtkStatsStripChart(GtkStatsMonitor *monitor, int thread_index, - int collector_index, bool show_level) : - PStatStripChart(monitor, thread_index, collector_index, show_level, 0, 0), - GtkStatsGraph(monitor, true) -{ - if (show_level) { - // If it's a level-type graph, show the appropriate units. - if (_unit_name.empty()) { - set_guide_bar_units(GBU_named); - } else { - set_guide_bar_units(GBU_named | GBU_show_units); - } - - } else { - // If it's a time-type graph, show the msHz units. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - } - - // Put some stuff on top of the graph. - _top_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_box_pack_start(GTK_BOX(_graph_vbox), _top_hbox, FALSE, FALSE, 0); - - _smooth_check_box = gtk_check_button_new_with_label("Smooth"); - g_signal_connect(G_OBJECT(_smooth_check_box), "toggled", - G_CALLBACK(toggled_callback), this); - - _total_label = gtk_label_new(""); - gtk_box_pack_start(GTK_BOX(_top_hbox), _smooth_check_box, FALSE, FALSE, 0); - gtk_box_pack_end(GTK_BOX(_top_hbox), _total_label, FALSE, FALSE, 0); - - // Add a DrawingArea widget to the right of the graph, to display all of the - // scale units. - _scale_area = gtk_drawing_area_new(); - g_signal_connect(G_OBJECT(_scale_area), "draw", - G_CALLBACK(draw_callback), this); - gtk_box_pack_start(GTK_BOX(_graph_hbox), _scale_area, FALSE, FALSE, 0); - - // Make it wide enough to display a typical label. - { - PangoLayout *layout = gtk_widget_create_pango_layout(_scale_area, "99 ms"); - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - gtk_widget_set_size_request(_scale_area, width, 0); - g_object_unref(layout); - } - - gtk_widget_set_size_request(_graph_window, - default_strip_chart_width * monitor->get_resolution() / 96, - default_strip_chart_height * monitor->get_resolution() / 96); - - gtk_widget_show_all(_window); - gtk_widget_show(_window); - - // Allow the window to be resized as small as the user likes. We have to do - // this after the window has been shown; otherwise, it will affect the - // window's initial size. - gtk_widget_set_size_request(_graph_window, 0, 0); - - clear_region(); - - // Update window title and total label. - new_data(0, 0); -} - -/** - * - */ -GtkStatsStripChart:: -~GtkStatsStripChart() { -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void GtkStatsStripChart:: -new_collector(int collector_index) { - GtkStatsGraph::new_collector(collector_index); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void GtkStatsStripChart:: -new_data(int thread_index, int frame_number) { - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - gtk_window_set_title(GTK_WINDOW(_window), window_title.c_str()); - } - } - - if (!_pause) { - update(); - - std::string text = get_total_text(); - if (_net_value_text != text) { - _net_value_text = text; - gtk_label_set_text(GTK_LABEL(_total_label), _net_value_text.c_str()); - } - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void GtkStatsStripChart:: -force_redraw() { - if (_cr) { - PStatStripChart::force_redraw(); - } -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void GtkStatsStripChart:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatStripChart::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void GtkStatsStripChart:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - gtk_widget_queue_draw(_scale_area); - } -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speed for the graph to the indicated value. - */ -void GtkStatsStripChart:: -set_scroll_speed(double scroll_speed) { - // The speed factor indicates chart widths per minute. - if (scroll_speed != 0.0f) { - set_horizontal_scale(60.0f / scroll_speed); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void GtkStatsStripChart:: -on_click_label(int collector_index) { - if (collector_index < 0) { - // Clicking on whitespace in the graph is the same as clicking on the top - // label. - collector_index = get_collector_index(); - } - - if (collector_index == get_collector_index() && collector_index != 0) { - // Clicking on the top label means to go up to the parent level. - const PStatClientData *client_data = - GtkStatsGraph::_monitor->get_client_data(); - if (client_data->has_collector(collector_index)) { - const PStatCollectorDef &def = - client_data->get_collector_def(collector_index); - if (def._parent_index == 0 && get_view().get_show_level()) { - // Unless the parent is "Frame", and we're not a time collector. - } else { - set_collector_index(def._parent_index); - } - } - - } else { - // Clicking on any other label means to focus on that. - set_collector_index(collector_index); - } - - // Update window title and total label. - new_data(0, 0); -} - -/** - * Called when the user right-clicks on a label. - */ -void GtkStatsStripChart:: -on_popup_label(int collector_index) { - GtkWidget *menu = gtk_menu_new(); - _popup_index = collector_index; - - std::string label = get_label_tooltip(collector_index); - if (!label.empty()) { - GtkWidget *menu_item = gtk_menu_item_new_with_label(label.c_str()); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - gtk_widget_set_sensitive(menu_item, FALSE); - } - - { - GtkWidget *menu_item = gtk_menu_item_new_with_label("Set as Focus"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - - if (collector_index == 0 && get_collector_index() == 0) { - gtk_widget_set_sensitive(menu_item, FALSE); - } else { - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(+[] (GtkWidget *widget, gpointer data) { - GtkStatsStripChart *self = (GtkStatsStripChart *)data; - self->set_collector_index(self->_popup_index); - }), - this); - } - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_strip_chart, _thread_index, collector_index, -1, - get_view().get_show_level(), - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - if (!get_view().get_show_level()) { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_flame_graph, _thread_index, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - GtkWidget *menu_item = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_choose_color, -1, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_reset_color, -1, collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - gtk_widget_show_all(menu); - gtk_menu_popup_at_pointer(GTK_MENU(menu), nullptr); -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsStripChart:: -get_label_tooltip(int collector_index) const { - return PStatStripChart::get_label_tooltip(collector_index); -} - -/** - * Changes the value the height of the vertical axis represents. This may - * force a redraw. - */ -void GtkStatsStripChart:: -set_vertical_scale(double value_height) { - PStatStripChart::set_vertical_scale(value_height); - - gtk_widget_queue_draw(_graph_window); - gtk_widget_queue_draw(_scale_area); -} - -/** - * Resets the list of labels. - */ -void GtkStatsStripChart:: -update_labels() { - PStatStripChart::update_labels(); - - _label_stack.clear_labels(); - for (int i = 0; i < get_num_labels(); i++) { - _label_stack.add_label(GtkStatsGraph::_monitor, this, _thread_index, - get_label_collector(i), false); - } - _labels_changed = false; -} - -/** - * Erases the chart area. - */ -void GtkStatsStripChart:: -clear_region() { - cairo_set_source_rgb(_cr, 1.0, 1.0, 1.0); - cairo_paint(_cr); -} - -/** - * Should be overridden by the user class to copy a region of the chart from - * one part of the chart to another. This is used to implement scrolling. - */ -void GtkStatsStripChart:: -copy_region(int start_x, int end_x, int dest_x) { - // We are not allowed to copy a surface onto itself, so we have to create a - // temporary surface to copy to. - end_x = std::min(end_x, get_xsize()); - GdkWindow *window = gtk_widget_get_window(_graph_window); - cairo_surface_t *temp_surface = - gdk_window_create_similar_image_surface(window, CAIRO_FORMAT_RGB24, end_x - start_x, get_ysize(), 1); - { - cairo_t *temp_cr = cairo_create(temp_surface); - cairo_set_source_surface(temp_cr, _cr_surface, -start_x, 0); - cairo_paint(temp_cr); - cairo_destroy(temp_cr); - } - - cairo_set_source_surface(_cr, temp_surface, 0, 0); - cairo_rectangle(_cr, dest_x, 0, end_x - start_x, get_ysize()); - cairo_fill(_cr); - - cairo_surface_destroy(temp_surface); - - gdk_window_invalidate_rect(window, nullptr, FALSE); -} - -/** - * Draws a single vertical slice of the strip chart, at the given pixel - * position, and corresponding to the indicated level data. - */ -void GtkStatsStripChart:: -draw_slice(int x, int w, const PStatStripChart::FrameData &fdata) { - // Start by clearing the band first. - cairo_set_source_rgb(_cr, 1.0, 1.0, 1.0); - cairo_rectangle(_cr, x, 0, w, get_ysize()); - cairo_fill(_cr); - - double overall_time = 0.0; - int y = get_ysize(); - - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - overall_time += cd._net_value; - cairo_set_source(_cr, get_collector_pattern(cd._collector_index, - _highlighted_index == cd._collector_index)); - - if (overall_time > get_vertical_scale()) { - // Off the top. Go ahead and clamp it by hand, in case it's so far off - // the top we'd overflow the 16-bit pixel value. - cairo_rectangle(_cr, x, 0, w, y); - cairo_fill(_cr); - // And we can consider ourselves done now. - return; - } - - int top_y = height_to_pixel(overall_time); - cairo_rectangle(_cr, x, top_y, w, y - top_y); - cairo_fill(_cr); - y = top_y; - } -} - -/** - * Draws a single vertical slice of background color. - */ -void GtkStatsStripChart:: -draw_empty(int x, int w) { - cairo_set_source_rgb(_cr, 1.0, 1.0, 1.0); - cairo_rectangle(_cr, x, 0, w, get_ysize()); -} - -/** - * Draws a single vertical slice of foreground color. - */ -void GtkStatsStripChart:: -draw_cursor(int x) { - cairo_set_source_rgb(_cr, 0.0, 0.0, 0.0); - cairo_move_to(_cr, x, 0); - cairo_line_to(_cr, x, get_ysize()); - cairo_stroke(_cr); -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars in the strip chart; it gives the pixel range - * that was just redrawn. - */ -void GtkStatsStripChart:: -end_draw(int from_x, int to_x) { - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_bar(_cr, from_x, to_x, get_guide_bar(i)); - } - - GdkWindow *window = gtk_widget_get_window(_graph_window); - int scale = gdk_window_get_scale_factor(window); - GdkRectangle rect = { - (from_x * scale) / scale, 0, (to_x - from_x) / scale, get_ysize() / scale - }; - gdk_window_invalidate_rect(window, &rect, FALSE); -} - -/** - * Returns the current window dimensions. - */ -bool GtkStatsStripChart:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - GtkStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void GtkStatsStripChart:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - GtkStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * This is called during the servicing of the draw event; it gives a derived - * class opportunity to do some further painting into the graph window. - */ -void GtkStatsStripChart:: -additional_graph_window_paint(cairo_t *cr) { - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_bar(cr, 0, get_xsize(), get_user_guide_bar(i)); - } -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsStripChart:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - if (_highlighted_index != -1) { - return get_label_tooltip(_highlighted_index); - } - return std::string(); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -GtkStatsGraph::DragMode GtkStatsStripChart:: -consider_drag_start(int graph_x, int graph_y) { - if (graph_x >= 0 && graph_x < get_xsize()) { - if (graph_y >= 0 && graph_y < get_ysize()) { - // See if the mouse is over a user-defined guide bar. - int y = graph_y; - double from_height = pixel_to_height(y + 2); - double to_height = pixel_to_height(y - 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else { - // The mouse is above or below the graph; maybe create a new guide bar. - return DM_new_guide_bar; - } - } - - return GtkStatsGraph::consider_drag_start(graph_x, graph_y); -} - -/** - * This should be called whenever the drag mode needs to change state. It - * provides hooks for a derived class to do something special. - */ -void GtkStatsStripChart:: -set_drag_mode(GtkStatsGraph::DragMode drag_mode) { - GtkStatsGraph::set_drag_mode(drag_mode); - - if (_drag_mode == DM_none) { - // Restore smoothing according to the current setting of the check box. - bool active = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(_smooth_check_box)); - set_average_mode(active); - } -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -gboolean GtkStatsStripChart:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - int collector_index = get_collector_under_pixel(graph_x, graph_y); - if (button == 3) { - // Right-clicking on a color bar in the graph is the same as right- - // clicking on the corresponding label. - if (collector_index >= 0) { - on_popup_label(collector_index); - return TRUE; - } - return FALSE; - } - else if (double_click && button == 1) { - // Double-clicking on a color bar in the graph is the same as double- - // clicking on the corresponding label. - on_click_label(get_collector_under_pixel(graph_x, graph_y)); - return TRUE; - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - _drag_scale_start = pixel_to_height(graph_y); - // SetCapture(_graph_window); - return TRUE; - } - } - - if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - _drag_start_y = graph_y; - // SetCapture(_graph_window); - return TRUE; - } - - return GtkStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -gboolean GtkStatsStripChart:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_y < 0 || graph_y >= get_ysize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_y)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return GtkStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -gboolean GtkStatsStripChart:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none && - graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - // When the mouse is over a color bar, highlight it. - int collector_index = get_collector_under_pixel(graph_x, graph_y); - _label_stack.highlight_label(collector_index); - on_enter_label(collector_index); - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_scale) { - double ratio = 1.0 - ((double)graph_y / (double)get_ysize()); - if (ratio > 0.0) { - double new_scale = _drag_scale_start / ratio; - if (!IS_NEARLY_EQUAL(get_vertical_scale(), new_scale)) { - // Disable smoothing while we do this expensive operation. - set_average_mode(false); - set_vertical_scale(_drag_scale_start / ratio); - } - } - return TRUE; - } - else if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - if (graph_y >= 0 && graph_y < get_ysize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_y)); - return TRUE; - } - } - else if (_drag_mode == DM_guide_bar) { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_y)); - return TRUE; - } - - return GtkStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -gboolean GtkStatsStripChart:: -handle_leave() { - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - return TRUE; -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void GtkStatsStripChart:: -draw_guide_bar(cairo_t *cr, int from_x, int to_x, - const PStatGraph::GuideBar &bar) { - int y = height_to_pixel(bar._height); - - if (y > 0) { - // Only draw it if it's not too close to the top. - switch (bar._style) { - case GBS_target: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_user: - cairo_set_source_rgb(cr, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2]); - break; - - default: - cairo_set_source_rgb(cr, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2]); - break; - } - cairo_move_to(cr, from_x, y); - cairo_line_to(cr, to_x, y); - cairo_stroke(cr); - } -} - -/** - * This is called during the servicing of the draw event. - */ -void GtkStatsStripChart:: -draw_guide_labels(cairo_t *cr) { - // Draw in the labels for the guide bars. - int last_y = -100; - - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; i++) { - last_y = draw_guide_label(cr, get_guide_bar(i), last_y); - } - - GuideBar top_value = make_guide_bar(get_vertical_scale()); - draw_guide_label(cr, top_value, last_y); - - last_y = -100; - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; i++) { - last_y = draw_guide_label(cr, get_user_guide_bar(i), last_y); - } -} - -/** - * Draws the text for the indicated guide bar label to the right of the graph, - * unless it would overlap with the indicated last label, whose top pixel - * value is given. Returns the top pixel value of the new label. - */ -int GtkStatsStripChart:: -draw_guide_label(cairo_t *cr, const PStatGraph::GuideBar &bar, int last_y) { - switch (bar._style) { - case GBS_target: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_user: - cairo_set_source_rgb(cr, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2]); - break; - - default: - cairo_set_source_rgb(cr, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2]); - break; - } - - int y = height_to_pixel(bar._height); - const std::string &label = bar._label; - - PangoLayout *layout = gtk_widget_create_pango_layout(_scale_area, label.c_str()); - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(y + height * _cr_scale); - double to_height = pixel_to_height(y - height * _cr_scale); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - g_object_unref(layout); - return last_y; - } - } - - if (y >= 0 && y < get_ysize()) { - // Now convert our y to a coordinate within our drawing area. - int junk_x; - - y /= _cr_scale; - - // The y coordinate comes from the graph_window. - gtk_widget_translate_coordinates(_graph_window, _scale_area, - 0, y, - &junk_x, &y); - - int this_y = y - height / 2; - if (last_y < this_y || last_y > this_y + height) { - cairo_move_to(cr, 0, this_y); - pango_cairo_show_layout(cr, layout); - last_y = this_y; - } - } - - g_object_unref(layout); - return last_y; -} - -/** - * Called when the smooth check box is toggled. - */ -void GtkStatsStripChart:: -toggled_callback(GtkToggleButton *button, gpointer data) { - GtkStatsStripChart *self = (GtkStatsStripChart *)data; - - bool active = gtk_toggle_button_get_active(button); - self->set_average_mode(active); -} - -/** - * Draws in the scale labels. - */ -gboolean GtkStatsStripChart:: -draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { - GtkStatsStripChart *self = (GtkStatsStripChart *)data; - self->draw_guide_labels(cr); - - return TRUE; -} diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.h b/pandatool/src/gtk-stats/gtkStatsStripChart.h deleted file mode 100644 index 687c3e70..00000000 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsStripChart.h - * @author drose - * @date 2006-01-16 - */ - -#ifndef GTKSTATSSTRIPCHART_H -#define GTKSTATSSTRIPCHART_H - -#include "pandatoolbase.h" - -#include "gtkStatsGraph.h" -#include "pStatStripChart.h" -#include "pointerTo.h" - -#include - -class GtkStatsMonitor; - -/** - * A window that draws a strip chart, given a view. - */ -class GtkStatsStripChart final : public PStatStripChart, public GtkStatsGraph { -public: - GtkStatsStripChart(GtkStatsMonitor *monitor, - int thread_index, int collector_index, bool show_level); - virtual ~GtkStatsStripChart(); - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void set_scroll_speed(double scroll_speed); - virtual void on_click_label(int collector_index); - virtual void on_popup_label(int collector_index); - virtual std::string get_label_tooltip(int collector_index) const; - void set_vertical_scale(double value_height); - -protected: - virtual void update_labels(); - - virtual void clear_region(); - virtual void copy_region(int start_x, int end_x, int dest_x); - virtual void draw_slice(int x, int w, - const PStatStripChart::FrameData &fdata); - virtual void draw_empty(int x, int w); - virtual void draw_cursor(int x); - virtual void end_draw(int from_x, int to_x); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual void additional_graph_window_paint(cairo_t *cr); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - virtual void set_drag_mode(DragMode drag_mode); - - virtual gboolean handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual gboolean handle_button_release(int graph_x, int graph_y); - virtual gboolean handle_motion(int graph_x, int graph_y); - virtual gboolean handle_leave(); - -private: - void draw_guide_bar(cairo_t *cr, int from_x, int to_x, - const PStatGraph::GuideBar &bar); - void draw_guide_labels(cairo_t *cr); - int draw_guide_label(cairo_t *cr, const PStatGraph::GuideBar &bar, int last_y); - - static void toggled_callback(GtkToggleButton *button, gpointer data); - static gboolean draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data); - -private: - std::string _net_value_text; - - GtkWidget *_top_hbox; - GtkWidget *_smooth_check_box; - GtkWidget *_total_label; - - int _popup_index = -1; -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkStatsTimeline.cxx b/pandatool/src/gtk-stats/gtkStatsTimeline.cxx deleted file mode 100644 index bffdd32e..00000000 --- a/pandatool/src/gtk-stats/gtkStatsTimeline.cxx +++ /dev/null @@ -1,929 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsTimeline.cxx - * @author rdb - * @date 2022-02-17 - */ - -#include "gtkStatsTimeline.h" -#include "gtkStatsMonitor.h" -#include "numeric_types.h" -#include "gtkStatsLabelStack.h" - -static const int default_timeline_width = 1000; -static const int default_timeline_height = 300; - -/** - * - */ -GtkStatsTimeline:: -GtkStatsTimeline(GtkStatsMonitor *monitor) : - PStatTimeline(monitor, 0, 0), - GtkStatsGraph(monitor, false) -{ - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - // Add a DrawingArea widget on top of the graph, to display all of the scale - // units. - _scale_area = gtk_drawing_area_new(); - g_signal_connect(G_OBJECT(_scale_area), "draw", - G_CALLBACK(scale_area_draw_callback), this); - gtk_box_pack_start(GTK_BOX(_graph_vbox), _scale_area, FALSE, FALSE, 0); - - // It should be large enough to display the labels. - { - PangoLayout *layout = gtk_widget_create_pango_layout(_scale_area, "0123456789 ms"); - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - gtk_widget_set_size_request(_scale_area, 0, height + _pixel_scale / 2); - g_object_unref(layout); - } - - // Add a drawing area to the left of the graph to show the thread labels. - _thread_area = gtk_drawing_area_new(); - gtk_box_pack_start(GTK_BOX(_graph_hbox), _thread_area, FALSE, FALSE, 0); - gtk_box_reorder_child(GTK_BOX(_graph_hbox), _thread_area, 0); - g_signal_connect(G_OBJECT(_thread_area), "draw", - G_CALLBACK(thread_area_draw_callback), this); - - // Listen for mouse wheel and keyboard events. - gtk_widget_add_events(_graph_window, GDK_SMOOTH_SCROLL_MASK | - GDK_SCROLL_MASK | - GDK_KEY_PRESS_MASK | - GDK_KEY_RELEASE_MASK); - gtk_widget_set_can_focus(_graph_window, TRUE); - g_signal_connect(G_OBJECT(_graph_window), "scroll_event", - G_CALLBACK(scroll_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "key_press_event", - G_CALLBACK(key_press_callback), this); - g_signal_connect(G_OBJECT(_graph_window), "key_release_event", - G_CALLBACK(key_release_callback), this); - - // Set up trackpad pinch and swipe gestures. - _zoom_gesture = gtk_gesture_zoom_new(_graph_window); - g_signal_connect(_zoom_gesture, "begin", - G_CALLBACK(+[](GtkGestureZoom *gesture, GdkEventSequence *sequence, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - self->_zoom_scale = self->get_horizontal_scale(); - }), this); - - g_signal_connect(_zoom_gesture, "scale-changed", - G_CALLBACK((+[](GtkGestureZoom *gesture, gdouble scale, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - gdouble x, y; - if (gtk_gesture_get_point(GTK_GESTURE(gesture), NULL, &x, &y)) { - int graph_x = (int)(x * self->_cr_scale); - self->zoom_by(log(scale) * 0.8, self->pixel_to_timestamp(graph_x)); - self->start_animation(); - } - })), this); - - int min_height = 0; - if (!_threads.empty()) { - double height = row_to_pixel(get_num_rows()) + _pixel_scale * 2.5; - min_height = height / _cr_scale; - - // Never make the window taller than the screen. - GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(_window)); - min_height = std::min(min_height, gdk_screen_get_height(screen)); - } - - gtk_widget_set_size_request(_graph_window, - default_timeline_width * monitor->get_resolution() / 96, - std::max(min_height, (int)(default_timeline_height * monitor->get_resolution() / 96))); - - gtk_window_set_title(GTK_WINDOW(_window), "Timeline"); - - _grid_pattern = cairo_pattern_create_rgb(0xdd / 255.0, 0xdd / 255.0, 0xdd / 255.0); - - gtk_widget_show_all(_window); - gtk_widget_show(_window); - - // Allow the window to be resized as small as the user likes. We have to do - // this after the window has been shown; otherwise, it will affect the - // window's initial size. - gtk_widget_set_size_request(_graph_window, 0, 0); - - clear_region(); -} - -/** - * - */ -GtkStatsTimeline:: -~GtkStatsTimeline() { - cairo_pattern_destroy(_grid_pattern); - g_object_unref(_zoom_gesture); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void GtkStatsTimeline:: -new_data(int thread_index, int frame_number) { - PStatTimeline::new_data(thread_index, frame_number); -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void GtkStatsTimeline:: -force_redraw() { - assert(_cr); - if (_cr) { - PStatTimeline::force_redraw(); - } -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void GtkStatsTimeline:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatTimeline::changed_size(graph_xsize, graph_ysize); -} - -/** - * Erases the chart area. - */ -void GtkStatsTimeline:: -clear_region() { - cairo_set_source_rgb(_cr, 1.0, 1.0, 1.0); - cairo_paint(_cr); -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void GtkStatsTimeline:: -begin_draw() { -} - -/** - * Draws a horizontal separator. - */ -void GtkStatsTimeline:: -draw_separator(int row) { - cairo_set_source(_cr, _grid_pattern); - cairo_rectangle(_cr, 0, (row_to_pixel(row) + row_to_pixel(row + 1)) / 2.0, - get_xsize(), _pixel_scale * 1 / 3); - cairo_fill(_cr); -} - -/** - * Draws a vertical guide bar. If the row is -1, draws it in all rows. - */ -void GtkStatsTimeline:: -draw_guide_bar(int x, GuideBarStyle style) { - double width = _pixel_scale / 3.0; - if (style == GBS_frame) { - width *= 2; - } - - cairo_set_source(_cr, _grid_pattern); - cairo_rectangle(_cr, x - width / 2.0, 0, width, get_ysize()); - cairo_fill(_cr); -} - -/** - * Draws a single bar in the chart for the indicated row, in the color for the - * given collector, for the indicated horizontal pixel range. - */ -void GtkStatsTimeline:: -draw_bar(int row, int from_x, int to_x, int collector_index, - const std::string &collector_name) { - int top = row_to_pixel(row); - int bottom = row_to_pixel(row + 1); - int scale = _pixel_scale; - - bool is_highlighted = row == _highlighted_row && _highlighted_x >= from_x && _highlighted_x < to_x; - cairo_set_source(_cr, get_collector_pattern(collector_index, is_highlighted)); - - if (to_x < from_x + 1) { - // Too tiny to draw. - } - else if (to_x < from_x + scale) { - // It's just a tiny sliver. This is a more reliable way to draw it. - cairo_rectangle(_cr, from_x, top, to_x - from_x, bottom - top); - cairo_fill(_cr); - } - else { - int left = std::max(from_x, -scale - 1); - int right = std::min(std::max(to_x, from_x + 1), get_xsize() + scale); - - double radius = std::min((double)scale, (right - left) / 2.0); - cairo_new_sub_path(_cr); - cairo_arc(_cr, right - radius, top + radius, radius, -0.5 * M_PI, 0.0); - cairo_arc(_cr, right - radius, bottom - radius, radius, 0.0, 0.5 * M_PI); - cairo_arc(_cr, left + radius, bottom - radius, radius, 0.5 * M_PI, M_PI); - cairo_arc(_cr, left + radius, top + radius, radius, M_PI, 1.5 * M_PI); - cairo_close_path(_cr); - cairo_fill(_cr); - - if ((to_x - from_x) >= scale * 4) { - // Only bother drawing the text if we've got some space to draw on. - // Choose a suitable foreground color. - LRGBColor fg = get_collector_text_color(collector_index, is_highlighted); - cairo_set_source_rgb(_cr, fg[0], fg[1], fg[2]); - - // Make sure that the text doesn't run off the chart. - int text_width, text_height; - PangoLayout *layout = gtk_widget_create_pango_layout(_graph_window, collector_name.c_str()); - pango_layout_set_attributes(layout, _pango_attrs); - pango_layout_set_height(layout, -1); - pango_layout_get_pixel_size(layout, &text_width, &text_height); - - double center = (from_x + to_x) / 2.0; - double text_left = std::max(from_x, 0) + scale / 2.0; - double text_right = std::min(to_x, get_xsize()) - scale / 2.0; - double text_top = top + (bottom - top - text_height) / 2.0; - - if (text_width >= text_right - text_left) { - size_t c = collector_name.rfind(':'); - if (text_right - text_left < scale * 6) { - // It's a really tiny space. Draw a single letter. - const char *ch = collector_name.data() + (c != std::string::npos ? c + 1 : 0); - pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); - pango_layout_set_text(layout, ch, 1); - } else { - // Maybe just use everything after the last colon. - if (c != std::string::npos) { - pango_layout_set_text(layout, collector_name.data() + c + 1, - collector_name.size() - c - 1); - pango_layout_get_pixel_size(layout, &text_width, &text_height); - } - } - } - - if (text_width >= text_right - text_left) { - // It's going to be tricky to fit it, let pango figure it out. - pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); - pango_layout_set_width(layout, (text_right - text_left) * PANGO_SCALE); - cairo_move_to(_cr, text_left, text_top); - } - else if (center - text_width / 2.0 < 0.0) { - // Put it against the left-most edge. - cairo_move_to(_cr, scale, text_top); - } - else if (center + text_width / 2.0 >= get_xsize()) { - // Put it against the right-most edge. - cairo_move_to(_cr, get_xsize() - scale - text_width, text_top); - } - else { - // It fits just fine, center it. - cairo_move_to(_cr, center - text_width / 2.0, text_top); - } - - pango_cairo_show_layout(_cr, layout); - g_object_unref(layout); - } - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void GtkStatsTimeline:: -end_draw() { - gtk_widget_queue_draw(_graph_window); - - if (_threads_changed) { - // Calculate the size of the thread area. - PangoLayout *layout = gtk_widget_create_pango_layout(_thread_area, ""); - - int max_width = 0; - for (const ThreadRow &thread_row : _threads) { - if (!thread_row._visible) { - continue; - } - pango_layout_set_text(layout, thread_row._label.c_str(), thread_row._label.size()); - - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - - if (width > max_width) { - max_width = width; - } - } - - gtk_widget_set_size_request(_thread_area, max_width + _pixel_scale * 2, 0); - g_object_unref(layout); - gtk_widget_queue_draw(_thread_area); - _threads_changed = false; - } - - if (_guide_bars_changed) { - gtk_widget_queue_draw(_scale_area); - _guide_bars_changed = false; - } -} - -/** - * Called at the end of the draw cycle. - */ -void GtkStatsTimeline:: -idle() { -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool GtkStatsTimeline:: -animate(double time, double dt) { - return PStatTimeline::animate(time, dt); -} - -/** - * Returns the current window dimensions. - */ -bool GtkStatsTimeline:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - GtkStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void GtkStatsTimeline:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - GtkStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * This is called during the servicing of the draw event; it gives a derived - * class opportunity to do some further painting into the graph window. - */ -void GtkStatsTimeline:: -additional_graph_window_paint(cairo_t *cr) { -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string GtkStatsTimeline:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return PStatTimeline::get_bar_tooltip(pixel_to_row(mouse_y), mouse_x); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -GtkStatsGraph::DragMode GtkStatsTimeline:: -consider_drag_start(int graph_x, int graph_y) { - return GtkStatsGraph::consider_drag_start(graph_x, graph_y); -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -gboolean GtkStatsTimeline:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - if (button == 3) { - // Right-clicking a color bar brings up a context menu. - int row = pixel_to_row(graph_y); - - ColorBar bar; - if (find_bar(row, graph_x, bar)) { - GtkWidget *menu = gtk_menu_new(); - _popup_bar = bar; - - std::string label = get_bar_tooltip(row, graph_x); - if (!label.empty()) { - GtkWidget *menu_item = gtk_menu_item_new_with_label(label.c_str()); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - gtk_widget_set_sensitive(menu_item, FALSE); - } - - { - GtkWidget *menu_item = gtk_menu_item_new_with_label("Zoom To"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(+[] (GtkWidget *widget, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - const ColorBar &bar = self->_popup_bar; - double width = bar._end - bar._start; - self->zoom_to(width * 1.5, (bar._end + bar._start) / 2.0); - self->scroll_to(bar._start - width / 4.0); - self->start_animation(); - }), - this); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_strip_chart, - bar._thread_index, bar._collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Strip Chart"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_flame_graph, - bar._thread_index, bar._collector_index, bar._frame_number, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Flame Graph"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_piano_roll, bar._thread_index, -1, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Open Piano Roll"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - GtkWidget *menu_item = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_choose_color, -1, bar._collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Change Color..."); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - { - const GtkStatsMonitor::MenuDef *menu_def = GtkStatsGraph::_monitor->add_menu({ - GtkStatsMonitor::CT_reset_color, -1, bar._collector_index, - }); - - GtkWidget *menu_item = gtk_menu_item_new_with_label("Reset Color"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - g_signal_connect(G_OBJECT(menu_item), "activate", - G_CALLBACK(GtkStatsMonitor::menu_activate), - (void *)menu_def); - } - - gtk_widget_show_all(menu); - gtk_menu_popup_at_pointer(GTK_MENU(menu), nullptr); - return TRUE; - } - return FALSE; - } - else if (double_click && button == 1) { - // Double-clicking on a color bar in the graph will zoom the graph into - // that collector. - int row = pixel_to_row(graph_y); - ColorBar bar; - if (find_bar(row, graph_x, bar)) { - double width = bar._end - bar._start; - zoom_to(width * 1.5, pixel_to_timestamp(graph_x)); - scroll_to(bar._start - width / 4.0); - } else { - // Double-clicking the white area zooms out. - _zoom_speed -= 100.0; - } - start_animation(); - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_pan); - _drag_start_x = graph_x; - _scroll_speed = 0.0; - _zoom_center = pixel_to_timestamp(graph_x); - return TRUE; - } - } - - return GtkStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -gboolean GtkStatsTimeline:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_x < 0 || graph_x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return GtkStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -gboolean GtkStatsTimeline:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none && - graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - // When the mouse is over a color bar, highlight it. - int row = pixel_to_row(graph_y); - std::swap(_highlighted_x, graph_x); - std::swap(_highlighted_row, row); - - if (row >= 0) { - PStatTimeline::force_redraw(row, graph_x, graph_x); - } - PStatTimeline::force_redraw(_highlighted_row, _highlighted_x, _highlighted_x); - - if ((_keys_held & (F_w | F_s)) != 0) { - // Update the zoom center if we move the mouse while zooming with the - // keyboard. - _zoom_center = pixel_to_timestamp(graph_x); - } - } - else { - // If the mouse is in some drag mode, stop highlighting. - if (_highlighted_row != -1) { - int row = _highlighted_row; - _highlighted_row = -1; - PStatTimeline::force_redraw(row, _highlighted_x, _highlighted_x); - } - } - - if (_drag_mode == DM_pan) { - int delta = _drag_start_x - graph_x; - _drag_start_x = graph_x; - set_horizontal_scroll(get_horizontal_scroll() + pixel_to_height(delta)); - return 0; - } - - return GtkStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -gboolean GtkStatsTimeline:: -handle_leave() { - if (_highlighted_row != -1) { - int row = _highlighted_row; - _highlighted_row = -1; - PStatTimeline::force_redraw(row, _highlighted_x, _highlighted_x); - } - return TRUE; -} - -/** - * - */ -gboolean GtkStatsTimeline:: -handle_scroll(int graph_x, int graph_y, double dx, double dy, bool ctrl_held) { - gboolean handled = FALSE; - - if (dy != 0.0) { - handled = TRUE; - if (ctrl_held) { - zoom_by(dy, pixel_to_timestamp(graph_x)); - start_animation(); - } else { - double delta = (int)(dy * _pixel_scale * 5 + 0.5); - int new_scroll = _scroll - delta; - if (_threads.empty()) { - new_scroll = 0; - } else { - new_scroll = (std::min)(new_scroll, get_num_rows() * _pixel_scale * 5 + _pixel_scale * 2 - get_ysize()); - new_scroll = (std::max)(new_scroll, 0); - } - delta = new_scroll - _scroll; - if (delta != 0) { - _scroll = new_scroll; - gtk_widget_queue_draw(_thread_area); - force_redraw(); - } - } - } - - if (dx != 0.0) { - _scroll_speed += dx * 10.0; - handled = TRUE; - start_animation(); - } - - return handled; -} - -/** - * - */ -gboolean GtkStatsTimeline:: -handle_zoom(int graph_x, int graph_y, double scale) { - zoom_to(get_horizontal_scale() / scale, pixel_to_timestamp(graph_x)); - start_animation(); - return TRUE; -} - -/** - * - */ -gboolean GtkStatsTimeline:: -handle_key(bool pressed, guint val, guint16 hw_code) { - // Accept WASD based on their position rather than their mapping - int flag = 0; - switch (hw_code) { - case 25: - flag = F_w; - break; - case 38: - flag = F_a; - break; - case 39: - flag = F_s; - break; - case 40: - flag = F_d; - break; - } - if (flag == 0) { - switch (val) { - case GDK_KEY_Left: - flag = F_left; - break; - case GDK_KEY_Right: - flag = F_right; - break; - case GDK_KEY_w: - flag = F_w; - break; - case GDK_KEY_a: - flag = F_a; - break; - case GDK_KEY_s: - flag = F_s; - break; - case GDK_KEY_d: - flag = F_d; - break; - } - } - if (flag != 0) { - if (pressed) { - if (flag & (F_w | F_s)) { - // Pfoo, GTK sure does make it hard to just get the cursor position. - GdkWindow *window = gtk_widget_get_window(_graph_window); - GdkDisplay *display = gdk_window_get_display(window); - GdkDeviceManager *device_manager = gdk_display_get_device_manager(display); - GdkDevice *device = gdk_device_manager_get_client_pointer(device_manager); - gint x, y; - gdk_window_get_device_position(window, device, &x, &y, nullptr); - _zoom_center = pixel_to_timestamp(x * _cr_scale); - } - if (_keys_held == 0) { - start_animation(); - } - _keys_held |= flag; - } - else if (_keys_held != 0) { - _keys_held &= ~flag; - } - return TRUE; - } - return FALSE; -} - -/** - * This is called during the servicing of the draw event. - */ -void GtkStatsTimeline:: -draw_guide_labels(cairo_t *cr) { - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_label(cr, get_guide_bar(i)); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void GtkStatsTimeline:: -draw_guide_label(cairo_t *cr, const PStatGraph::GuideBar &bar) { - const std::string &label = bar._label; - if (label.empty()) { - return; - } - - bool center = true; - switch (bar._style) { - case GBS_target: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_user: - cairo_set_source_rgb(cr, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2]); - break; - - case GBS_normal: - cairo_set_source_rgb(cr, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2]); - break; - - case GBS_frame: - cairo_set_source_rgb(cr, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2]); - center = false; - break; - } - - PangoLayout *layout = gtk_widget_create_pango_layout(_scale_area, label.c_str()); - - if (bar._style != GBS_frame) { - // Make the offsets slightly smaller. - PangoAttrList *attrs = pango_attr_list_new(); - PangoAttribute *attr = pango_attr_scale_new(0.9); - attr->start_index = 0; - attr->end_index = -1; - pango_attr_list_insert(attrs, attr); - pango_layout_set_attributes(layout, attrs); - pango_attr_list_unref(attrs); - } - - int width, height; - pango_layout_get_pixel_size(layout, &width, &height); - - int x = timestamp_to_pixel(bar._height); - if (x >= 0 && x + width * _cr_scale < get_xsize()) { - // Now convert our x to a coordinate within our drawing area. - int junk_y; - - x /= _cr_scale; - - // The x coordinate comes from the graph_window. - gtk_widget_translate_coordinates(_graph_window, _scale_area, - x, 0, &x, &junk_y); - - GtkAllocation allocation; - gtk_widget_get_allocation(_scale_area, &allocation); - - if (x >= 0) { - int this_x = x; - if (center) { - this_x -= width / 2; - } - if (this_x + width < allocation.width) { - cairo_move_to(cr, this_x, allocation.height - height); - pango_cairo_show_layout(cr, layout); - } - } - } - - g_object_unref(layout); -} - -/** - * This is called during the servicing of the draw event. - */ -void GtkStatsTimeline:: -draw_thread_labels(cairo_t *cr) { - for (const ThreadRow &thread_row : _threads) { - if (thread_row._visible) { - draw_thread_label(cr, thread_row); - } - } -} - -/** - * Draws the text for the indicated thread on the side of the graph. - */ -void GtkStatsTimeline:: -draw_thread_label(cairo_t *cr, const ThreadRow &thread_row) { - int top = row_to_pixel(thread_row._row_offset); - if (top <= get_ysize()) { - // Now convert our y to a coordinate within our drawing area. - top /= _cr_scale; - - // The y coordinate comes from the graph_window. - int junk_x; - gtk_widget_translate_coordinates(_graph_window, _thread_area, - 0, top, &junk_x, &top); - - GtkAllocation allocation; - gtk_widget_get_allocation(_thread_area, &allocation); - - PangoLayout *layout = gtk_widget_create_pango_layout(_thread_area, thread_row._label.c_str()); - pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); - pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); - pango_layout_set_width(layout, (allocation.width - _pixel_scale * 2) * PANGO_SCALE); - - cairo_move_to(cr, _pixel_scale, top); - pango_cairo_show_layout(cr, layout); - g_object_unref(layout); - } -} - -/** - * Draws in the scale labels. - */ -gboolean GtkStatsTimeline:: -scale_area_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - self->draw_guide_labels(cr); - - return TRUE; -} - -/** - * Draws in the thread labels. - */ -gboolean GtkStatsTimeline:: -thread_area_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - self->draw_thread_labels(cr); - - return TRUE; -} - -/** - * - */ -gboolean GtkStatsTimeline:: -scroll_callback(GtkWidget *widget, GdkEventScroll *event, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - - bool ctrl_held = (event->state & GDK_CONTROL_MASK) != 0; - - double dx, dy; - if (event->direction == GDK_SCROLL_UP) { - dx = 0; - dy = 1; - } - else if (event->direction == GDK_SCROLL_DOWN) { - dx = 0; - dy = -1; - } - else if (event->direction == GDK_SCROLL_LEFT) { - dx = 1; - dy = 0; - } - else if (event->direction == GDK_SCROLL_RIGHT) { - dx = -1; - dy = 0; - } - else if (!gdk_event_get_scroll_deltas((GdkEvent *)event, &dx, &dy)) { - return FALSE; - } - - int graph_x = (int)(event->x * self->_cr_scale); - int graph_y = (int)(event->y * self->_cr_scale); - return self->handle_scroll(graph_x, graph_y, dx, dy, ctrl_held); -} - -/** - * - */ -gboolean GtkStatsTimeline:: -key_press_callback(GtkWidget *widget, GdkEventKey *event, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - return self->handle_key(true, event->keyval, event->hardware_keycode); -} - -/** - * - */ -gboolean GtkStatsTimeline:: -key_release_callback(GtkWidget *widget, GdkEventKey *event, gpointer data) { - GtkStatsTimeline *self = (GtkStatsTimeline *)data; - return self->handle_key(false, event->keyval, event->hardware_keycode); -} diff --git a/pandatool/src/gtk-stats/gtkStatsTimeline.h b/pandatool/src/gtk-stats/gtkStatsTimeline.h deleted file mode 100644 index b354712d..00000000 --- a/pandatool/src/gtk-stats/gtkStatsTimeline.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file gtkStatsTimeline.h - * @author rdb - * @date 2022-02-17 - */ - -#ifndef GTKSTATSTIMELINE_H -#define GTKSTATSTIMELINE_H - -#include "pandatoolbase.h" - -#include "gtkStatsGraph.h" -#include "pStatTimeline.h" - -class GtkStatsMonitor; - -/** - * A window that draws all of the start/stop event pairs on each thread on a - * horizontal scrolling timeline, with concurrent start/stop pairs stacked - * underneath each other. - */ -class GtkStatsTimeline final : public PStatTimeline, public GtkStatsGraph { -public: - GtkStatsTimeline(GtkStatsMonitor *monitor); - virtual ~GtkStatsTimeline(); - - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - -protected: - virtual void clear_region(); - virtual void begin_draw(); - virtual void draw_separator(int row); - virtual void draw_guide_bar(int x, GuideBarStyle style); - virtual void draw_bar(int row, int from_x, int to_x, int collector_index, - const std::string &collector_name); - virtual void end_draw(); - virtual void idle(); - - virtual bool animate(double time, double dt); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual void additional_graph_window_paint(cairo_t *cr); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - - virtual gboolean handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual gboolean handle_button_release(int graph_x, int graph_y); - virtual gboolean handle_motion(int graph_x, int graph_y); - virtual gboolean handle_leave(); - gboolean handle_scroll(int graph_x, int graph_y, - double dx, double dy, bool ctrl_held); - gboolean handle_zoom(int graph_x, int graph_y, double scale); - gboolean handle_key(bool pressed, guint val, guint16 hw_code); - -private: - void draw_guide_labels(cairo_t *cr); - void draw_guide_label(cairo_t *cr, const GuideBar &bar); - void draw_thread_labels(cairo_t *cr); - void draw_thread_label(cairo_t *cr, const ThreadRow &thread_row); - - static gboolean scale_area_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data); - static gboolean thread_area_draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data); - static gboolean scroll_callback(GtkWidget *widget, GdkEventScroll *event, gpointer data); - static gboolean key_press_callback(GtkWidget *widget, GdkEventKey *event, gpointer data); - static gboolean key_release_callback(GtkWidget *widget, GdkEventKey *event, gpointer data); - - int row_to_pixel(int y) const { - return y * _pixel_scale * 5 + _pixel_scale - _scroll; - } - int pixel_to_row(int y) const { - return (y + _scroll - _pixel_scale) / (_pixel_scale * 5); - } - - GtkWidget *_thread_area; - - cairo_pattern_t *_grid_pattern; - - int _highlighted_row = -1; - int _highlighted_x = 0; - int _scroll = 0; - ColorBar _popup_bar; - - double _zoom_scale = 1.0; - GtkGesture *_zoom_gesture = nullptr; -}; - -#endif diff --git a/pandatool/src/gtk-stats/gtkstats_composite1.cxx b/pandatool/src/gtk-stats/gtkstats_composite1.cxx deleted file mode 100644 index 3ab44d39..00000000 --- a/pandatool/src/gtk-stats/gtkstats_composite1.cxx +++ /dev/null @@ -1,11 +0,0 @@ -#include "gtkStats.cxx" -#include "gtkStatsChartMenu.cxx" -#include "gtkStatsFlameGraph.cxx" -#include "gtkStatsGraph.cxx" -#include "gtkStatsLabel.cxx" -#include "gtkStatsLabelStack.cxx" -#include "gtkStatsMonitor.cxx" -#include "gtkStatsPianoRoll.cxx" -#include "gtkStatsServer.cxx" -#include "gtkStatsStripChart.cxx" -#include "gtkStatsTimeline.cxx" diff --git a/pandatool/src/imagebase/CMakeLists.txt b/pandatool/src/imagebase/CMakeLists.txt deleted file mode 100644 index 46ffce3d..00000000 --- a/pandatool/src/imagebase/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -set(P3IMAGEBASE_HEADERS - imageBase.h - imageFilter.h - imageReader.h - imageWriter.h imageWriter.I -) - -set(P3IMAGEBASE_SOURCES - imageBase.cxx - imageFilter.cxx - imageReader.cxx - imageWriter.cxx -) - -composite_sources(p3imagebase P3IMAGEBASE_SOURCES) -add_library(p3imagebase STATIC ${P3IMAGEBASE_HEADERS} ${P3IMAGEBASE_SOURCES}) -target_link_libraries(p3imagebase p3progbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/imagebase/imageBase.cxx b/pandatool/src/imagebase/imageBase.cxx deleted file mode 100644 index 837f0bdf..00000000 --- a/pandatool/src/imagebase/imageBase.cxx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageBase.cxx - * @author drose - * @date 2000-06-19 - */ - -#include "imageBase.h" - -/** - * - */ -ImageBase:: -ImageBase() { -} - - -/** - * - */ -bool ImageBase:: -post_command_line() { - return ProgramBase::post_command_line(); -} diff --git a/pandatool/src/imagebase/imageBase.h b/pandatool/src/imagebase/imageBase.h deleted file mode 100644 index 5b106c8c..00000000 --- a/pandatool/src/imagebase/imageBase.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageBase.h - * @author drose - * @date 2000-06-19 - */ - -#ifndef IMAGEBASE_H -#define IMAGEBASE_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "coordinateSystem.h" -#include "pnmImage.h" - -/** - * This specialization of ProgramBase is intended for programs that read - * and/or write a single image file. (See ImageMultiBase for programs that - * operate on multiple image files at once.) - * - * This is just a base class; see ImageReader, ImageWriter, or ImageFilter - * according to your particular I/O needs. - */ -class ImageBase : public ProgramBase { -public: - ImageBase(); - -protected: - virtual bool post_command_line(); - -protected: - PNMImage _image; -}; - -#endif diff --git a/pandatool/src/imagebase/imageFilter.cxx b/pandatool/src/imagebase/imageFilter.cxx deleted file mode 100644 index 63957ed5..00000000 --- a/pandatool/src/imagebase/imageFilter.cxx +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageFilter.cxx - * @author drose - * @date 2000-06-19 - */ - -#include "imageFilter.h" - -/** - * - */ -ImageFilter:: -ImageFilter(bool allow_last_param) : - ImageWriter(allow_last_param) -{ - clear_runlines(); - if (_allow_last_param) { - add_runline("[opts] inputimage outputimage"); - } - add_runline("[opts] -o outputimage inputimage"); -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool ImageFilter:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 1)) { - return false; - } - - return ImageReader::handle_args(args); -} diff --git a/pandatool/src/imagebase/imageFilter.h b/pandatool/src/imagebase/imageFilter.h deleted file mode 100644 index ae53da53..00000000 --- a/pandatool/src/imagebase/imageFilter.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageFilter.h - * @author drose - * @date 2000-06-19 - */ - -#ifndef IMAGEFILTER_H -#define IMAGEFILTER_H - -#include "pandatoolbase.h" - -#include "imageReader.h" -#include "imageWriter.h" - -/** - * This is the base class for a program that reads an image file, operates on - * it, and writes another image file out. - */ -class ImageFilter : public ImageReader, public ImageWriter { -public: - ImageFilter(bool allow_last_param); - -protected: - virtual bool handle_args(Args &args); -}; - -#endif diff --git a/pandatool/src/imagebase/imageReader.cxx b/pandatool/src/imagebase/imageReader.cxx deleted file mode 100644 index 4e4e6690..00000000 --- a/pandatool/src/imagebase/imageReader.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageReader.cxx - * @author drose - * @date 2000-06-19 - */ - -#include "imageReader.h" - -/** - * - */ -ImageReader:: -ImageReader() { - clear_runlines(); - add_runline("[opts] imagename"); -} - -/** - * - */ -bool ImageReader:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the image file to read on the command line.\n"; - return false; - } - - if (args.size() > 1) { - nout << "Specify only one image on the command line.\n"; - return false; - } - - if (!_image.read(args[0])) { - nout << "Unable to read image file " << args[0] << ".\n"; - exit(1); - } - - return true; -} diff --git a/pandatool/src/imagebase/imageReader.h b/pandatool/src/imagebase/imageReader.h deleted file mode 100644 index c3c81856..00000000 --- a/pandatool/src/imagebase/imageReader.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageReader.h - * @author drose - * @date 2000-06-19 - */ - -#ifndef IMAGEREADER_H -#define IMAGEREADER_H - -#include "pandatoolbase.h" - -#include "imageBase.h" - -/** - * This is the base class for a program that reads an image file, but doesn't - * write an image file. - */ -class ImageReader : virtual public ImageBase { -public: - ImageReader(); - -protected: - virtual bool handle_args(Args &args); - -}; - -#endif diff --git a/pandatool/src/imagebase/imageWriter.I b/pandatool/src/imagebase/imageWriter.I deleted file mode 100644 index b8400819..00000000 --- a/pandatool/src/imagebase/imageWriter.I +++ /dev/null @@ -1,20 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageWriter.I - * @author drose - * @date 2000-06-19 - */ - -/** - * Writes the generated to the user's specified output filename. - */ -INLINE void ImageWriter:: -write_image() { - write_image(_image); -} diff --git a/pandatool/src/imagebase/imageWriter.cxx b/pandatool/src/imagebase/imageWriter.cxx deleted file mode 100644 index eb50188e..00000000 --- a/pandatool/src/imagebase/imageWriter.cxx +++ /dev/null @@ -1,80 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageWriter.cxx - * @author drose - * @date 2000-06-19 - */ - -#include "imageWriter.h" - -/** - * Image-writing type programs *must* specify their output file using -o. - */ -ImageWriter:: -ImageWriter(bool allow_last_param) : - WithOutputFile(allow_last_param, false, true) -{ - clear_runlines(); - if (_allow_last_param) { - add_runline("[opts] outputimage"); - } - add_runline("[opts] -o outputimage"); - - std::string o_description; - if (_allow_last_param) { - o_description = - "Specify the filename to which the resulting image file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file."; - } else { - o_description = - "Specify the filename to which the resulting image file will be written."; - } - - add_option - ("o", "filename", 50, o_description, - &ImageWriter::dispatch_filename, &_got_output_filename, &_output_filename); -} - - -/** - * Writes the generated to the user's specified output filename. - */ -void ImageWriter:: -write_image(const PNMImage &image) { - if (!image.write(get_output_filename())) { - nout << "Unable to write output image to " - << get_output_filename() << "\n"; - exit(1); - } -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool ImageWriter:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 0)) { - return false; - } - - if (!args.empty()) { - nout << "Unexpected arguments on command line:\n"; - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - nout << (*ai) << " "; - } - nout << "\r"; - return false; - } - - return true; -} diff --git a/pandatool/src/imagebase/imageWriter.h b/pandatool/src/imagebase/imageWriter.h deleted file mode 100644 index f902af29..00000000 --- a/pandatool/src/imagebase/imageWriter.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageWriter.h - * @author drose - * @date 2000-06-19 - */ - -#ifndef IMAGEWRITER_H -#define IMAGEWRITER_H - -#include "pandatoolbase.h" -#include "imageBase.h" -#include "withOutputFile.h" - -#include "filename.h" - -/** - * This is the base class for a program that generates an image file output, - * but doesn't read any for input. - */ -class ImageWriter : virtual public ImageBase, public WithOutputFile { -public: - ImageWriter(bool allow_last_param); - - INLINE void write_image(); - void write_image(const PNMImage &image); - -protected: - virtual bool handle_args(Args &args); -}; - -#include "imageWriter.I" - -#endif diff --git a/pandatool/src/imagebase/p3imagebase_composite1.cxx b/pandatool/src/imagebase/p3imagebase_composite1.cxx deleted file mode 100644 index 35b20753..00000000 --- a/pandatool/src/imagebase/p3imagebase_composite1.cxx +++ /dev/null @@ -1,6 +0,0 @@ - -#include "imageBase.cxx" -#include "imageFilter.cxx" -#include "imageReader.cxx" -#include "imageWriter.cxx" - diff --git a/pandatool/src/imageprogs/CMakeLists.txt b/pandatool/src/imageprogs/CMakeLists.txt deleted file mode 100644 index e91d4c69..00000000 --- a/pandatool/src/imageprogs/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(image-fix-hidden-color imageFixHiddenColor.cxx imageFixHiddenColor.h) -target_link_libraries(image-fix-hidden-color p3imagebase) -install(TARGETS image-fix-hidden-color EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(image-info imageInfo.cxx imageInfo.h) -target_link_libraries(image-info p3imagebase) -install(TARGETS image-info EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(image-resize imageResize.cxx imageResize.h) -target_link_libraries(image-resize p3imagebase) -install(TARGETS image-resize EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(image-transform-colors imageTransformColors.cxx imageTransformColors.h) -target_link_libraries(image-transform-colors p3imagebase) -install(TARGETS image-transform-colors EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(image-trans imageTrans.cxx imageTrans.h) -target_link_libraries(image-trans p3imagebase) -install(TARGETS image-trans EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/imageprogs/imageFixHiddenColor.I b/pandatool/src/imageprogs/imageFixHiddenColor.I deleted file mode 100644 index 8c41f570..00000000 --- a/pandatool/src/imageprogs/imageFixHiddenColor.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageFixHiddenColor.I - * @author drose - * @date 2003-03-13 - */ diff --git a/pandatool/src/imageprogs/imageFixHiddenColor.cxx b/pandatool/src/imageprogs/imageFixHiddenColor.cxx deleted file mode 100644 index 44d1c91a..00000000 --- a/pandatool/src/imageprogs/imageFixHiddenColor.cxx +++ /dev/null @@ -1,149 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageFixHiddenColor.cxx - * @author drose - * @date 2003-03-13 - */ - -#include "imageFixHiddenColor.h" -#include "string_utils.h" - -/** - * - */ -ImageFixHiddenColor:: -ImageFixHiddenColor() : ImageFilter(true) { - set_program_brief("change the color of transparent pixels in an image"); - set_program_description - ("This program is designed to fix the color channels of an " - "alpha-cutout image, making the \"color\" of the invisible part of the " - "image consistent with the rest of the image. It does this by " - "analyzing the RGB values of the image where alpha == 1, and using the " - "average of these values as the overall image color, which it then " - "applies to the image wherever alpha == 0. When the alpha value is " - "neither 1 nor 0, the pixel is ignored.\n\n" - - "This process is important for applications that filter the texture " - "size down by averaging neighboring pixels. If the color under the " - "alpha == 0 pixels is very different from the color elsewhere, this " - "kind of filtering can have a visible effect on the image's color, even " - "where alpha != 0."); - - add_option - ("alpha", "filename", 0, - "Specifies a separate filename that will be used in lieu of the " - "alpha channel on the source image. If this file has an alpha " - "channel, that alpha channel is used; otherwise, the grayscale " - "value of the image is used.", - &ImageFixHiddenColor::dispatch_filename, nullptr, &_alpha_filename); - - add_option - ("opaque", "alpha", 0, - "Specifies the minimum alpha value (in the range of 0 to 1) for a " - "pixel to be considered fully opaque. The default is 1.", - &ImageFixHiddenColor::dispatch_double, nullptr, &_min_opaque_alpha); - - add_option - ("transparent", "alpha", 0, - "Specifies the maximum alpha value (in the range of 0 to 1) for a " - "pixel to be considered fully transparent. The default is 0.", - &ImageFixHiddenColor::dispatch_double, nullptr, &_max_transparent_alpha); - - _min_opaque_alpha = 1.0; - _max_transparent_alpha = 0.0; -} - -/** - * - */ -void ImageFixHiddenColor:: -run() { - PNMImage alpha_image; - - if (_alpha_filename.empty()) { - // No separate alpha file is provided; use the base file's alpha channel. - if (!_image.has_alpha()) { - nout << "Image does not have an alpha channel.\n"; - exit(1); - } - alpha_image = _image; - - } else { - // In this case, the alpha channel is in a separate file. - if (!alpha_image.read(_alpha_filename)) { - nout << "Unable to read " << _alpha_filename << ".\n"; - exit(1); - } - - if (!alpha_image.has_alpha()) { - // Copy the grayscale value to the alpha channel for the benefit of the - // code below. - alpha_image.add_alpha(); - int xi, yi; - for (yi = 0; yi < alpha_image.get_y_size(); ++yi) { - for (xi = 0; xi < alpha_image.get_x_size(); ++xi) { - alpha_image.set_alpha(xi, yi, alpha_image.get_gray(xi, yi)); - } - } - } - - // Make sure the alpha image matches the size of the source image. - if (alpha_image.get_x_size() != _image.get_x_size() || - alpha_image.get_y_size() != _image.get_y_size()) { - PNMImage scaled(_image.get_x_size(), _image.get_y_size(), alpha_image.get_num_channels()); - scaled.quick_filter_from(alpha_image); - alpha_image = scaled; - } - } - - // First, get the average color of all the opaque pixels. - int count = 0; - LRGBColorf color(0.0, 0.0, 0.0); - int xi, yi; - for (yi = 0; yi < _image.get_y_size(); ++yi) { - for (xi = 0; xi < _image.get_x_size(); ++xi) { - if (alpha_image.get_alpha(xi, yi) >= _min_opaque_alpha) { - color += _image.get_xel(xi, yi); - ++count; - } - } - } - if (count == 0) { - nout << "Image has no opaque pixels.\n"; - exit(1); - } - color /= (double)count; - nout << " average color of " << count << " opaque pixels is " << color << "\n"; - - // Now, apply that wherever there are transparent pixels. - count = 0; - for (yi = 0; yi < _image.get_y_size(); ++yi) { - for (xi = 0; xi < _image.get_x_size(); ++xi) { - if (alpha_image.get_alpha(xi, yi) <= _max_transparent_alpha) { - _image.set_xel(xi, yi, color); - ++count; - } - } - } - if (count == 0) { - nout << "Image has no transparent pixels.\n"; - exit(1); - } - nout << " applied to " << count << " transparent pixels.\n"; - - write_image(_image); -} - - -int main(int argc, char *argv[]) { - ImageFixHiddenColor prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/imageprogs/imageFixHiddenColor.h b/pandatool/src/imageprogs/imageFixHiddenColor.h deleted file mode 100644 index eb272eb0..00000000 --- a/pandatool/src/imageprogs/imageFixHiddenColor.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageFixHiddenColor.h - * @author drose - * @date 2003-03-13 - */ - -#ifndef IMAGEFIXHIDDENCOLOR_H -#define IMAGEFIXHIDDENCOLOR_H - -#include "pandatoolbase.h" - -#include "imageFilter.h" - -/** - * This program repairs an image's RGB values hidden behind an A value of 0. - */ -class ImageFixHiddenColor : public ImageFilter { -public: - ImageFixHiddenColor(); - - void run(); - -private: - Filename _alpha_filename; - double _min_opaque_alpha; - double _max_transparent_alpha; -}; - -#include "imageFixHiddenColor.I" - -#endif diff --git a/pandatool/src/imageprogs/imageInfo.cxx b/pandatool/src/imageprogs/imageInfo.cxx deleted file mode 100644 index 7cbde069..00000000 --- a/pandatool/src/imageprogs/imageInfo.cxx +++ /dev/null @@ -1,94 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageInfo.cxx - * @author drose - * @date 2003-03-13 - */ - -#include "imageInfo.h" -#include "pnmImageHeader.h" - -/** - * - */ -ImageInfo:: -ImageInfo() { - set_program_brief("report the size of image files"); - set_program_description - ("This program reads the headers of a series of one or more " - "image files and reports the image sizes to standard output."); - - add_option - ("2", "", 0, - "Report only images that have a non-power-of-two size in either " - "dimension. Images whose dimensions are both a power of two will " - "not be mentioned.", - &ImageInfo::dispatch_none, &_report_power_2, nullptr); -} - -/** - * - */ -void ImageInfo:: -run() { - Args::const_iterator ai; - for (ai = _filenames.begin(); ai != _filenames.end(); ++ai) { - Filename filename = (*ai); - PNMImageHeader header; - if (!header.read_header(filename)) { - // Could not read the image header. - if (filename.exists()) { - nout << filename << ": could not read image.\n"; - } else { - nout << filename << ": does not exist.\n"; - } - } else { - // Successfully read the image header. - if (!_report_power_2 || - !is_power_2(header.get_x_size()) || - !is_power_2(header.get_y_size())) { - nout << filename << ": " << header.get_x_size() << " x " - << header.get_y_size() << " x " << header.get_num_channels() - << " (maxval = " << header.get_maxval() << ")\n"; - } - } - } -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool ImageInfo:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "List one or more image filenames on command line.\n"; - return false; - } - _filenames = args; - - return true; -} - -/** - * Returns true if the indicated value is a power of 2, false otherwise. - */ -bool ImageInfo:: -is_power_2(int value) const { - return (value & (value - 1)) == 0; -} - - -int main(int argc, char *argv[]) { - ImageInfo prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/imageprogs/imageInfo.h b/pandatool/src/imageprogs/imageInfo.h deleted file mode 100644 index 4a6e2e9e..00000000 --- a/pandatool/src/imageprogs/imageInfo.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageInfo.h - * @author drose - * @date 2003-03-13 - */ - -#ifndef IMAGEINFO_H -#define IMAGEINFO_H - -#include "pandatoolbase.h" - -#include "programBase.h" - -/** - * This program reads the headers of a series of one or more images and - * reports their sizes to standard output. - */ -class ImageInfo : public ProgramBase { -public: - ImageInfo(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - -private: - bool is_power_2(int value) const; - - Args _filenames; - bool _report_power_2; -}; - -#endif diff --git a/pandatool/src/imageprogs/imageResize.I b/pandatool/src/imageprogs/imageResize.I deleted file mode 100644 index 25dd5f87..00000000 --- a/pandatool/src/imageprogs/imageResize.I +++ /dev/null @@ -1,99 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageResize.I - * @author drose - * @date 2003-03-13 - */ - -/** - * - */ -INLINE ImageResize::SizeRequest:: -SizeRequest() { - _type = RT_none; -} - -/** - * Returns the type of the size request, or RT_none if the request has not - * been specified. - */ -INLINE ImageResize::RequestType ImageResize::SizeRequest:: -get_type() const { - return _type; -} - -/** - * Sets the size request to store an explicit pixel size. - */ -INLINE void ImageResize::SizeRequest:: -set_pixel_size(int pixel_size) { - _type = RT_pixel_size; - _e._pixel_size = pixel_size; -} - -/** - * Returns the explicit pixel size stored within the size request. - */ -INLINE int ImageResize::SizeRequest:: -get_pixel_size() const { - nassertr(_type == RT_pixel_size, 0); - return _e._pixel_size; -} - -/** - * Returns the explicit pixel size stored within the size request, or if a - * ratio has been stored, returns the computed pixel size based on the - * original size. - */ -INLINE int ImageResize::SizeRequest:: -get_pixel_size(int orig_pixel_size) const { - switch (_type) { - case RT_pixel_size: - return _e._pixel_size; - case RT_ratio: - return (int)(_e._ratio * orig_pixel_size + 0.5); - default: - return orig_pixel_size; - } -} - -/** - * Sets the size request to store a specific ratio. - */ -INLINE void ImageResize::SizeRequest:: -set_ratio(double ratio) { - _type = RT_ratio; - _e._ratio = ratio; -} - -/** - * Returns the specific ratio stored within the size request. - */ -INLINE double ImageResize::SizeRequest:: -get_ratio() const { - nassertr(_type == RT_ratio, 0); - return _e._ratio; -} - -/** - * Returns the specific ratio stored within the size request, or if a pixel - * size has been stored, returns the computed ratio based on the original - * size. - */ -INLINE double ImageResize::SizeRequest:: -get_ratio(int orig_pixel_size) const { - switch (_type) { - case RT_ratio: - return _e._ratio; - case RT_pixel_size: - return (double)_e._pixel_size / (double)orig_pixel_size; - default: - return 1.0; - } -} diff --git a/pandatool/src/imageprogs/imageResize.cxx b/pandatool/src/imageprogs/imageResize.cxx deleted file mode 100644 index a41ff771..00000000 --- a/pandatool/src/imageprogs/imageResize.cxx +++ /dev/null @@ -1,123 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageResize.cxx - * @author drose - * @date 2003-03-13 - */ - -#include "imageResize.h" -#include "string_utils.h" - -/** - * - */ -ImageResize:: -ImageResize() : ImageFilter(true) { - set_program_brief("resize an image file"); - set_program_description - ("This program reads an image file and resizes it to a larger or smaller " - "image file."); - - add_option - ("x", "xsize", 0, - "Specify the width of the output image in pixels, or as a percentage " - "of the original width (if a trailing percent sign is included). " - "If this is omitted, the ratio is taken from the ysize parameter.", - &ImageResize::dispatch_size_request, nullptr, &_x_size); - - add_option - ("y", "ysize", 0, - "Specify the height of the output image in pixels, or as a percentage " - "of the original height (if a trailing percent sign is included). " - "If this is omitted, the ratio is taken from the xsize parameter.", - &ImageResize::dispatch_size_request, nullptr, &_y_size); - - add_option - ("g", "radius", 0, - "Use Gaussian filtering to resize the image, with the indicated radius.", - &ImageResize::dispatch_double, &_use_gaussian_filter, &_filter_radius); - - add_option - ("1", "", 0, - "This option is ignored. It is provided only for backward compatibility " - "with a previous version of image-resize.", - &ImageResize::dispatch_none, nullptr, nullptr); - - _filter_radius = 1.0; -} - -/** - * - */ -void ImageResize:: -run() { - if (_x_size.get_type() == RT_none && _y_size.get_type() == RT_none) { - _x_size.set_ratio(1.0); - _y_size.set_ratio(1.0); - } else if (_x_size.get_type() == RT_none) { - _x_size.set_ratio(_y_size.get_ratio(_image.get_y_size())); - } else if (_y_size.get_type() == RT_none) { - _y_size.set_ratio(_x_size.get_ratio(_image.get_x_size())); - } - - int x_size = _x_size.get_pixel_size(_image.get_x_size()); - int y_size = _y_size.get_pixel_size(_image.get_y_size()); - - nout << "Resizing to " << x_size << " x " << y_size << "\n"; - PNMImage new_image(x_size, y_size, - _image.get_num_channels(), - _image.get_maxval(), _image.get_type()); - - if (_use_gaussian_filter) { - new_image.gaussian_filter_from(_filter_radius, _image); - } else { - new_image.quick_filter_from(_image); - } - - write_image(new_image); -} - -/** - * Interprets the -x or -y parameters. - */ -bool ImageResize:: -dispatch_size_request(const std::string &opt, const std::string &arg, void *var) { - SizeRequest *ip = (SizeRequest *)var; - if (!arg.empty() && arg[arg.length() - 1] == '%') { - // A ratio. - std::string str = arg.substr(0, arg.length() - 1); - double ratio; - if (!string_to_double(str, ratio)) { - nout << "Invalid ratio for -" << opt << ": " - << str << "\n"; - return false; - } - ip->set_ratio(ratio / 100.0); - - } else { - // A pixel size. - int pixel_size; - if (!string_to_int(arg, pixel_size)) { - nout << "Invalid pixel size for -" << opt << ": " - << arg << "\n"; - return false; - } - ip->set_pixel_size(pixel_size); - } - - return true; -} - - -int main(int argc, char *argv[]) { - ImageResize prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/imageprogs/imageResize.h b/pandatool/src/imageprogs/imageResize.h deleted file mode 100644 index 731786a4..00000000 --- a/pandatool/src/imageprogs/imageResize.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageResize.h - * @author drose - * @date 2003-03-13 - */ - -#ifndef IMAGERESIZE_H -#define IMAGERESIZE_H - -#include "pandatoolbase.h" - -#include "imageFilter.h" - -/** - * A program to read an image file and resize it to a larger or smaller image - * file. - */ -class ImageResize : public ImageFilter { -public: - ImageResize(); - - void run(); - -private: - static bool dispatch_size_request(const std::string &opt, const std::string &arg, void *var); - - enum RequestType { - RT_none, - RT_pixel_size, - RT_ratio, - }; - class SizeRequest { - public: - INLINE SizeRequest(); - INLINE RequestType get_type() const; - - INLINE void set_pixel_size(int pixel_size); - INLINE int get_pixel_size() const; - INLINE int get_pixel_size(int orig_pixel_size) const; - INLINE void set_ratio(double ratio); - INLINE double get_ratio() const; - INLINE double get_ratio(int orig_pixel_size) const; - - private: - RequestType _type; - union { - int _pixel_size; - double _ratio; - } _e; - }; - - SizeRequest _x_size; - SizeRequest _y_size; - - bool _use_gaussian_filter; - double _filter_radius; -}; - -#include "imageResize.I" - -#endif diff --git a/pandatool/src/imageprogs/imageTrans.cxx b/pandatool/src/imageprogs/imageTrans.cxx deleted file mode 100644 index 517abee6..00000000 --- a/pandatool/src/imageprogs/imageTrans.cxx +++ /dev/null @@ -1,209 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageTrans.cxx - * @author drose - * @date 2000-06-19 - */ - -#include "imageTrans.h" -#include "string_utils.h" - -/** - * - */ -ImageTrans:: -ImageTrans() : ImageFilter(true) { - set_program_brief("apply transformations to an image file"); - set_program_description - ("This program reads an image file and writes a similar " - "image file to the output. It can implicitly convert from one image " - "file format to another; it uses the extension of the output filename " - "to specify the destination file format."); - - add_option - ("chan", "channels", 50, - "Elevate (or truncate) the image to the indicated number of channels. " - "This may be 1, 2, 3, or 4. You may also specify one of the keywords " - "l, la, rgb, or rgba, respectively, or any of the keywords r, g, b, or " - "a to extract out just the indicated channel as a single grayscale " - "image.", - &ImageTrans::dispatch_channels, nullptr, &_channels); - - add_option - ("cscale", "r,g,b[,a]", 50, - "Apply the indicated color scale to each pixel of the image.", - &ImageTrans::dispatch_color, &_has_color_scale, &_color_scale); - - add_option - ("flip", "", 50, - "Flip the image vertically.", - &ImageTrans::dispatch_none, &_flip); - - add_option - ("mirror", "", 50, - "Reverse the image horizontally.", - &ImageTrans::dispatch_none, &_mirror); - - add_option - ("cw", "", 50, - "Rotate the image 90 degrees clockwise.", - &ImageTrans::dispatch_none, &_cw); - - add_option - ("ccw", "", 50, - "Rotate the image 90 degrees counter-clockwise.", - &ImageTrans::dispatch_none, &_ccw); - - _channels = C_default; - _color_scale.set(1.0f, 1.0f, 1.0f, 1.0f); -} - -/** - * - */ -void ImageTrans:: -run() { - switch (_channels) { - case C_default: - break; - - case C_l: - case C_la: - case C_rgb: - case C_rgba: - _image.set_num_channels((int)_channels); - break; - - case C_r: - _image.make_grayscale(1.0, 0.0, 0.0); - _image.remove_alpha(); - break; - - case C_g: - _image.make_grayscale(0.0, 1.0, 0.0); - _image.remove_alpha(); - break; - - case C_b: - _image.make_grayscale(0.0, 0.0, 1.0); - _image.remove_alpha(); - break; - - case C_a: - extract_alpha(); - break; - } - - if (_has_color_scale) { - if (_color_scale[0] != 1.0f || - _color_scale[1] != 1.0f || - _color_scale[2] != 1.0f) { - for (int yi = 0; yi < _image.get_y_size(); ++yi) { - for (int xi = 0; xi < _image.get_x_size(); ++xi) { - LRGBColorf rgb = _image.get_xel(xi, yi); - _image.set_xel(xi, yi, - rgb[0] * _color_scale[0], - rgb[1] * _color_scale[1], - rgb[2] * _color_scale[2]); - } - } - } - if (_image.has_alpha() && _color_scale[3] != 1.0f) { - for (int yi = 0; yi < _image.get_y_size(); ++yi) { - for (int xi = 0; xi < _image.get_x_size(); ++xi) { - PN_stdfloat a = _image.get_alpha(xi, yi); - _image.set_alpha(xi, yi, a * _color_scale[3]); - } - } - } - } - - bool transpose = false; - if (_cw) { - _flip = !_flip; - transpose = !transpose; - } - if (_ccw) { - _mirror = !_mirror; - transpose = !transpose; - } - if (_flip || _mirror || transpose) { - _image.flip(_mirror, _flip, transpose); - } - - write_image(); -} - -/** - * Interprets the -chan parameter. - */ -bool ImageTrans:: -dispatch_channels(const std::string &opt, const std::string &arg, void *var) { - Channels *ip = (Channels *)var; - if (cmp_nocase(arg, "l") == 0) { - (*ip) = C_l; - } else if (cmp_nocase(arg, "la") == 0) { - (*ip) = C_la; - } else if (cmp_nocase(arg, "rgb") == 0) { - (*ip) = C_rgb; - } else if (cmp_nocase(arg, "rgba") == 0) { - (*ip) = C_rgba; - } else if (cmp_nocase(arg, "r") == 0) { - (*ip) = C_r; - } else if (cmp_nocase(arg, "g") == 0) { - (*ip) = C_g; - } else if (cmp_nocase(arg, "b") == 0) { - (*ip) = C_b; - } else if (cmp_nocase(arg, "a") == 0) { - (*ip) = C_a; - } else { - int value; - if (!string_to_int(arg, value)) { - nout << "Invalid parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - if (value < 1 || value > 4) { - nout << "Number of channels must be one of 1, 2, 3, or 4.\n"; - return false; - } - (*ip) = (Channels)value; - } - - return true; -} - -/** - * Extracts out just the alpha channel and stores it as a grayscale image. - */ -void ImageTrans:: -extract_alpha() { - if (!_image.has_alpha()) { - nout << "Source image does not have an alpha channel!\n"; - _image.make_grayscale(); - _image.fill(); - return; - } - - _image.make_grayscale(); - for (int y = 0; y < _image.get_y_size(); y++) { - for (int x = 0; x < _image.get_x_size(); x++) { - _image.set_gray_val(x, y, _image.get_alpha_val(x, y)); - } - } - _image.remove_alpha(); -} - - -int main(int argc, char *argv[]) { - ImageTrans prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/imageprogs/imageTrans.h b/pandatool/src/imageprogs/imageTrans.h deleted file mode 100644 index a41d3ef5..00000000 --- a/pandatool/src/imageprogs/imageTrans.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageTrans.h - * @author drose - * @date 2000-06-19 - */ - -#ifndef IMAGETRANS_H -#define IMAGETRANS_H - -#include "pandatoolbase.h" - -#include "imageFilter.h" - -/** - * A program to read an image file and write an equivalent image file, - * possibly performing some minor operations along the way. - */ -class ImageTrans : public ImageFilter { -public: - ImageTrans(); - - void run(); - -private: - static bool dispatch_channels(const std::string &opt, const std::string &arg, void *var); - void extract_alpha(); - - enum Channels { - C_default, - C_l = 1, - C_la = 2, - C_rgb = 3, - C_rgba = 4, - C_r, - C_g, - C_b, - C_a - }; - - Channels _channels; - LColor _color_scale; - bool _has_color_scale; - bool _flip, _mirror, _cw, _ccw; -}; - -#endif diff --git a/pandatool/src/imageprogs/imageTransformColors.I b/pandatool/src/imageprogs/imageTransformColors.I deleted file mode 100644 index 6a6ba23e..00000000 --- a/pandatool/src/imageprogs/imageTransformColors.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageTransformColors.I - * @author drose - * @date 2009-03-25 - */ diff --git a/pandatool/src/imageprogs/imageTransformColors.cxx b/pandatool/src/imageprogs/imageTransformColors.cxx deleted file mode 100644 index 0efee4aa..00000000 --- a/pandatool/src/imageprogs/imageTransformColors.cxx +++ /dev/null @@ -1,481 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageTransformColors.cxx - * @author drose - * @date 2009-03-25 - */ - -#include "imageTransformColors.h" -#include "string_utils.h" -#include "pnmImage.h" -#include - -using std::max; -using std::min; -using std::string; - -/** - * - */ -ImageTransformColors:: -ImageTransformColors() { - set_program_brief("transform colors in an image file"); - set_program_description - ("This program can apply a global color transform to all of the " - "pixels in an image, or in a series of images. This can be used, " - "for instance, to increase or decrease the dynamic range; or to " - "rotate the hue; or to reduce the saturation of colors in the image.\n\n" - - "Each parameter is encoded in a 4x4 matrix, which modifies the R, G, B " - "colors of the image (the alpha values, if any, are not affected). " - "RGB values are clamped at 0 and 1 after the operation. " - "Multiple parameters are composed together in the order in which they " - "are listed."); - - add_option - ("hls", "", 0, - "Specifies that all of the matrix operations are performed in HLS " - "space, instead of the default RGB space. In this mode, the first " - "component controls hue, the second controls lightness, and the third " - "controls saturation.", - &ImageTransformColors::dispatch_none, &_hls, nullptr); - - add_option - ("range", "min,max", 0, - "Compresses the overall dynamic range from 0,1 to min,max. If min,max " - "exceed 0,1, the dynamic range is expanded. This doesn't make sense in " - "HLS mode.", - &ImageTransformColors::dispatch_range, nullptr, &_mat); - - add_option - ("scale", "r,g,b", 0, - "Scales the r,g,b components by the indicated values. In HLS mode, " - "the scale is applied to the h,l,s components.", - &ImageTransformColors::dispatch_scale, nullptr, &_mat); - - add_option - ("add", "r,g,b", 0, - "Adds the indicated values to the r,g,b components. In HLS mode, " - "the sum is applied to the h,l,s components.", - &ImageTransformColors::dispatch_add, nullptr, &_mat); - - add_option - ("mat4", "m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33", - 0, "Defines an arbitrary 4x4 RGB matrix.", - &ImageTransformColors::dispatch_mat4, nullptr, &_mat); - - add_option - ("mat3", "m00,m01,m02,m10,m11,m12,m20,m21,m22", 0, - "Defines an arbitrary 3x3 RGB matrix.", - &ImageTransformColors::dispatch_mat3, nullptr, &_mat); - - add_option - ("o", "filename", 50, - "Specify the filename to which the resulting image file will be written. " - "This is only valid when there is only one input image file on the command " - "line. If you want to process multiple files simultaneously, you must " - "use either -d or -inplace.", - &ImageTransformColors::dispatch_filename, &_got_output_filename, &_output_filename); - - add_option - ("d", "dirname", 50, - "Specify the name of the directory in which to write the resulting image " - "files. If you are processing only one image file, this may be omitted " - "in lieu of the -o option. If you are processing multiple image files, " - "this may be omitted only if you specify -inplace instead.", - &ImageTransformColors::dispatch_filename, &_got_output_dirname, &_output_dirname); - - add_option - ("inplace", "", 50, - "If this option is given, the input image files will be rewritten in " - "place with the results. This obviates the need to specify -d " - "for an output directory; however, it's risky because the original " - "input image files are lost.", - &ImageTransformColors::dispatch_none, &_inplace); - - _mat = LMatrix4d::ident_mat(); -} - -/** - * - */ -void ImageTransformColors:: -run() { - _mat.write(nout, 0); - nout << "\n"; - - Filenames::iterator fi; - for (fi = _filenames.begin(); fi != _filenames.end(); ++fi) { - const Filename &source_filename = (*fi); - nout << source_filename << "\n"; - PNMImage image; - if (!image.read(source_filename)) { - nout << "Couldn't read " << source_filename << "; ignoring.\n"; - continue; - } - - process_image(image); - - Filename output_filename = get_output_filename(source_filename); - if (!image.write(output_filename)) { - nout << "Couldn't write " << output_filename << "; ignoring.\n"; - } - } -} - -/** - * Takes a series of 16 numbers as a 4x4 matrix. - */ -bool ImageTransformColors:: -dispatch_mat4(const string &opt, const string &arg, void *var) { - LMatrix4d &orig = *(LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - LMatrix4d mat; - bool okflag = false; - if (words.size() == 16) { - okflag = - string_to_double(words[0], mat[0][0]) && - string_to_double(words[1], mat[0][1]) && - string_to_double(words[2], mat[0][2]) && - string_to_double(words[3], mat[0][3]) && - string_to_double(words[4], mat[1][0]) && - string_to_double(words[5], mat[1][1]) && - string_to_double(words[6], mat[1][2]) && - string_to_double(words[7], mat[1][3]) && - string_to_double(words[8], mat[2][0]) && - string_to_double(words[9], mat[2][1]) && - string_to_double(words[10], mat[2][2]) && - string_to_double(words[11], mat[2][3]) && - string_to_double(words[12], mat[3][0]) && - string_to_double(words[13], mat[3][1]) && - string_to_double(words[14], mat[3][2]) && - string_to_double(words[15], mat[3][3]); - } - - if (!okflag) { - nout << "-" << opt - << " requires sixteen numbers separated by commas.\n"; - return false; - } - - orig *= mat; - - return true; -} - -/** - * Takes a series of 9 numbers as a 3x3 matrix. - */ -bool ImageTransformColors:: -dispatch_mat3(const string &opt, const string &arg, void *var) { - LMatrix4d &orig = *(LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - LMatrix3d mat; - bool okflag = false; - if (words.size() == 9) { - okflag = - string_to_double(words[0], mat[0][0]) && - string_to_double(words[1], mat[0][1]) && - string_to_double(words[2], mat[0][2]) && - string_to_double(words[3], mat[1][0]) && - string_to_double(words[4], mat[1][1]) && - string_to_double(words[5], mat[1][2]) && - string_to_double(words[6], mat[2][0]) && - string_to_double(words[7], mat[2][1]) && - string_to_double(words[8], mat[2][2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires nine numbers separated by commas.\n"; - return false; - } - - orig *= LMatrix4d(mat); - - return true; -} - -/** - * Takes a min,max dynamic range. - */ -bool ImageTransformColors:: -dispatch_range(const string &opt, const string &arg, void *var) { - LMatrix4d &orig = *(LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - double min, max; - bool okflag = false; - if (words.size() == 2) { - okflag = - string_to_double(words[0], min) && - string_to_double(words[1], max); - } - - if (!okflag) { - nout << "-" << opt - << " requires two numbers separated by commas.\n"; - return false; - } - - orig *= LMatrix4d::scale_mat(max - min) * LMatrix4d::translate_mat(min); - - return true; -} - -/** - * Accepts a componentwise scale. - */ -bool ImageTransformColors:: -dispatch_scale(const string &opt, const string &arg, void *var) { - LMatrix4d &orig = *(LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - double r, g, b; - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_double(words[0], r) && - string_to_double(words[1], g) && - string_to_double(words[2], b); - } - - if (!okflag) { - nout << "-" << opt - << " requires three numbers separated by commas.\n"; - return false; - } - - orig *= LMatrix4d::scale_mat(r, g, b); - - return true; -} - -/** - * Accepts a componentwise add. - */ -bool ImageTransformColors:: -dispatch_add(const string &opt, const string &arg, void *var) { - LMatrix4d &orig = *(LMatrix4d *)var; - - vector_string words; - tokenize(arg, words, ","); - - double r, g, b; - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_double(words[0], r) && - string_to_double(words[1], g) && - string_to_double(words[2], b); - } - - if (!okflag) { - nout << "-" << opt - << " requires three numbers separated by commas.\n"; - return false; - } - - orig *= LMatrix4d::translate_mat(r, g, b); - - return true; -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool ImageTransformColors:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the image file(s) to read on the command line.\n"; - return false; - - } else { - // These only apply if we have specified any image files. - if (_got_output_filename && args.size() == 1) { - if (_got_output_dirname) { - nout << "Cannot specify both -o and -d.\n"; - return false; - } else if (_inplace) { - nout << "Cannot specify both -o and -inplace.\n"; - return false; - } - - } else { - if (_got_output_filename) { - nout << "Cannot use -o when multiple image files are specified.\n"; - return false; - } - - if (_got_output_dirname && _inplace) { - nout << "Cannot specify both -inplace and -d.\n"; - return false; - - } else if (!_got_output_dirname && !_inplace) { - nout << "You must specify either -inplace or -d.\n"; - return false; - } - } - } - - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - Filename filename = (*ai); - if (!filename.exists()) { - nout << "Image file not found: " << filename << "\n"; - return false; - } - _filenames.push_back(filename); - } - - return true; -} - -/** - * Returns the output filename of the egg file with the given input filename. - * This is based on the user's choice of -inplace, -o, or -d. - */ -Filename ImageTransformColors:: -get_output_filename(const Filename &source_filename) const { - if (_got_output_filename) { - nassertr(!_inplace && !_got_output_dirname && _filenames.size() == 1, Filename()); - return _output_filename; - - } else if (_got_output_dirname) { - nassertr(!_inplace, Filename()); - Filename result = source_filename; - result.set_dirname(_output_dirname); - return result; - } - - nassertr(_inplace, Filename()); - return source_filename; -} - -inline double -hue2rgb(double m1, double m2, double h) { - h -= floor(h); - if (h < 1.0/6.0) { - return m1 + (m2 - m1) * h * 6.0; - } - if (h < 1.0/2.0) { - return m2; - } - if (h < 2.0/3.0) { - return m1 + (m2 - m1) * (2.0/3.0 - h) * 6; - } - return m1; -} - -static LRGBColord -hls2rgb(const LRGBColord &hls) { - double h = hls[0]; - double l = max(min(hls[1], 1.0), 0.0); - double s = max(min(hls[2], 1.0), 0.0); - - double m2; - if (l <= 0.5) { - m2 = l * (s + 1.0); - } else { - m2 = l + s - l * s; - } - double m1 = l * 2 - m2; - - LRGBColord rgb(hue2rgb(m1, m2, h + 1.0/3.0), - hue2rgb(m1, m2, h), - hue2rgb(m1, m2, h - 1.0/3.0)); - return rgb; -} - -static LRGBColord -rgb2hls(const LRGBColord &rgb) { - double r = rgb[0]; - double g = rgb[1]; - double b = rgb[2]; - double h, l, s; - - double minval = min(min(r, g), b); - double maxval = max(max(r, g), b); - - double rnorm = 0.0, gnorm = 0.0, bnorm = 0.0; - double mdiff = maxval - minval; - double msum = maxval + minval; - l = 0.5 * msum; - if (maxval == minval) { - // Grayscale. - return LRGBColord(0.0, l, 0.0); - } - - rnorm = (maxval - r) / mdiff; - gnorm = (maxval - g) / mdiff; - bnorm = (maxval - b) / mdiff; - - if (l < 0.5) { - s = mdiff / msum; - } else { - s = mdiff / (2.0 - msum); - } - - if (r == maxval) { - h = (6.0 + bnorm - gnorm) / 6.0; - } else if (g == maxval) { - h = (2.0 + rnorm - bnorm) / 6.0; - } else { - h = (4.0 + gnorm - rnorm) / 6.0; - } - - if (h > 1.0) { - h -= 1.0; - } - - return LRGBColord(h, l, s); -} - -/** - * Processes a single image in-place. - */ -void ImageTransformColors:: -process_image(PNMImage &image) { - if (_hls) { - for (int yi = 0; yi < image.get_y_size(); ++yi) { - for (int xi = 0; xi < image.get_x_size(); ++xi) { - LRGBColord rgb = LCAST(double, image.get_xel(xi, yi)); - rgb = hls2rgb(_mat.xform_point(rgb2hls(rgb))); - image.set_xel(xi, yi, LCAST(float, rgb)); - } - } - } else { - for (int yi = 0; yi < image.get_y_size(); ++yi) { - for (int xi = 0; xi < image.get_x_size(); ++xi) { - LRGBColord rgb = LCAST(double, image.get_xel(xi, yi)); - rgb = _mat.xform_point(rgb); - image.set_xel(xi, yi, LCAST(float, rgb)); - } - } - } -} - -int main(int argc, char *argv[]) { - ImageTransformColors prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/imageprogs/imageTransformColors.h b/pandatool/src/imageprogs/imageTransformColors.h deleted file mode 100644 index a6d11bb1..00000000 --- a/pandatool/src/imageprogs/imageTransformColors.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageTransformColors.h - * @author drose - * @date 2009-03-25 - */ - -#ifndef IMAGETRANSFORMCOLORS_H -#define IMAGETRANSFORMCOLORS_H - -#include "pandatoolbase.h" -#include "programBase.h" -#include "pvector.h" -#include "filename.h" -#include "luse.h" - -class PNMImage; - -/** - * This program can apply a 4x4 color transform to all of the colors in the - * pixels of a series of images. - */ -class ImageTransformColors : public ProgramBase { -public: - ImageTransformColors(); - - void run(); - -protected: - static bool dispatch_mat4(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_mat3(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_range(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_scale(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_add(const std::string &opt, const std::string &arg, void *var); - - virtual bool handle_args(Args &args); - Filename get_output_filename(const Filename &source_filename) const; - - void process_image(PNMImage &image); - -private: - bool _hls; - LMatrix4d _mat; - - bool _got_output_filename; - Filename _output_filename; - bool _got_output_dirname; - Filename _output_dirname; - bool _inplace; - - typedef pvector Filenames; - Filenames _filenames; -}; - -#include "imageTransformColors.I" - -#endif diff --git a/pandatool/src/lwo/CMakeLists.txt b/pandatool/src/lwo/CMakeLists.txt deleted file mode 100644 index c7c7f33c..00000000 --- a/pandatool/src/lwo/CMakeLists.txt +++ /dev/null @@ -1,69 +0,0 @@ -set(P3LWO_HEADERS - config_lwo.h - iffChunk.h iffChunk.I - iffGenericChunk.h iffGenericChunk.I - iffId.h iffId.I - iffInputFile.h iffInputFile.I - lwoBoundingBox.h - lwoChunk.h - lwoClip.h - lwoDiscontinuousVertexMap.h - lwoGroupChunk.h - lwoHeader.h lwoHeader.I - lwoInputFile.h lwoInputFile.I - lwoLayer.h - lwoPoints.h - lwoPolygons.h lwoPolygonTags.h - lwoStillImage.h - lwoSurfaceBlockAxis.h lwoSurfaceBlockChannel.h lwoSurfaceBlockCoordSys.h - lwoSurfaceBlockEnabled.h lwoSurfaceBlock.h lwoSurfaceBlockHeader.h - lwoSurfaceBlockImage.h lwoSurfaceBlockOpacity.h lwoSurfaceBlockProjection.h - lwoSurfaceBlockRefObj.h lwoSurfaceBlockRepeat.h lwoSurfaceBlockTMap.h - lwoSurfaceBlockTransform.h lwoSurfaceBlockVMapName.h lwoSurfaceBlockWrap.h - lwoSurfaceColor.h - lwoSurface.h - lwoSurfaceParameter.h - lwoSurfaceSidedness.h - lwoSurfaceSmoothingAngle.h - lwoTags.h - lwoVertexMap.h -) - -set(P3LWO_SOURCES - config_lwo.cxx - iffChunk.cxx - iffGenericChunk.cxx - iffId.cxx - iffInputFile.cxx - lwoBoundingBox.cxx - lwoChunk.cxx - lwoClip.cxx - lwoDiscontinuousVertexMap.cxx - lwoGroupChunk.cxx - lwoHeader.cxx - lwoInputFile.cxx - lwoLayer.cxx - lwoPoints.cxx - lwoPolygons.cxx - lwoPolygonTags.cxx - lwoStillImage.cxx - lwoSurfaceBlockAxis.cxx lwoSurfaceBlockChannel.cxx lwoSurfaceBlockCoordSys.cxx - lwoSurfaceBlock.cxx lwoSurfaceBlockEnabled.cxx lwoSurfaceBlockHeader.cxx - lwoSurfaceBlockImage.cxx lwoSurfaceBlockOpacity.cxx lwoSurfaceBlockProjection.cxx - lwoSurfaceBlockRefObj.cxx lwoSurfaceBlockRepeat.cxx lwoSurfaceBlockTMap.cxx - lwoSurfaceBlockTransform.cxx lwoSurfaceBlockVMapName.cxx lwoSurfaceBlockWrap.cxx - lwoSurfaceColor.cxx - lwoSurface.cxx - lwoSurfaceParameter.cxx - lwoSurfaceSidedness.cxx - lwoSurfaceSmoothingAngle.cxx - lwoTags.cxx - lwoVertexMap.cxx -) - -composite_sources(p3lwo P3LWO_SOURCES) -add_library(p3lwo STATIC ${P3LWO_HEADERS} ${P3LWO_SOURCES}) -target_link_libraries(p3lwo p3pandatoolbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/lwo/config_lwo.cxx b/pandatool/src/lwo/config_lwo.cxx deleted file mode 100644 index de7d9247..00000000 --- a/pandatool/src/lwo/config_lwo.cxx +++ /dev/null @@ -1,112 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_lwo.cxx - * @author drose - * @date 2001-04-23 - */ - -#include "config_lwo.h" -#include "iffChunk.h" -#include "iffGenericChunk.h" -#include "iffInputFile.h" -#include "lwoBoundingBox.h" -#include "lwoChunk.h" -#include "lwoClip.h" -#include "lwoDiscontinuousVertexMap.h" -#include "lwoGroupChunk.h" -#include "lwoHeader.h" -#include "lwoInputFile.h" -#include "lwoLayer.h" -#include "lwoPoints.h" -#include "lwoPolygons.h" -#include "lwoPolygonTags.h" -#include "lwoStillImage.h" -#include "lwoSurface.h" -#include "lwoSurfaceBlock.h" -#include "lwoSurfaceBlockAxis.h" -#include "lwoSurfaceBlockChannel.h" -#include "lwoSurfaceBlockCoordSys.h" -#include "lwoSurfaceBlockEnabled.h" -#include "lwoSurfaceBlockImage.h" -#include "lwoSurfaceBlockOpacity.h" -#include "lwoSurfaceBlockProjection.h" -#include "lwoSurfaceBlockHeader.h" -#include "lwoSurfaceBlockRefObj.h" -#include "lwoSurfaceBlockRepeat.h" -#include "lwoSurfaceBlockTMap.h" -#include "lwoSurfaceBlockTransform.h" -#include "lwoSurfaceBlockVMapName.h" -#include "lwoSurfaceBlockWrap.h" -#include "lwoSurfaceColor.h" -#include "lwoSurfaceParameter.h" -#include "lwoSurfaceSidedness.h" -#include "lwoSurfaceSmoothingAngle.h" -#include "lwoTags.h" -#include "lwoVertexMap.h" - -#include "dconfig.h" - -Configure(config_lwo); - -ConfigureFn(config_lwo) { - init_liblwo(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_liblwo() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - IffChunk::init_type(); - IffGenericChunk::init_type(); - IffInputFile::init_type(); - LwoBoundingBox::init_type(); - LwoChunk::init_type(); - LwoClip::init_type(); - LwoDiscontinuousVertexMap::init_type(); - LwoGroupChunk::init_type(); - LwoHeader::init_type(); - LwoInputFile::init_type(); - LwoLayer::init_type(); - LwoPoints::init_type(); - LwoPolygons::init_type(); - LwoPolygonTags::init_type(); - LwoTags::init_type(); - LwoStillImage::init_type(); - LwoSurface::init_type(); - LwoSurfaceBlock::init_type(); - LwoSurfaceBlockAxis::init_type(); - LwoSurfaceBlockChannel::init_type(); - LwoSurfaceBlockCoordSys::init_type(); - LwoSurfaceBlockEnabled::init_type(); - LwoSurfaceBlockImage::init_type(); - LwoSurfaceBlockOpacity::init_type(); - LwoSurfaceBlockProjection::init_type(); - LwoSurfaceBlockHeader::init_type(); - LwoSurfaceBlockRefObj::init_type(); - LwoSurfaceBlockRepeat::init_type(); - LwoSurfaceBlockTMap::init_type(); - LwoSurfaceBlockTransform::init_type(); - LwoSurfaceBlockVMapName::init_type(); - LwoSurfaceBlockWrap::init_type(); - LwoSurfaceColor::init_type(); - LwoSurfaceParameter::init_type(); - LwoSurfaceSidedness::init_type(); - LwoSurfaceSmoothingAngle::init_type(); - LwoVertexMap::init_type(); -} diff --git a/pandatool/src/lwo/config_lwo.h b/pandatool/src/lwo/config_lwo.h deleted file mode 100644 index b2ed9850..00000000 --- a/pandatool/src/lwo/config_lwo.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_lwo.h - * @author drose - * @date 2001-04-23 - */ - -#ifndef CONFIG_LWO_H -#define CONFIG_LWO_H - -#include "pandatoolbase.h" - -extern void init_liblwo(); - -#endif diff --git a/pandatool/src/lwo/iffChunk.I b/pandatool/src/lwo/iffChunk.I deleted file mode 100644 index 716e8935..00000000 --- a/pandatool/src/lwo/iffChunk.I +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffChunk.I - * @author drose - * @date 2001-04-23 - */ - -/** - * - */ -INLINE IffChunk:: -IffChunk() { -} - -/** - * Returns the ID associated with this chunk. - */ -INLINE IffId IffChunk:: -get_id() const { - return _id; -} - -/** - * Changes the ID associated with this chunk. - */ -INLINE void IffChunk:: -set_id(IffId id) { - _id = id; -} diff --git a/pandatool/src/lwo/iffChunk.cxx b/pandatool/src/lwo/iffChunk.cxx deleted file mode 100644 index a86ac62d..00000000 --- a/pandatool/src/lwo/iffChunk.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffChunk.cxx - * @author drose - * @date 2001-04-23 - */ - -#include "iffChunk.h" -#include "iffInputFile.h" - -#include "indent.h" - -TypeHandle IffChunk::_type_handle; - -/** - * - */ -void IffChunk:: -output(std::ostream &out) const { - out << _id << " (" << get_type() << ")"; -} - -/** - * - */ -void IffChunk:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) << _id << " { ... }\n"; -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID, according to the context given by this chunk itself. - */ -IffChunk *IffChunk:: -make_new_chunk(IffInputFile *in, IffId id) { - return in->make_new_chunk(id); -} diff --git a/pandatool/src/lwo/iffChunk.h b/pandatool/src/lwo/iffChunk.h deleted file mode 100644 index 58de2647..00000000 --- a/pandatool/src/lwo/iffChunk.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffChunk.h - * @author drose - * @date 2001-04-23 - */ - -#ifndef IFFCHUNK_H -#define IFFCHUNK_H - -#include "pandatoolbase.h" - -#include "iffId.h" - -#include "typedObject.h" -#include "typedReferenceCount.h" - -class IffInputFile; - -/** - * The basic kind of record in an EA "IFF" file, which the LightWave object - * file is based on. - */ -class IffChunk : public TypedReferenceCount { -public: - INLINE IffChunk(); - - INLINE IffId get_id() const; - INLINE void set_id(IffId id); - - virtual bool read_iff(IffInputFile *in, size_t stop_at)=0; - - virtual void output(std::ostream &out) const; - virtual void write(std::ostream &out, int indent_level = 0) const; - - virtual IffChunk *make_new_chunk(IffInputFile *in, IffId id); - -private: - IffId _id; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedReferenceCount::init_type(); - register_type(_type_handle, "IffChunk", - TypedReferenceCount::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "iffChunk.I" - -INLINE std::ostream &operator << (std::ostream &out, const IffChunk &chunk) { - chunk.output(out); - return out; -} - -#endif diff --git a/pandatool/src/lwo/iffGenericChunk.I b/pandatool/src/lwo/iffGenericChunk.I deleted file mode 100644 index bfa0a138..00000000 --- a/pandatool/src/lwo/iffGenericChunk.I +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffGenericChunk.I - * @author drose - * @date 2001-04-23 - */ - -/** - * - */ -INLINE IffGenericChunk:: -IffGenericChunk() { -} - -/** - * Returns the data in the chunk. - */ -INLINE const Datagram &IffGenericChunk:: -get_data() const { - return _data; -} - -/** - * Changes the data in the chunk - */ -INLINE void IffGenericChunk:: -set_data(const Datagram &data) { - _data = data; -} diff --git a/pandatool/src/lwo/iffGenericChunk.cxx b/pandatool/src/lwo/iffGenericChunk.cxx deleted file mode 100644 index c8eaf015..00000000 --- a/pandatool/src/lwo/iffGenericChunk.cxx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffGenericChunk.cxx - * @author drose - * @date 2001-04-23 - */ - -#include "iffGenericChunk.h" -#include "iffInputFile.h" - -#include "indent.h" - -TypeHandle IffGenericChunk::_type_handle; - - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool IffGenericChunk:: -read_iff(IffInputFile *in, size_t stop_at) { - size_t length = stop_at - in->get_bytes_read(); - bool result = in->read_bytes(_data, length); - in->align(); - return result; -} - -/** - * - */ -void IffGenericChunk:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { " << _data.get_length() << " bytes }\n"; -} diff --git a/pandatool/src/lwo/iffGenericChunk.h b/pandatool/src/lwo/iffGenericChunk.h deleted file mode 100644 index e1e99024..00000000 --- a/pandatool/src/lwo/iffGenericChunk.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffGenericChunk.h - * @author drose - * @date 2001-04-23 - */ - -#ifndef IFFGENERICCHUNK_H -#define IFFGENERICCHUNK_H - -#include "pandatoolbase.h" - -#include "iffChunk.h" - -#include "datagram.h" - - -/** - * A class for a generic kind of IffChunk that is not understood by a - * particular IffReader. It remembers its entire contents. - */ -class IffGenericChunk : public IffChunk { -public: - INLINE IffGenericChunk(); - - INLINE const Datagram &get_data() const; - INLINE void set_data(const Datagram &data); - - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - Datagram _data; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - IffChunk::init_type(); - register_type(_type_handle, "IffGenericChunk", - IffChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "iffGenericChunk.I" - -#endif diff --git a/pandatool/src/lwo/iffId.I b/pandatool/src/lwo/iffId.I deleted file mode 100644 index 938e26c4..00000000 --- a/pandatool/src/lwo/iffId.I +++ /dev/null @@ -1,84 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffId.I - * @author drose - * @date 2001-04-23 - */ - -/** - * - */ -INLINE IffId:: -IffId() { - _id._c[0] = 0; - _id._c[1] = 0; - _id._c[2] = 0; - _id._c[3] = 0; -} - -/** - * - */ -INLINE IffId:: -IffId(const char id[4]) { - _id._c[0] = id[0]; - _id._c[1] = id[1]; - _id._c[2] = id[2]; - _id._c[3] = id[3]; -} - -/** - * - */ -INLINE IffId:: -IffId(const IffId ©) { - _id._n = copy._id._n; -} - -/** - * - */ -INLINE void IffId:: -operator = (const IffId ©) { - _id._n = copy._id._n; -} - -/** - * - */ -INLINE bool IffId:: -operator == (const IffId &other) const { - return (_id._n == other._id._n); -} - -/** - * - */ -INLINE bool IffId:: -operator != (const IffId &other) const { - return (_id._n != other._id._n); -} - -/** - * The ordering is arbitrary, and may not even be consistent between different - * architectures (e.g. big-endian and little-endian). It is useful mainly - * for putting IffId's into a sorted container, like sets and maps. - */ -INLINE bool IffId:: -operator < (const IffId &other) const { - return (_id._n < other._id._n); -} - -/** - * Returns the four-character name of the Id, for outputting. - */ -INLINE std::string IffId:: -get_name() const { - return std::string(_id._c, 4); -} diff --git a/pandatool/src/lwo/iffId.cxx b/pandatool/src/lwo/iffId.cxx deleted file mode 100644 index eda63c0b..00000000 --- a/pandatool/src/lwo/iffId.cxx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffId.cxx - * @author drose - * @date 2001-04-23 - */ - -#include "iffId.h" - -#include - -/** - * - */ -void IffId:: -output(std::ostream &out) const { - // If all of the characters are printable, just output them. - if (isprint(_id._c[0]) && isprint(_id._c[1]) && - isprint(_id._c[2]) && isprint(_id._c[3])) { - out << _id._c[0] << _id._c[1] << _id._c[2] << _id._c[3]; - - } else if (isprint(_id._c[0]) && isprint(_id._c[1]) && - isprint(_id._c[2]) && _id._c[3] == '\0') { - // If the last character is 0, output a 3-letter ID. - out << _id._c[0] << _id._c[1] << _id._c[2]; - - } else { - // Otherwise, write out the hex. - out << "0x" << std::hex << std::setfill('0'); - for (int i = 0; i < 4; i++) { - out << std::setw(2) << (int)(unsigned char)_id._c[i]; - } - out << std::dec << std::setfill(' '); - } -} diff --git a/pandatool/src/lwo/iffId.h b/pandatool/src/lwo/iffId.h deleted file mode 100644 index c3d14a7a..00000000 --- a/pandatool/src/lwo/iffId.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffId.h - * @author drose - * @date 2001-04-23 - */ - -#ifndef IFFID_H -#define IFFID_H - -#include "pandatoolbase.h" - -#include "numeric_types.h" - -/** - * A four-byte chunk ID appearing in an "IFF" file. This is used to identify - * the meaning of each chunk, and can be treated either as a concrete object - * or as a string, something like a TypeHandle. - */ -class IffId { -public: - INLINE IffId(); - INLINE IffId(const char id[4]); - INLINE IffId(const IffId ©); - INLINE void operator = (const IffId ©); - - INLINE bool operator == (const IffId &other) const; - INLINE bool operator != (const IffId &other) const; - INLINE bool operator < (const IffId &other) const; - - INLINE std::string get_name() const; - - void output(std::ostream &out) const; - -private: - union { - uint32_t _n; - char _c[4]; - } _id; -}; - -#include "iffId.I" - -INLINE std::ostream &operator << (std::ostream &out, const IffId &id) { - id.output(out); - return out; -} - -#endif diff --git a/pandatool/src/lwo/iffInputFile.I b/pandatool/src/lwo/iffInputFile.I deleted file mode 100644 index 18fe7e90..00000000 --- a/pandatool/src/lwo/iffInputFile.I +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffInputFile.I - * @author drose - * @date 2001-04-24 - */ - -/** - * Indicates the filename that the InputFile is currently opened on. - */ -INLINE void IffInputFile:: -set_filename(const Filename &filename) { - _filename = filename; -} - -/** - * Returns the filename that the InputFile is currently opened on, if - * available. - */ -INLINE const Filename &IffInputFile:: -get_filename() const { - return _filename; -} - -/** - * Returns true if the last read operation failed because of reaching EOF, - * false otherwise. - */ -INLINE bool IffInputFile:: -is_eof() const { - return _eof; -} - -/** - * Returns the number of bytes read so far from the input file. - */ -INLINE size_t IffInputFile:: -get_bytes_read() const { - return _bytes_read; -} - -/** - * If the current file pointer is not positioned on an even-byte boundary, - * reads and discards one byte so that it is. - */ -INLINE void IffInputFile:: -align() { - if ((_bytes_read & 1) != 0) { - get_int8(); - } -} diff --git a/pandatool/src/lwo/iffInputFile.cxx b/pandatool/src/lwo/iffInputFile.cxx deleted file mode 100644 index f00dbf54..00000000 --- a/pandatool/src/lwo/iffInputFile.cxx +++ /dev/null @@ -1,369 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffInputFile.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "iffInputFile.h" -#include "iffGenericChunk.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "virtualFileSystem.h" - -TypeHandle IffInputFile::_type_handle; - -/** - * - */ -IffInputFile:: -IffInputFile() { - _input = nullptr; - _owns_istream = false; - _eof = true; - _unexpected_eof = false; - _bytes_read = 0; -} - -/** - * - */ -IffInputFile:: -~IffInputFile() { - if (_owns_istream) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->close_read_file(_input); - } -} - -/** - * Attempts to open the indicated filename for reading. Returns true if - * successful, false otherwise. - */ -bool IffInputFile:: -open_read(Filename filename) { - filename.set_binary(); - - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - std::istream *in = vfs->open_read_file(filename, true); - if (in == nullptr) { - return false; - } - - set_input(in, true); - set_filename(filename); - - return true; -} - -/** - * Sets up the input to use an arbitrary istream. If owns_istream is true, - * the istream will be deleted (via vfs->close_read_file()) when the - * IffInputFile destructs. - */ -void IffInputFile:: -set_input(std::istream *input, bool owns_istream) { - if (_owns_istream) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->close_read_file(_input); - } - _input = input; - _owns_istream = owns_istream; - _eof = false; - _unexpected_eof = false; - _bytes_read = 0; -} - -/** - * Extracts a signed 8-bit integer. - */ -int8_t IffInputFile:: -get_int8() { - Datagram dg; - if (!read_bytes(dg, 1)) { - return 0; - } - DatagramIterator dgi(dg); - return dgi.get_int8(); -} - -/** - * Extracts an unsigned 8-bit integer. - */ -uint8_t IffInputFile:: -get_uint8() { - Datagram dg; - if (!read_bytes(dg, 1)) { - return 0; - } - DatagramIterator dgi(dg); - return dgi.get_int8(); -} - -/** - * Extracts a signed 16-bit big-endian integer. - */ -int16_t IffInputFile:: -get_be_int16() { - Datagram dg; - if (!read_bytes(dg, 2)) { - return 0; - } - DatagramIterator dgi(dg); - return dgi.get_be_int16(); -} - -/** - * Extracts a signed 32-bit big-endian integer. - */ -int32_t IffInputFile:: -get_be_int32() { - Datagram dg; - if (!read_bytes(dg, 4)) { - return 0; - } - DatagramIterator dgi(dg); - return dgi.get_be_int32(); -} - -/** - * Extracts an unsigned 16-bit big-endian integer. - */ -uint16_t IffInputFile:: -get_be_uint16() { - Datagram dg; - if (!read_bytes(dg, 2)) { - return 0; - } - DatagramIterator dgi(dg); - return dgi.get_be_uint16(); -} - -/** - * Extracts an unsigned 32-bit big-endian integer. - */ -uint32_t IffInputFile:: -get_be_uint32() { - Datagram dg; - if (!read_bytes(dg, 4)) { - return 0; - } - DatagramIterator dgi(dg); - return dgi.get_be_uint32(); -} - -/** - * Extracts a 32-bit big-endian single-precision floating-point number. - */ -PN_stdfloat IffInputFile:: -get_be_float32() { - Datagram dg; - if (!read_bytes(dg, 4)) { - return 0; - } - DatagramIterator dgi(dg); - return dgi.get_be_float32(); -} - -/** - * Extracts a null-terminated string. - */ -std::string IffInputFile:: -get_string() { - std::string result; - char byte; - while (read_byte(byte)) { - if (byte == 0) { - break; - } - result += byte; - } - - align(); - return result; -} - -/** - * Extracts a 4-character IFF ID. - */ -IffId IffInputFile:: -get_id() { - Datagram dg; - if (!read_bytes(dg, 4)) { - return IffId(); - } - const char *id = (const char *)dg.get_data(); - return IffId(id); -} - -/** - * Reads a single IffChunk, determining its type based on its ID. Allocates - * and returns a new IffChunk object of the appropriate type. Returns NULL if - * EOF is reached before the chunk can be read completely, or if there is some - * other error in reading the chunk. - */ -PT(IffChunk) IffInputFile:: -get_chunk() { - if (is_eof()) { - return nullptr; - } - - IffId id = get_id(); - uint32_t length = get_be_uint32(); - - if (!is_eof()) { - PT(IffChunk) chunk = make_new_chunk(id); - chunk->set_id(id); - - size_t start_point = get_bytes_read(); - size_t end_point = start_point + length; - - if (chunk->read_iff(this, end_point)) { - if (is_eof()) { - if (!_unexpected_eof) { - nout << "Unexpected EOF on file reading " << *chunk << "\n"; - _unexpected_eof = true; - } - return nullptr; - } - - size_t num_bytes_read = get_bytes_read() - start_point; - if (num_bytes_read > length) { - nout << *chunk << " read " << num_bytes_read - << " instead of " << length << " bytes.\n"; - return nullptr; - - } else if (num_bytes_read < length) { - size_t skip_count = length - num_bytes_read; - nout << "Ignoring " << skip_count << " bytes at the end of " - << *chunk << "\n"; - skip_bytes(skip_count); - } - return chunk; - } - } - - return nullptr; -} - -/** - * Similar to get_chunk(), except the chunk size is only a 16-bit number - * instead of 32-bit, and it takes a context, which is the chunk in which this - * chunk is encountered. The parent chunk may (or may not) decide what kind - * of chunk is meant by the various id's encountered. - */ -PT(IffChunk) IffInputFile:: -get_subchunk(IffChunk *context) { - if (is_eof()) { - return nullptr; - } - - IffId id = get_id(); - uint16_t length = get_be_uint16(); - - if (!is_eof()) { - PT(IffChunk) chunk = context->make_new_chunk(this, id); - chunk->set_id(id); - - size_t start_point = get_bytes_read(); - size_t end_point = start_point + length; - - if (chunk->read_iff(this, end_point)) { - if (is_eof()) { - if (!_unexpected_eof) { - nout << "Unexpected EOF on file reading " << *chunk << "\n"; - _unexpected_eof = true; - } - return nullptr; - } - - size_t num_bytes_read = get_bytes_read() - start_point; - if (num_bytes_read > length) { - nout << *chunk << " read " << num_bytes_read - << " instead of " << length << " bytes.\n"; - return nullptr; - - } else if (num_bytes_read < length) { - size_t skip_count = length - num_bytes_read; - nout << "Ignoring " << skip_count << " bytes at the end of " - << *chunk << "\n"; - skip_bytes(skip_count); - } - return chunk; - } - } - - return nullptr; -} - -/** - * Reads a single byte. Returns true if successful, false otherwise. - */ -bool IffInputFile:: -read_byte(char &byte) { - if (is_eof()) { - return false; - } - - _input->get(byte); - _bytes_read++; - _eof = _input->eof() || _input->fail(); - return !is_eof(); -} - -/** - * Reads a series of bytes, and stores them in the indicated Datagram. - * Returns true if successful, false otherwise. - */ -bool IffInputFile:: -read_bytes(Datagram &datagram, int length) { - if (is_eof()) { - return false; - } - - char *buffer = new char[length]; - _input->read(buffer, length); - _eof = (_input->gcount() != length); - if (is_eof()) { - return false; - } - - _bytes_read += length; - datagram = Datagram(buffer, length); - delete[] buffer; - return true; -} - -/** - * Reads a series of bytes, but does not store them. Returns true if - * successful, false otherwise. - */ -bool IffInputFile:: -skip_bytes(int length) { - if (is_eof()) { - return false; - } - - char byte; - while (length > 0 && !is_eof()) { - read_byte(byte); - length--; - } - - return !is_eof(); -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID. - */ -IffChunk *IffInputFile:: -make_new_chunk(IffId) { - return new IffGenericChunk; -} diff --git a/pandatool/src/lwo/iffInputFile.h b/pandatool/src/lwo/iffInputFile.h deleted file mode 100644 index dc39be7d..00000000 --- a/pandatool/src/lwo/iffInputFile.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file iffInputFile.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef IFFINPUTFILE_H -#define IFFINPUTFILE_H - -#include "pandatoolbase.h" - -#include "iffId.h" -#include "iffChunk.h" - -#include "typedObject.h" -#include "pointerTo.h" - -class Datagram; - -/** - * A wrapper around an istream used for reading an IFF file. - */ -class IffInputFile : public TypedObject { -public: - IffInputFile(); - virtual ~IffInputFile(); - - bool open_read(Filename filename); - void set_input(std::istream *input, bool owns_istream); - - INLINE void set_filename(const Filename &filename); - INLINE const Filename &get_filename() const; - - INLINE bool is_eof() const; - INLINE size_t get_bytes_read() const; - - INLINE void align(); - - int8_t get_int8(); - uint8_t get_uint8(); - - int16_t get_be_int16(); - int32_t get_be_int32(); - uint16_t get_be_uint16(); - uint32_t get_be_uint32(); - PN_stdfloat get_be_float32(); - - std::string get_string(); - - IffId get_id(); - - PT(IffChunk) get_chunk(); - PT(IffChunk) get_subchunk(IffChunk *context); - - bool read_byte(char &byte); - bool read_bytes(Datagram &datagram, int length); - bool skip_bytes(int length); - -protected: - virtual IffChunk *make_new_chunk(IffId id); - - std::istream *_input; - Filename _filename; - bool _owns_istream; - bool _eof; - bool _unexpected_eof; - size_t _bytes_read; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedObject::init_type(); - register_type(_type_handle, "IffInputFile", - TypedObject::get_class_type()); - } - -private: - static TypeHandle _type_handle; - - friend class IffChunk; -}; - -#include "iffInputFile.I" - -#endif diff --git a/pandatool/src/lwo/lwoBoundingBox.cxx b/pandatool/src/lwo/lwoBoundingBox.cxx deleted file mode 100644 index 10ef60a7..00000000 --- a/pandatool/src/lwo/lwoBoundingBox.cxx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoBoundingBox.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoBoundingBox.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoBoundingBox::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoBoundingBox:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _min = lin->get_vec3(); - _max = lin->get_vec3(); - - return true; -} - -/** - * - */ -void LwoBoundingBox:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { min = " << _min << ", max = " << _max << " }\n"; -} diff --git a/pandatool/src/lwo/lwoBoundingBox.h b/pandatool/src/lwo/lwoBoundingBox.h deleted file mode 100644 index 993425ff..00000000 --- a/pandatool/src/lwo/lwoBoundingBox.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoBoundingBox.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOBOUNDINGBOX_H -#define LWOBOUNDINGBOX_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "luse.h" - -/** - * Stores the bounding box for the vertex data in a layer. Optional. - */ -class LwoBoundingBox : public LwoChunk { -public: - LVecBase3 _min; - LVecBase3 _max; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoBoundingBox", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoChunk.cxx b/pandatool/src/lwo/lwoChunk.cxx deleted file mode 100644 index 3abc0823..00000000 --- a/pandatool/src/lwo/lwoChunk.cxx +++ /dev/null @@ -1,16 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoChunk.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoChunk.h" - -TypeHandle LwoChunk::_type_handle; diff --git a/pandatool/src/lwo/lwoChunk.h b/pandatool/src/lwo/lwoChunk.h deleted file mode 100644 index 73101597..00000000 --- a/pandatool/src/lwo/lwoChunk.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoChunk.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOCHUNK_H -#define LWOCHUNK_H - -#include "pandatoolbase.h" - -#include "iffChunk.h" - -/** - * A specialization of IffChunk for Lightwave Object files. Each kind of - * chunk that is specific to a Lightwave file should inherit directly or - * indirectly from LwoChunk. - */ -class LwoChunk : public IffChunk { -public: - // No particular interface here. - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - IffChunk::init_type(); - register_type(_type_handle, "LwoChunk", - IffChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoClip.cxx b/pandatool/src/lwo/lwoClip.cxx deleted file mode 100644 index fd1e602a..00000000 --- a/pandatool/src/lwo/lwoClip.cxx +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoClip.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoClip.h" -#include "iffInputFile.h" -#include "lwoStillImage.h" - -#include "indent.h" - -TypeHandle LwoClip::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoClip:: -read_iff(IffInputFile *in, size_t stop_at) { - _index = in->get_be_int32(); - read_subchunks_iff(in, stop_at); - return true; -} - -/** - * - */ -void LwoClip:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " {\n"; - indent(out, indent_level + 2) - << "index = " << _index << "\n"; - write_chunks(out, indent_level + 2); - indent(out, indent_level) - << "}\n"; -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID, according to the context given by this chunk itself. - */ -IffChunk *LwoClip:: -make_new_chunk(IffInputFile *in, IffId id) { - if (id == IffId("STIL")) { - return new LwoStillImage; - - } else { - return IffChunk::make_new_chunk(in, id); - } -} diff --git a/pandatool/src/lwo/lwoClip.h b/pandatool/src/lwo/lwoClip.h deleted file mode 100644 index 3955efa5..00000000 --- a/pandatool/src/lwo/lwoClip.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoClip.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOCLIP_H -#define LWOCLIP_H - -#include "pandatoolbase.h" - -#include "lwoGroupChunk.h" - -/** - * A single image file, or a numbered sequence of images (e.g. a texture-flip - * animation). - */ -class LwoClip : public LwoGroupChunk { -public: - int _index; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - - virtual IffChunk *make_new_chunk(IffInputFile *in, IffId id); - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoGroupChunk::init_type(); - register_type(_type_handle, "LwoClip", - LwoGroupChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoDiscontinuousVertexMap.cxx b/pandatool/src/lwo/lwoDiscontinuousVertexMap.cxx deleted file mode 100644 index 3e4b0c00..00000000 --- a/pandatool/src/lwo/lwoDiscontinuousVertexMap.cxx +++ /dev/null @@ -1,124 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoDiscontinuousVertexMap.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoDiscontinuousVertexMap.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -#include - -TypeHandle LwoDiscontinuousVertexMap::_type_handle; - - -/** - * Returns true if the map has a value associated with the given index, false - * otherwise. - */ -bool LwoDiscontinuousVertexMap:: -has_value(int polygon_index, int vertex_index) const { - VMad::const_iterator di; - di = _vmad.find(polygon_index); - if (di != _vmad.end()) { - const VMap &vmap = (*di).second; - return (vmap.count(vertex_index) != 0); - } - - return false; -} - -/** - * Returns the mapping value associated with the given index, or an empty - * PTA_stdfloat if there is no mapping value associated. - */ -PTA_stdfloat LwoDiscontinuousVertexMap:: -get_value(int polygon_index, int vertex_index) const { - VMad::const_iterator di; - di = _vmad.find(polygon_index); - if (di != _vmad.end()) { - const VMap &vmap = (*di).second; - VMap::const_iterator vi; - vi = vmap.find(vertex_index); - if (vi != vmap.end()) { - return (*vi).second; - } - } - - return PTA_stdfloat(); -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoDiscontinuousVertexMap:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _map_type = lin->get_id(); - _dimension = lin->get_be_uint16(); - _name = lin->get_string(); - - while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { - int vertex_index = lin->get_vx(); - int polygon_index = lin->get_vx(); - - PTA_stdfloat value; - for (int i = 0; i < _dimension; i++) { - value.push_back(lin->get_be_float32()); - } - - VMap &vmap = _vmad[polygon_index]; - std::pair ir = - vmap.insert(VMap::value_type(vertex_index, value)); - if (!ir.second) { - // This polygonvertex pair was repeated in the vmad. Is it simply - // redundant, or is it contradictory? - PTA_stdfloat orig_value = (*ir.first).second; - - if (value.v() != orig_value.v()) { - nout << "Multiple UV values for vertex " << vertex_index - << " of polygon " << polygon_index - << " specified by discontinuous vertex map.\n" - << "Original value = "; - - PTA_stdfloat::const_iterator vi; - for (vi = orig_value.begin(); vi != orig_value.end(); ++vi) { - nout << (*vi) << " "; - } - nout << " new value = "; - for (vi = value.begin(); vi != value.end(); ++vi) { - nout << (*vi) << " "; - } - nout << "\n"; - } - } - } - - return (lin->get_bytes_read() == stop_at); -} - -/** - * - */ -void LwoDiscontinuousVertexMap:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { map_type = " << _map_type - << ", dimension = " << _dimension - << ", name = \"" << _name << "\", " - << _vmad.size() << " polygons }\n"; -} diff --git a/pandatool/src/lwo/lwoDiscontinuousVertexMap.h b/pandatool/src/lwo/lwoDiscontinuousVertexMap.h deleted file mode 100644 index 2f48e146..00000000 --- a/pandatool/src/lwo/lwoDiscontinuousVertexMap.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoDiscontinuousVertexMap.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWODISCONTINUOUSVERTEXMAP_H -#define LWODISCONTINUOUSVERTEXMAP_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "pta_stdfloat.h" -#include "pmap.h" - -/** - * A mapping of floating-point values per integer index. The meaning of these - * values is determined by the mapping type code and/or its name. - */ -class LwoDiscontinuousVertexMap : public LwoChunk { -public: - bool has_value(int polygon_index, int vertex_index) const; - PTA_stdfloat get_value(int polygon_index, int vertex_index) const; - - IffId _map_type; - int _dimension; - std::string _name; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - typedef pmap VMap; - typedef pmap VMad; - VMad _vmad; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoDiscontinuousVertexMap", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoGroupChunk.cxx b/pandatool/src/lwo/lwoGroupChunk.cxx deleted file mode 100644 index 481f27bb..00000000 --- a/pandatool/src/lwo/lwoGroupChunk.cxx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoGroupChunk.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoGroupChunk.h" -#include "lwoInputFile.h" - -#include "pnotify.h" - -TypeHandle LwoGroupChunk::_type_handle; - -/** - * Returns the number of child chunks of this group. - */ -int LwoGroupChunk:: -get_num_chunks() const { - return _chunks.size(); -} - -/** - * Returns the nth child chunk of this group. - */ -IffChunk *LwoGroupChunk:: -get_chunk(int n) const { - nassertr(n >= 0 && n < (int)_chunks.size(), nullptr); - return _chunks[n]; -} - -/** - * Reads a sequence of child chunks, until byte stop_at has been been reached, - * and stores them as the children. Returns true if successful (and exactly - * the correct number of bytes were read), or false otherwise. - */ -bool LwoGroupChunk:: -read_chunks_iff(IffInputFile *in, size_t stop_at) { - while (in->get_bytes_read() < stop_at && !in->is_eof()) { - PT(IffChunk) chunk = in->get_chunk(); - if (chunk == nullptr) { - return false; - } - _chunks.push_back(chunk); - } - - return (in->get_bytes_read() == stop_at); -} - -/** - * Similar to read_chunks_iff(), but reads them as subchunks. - */ -bool LwoGroupChunk:: -read_subchunks_iff(IffInputFile *in, size_t stop_at) { - while (in->get_bytes_read() < stop_at && !in->is_eof()) { - PT(IffChunk) chunk = in->get_subchunk(this); - if (chunk == nullptr) { - return false; - } - _chunks.push_back(chunk); - } - - return (in->get_bytes_read() == stop_at); -} - -/** - * Formats the list of chunks for output to the user (primarily for - * debugging), one per line. - */ -void LwoGroupChunk:: -write_chunks(std::ostream &out, int indent_level) const { - Chunks::const_iterator ci; - for (ci = _chunks.begin(); ci != _chunks.end(); ++ci) { - (*ci)->write(out, indent_level); - } -} diff --git a/pandatool/src/lwo/lwoGroupChunk.h b/pandatool/src/lwo/lwoGroupChunk.h deleted file mode 100644 index 2a72dd79..00000000 --- a/pandatool/src/lwo/lwoGroupChunk.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoGroupChunk.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOGROUPCHUNK_H -#define LWOGROUPCHUNK_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" -#include "iffChunk.h" - -#include "pointerTo.h" - -#include "pvector.h" - -/** - * A particular kind of LwoChunk that is expected to contain an arbitrary - * number of child chunks. - */ -class LwoGroupChunk : public LwoChunk { -public: - int get_num_chunks() const; - IffChunk *get_chunk(int n) const; - -protected: - bool read_chunks_iff(IffInputFile *in, size_t stop_at); - bool read_subchunks_iff(IffInputFile *in, size_t stop_at); - void write_chunks(std::ostream &out, int indent_level) const; - - typedef pvector< PT(IffChunk) > Chunks; - Chunks _chunks; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoGroupChunk", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoHeader.I b/pandatool/src/lwo/lwoHeader.I deleted file mode 100644 index 2d82f6c9..00000000 --- a/pandatool/src/lwo/lwoHeader.I +++ /dev/null @@ -1,29 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoHeader.I - * @author drose - * @date 2001-04-24 - */ - -/** - * Returns true if the header represents a valid and recognized Lightwave - * header, false otherwise. - */ -INLINE bool LwoHeader:: -is_valid() const { - return _valid; -} - -/** - * Returns the version of the Lightwave file. - */ -INLINE double LwoHeader:: -get_version() const { - return _version; -} diff --git a/pandatool/src/lwo/lwoHeader.cxx b/pandatool/src/lwo/lwoHeader.cxx deleted file mode 100644 index aba632eb..00000000 --- a/pandatool/src/lwo/lwoHeader.cxx +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoHeader.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoHeader.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoHeader::_type_handle; - -/** - * - */ -LwoHeader:: -LwoHeader() { - _valid = false; - _version = 0.0; -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoHeader:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _lwid = lin->get_id(); - - if (_lwid == IffId("LWO2")) { - _valid = true; - _version = 6.0; - } else if (_lwid == IffId("LWOB")) { - _valid = true; - _version = 5.0; - } - - if (_valid) { - lin->set_lwo_version(_version); - } - - read_chunks_iff(lin, stop_at); - - return true; -} - -/** - * - */ -void LwoHeader:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " {\n"; - indent(out, indent_level + 2) - << "id = " << _lwid << "\n"; - write_chunks(out, indent_level + 2); - indent(out, indent_level) - << "}\n"; -} diff --git a/pandatool/src/lwo/lwoHeader.h b/pandatool/src/lwo/lwoHeader.h deleted file mode 100644 index 539d4976..00000000 --- a/pandatool/src/lwo/lwoHeader.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoHeader.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOHEADER_H -#define LWOHEADER_H - -#include "pandatoolbase.h" - -#include "lwoGroupChunk.h" - -/** - * The first chunk in a Lightwave Object file. - */ -class LwoHeader : public LwoGroupChunk { -public: - LwoHeader(); - - IffId _lwid; - - INLINE bool is_valid() const; - INLINE double get_version() const; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - bool _valid; - double _version; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoGroupChunk::init_type(); - register_type(_type_handle, "LwoHeader", - LwoGroupChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "lwoHeader.I" - -#endif diff --git a/pandatool/src/lwo/lwoInputFile.I b/pandatool/src/lwo/lwoInputFile.I deleted file mode 100644 index 7824cdbb..00000000 --- a/pandatool/src/lwo/lwoInputFile.I +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoInputFile.I - * @author drose - * @date 2001-04-24 - */ - -/** - * Returns the version of the Lightwave file being read. This is unknown - * until the header record has been read; then it will be set by the header. - */ -INLINE double LwoInputFile:: -get_lwo_version() const { - return _lwo_version; -} - - -/** - * Changes the version number reported for the Lightwave file. Normally this - * is only called by LwoHeader as it is read. - */ -INLINE void LwoInputFile:: -set_lwo_version(double lwo_version) { - _lwo_version = lwo_version; -} diff --git a/pandatool/src/lwo/lwoInputFile.cxx b/pandatool/src/lwo/lwoInputFile.cxx deleted file mode 100644 index a6737855..00000000 --- a/pandatool/src/lwo/lwoInputFile.cxx +++ /dev/null @@ -1,138 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoInputFile.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoInputFile.h" -#include "lwoBoundingBox.h" -#include "lwoClip.h" -#include "lwoDiscontinuousVertexMap.h" -#include "lwoHeader.h" -#include "lwoLayer.h" -#include "lwoPoints.h" -#include "lwoPolygons.h" -#include "lwoPolygonTags.h" -#include "lwoTags.h" -#include "lwoSurface.h" -#include "lwoVertexMap.h" - -using std::string; - -TypeHandle LwoInputFile::_type_handle; - -/** - * - */ -LwoInputFile:: -LwoInputFile() { -} - -/** - * - */ -LwoInputFile:: -~LwoInputFile() { -} - -/** - * Reads a Lightwave variable-length index. This is either a 2-byte or 4-byte - * integer. - */ -int LwoInputFile:: -get_vx() { - uint16_t top = get_be_uint16(); - if ((top & 0xff00) == 0xff00) { - // The first byte is 0xff, which indicates we have a 4-byte integer. - uint16_t bottom = get_be_uint16(); - return ((int)(top & 0xff) << 16) | bottom; - } - - // The first byte is not 0xff, which indicates we have a 2-byte integer. - return top; -} - -/** - * Reads a three-component vector of floats. - */ -LVecBase3 LwoInputFile:: -get_vec3() { - LVecBase3 result; - result[0] = get_be_float32(); - result[1] = get_be_float32(); - result[2] = get_be_float32(); - return result; -} - -/** - * Reads a Lightwave platform-neutral filename and converts it to a Panda - * platform-neutral filename. - */ -Filename LwoInputFile:: -get_filename() { - string name = get_string(); - size_t colon = name.find(':'); - if (colon == string::npos) { - // No colon; it's just a relative path. - return Filename(name); - } - - // The colon separates the device and the path. - string device = name.substr(0, colon); - string path = name.substr(colon + 1); - - nout << "Ignoring filename device " << device << "\n"; - return Filename("/", path); -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID. - */ -IffChunk *LwoInputFile:: -make_new_chunk(IffId id) { - if (id == IffId("FORM")) { - return new LwoHeader; - - } else if (id == IffId("LAYR")) { - return new LwoLayer; - - } else if (id == IffId("PNTS")) { - return new LwoPoints; - - } else if (id == IffId("VMAP")) { - return new LwoVertexMap; - - } else if (id == IffId("VMAD")) { - return new LwoDiscontinuousVertexMap; - - } else if (id == IffId("POLS")) { - return new LwoPolygons; - - } else if (id == IffId("TAGS") || - id == IffId("SRFS")) { - return new LwoTags; - - } else if (id == IffId("PTAG")) { - return new LwoPolygonTags; - - } else if (id == IffId("CLIP")) { - return new LwoClip; - - } else if (id == IffId("SURF")) { - return new LwoSurface; - - } else if (id == IffId("BBOX")) { - return new LwoBoundingBox; - - } else { - return IffInputFile::make_new_chunk(id); - } -} diff --git a/pandatool/src/lwo/lwoInputFile.h b/pandatool/src/lwo/lwoInputFile.h deleted file mode 100644 index 59794684..00000000 --- a/pandatool/src/lwo/lwoInputFile.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoInputFile.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOINPUTFILE_H -#define LWOINPUTFILE_H - -#include "pandatoolbase.h" - -#include "iffInputFile.h" - -#include "luse.h" - -/** - * A specialization of IffInputFile to handle reading a Lightwave Object file. - */ -class LwoInputFile : public IffInputFile { -public: - LwoInputFile(); - ~LwoInputFile(); - - INLINE double get_lwo_version() const; - INLINE void set_lwo_version(double version); - - int get_vx(); - LVecBase3 get_vec3(); - Filename get_filename(); - -protected: - virtual IffChunk *make_new_chunk(IffId id); - -private: - double _lwo_version; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - IffInputFile::init_type(); - register_type(_type_handle, "LwoInputFile", - IffInputFile::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#include "lwoInputFile.I" - -#endif diff --git a/pandatool/src/lwo/lwoLayer.cxx b/pandatool/src/lwo/lwoLayer.cxx deleted file mode 100644 index 1fea2cd5..00000000 --- a/pandatool/src/lwo/lwoLayer.cxx +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoLayer.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoLayer.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoLayer::_type_handle; - -/** - * Resets the layer's parameters to initial defaults for a generic layer - * created implicitly. - */ -void LwoLayer:: -make_generic() { - _number = -1; - _flags = 0; - _pivot.set(0.0, 0.0, 0.0); - _name = "Generic"; - _parent = -1; -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoLayer:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _number = lin->get_be_uint16(); - _flags = lin->get_be_uint16(); - _pivot = lin->get_vec3(); - _name = lin->get_string(); - - if (lin->get_bytes_read() >= stop_at) { - _parent = -1; - } else { - _parent = lin->get_be_uint16(); - if (_parent == 0xffff) { - _parent = -1; - } - } - - return true; -} - -/** - * - */ -void LwoLayer:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { number = " << _number << ", flags = 0x" - << std::hex << _flags << std::dec << ", pivot = " << _pivot - << ", _name = \"" << _name << "\", _parent = " << _parent << " }\n"; -} diff --git a/pandatool/src/lwo/lwoLayer.h b/pandatool/src/lwo/lwoLayer.h deleted file mode 100644 index a959d489..00000000 --- a/pandatool/src/lwo/lwoLayer.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoLayer.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOLAYER_H -#define LWOLAYER_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "luse.h" - -/** - * Signals the start of a new layer. All the data chunks which follow will be - * included in this layer until another layer chunk is encountered. If data - * is encountered before a layer chunk, it goes into an arbitrary layer. - */ -class LwoLayer : public LwoChunk { -public: - void make_generic(); - - enum Flags { - F_hidden = 0x0001 - }; - - int _number; - int _flags; - LPoint3 _pivot; - std::string _name; - int _parent; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoLayer", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoPoints.cxx b/pandatool/src/lwo/lwoPoints.cxx deleted file mode 100644 index 7abfeea6..00000000 --- a/pandatool/src/lwo/lwoPoints.cxx +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoPoints.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoPoints.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoPoints::_type_handle; - -/** - * Returns the number of points of this group. - */ -int LwoPoints:: -get_num_points() const { - return _points.size(); -} - -/** - * Returns the nth point of this group. - */ -const LPoint3 &LwoPoints:: -get_point(int n) const { - nassertr(n >= 0 && n < (int)_points.size(), LPoint3::zero()); - return _points[n]; -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoPoints:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { - LPoint3 point = lin->get_vec3(); - _points.push_back(point); - } - - return (lin->get_bytes_read() == stop_at); -} - -/** - * - */ -void LwoPoints:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { " << _points.size() << " points }\n"; -} diff --git a/pandatool/src/lwo/lwoPoints.h b/pandatool/src/lwo/lwoPoints.h deleted file mode 100644 index 27f2a36c..00000000 --- a/pandatool/src/lwo/lwoPoints.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoPoints.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOPOINTS_H -#define LWOPOINTS_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "luse.h" - -/** - * An array of points that will be referenced by later chunks. - */ -class LwoPoints : public LwoChunk { -public: - int get_num_points() const; - const LPoint3 &get_point(int n) const; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - typedef pvector Points; - Points _points; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoPoints", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoPolygonTags.cxx b/pandatool/src/lwo/lwoPolygonTags.cxx deleted file mode 100644 index 48f81b47..00000000 --- a/pandatool/src/lwo/lwoPolygonTags.cxx +++ /dev/null @@ -1,80 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoPolygonTags.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoPolygonTags.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoPolygonTags::_type_handle; - - -/** - * Returns true if the map has a tag associated with the given polygon index, - * false otherwise. - */ -bool LwoPolygonTags:: -has_tag(int polygon_index) const { - return (_tmap.count(polygon_index) != 0); -} - -/** - * Returns the tag associated with the given polygon index, or -1 if there is - * no tag associated. - */ -int LwoPolygonTags:: -get_tag(int polygon_index) const { - TMap::const_iterator ti; - ti = _tmap.find(polygon_index); - if (ti != _tmap.end()) { - return (*ti).second; - } - - return -1; -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoPolygonTags:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _tag_type = lin->get_id(); - - while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { - int polygon_index = lin->get_vx(); - int tag = lin->get_be_int16(); - - bool inserted = _tmap.insert(TMap::value_type(polygon_index, tag)).second; - if (!inserted) { - nout << "Duplicate index " << polygon_index << " in map.\n"; - } - } - - return (lin->get_bytes_read() == stop_at); -} - -/** - * - */ -void LwoPolygonTags:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { tag_type = " << _tag_type << ", " - << _tmap.size() << " values }\n"; -} diff --git a/pandatool/src/lwo/lwoPolygonTags.h b/pandatool/src/lwo/lwoPolygonTags.h deleted file mode 100644 index 8603492c..00000000 --- a/pandatool/src/lwo/lwoPolygonTags.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoPolygonTags.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOPOLYGONTAGS_H -#define LWOPOLYGONTAGS_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * An association of polygons defined in the most recent LwoPolygons chunk to - * tag ids defined in the most recent LwoTags chunk. This associated - * properties with the polygons, depending on the tag_type. - */ -class LwoPolygonTags : public LwoChunk { -public: - bool has_tag(int polygon_index) const; - int get_tag(int polygon_index) const; - - IffId _tag_type; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - typedef pmap TMap; - TMap _tmap; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoPolygonTags", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoPolygons.cxx b/pandatool/src/lwo/lwoPolygons.cxx deleted file mode 100644 index 22d03c21..00000000 --- a/pandatool/src/lwo/lwoPolygons.cxx +++ /dev/null @@ -1,120 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoPolygons.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoPolygons.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoPolygons::_type_handle; - -/** - * Returns the number of polygons of this group. - */ -int LwoPolygons:: -get_num_polygons() const { - return _polygons.size(); -} - -/** - * Returns the nth polygon of this group. - */ -LwoPolygons::Polygon *LwoPolygons:: -get_polygon(int n) const { - nassertr(n >= 0 && n < (int)_polygons.size(), nullptr); - return _polygons[n]; -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoPolygons:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - if (lin->get_lwo_version() >= 6.0) { - // 6.x style syntax: POLS { type[ID4], ( numvert+flags[U2], vert[VX] # - // numvert )* } - - _polygon_type = lin->get_id(); - - while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { - int nf = lin->get_be_uint16(); - int num_vertices = nf & PF_numverts_mask; - - PT(Polygon) poly = new Polygon; - poly->_flags = nf & ~PF_numverts_mask; - poly->_surface_index = -1; - - for (int i = 0; i < num_vertices; i++) { - int vindex = lin->get_vx(); - poly->_vertices.push_back(vindex); - } - - _polygons.push_back(poly); - } - - } else { - // 5.x style syntax: POLS { ( numvert[U2], vert[VX] # numvert, - // +-(surf+1)[I2], numdetail[U2]? )* } - _polygon_type = IffId("FACE"); - - int num_decals = 0; - while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { - int num_vertices = lin->get_be_uint16(); - - PT(Polygon) poly = new Polygon; - poly->_flags = 0; - - for (int i = 0; i < num_vertices; i++) { - int vindex = lin->get_vx(); - poly->_vertices.push_back(vindex); - } - - int surface = lin->get_be_int16(); - - if (num_decals > 0) { - // This is a decal polygon of a previous polygon. - num_decals--; - poly->_flags |= PF_decal; - - } else { - if (surface < 0) { - num_decals = lin->get_be_int16(); - surface = -surface; - } - } - - // The surface index is stored +1 to allow signedness to be examined. - poly->_surface_index = surface - 1; - - _polygons.push_back(poly); - } - } - - return true; -} - -/** - * - */ -void LwoPolygons:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { polygon_type = " << _polygon_type - << ", " << _polygons.size() << " polygons }\n"; -} diff --git a/pandatool/src/lwo/lwoPolygons.h b/pandatool/src/lwo/lwoPolygons.h deleted file mode 100644 index d7ad6556..00000000 --- a/pandatool/src/lwo/lwoPolygons.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoPolygons.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOPOLYGONS_H -#define LWOPOLYGONS_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "luse.h" -#include "vector_int.h" -#include "referenceCount.h" -#include "pointerTo.h" - -/** - * An array of polygons that will be referenced by later chunks. - */ -class LwoPolygons : public LwoChunk { -public: - enum PolygonFlags { - PF_continuity_1 = 0x0400, - PF_continuity_2 = 0x0800, - PF_numverts_mask = 0x03f, - - // This "flag" is stored artificially when reading 5.x LWOB files, and - // indicates that the polygon is a decal of a preceding polygon. - PF_decal = 0x0001 - }; - - class Polygon : public ReferenceCount { - public: - int _flags; - vector_int _vertices; - - // This value is only filled in when reading 5.x LWOB files, and indicates - // the surface index of the polygon within a preceding SRFS (LwoTags) - // chunk. For 6.x and later files, this will be set to -1. - int _surface_index; - }; - - int get_num_polygons() const; - Polygon *get_polygon(int n) const; - - IffId _polygon_type; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - typedef pvector< PT(Polygon) > Polygons; - Polygons _polygons; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoPolygons", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoStillImage.cxx b/pandatool/src/lwo/lwoStillImage.cxx deleted file mode 100644 index 9a31986c..00000000 --- a/pandatool/src/lwo/lwoStillImage.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoStillImage.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoStillImage.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoStillImage::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoStillImage:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _filename = lin->get_filename(); - - return true; -} - -/** - * - */ -void LwoStillImage:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { filename = \"" << _filename << "\" }\n"; -} diff --git a/pandatool/src/lwo/lwoStillImage.h b/pandatool/src/lwo/lwoStillImage.h deleted file mode 100644 index c800cfb0..00000000 --- a/pandatool/src/lwo/lwoStillImage.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoStillImage.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSTILLIMAGE_H -#define LWOSTILLIMAGE_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "filename.h" - -/** - * A single still image associated with a LwoClip chunk. - */ -class LwoStillImage : public LwoChunk { -public: - Filename _filename; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoStillImage", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurface.cxx b/pandatool/src/lwo/lwoSurface.cxx deleted file mode 100644 index e1318947..00000000 --- a/pandatool/src/lwo/lwoSurface.cxx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurface.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurface.h" -#include "iffInputFile.h" -#include "lwoSurfaceBlock.h" -#include "lwoSurfaceColor.h" -#include "lwoSurfaceParameter.h" -#include "lwoSurfaceSidedness.h" -#include "lwoSurfaceSmoothingAngle.h" - -#include "indent.h" - -TypeHandle LwoSurface::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurface:: -read_iff(IffInputFile *in, size_t stop_at) { - _name = in->get_string(); - _source = in->get_string(); - read_subchunks_iff(in, stop_at); - return true; -} - -/** - * - */ -void LwoSurface:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " {\n"; - indent(out, indent_level + 2) - << "name = \"" << _name << "\", source = \"" << _source << "\"\n"; - write_chunks(out, indent_level + 2); - indent(out, indent_level) - << "}\n"; -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID, according to the context given by this chunk itself. - */ -IffChunk *LwoSurface:: -make_new_chunk(IffInputFile *in, IffId id) { - if (id == IffId("COLR")) { - return new LwoSurfaceColor; - - } else if (id == IffId("DIFF") || - id == IffId("LUMI") || - id == IffId("SPEC") || - id == IffId("REFL") || - id == IffId("TRAN") || - id == IffId("TRNL") || - id == IffId("GLOS") || - id == IffId("SHRP") || - id == IffId("BUMP") || - id == IffId("RSAN") || - id == IffId("RIND")) { - return new LwoSurfaceParameter; - - } else if (id == IffId("SIDE")) { - return new LwoSurfaceSidedness; - - } else if (id == IffId("SMAN")) { - return new LwoSurfaceSmoothingAngle; - - } else if (id == IffId("BLOK")) { - return new LwoSurfaceBlock; - - } else { - return IffChunk::make_new_chunk(in, id); - } -} diff --git a/pandatool/src/lwo/lwoSurface.h b/pandatool/src/lwo/lwoSurface.h deleted file mode 100644 index 75523f0c..00000000 --- a/pandatool/src/lwo/lwoSurface.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurface.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACE_H -#define LWOSURFACE_H - -#include "pandatoolbase.h" - -#include "lwoGroupChunk.h" - -/** - * Describes the shading attributes of a surface. This is similar to the - * concept usually called a "material" or "shader" in other file formats. - */ -class LwoSurface : public LwoGroupChunk { -public: - std::string _name; - std::string _source; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - - virtual IffChunk *make_new_chunk(IffInputFile *in, IffId id); - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoGroupChunk::init_type(); - register_type(_type_handle, "LwoSurface", - LwoGroupChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlock.cxx b/pandatool/src/lwo/lwoSurfaceBlock.cxx deleted file mode 100644 index 8dd32652..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlock.cxx +++ /dev/null @@ -1,104 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlock.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlock.h" -#include "iffInputFile.h" -#include "lwoSurfaceBlockAxis.h" -#include "lwoSurfaceBlockImage.h" -#include "lwoSurfaceBlockHeader.h" -#include "lwoSurfaceBlockProjection.h" -#include "lwoSurfaceBlockRepeat.h" -#include "lwoSurfaceBlockTMap.h" -#include "lwoSurfaceBlockWrap.h" -#include "lwoSurfaceBlockVMapName.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlock::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlock:: -read_iff(IffInputFile *in, size_t stop_at) { - PT(IffChunk) chunk = in->get_subchunk(this); - if (chunk == nullptr) { - return false; - } - if (!chunk->is_of_type(LwoSurfaceBlockHeader::get_class_type())) { - nout << "Invalid chunk for header of surface block: " << *chunk << "\n"; - return false; - } - - _header = DCAST(LwoSurfaceBlockHeader, chunk); - - read_subchunks_iff(in, stop_at); - return true; -} - -/** - * - */ -void LwoSurfaceBlock:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " {\n"; - _header->write(out, indent_level + 2); - out << "\n"; - write_chunks(out, indent_level + 2); - indent(out, indent_level) - << "}\n"; -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID, according to the context given by this chunk itself. - */ -IffChunk *LwoSurfaceBlock:: -make_new_chunk(IffInputFile *in, IffId id) { - if (id == IffId("IMAP") || - id == IffId("PROC") || - id == IffId("GRAD") || - id == IffId("SHDR")) { - return new LwoSurfaceBlockHeader; - - } else if (id == IffId("TMAP")) { - return new LwoSurfaceBlockTMap; - - } else if (id == IffId("PROJ")) { - return new LwoSurfaceBlockProjection; - - } else if (id == IffId("AXIS")) { - return new LwoSurfaceBlockAxis; - - } else if (id == IffId("IMAG")) { - return new LwoSurfaceBlockImage; - - } else if (id == IffId("WRAP")) { - return new LwoSurfaceBlockWrap; - - } else if (id == IffId("WRPH") || - id == IffId("WRPW")) { - return new LwoSurfaceBlockRepeat; - - } else if (id == IffId("VMAP")) { - return new LwoSurfaceBlockVMapName; - - } else { - return IffChunk::make_new_chunk(in, id); - } -} diff --git a/pandatool/src/lwo/lwoSurfaceBlock.h b/pandatool/src/lwo/lwoSurfaceBlock.h deleted file mode 100644 index bfac032a..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlock.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlock.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCK_H -#define LWOSURFACEBLOCK_H - -#include "pandatoolbase.h" - -#include "lwoGroupChunk.h" -#include "lwoSurfaceBlockHeader.h" - -/** - * A texture layer or shader, part of a LwoSurface chunk. - */ -class LwoSurfaceBlock : public LwoGroupChunk { -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - - virtual IffChunk *make_new_chunk(IffInputFile *in, IffId id); - - PT(LwoSurfaceBlockHeader) _header; - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockAxis.cxx b/pandatool/src/lwo/lwoSurfaceBlockAxis.cxx deleted file mode 100644 index 3390debd..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockAxis.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockAxis.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockAxis.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockAxis::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockAxis:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _axis = (Axis)lin->get_be_uint16(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockAxis:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { axis = " << (int)_axis << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockAxis.h b/pandatool/src/lwo/lwoSurfaceBlockAxis.h deleted file mode 100644 index 4e0920c5..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockAxis.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockAxis.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKAXIS_H -#define LWOSURFACEBLOCKAXIS_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Indicates the axis for this particular shader's projection. This works in - * conjunction with LwoSurfaceBlockProjection. This is a subchunk of - * LwoSurfaceBlock. - */ -class LwoSurfaceBlockAxis : public LwoChunk { -public: - enum Axis { - A_x = 0, - A_y = 1, - A_z = 2 - }; - Axis _axis; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockAxis", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockChannel.cxx b/pandatool/src/lwo/lwoSurfaceBlockChannel.cxx deleted file mode 100644 index 94dc45c8..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockChannel.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockChannel.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockChannel.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockChannel::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockChannel:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _channel_id = lin->get_id(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockChannel:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { channel_id = " << _channel_id << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockChannel.h b/pandatool/src/lwo/lwoSurfaceBlockChannel.h deleted file mode 100644 index 00e35bc2..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockChannel.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockChannel.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKCHANNEL_H -#define LWOSURFACEBLOCKCHANNEL_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Indicates which channel the texture in this LwoSurfaceBlock is applied to. - * This is a subchunk of LwoSurfaceBlockHeader. - */ -class LwoSurfaceBlockChannel : public LwoChunk { -public: - IffId _channel_id; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockChannel", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockCoordSys.cxx b/pandatool/src/lwo/lwoSurfaceBlockCoordSys.cxx deleted file mode 100644 index e2c9b77a..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockCoordSys.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockCoordSys.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockCoordSys.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockCoordSys::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockCoordSys:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _type = (Type)lin->get_be_uint16(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockCoordSys:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { type = " << (int)_type << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockCoordSys.h b/pandatool/src/lwo/lwoSurfaceBlockCoordSys.h deleted file mode 100644 index a9be9419..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockCoordSys.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockCoordSys.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKCOORDSYS_H -#define LWOSURFACEBLOCKCOORDSYS_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Specifies whether texture coordinates are computed based on the vertices' - * world coordinates or local coordinates. - */ -class LwoSurfaceBlockCoordSys : public LwoChunk { -public: - enum Type { - T_object = 0, - T_world = 1 - }; - - Type _type; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockCoordSys", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockEnabled.cxx b/pandatool/src/lwo/lwoSurfaceBlockEnabled.cxx deleted file mode 100644 index 82405395..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockEnabled.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockEnabled.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockEnabled.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockEnabled::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockEnabled:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _enabled = (lin->get_be_uint16() != 0); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockEnabled:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { enabled = " << _enabled << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockEnabled.h b/pandatool/src/lwo/lwoSurfaceBlockEnabled.h deleted file mode 100644 index a07c6ea3..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockEnabled.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockEnabled.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKENABLED_H -#define LWOSURFACEBLOCKENABLED_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Indicates whether this particular layer or shader should be rendered or - * not. This is a subchunk of LwoSurfaceBlockHeader. - */ -class LwoSurfaceBlockEnabled : public LwoChunk { -public: - bool _enabled; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockEnabled", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockHeader.cxx b/pandatool/src/lwo/lwoSurfaceBlockHeader.cxx deleted file mode 100644 index 69351fa4..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockHeader.cxx +++ /dev/null @@ -1,85 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockHeader.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockHeader.h" -#include "lwoInputFile.h" -#include "lwoSurfaceBlockChannel.h" -#include "lwoSurfaceBlockEnabled.h" -#include "lwoSurfaceBlockOpacity.h" -#include "lwoSurfaceBlockAxis.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockHeader::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockHeader:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _ordinal = lin->get_string(); - read_subchunks_iff(lin, stop_at); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockHeader:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " {\n"; - indent(out, indent_level + 2) - << "ordinal = 0x" << std::hex << std::setfill('0'); - - std::string::const_iterator si; - for (si = _ordinal.begin(); si != _ordinal.end(); ++si) { - out << std::setw(2) << (int)(unsigned char)(*si); - } - - out << std::dec << std::setfill(' ') << "\n"; - - write_chunks(out, indent_level + 2); - indent(out, indent_level) - << "}\n"; -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID, according to the context given by this chunk itself. - */ -IffChunk *LwoSurfaceBlockHeader:: -make_new_chunk(IffInputFile *in, IffId id) { - if (id == IffId("CHAN")) { - return new LwoSurfaceBlockChannel; - - } else if (id == IffId("ENAB")) { - return new LwoSurfaceBlockEnabled; - - } else if (id == IffId("OPAC")) { - return new LwoSurfaceBlockOpacity; - - } else if (id == IffId("AXIS")) { - return new LwoSurfaceBlockAxis; - - } else { - return IffChunk::make_new_chunk(in, id); - } -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockHeader.h b/pandatool/src/lwo/lwoSurfaceBlockHeader.h deleted file mode 100644 index 6249db26..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockHeader.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockHeader.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKHEADER_H -#define LWOSURFACEBLOCKHEADER_H - -#include "pandatoolbase.h" - -#include "lwoGroupChunk.h" - -/** - * The header chunk within a LwoSurfaceBlock chunk. - */ -class LwoSurfaceBlockHeader : public LwoGroupChunk { -public: - std::string _ordinal; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - - virtual IffChunk *make_new_chunk(IffInputFile *in, IffId id); - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoGroupChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockHeader", - LwoGroupChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockImage.cxx b/pandatool/src/lwo/lwoSurfaceBlockImage.cxx deleted file mode 100644 index 520d8cef..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockImage.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockImage.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockImage.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockImage::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockImage:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _index = lin->get_vx(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockImage:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { index = " << _index << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockImage.h b/pandatool/src/lwo/lwoSurfaceBlockImage.h deleted file mode 100644 index 968f5d3a..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockImage.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockImage.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKIMAGE_H -#define LWOSURFACEBLOCKIMAGE_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Specifies the particular image that is being applied as a texture. This - * references a recently-defined CLIP image by index number. - */ -class LwoSurfaceBlockImage : public LwoChunk { -public: - int _index; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockImage", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockOpacity.cxx b/pandatool/src/lwo/lwoSurfaceBlockOpacity.cxx deleted file mode 100644 index 456e1383..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockOpacity.cxx +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockOpacity.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockOpacity.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockOpacity::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockOpacity:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _type = (Type)lin->get_be_uint16(); - _opacity = lin->get_be_float32(); - _envelope = lin->get_vx(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockOpacity:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { type = " << (int)_type - << ", opacity = " << _opacity * 100.0 << "%, envelope = " << _envelope - << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockOpacity.h b/pandatool/src/lwo/lwoSurfaceBlockOpacity.h deleted file mode 100644 index 906c8615..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockOpacity.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockOpacity.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKOPACITY_H -#define LWOSURFACEBLOCKOPACITY_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Indicates how transparent or opaque this particular layer is in relation to - * the layers beneath it. This is a subchunk of LwoSurfaceBlockHeader. - */ -class LwoSurfaceBlockOpacity : public LwoChunk { -public: - enum Type { - T_additive = 0, - T_subtractive = 1, - T_difference = 2, - T_multiply = 3, - T_divide = 4, - T_alpha = 5, - T_texture_displacement = 6 - }; - - Type _type; - PN_stdfloat _opacity; - int _envelope; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockOpacity", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockProjection.cxx b/pandatool/src/lwo/lwoSurfaceBlockProjection.cxx deleted file mode 100644 index 500d90c2..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockProjection.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockProjection.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockProjection.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockProjection::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockProjection:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _mode = (Mode)lin->get_be_uint16(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockProjection:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { mode = " << (int)_mode << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockProjection.h b/pandatool/src/lwo/lwoSurfaceBlockProjection.h deleted file mode 100644 index bcbbff41..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockProjection.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockProjection.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKPROJECTION_H -#define LWOSURFACEBLOCKPROJECTION_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Indicates the projection mode for this particular shader. This determines - * how UV coordinates should be computed based on the vertex positions. This - * is a subchunk of LwoSurfaceBlock. - */ -class LwoSurfaceBlockProjection : public LwoChunk { -public: - enum Mode { - M_planar = 0, - M_cylindrical = 1, - M_spherical = 2, - M_cubic = 3, - M_front = 4, - M_uv = 5 - }; - Mode _mode; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockProjection", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockRefObj.cxx b/pandatool/src/lwo/lwoSurfaceBlockRefObj.cxx deleted file mode 100644 index 1c19fedf..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockRefObj.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockRefObj.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockRefObj.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockRefObj::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockRefObj:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _name = lin->get_string(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockRefObj:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { name = \"" << _name << "\" }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockRefObj.h b/pandatool/src/lwo/lwoSurfaceBlockRefObj.h deleted file mode 100644 index 77818957..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockRefObj.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockRefObj.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKREFOBJ_H -#define LWOSURFACEBLOCKREFOBJ_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Specifies a reference object that the texture UV's are to be computed - * relative to. - */ -class LwoSurfaceBlockRefObj : public LwoChunk { -public: - std::string _name; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockRefObj", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockRepeat.cxx b/pandatool/src/lwo/lwoSurfaceBlockRepeat.cxx deleted file mode 100644 index 9036c143..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockRepeat.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockRepeat.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockRepeat.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockRepeat::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockRepeat:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _cycles = lin->get_be_float32(); - _envelope = lin->get_vx(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockRepeat:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { cycles = " << _cycles - << ", envelope = " << _envelope << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockRepeat.h b/pandatool/src/lwo/lwoSurfaceBlockRepeat.h deleted file mode 100644 index 73c77a45..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockRepeat.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockRepeat.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKREPEAT_H -#define LWOSURFACEBLOCKREPEAT_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * For cylindrical and spherical projections, this parameter controls how many - * times the image repeats over each full interval, in either dimension. The - * dimension is specified by the id of the chunk, either WRPW or WRPH. This - * is a subchunk of LwoSurfaceBlock. - */ -class LwoSurfaceBlockRepeat : public LwoChunk { -public: - PN_stdfloat _cycles; - int _envelope; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockRepeat", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockTMap.cxx b/pandatool/src/lwo/lwoSurfaceBlockTMap.cxx deleted file mode 100644 index 1f355d2d..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockTMap.cxx +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockTMap.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockTMap.h" -#include "lwoInputFile.h" -#include "lwoSurfaceBlockCoordSys.h" -#include "lwoSurfaceBlockTransform.h" -#include "lwoSurfaceBlockRefObj.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockTMap::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockTMap:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - read_subchunks_iff(lin, stop_at); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockTMap:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " {\n"; - write_chunks(out, indent_level + 2); - indent(out, indent_level) - << "}\n"; -} - -/** - * Allocates and returns a new chunk of the appropriate type based on the - * given ID, according to the context given by this chunk itself. - */ -IffChunk *LwoSurfaceBlockTMap:: -make_new_chunk(IffInputFile *in, IffId id) { - if (id == IffId("CNTR") || - id == IffId("SIZE") || - id == IffId("ROTA")) { - return new LwoSurfaceBlockTransform; - - } else if (id == IffId("OREF")) { - return new LwoSurfaceBlockRefObj; - - } else if (id == IffId("CSYS")) { - return new LwoSurfaceBlockCoordSys; - - } else { - return IffChunk::make_new_chunk(in, id); - } -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockTMap.h b/pandatool/src/lwo/lwoSurfaceBlockTMap.h deleted file mode 100644 index 273522d5..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockTMap.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockTMap.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKTMAP_H -#define LWOSURFACEBLOCKTMAP_H - -#include "pandatoolbase.h" - -#include "lwoGroupChunk.h" - -/** - * The tMap chunk within a LwoSurfaceBlock chunk. - */ -class LwoSurfaceBlockTMap : public LwoGroupChunk { -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - - virtual IffChunk *make_new_chunk(IffInputFile *in, IffId id); - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoGroupChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockTMap", - LwoGroupChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockTransform.cxx b/pandatool/src/lwo/lwoSurfaceBlockTransform.cxx deleted file mode 100644 index 2ed27381..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockTransform.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockTransform.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockTransform.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockTransform::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockTransform:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _vec = lin->get_vec3(); - _envelope = lin->get_vx(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockTransform:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { vec = " << _vec - << ", envelope = " << _envelope << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockTransform.h b/pandatool/src/lwo/lwoSurfaceBlockTransform.h deleted file mode 100644 index e3e07a49..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockTransform.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockTransform.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKTRANSFORM_H -#define LWOSURFACEBLOCKTRANSFORM_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "luse.h" - -/** - * Specifies a center point, scale, or rotation for the texture coordinates in - * this shader's texture mapping. The type of transform is specified by the - * ID of the chunk; either CNTR, SIZE, or ROTA. This is a subchunk of - * LwoSurfaceBlockTMap. - */ -class LwoSurfaceBlockTransform : public LwoChunk { -public: - LVecBase3 _vec; - int _envelope; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockTransform", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockVMapName.cxx b/pandatool/src/lwo/lwoSurfaceBlockVMapName.cxx deleted file mode 100644 index f4db6994..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockVMapName.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockVMapName.cxx - * @author drose - * @date 2001-04-30 - */ - -#include "lwoSurfaceBlockVMapName.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockVMapName::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockVMapName:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _name = lin->get_string(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockVMapName:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { name = \"" << _name << "\" }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockVMapName.h b/pandatool/src/lwo/lwoSurfaceBlockVMapName.h deleted file mode 100644 index 1433bfad..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockVMapName.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockVMapName.h - * @author drose - * @date 2001-04-30 - */ - -#ifndef LWOSURFACEBLOCKVMAPNAME_H -#define LWOSURFACEBLOCKVMAPNAME_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Specifies the name of a set of UV's defined on the polygons that use this - * model. - */ -class LwoSurfaceBlockVMapName : public LwoChunk { -public: - std::string _name; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockVMapName", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceBlockWrap.cxx b/pandatool/src/lwo/lwoSurfaceBlockWrap.cxx deleted file mode 100644 index 006be5f8..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockWrap.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockWrap.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceBlockWrap.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceBlockWrap::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceBlockWrap:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _width = (Mode)lin->get_be_uint16(); - _height = (Mode)lin->get_be_uint16(); - - return true; -} - -/** - * - */ -void LwoSurfaceBlockWrap:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { width = " << (int)_width - << ", height = " << (int)_height << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceBlockWrap.h b/pandatool/src/lwo/lwoSurfaceBlockWrap.h deleted file mode 100644 index bf18e92d..00000000 --- a/pandatool/src/lwo/lwoSurfaceBlockWrap.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceBlockWrap.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEBLOCKWRAP_H -#define LWOSURFACEBLOCKWRAP_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Specifies how the texture image appears for areas outside the image. - */ -class LwoSurfaceBlockWrap : public LwoChunk { -public: - enum Mode { - M_reset = 0, // black outside - M_repeat = 1, // standard repeat - M_mirror = 2, // repeat with reflection - M_edge = 3 // GL-style clamping - }; - Mode _width, _height; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceBlockWrap", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceColor.cxx b/pandatool/src/lwo/lwoSurfaceColor.cxx deleted file mode 100644 index 5a4526eb..00000000 --- a/pandatool/src/lwo/lwoSurfaceColor.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceColor.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceColor.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceColor::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceColor:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _color = lin->get_vec3(); - _envelope = lin->get_vx(); - - return true; -} - -/** - * - */ -void LwoSurfaceColor:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { color = " << _color - << ", envelope = " << _envelope << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceColor.h b/pandatool/src/lwo/lwoSurfaceColor.h deleted file mode 100644 index 584d1e78..00000000 --- a/pandatool/src/lwo/lwoSurfaceColor.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceColor.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACECOLOR_H -#define LWOSURFACECOLOR_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "luse.h" - -/** - * Records the base color of a surface, as an entry within a LwoSurface chunk. - */ -class LwoSurfaceColor : public LwoChunk { -public: - LRGBColor _color; - int _envelope; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceColor", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceParameter.cxx b/pandatool/src/lwo/lwoSurfaceParameter.cxx deleted file mode 100644 index fd3543f1..00000000 --- a/pandatool/src/lwo/lwoSurfaceParameter.cxx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceParameter.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceParameter.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceParameter::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceParameter:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _value = lin->get_be_float32(); - _envelope = lin->get_vx(); - - return true; -} - -/** - * - */ -void LwoSurfaceParameter:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { value = " << _value - << ", envelope = " << _envelope << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceParameter.h b/pandatool/src/lwo/lwoSurfaceParameter.h deleted file mode 100644 index 075383b3..00000000 --- a/pandatool/src/lwo/lwoSurfaceParameter.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceParameter.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACEPARAMETER_H -#define LWOSURFACEPARAMETER_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Records some parameter value of a surface material, as an entry within a - * LwoSurface chunk. The meaning of the value is determined by the id of this - * chunk. - */ -class LwoSurfaceParameter : public LwoChunk { -public: - PN_stdfloat _value; - int _envelope; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceParameter", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceSidedness.cxx b/pandatool/src/lwo/lwoSurfaceSidedness.cxx deleted file mode 100644 index 2c773b25..00000000 --- a/pandatool/src/lwo/lwoSurfaceSidedness.cxx +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceSidedness.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceSidedness.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoSurfaceSidedness::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceSidedness:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _sidedness = (Sidedness)lin->get_be_int16(); - - return true; -} - -/** - * - */ -void LwoSurfaceSidedness:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { sidedness = " << (int)_sidedness << " }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceSidedness.h b/pandatool/src/lwo/lwoSurfaceSidedness.h deleted file mode 100644 index f64ef112..00000000 --- a/pandatool/src/lwo/lwoSurfaceSidedness.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceSidedness.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACESIDEDNESS_H -#define LWOSURFACESIDEDNESS_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Records whether polygons are frontfacing only or backfacing also. This is - * associated with the LwoSurface chunk. - */ -class LwoSurfaceSidedness : public LwoChunk { -public: - enum Sidedness { - S_front = 1, - S_front_and_back = 3 - }; - - Sidedness _sidedness; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceSidedness", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoSurfaceSmoothingAngle.cxx b/pandatool/src/lwo/lwoSurfaceSmoothingAngle.cxx deleted file mode 100644 index 49c1f729..00000000 --- a/pandatool/src/lwo/lwoSurfaceSmoothingAngle.cxx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceSmoothingAngle.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoSurfaceSmoothingAngle.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" -#include "deg_2_rad.h" - -TypeHandle LwoSurfaceSmoothingAngle::_type_handle; - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoSurfaceSmoothingAngle:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _angle = lin->get_be_float32(); - - return true; -} - -/** - * - */ -void LwoSurfaceSmoothingAngle:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { angle = " << rad_2_deg(_angle) << " degrees }\n"; -} diff --git a/pandatool/src/lwo/lwoSurfaceSmoothingAngle.h b/pandatool/src/lwo/lwoSurfaceSmoothingAngle.h deleted file mode 100644 index c27b9a30..00000000 --- a/pandatool/src/lwo/lwoSurfaceSmoothingAngle.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoSurfaceSmoothingAngle.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOSURFACESMOOTHINGANGLE_H -#define LWOSURFACESMOOTHINGANGLE_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -/** - * Indicates the maximum angle (in radians) between adjacent polygons that - * should be smooth-shaded. - */ -class LwoSurfaceSmoothingAngle : public LwoChunk { -public: - PN_stdfloat _angle; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoSurfaceSmoothingAngle", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoTags.cxx b/pandatool/src/lwo/lwoTags.cxx deleted file mode 100644 index 43eaa2ab..00000000 --- a/pandatool/src/lwo/lwoTags.cxx +++ /dev/null @@ -1,75 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoTags.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoTags.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoTags::_type_handle; - -/** - * Returns the number of tags of this group. - */ -int LwoTags:: -get_num_tags() const { - return _tags.size(); -} - -/** - * Returns the nth tag of this group. - */ -std::string LwoTags:: -get_tag(int n) const { - nassertr(n >= 0 && n < (int)_tags.size(), std::string()); - return _tags[n]; -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoTags:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { - std::string tag = lin->get_string(); - _tags.push_back(tag); - } - - return (lin->get_bytes_read() == stop_at); -} - -/** - * - */ -void LwoTags:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { "; - - if (!_tags.empty()) { - Tags::const_iterator ti = _tags.begin(); - out << '"' << *ti << '"'; - ++ti; - while (ti != _tags.end()) { - out << ", \"" << *ti << '"'; - ++ti; - } - } - out << " }\n"; -} diff --git a/pandatool/src/lwo/lwoTags.h b/pandatool/src/lwo/lwoTags.h deleted file mode 100644 index 03ac6ede..00000000 --- a/pandatool/src/lwo/lwoTags.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoTags.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOTAGS_H -#define LWOTAGS_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "luse.h" -#include "vector_string.h" - -/** - * An array of tag strings that will be referenced by later chunks. - * - * This also serves as an array of surface names to be referenced by a later - * LwoPolygons chunk, in 5.x LWOB files. The chunk id can be used to - * differentiate the meaning (TAGS vs. SRFS). - */ -class LwoTags : public LwoChunk { -public: - int get_num_tags() const; - std::string get_tag(int n) const; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - typedef vector_string Tags; - Tags _tags; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoTags", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/lwoVertexMap.cxx b/pandatool/src/lwo/lwoVertexMap.cxx deleted file mode 100644 index a0ecbf9c..00000000 --- a/pandatool/src/lwo/lwoVertexMap.cxx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoVertexMap.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoVertexMap.h" -#include "lwoInputFile.h" - -#include "dcast.h" -#include "indent.h" - -TypeHandle LwoVertexMap::_type_handle; - - -/** - * Returns true if the map has a value associated with the given index, false - * otherwise. - */ -bool LwoVertexMap:: -has_value(int index) const { - return (_vmap.count(index) != 0); -} - -/** - * Returns the mapping value associated with the given index, or an empty - * PTA_stdfloat if there is no mapping value associated. - */ -PTA_stdfloat LwoVertexMap:: -get_value(int index) const { - VMap::const_iterator vi; - vi = _vmap.find(index); - if (vi != _vmap.end()) { - return (*vi).second; - } - - return PTA_stdfloat(); -} - -/** - * Reads the data of the chunk in from the given input file, if possible. The - * ID and length of the chunk have already been read. stop_at is the byte - * position of the file to stop at (based on the current position at - * in->get_bytes_read()). Returns true on success, false otherwise. - */ -bool LwoVertexMap:: -read_iff(IffInputFile *in, size_t stop_at) { - LwoInputFile *lin = DCAST(LwoInputFile, in); - - _map_type = lin->get_id(); - _dimension = lin->get_be_uint16(); - _name = lin->get_string(); - - while (lin->get_bytes_read() < stop_at && !lin->is_eof()) { - int index = lin->get_vx(); - - PTA_stdfloat value; - for (int i = 0; i < _dimension; i++) { - value.push_back(lin->get_be_float32()); - } - - bool inserted = _vmap.insert(VMap::value_type(index, value)).second; - if (!inserted) { - nout << "Duplicate index " << index << " in map.\n"; - } - } - - return (lin->get_bytes_read() == stop_at); -} - -/** - * - */ -void LwoVertexMap:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_id() << " { map_type = " << _map_type - << ", dimension = " << _dimension - << ", name = \"" << _name << "\", " - << _vmap.size() << " values }\n"; -} diff --git a/pandatool/src/lwo/lwoVertexMap.h b/pandatool/src/lwo/lwoVertexMap.h deleted file mode 100644 index e2b05906..00000000 --- a/pandatool/src/lwo/lwoVertexMap.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoVertexMap.h - * @author drose - * @date 2001-04-24 - */ - -#ifndef LWOVERTEXMAP_H -#define LWOVERTEXMAP_H - -#include "pandatoolbase.h" - -#include "lwoChunk.h" - -#include "pta_stdfloat.h" - -/** - * A mapping of floating-point values per integer index. The meaning of these - * values is determined by the mapping type code and/or its name. - */ -class LwoVertexMap : public LwoChunk { -public: - bool has_value(int index) const; - PTA_stdfloat get_value(int index) const; - - IffId _map_type; - int _dimension; - std::string _name; - -public: - virtual bool read_iff(IffInputFile *in, size_t stop_at); - virtual void write(std::ostream &out, int indent_level = 0) const; - -private: - typedef pmap VMap; - VMap _vmap; - -public: - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LwoChunk::init_type(); - register_type(_type_handle, "LwoVertexMap", - LwoChunk::get_class_type()); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/lwo/p3lwo_composite1.cxx b/pandatool/src/lwo/p3lwo_composite1.cxx deleted file mode 100644 index e3589ed7..00000000 --- a/pandatool/src/lwo/p3lwo_composite1.cxx +++ /dev/null @@ -1,41 +0,0 @@ - -#include "config_lwo.cxx" -#include "iffChunk.cxx" -#include "iffGenericChunk.cxx" -#include "iffId.cxx" -#include "iffInputFile.cxx" -#include "lwoBoundingBox.cxx" -#include "lwoChunk.cxx" -#include "lwoClip.cxx" -#include "lwoDiscontinuousVertexMap.cxx" -#include "lwoGroupChunk.cxx" -#include "lwoHeader.cxx" -#include "lwoInputFile.cxx" -#include "lwoLayer.cxx" -#include "lwoPoints.cxx" -#include "lwoPolygons.cxx" -#include "lwoPolygonTags.cxx" -#include "lwoTags.cxx" -#include "lwoStillImage.cxx" -#include "lwoSurface.cxx" -#include "lwoSurfaceBlock.cxx" -#include "lwoSurfaceBlockAxis.cxx" -#include "lwoSurfaceBlockChannel.cxx" -#include "lwoSurfaceBlockCoordSys.cxx" -#include "lwoSurfaceBlockEnabled.cxx" -#include "lwoSurfaceBlockImage.cxx" -#include "lwoSurfaceBlockOpacity.cxx" -#include "lwoSurfaceBlockProjection.cxx" -#include "lwoSurfaceBlockHeader.cxx" -#include "lwoSurfaceBlockRefObj.cxx" -#include "lwoSurfaceBlockRepeat.cxx" -#include "lwoSurfaceBlockTMap.cxx" -#include "lwoSurfaceBlockTransform.cxx" -#include "lwoSurfaceBlockVMapName.cxx" -#include "lwoSurfaceBlockWrap.cxx" -#include "lwoSurfaceColor.cxx" -#include "lwoSurfaceParameter.cxx" -#include "lwoSurfaceSidedness.cxx" -#include "lwoSurfaceSmoothingAngle.cxx" -#include "lwoVertexMap.cxx" - diff --git a/pandatool/src/lwo/test_lwo.cxx b/pandatool/src/lwo/test_lwo.cxx deleted file mode 100644 index baba5984..00000000 --- a/pandatool/src/lwo/test_lwo.cxx +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file test_lwo.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoInputFile.h" -#include "lwoChunk.h" -#include "config_lwo.h" - -int -main(int argc, char *argv[]) { - init_liblwo(); - if (argc != 2) { - nout << "test_lwo file.lwo\n"; - exit(1); - } - - LwoInputFile in; - if (!in.open_read(argv[1])) { - nout << "Unable to open " << argv[1] << "\n"; - exit(1); - } - - PT(IffChunk) chunk = in.get_chunk(); - while (chunk != nullptr) { - nout << "Got chunk type " << chunk->get_type() << ":\n"; - chunk->write(nout, 2); - chunk = in.get_chunk(); - } - - nout << "EOF = " << in.is_eof() << "\n"; - - return (0); -} diff --git a/pandatool/src/lwoegg/CMakeLists.txt b/pandatool/src/lwoegg/CMakeLists.txt deleted file mode 100644 index dbd4cff0..00000000 --- a/pandatool/src/lwoegg/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3LWOEGG_HEADERS - cLwoClip.h cLwoClip.I - cLwoLayer.h cLwoLayer.I - cLwoPoints.h cLwoPoints.I - cLwoPolygons.h cLwoPolygons.I - cLwoSurfaceBlock.h cLwoSurfaceBlock.I - cLwoSurfaceBlockTMap.h cLwoSurfaceBlockTMap.I - cLwoSurface.h cLwoSurface.I - lwoToEggConverter.h lwoToEggConverter.I -) - -set(P3LWOEGG_SOURCES - cLwoClip.cxx - cLwoLayer.cxx - cLwoPoints.cxx - cLwoPolygons.cxx - cLwoSurfaceBlock.cxx - cLwoSurfaceBlockTMap.cxx - cLwoSurface.cxx - lwoToEggConverter.cxx -) - -add_library(p3lwoegg STATIC ${P3LWOEGG_HEADERS} ${P3LWOEGG_SOURCES}) -target_link_libraries(p3lwoegg p3lwo p3eggbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/lwoegg/cLwoClip.I b/pandatool/src/lwoegg/cLwoClip.I deleted file mode 100644 index 8b2e4ccb..00000000 --- a/pandatool/src/lwoegg/cLwoClip.I +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoClip.I - * @author drose - * @date 2001-04-27 - */ - -/** - * Returns the index number of this clip. Each clip in a Lightwave object - * file should have a unique index number. - */ -int CLwoClip:: -get_index() const { - return _clip->_index; -} - -/** - * Returns true if this clip represents a still image, as opposed to an - * animated image. If this is true, _filename will contain the image - * filename. - */ -bool CLwoClip:: -is_still_image() const { - return _still_image; -} diff --git a/pandatool/src/lwoegg/cLwoClip.cxx b/pandatool/src/lwoegg/cLwoClip.cxx deleted file mode 100644 index 42850133..00000000 --- a/pandatool/src/lwoegg/cLwoClip.cxx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoClip.cxx - * @author drose - * @date 2001-04-27 - */ - -#include "cLwoClip.h" -#include "lwoToEggConverter.h" - -#include "lwoClip.h" -#include "lwoStillImage.h" -#include "dcast.h" - - -/** - * - */ -CLwoClip:: -CLwoClip(LwoToEggConverter *converter, const LwoClip *clip) : - _converter(converter), - _clip(clip) -{ - _still_image = false; - - // Walk through the chunk list, looking for some basic properties. - int num_chunks = _clip->get_num_chunks(); - for (int i = 0; i < num_chunks; i++) { - const IffChunk *chunk = _clip->get_chunk(i); - - if (chunk->is_of_type(LwoStillImage::get_class_type())) { - const LwoStillImage *image = DCAST(LwoStillImage, chunk); - _filename = image->_filename; - _still_image = true; - } - } -} diff --git a/pandatool/src/lwoegg/cLwoClip.h b/pandatool/src/lwoegg/cLwoClip.h deleted file mode 100644 index 118d883c..00000000 --- a/pandatool/src/lwoegg/cLwoClip.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoClip.h - * @author drose - * @date 2001-04-26 - */ - -#ifndef CLWOCLIP_H -#define CLWOCLIP_H - -#include "pandatoolbase.h" - -#include "lwoClip.h" -#include "eggGroup.h" -#include "pointerTo.h" - -class LwoToEggConverter; - -/** - * This class is a wrapper around LwoClip and stores additional information - * useful during the conversion-to-egg process. - */ -class CLwoClip { -public: - CLwoClip(LwoToEggConverter *converter, const LwoClip *clip); - - INLINE int get_index() const; - INLINE bool is_still_image() const; - - LwoToEggConverter *_converter; - CPT(LwoClip) _clip; - - Filename _filename; - bool _still_image; -}; - -#include "cLwoClip.I" - -#endif diff --git a/pandatool/src/lwoegg/cLwoLayer.I b/pandatool/src/lwoegg/cLwoLayer.I deleted file mode 100644 index 56f8a4b5..00000000 --- a/pandatool/src/lwoegg/cLwoLayer.I +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoLayer.I - * @author drose - * @date 2001-04-25 - */ - -/** - * - */ -INLINE CLwoLayer:: -CLwoLayer(LwoToEggConverter *converter, const LwoLayer *layer) : - _converter(converter), - _layer(layer) -{ -} - -/** - * Returns the index number associated with this particular layer. This - * should be unique among all Lightwave layers in a single file. - */ -INLINE int CLwoLayer:: -get_number() const { - return _layer->_number; -} diff --git a/pandatool/src/lwoegg/cLwoLayer.cxx b/pandatool/src/lwoegg/cLwoLayer.cxx deleted file mode 100644 index 73562125..00000000 --- a/pandatool/src/lwoegg/cLwoLayer.cxx +++ /dev/null @@ -1,52 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoLayer.cxx - * @author drose - * @date 2001-04-25 - */ - -#include "cLwoLayer.h" -#include "lwoToEggConverter.h" - -#include "eggData.h" - - -/** - * Creates the egg structures associated with this Lightwave object. - */ -void CLwoLayer:: -make_egg() { - _egg_group = new EggGroup(_layer->_name); - - if (_layer->_pivot != LPoint3::zero()) { - // If we have a nonzero pivot point, that's a translation transform. - LPoint3d translate = LCAST(double, _layer->_pivot); - _egg_group->set_transform3d(LMatrix4d::translate_mat(translate)); - _egg_group->set_group_type(EggGroup::GT_instance); - } -} - -/** - * Connects all the egg structures together. - */ -void CLwoLayer:: -connect_egg() { - if (_layer->_parent != -1) { - const CLwoLayer *parent = _converter->get_layer(_layer->_parent); - if (parent != nullptr) { - parent->_egg_group->add_child(_egg_group.p()); - return; - } - - nout << "No layer found with number " << _layer->_parent - << "; cannot parent layer " << _layer->_number << " properly.\n"; - } - - _converter->get_egg_data()->add_child(_egg_group.p()); -} diff --git a/pandatool/src/lwoegg/cLwoLayer.h b/pandatool/src/lwoegg/cLwoLayer.h deleted file mode 100644 index 568654ff..00000000 --- a/pandatool/src/lwoegg/cLwoLayer.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoLayer.h - * @author drose - * @date 2001-04-25 - */ - -#ifndef CLWOLAYER_H -#define CLWOLAYER_H - -#include "pandatoolbase.h" - -#include "lwoLayer.h" -#include "eggGroup.h" -#include "pointerTo.h" - -class LwoToEggConverter; - -/** - * This class is a wrapper around LwoLayer and stores additional information - * useful during the conversion-to-egg process. - */ -class CLwoLayer { -public: - INLINE CLwoLayer(LwoToEggConverter *converter, const LwoLayer *layer); - INLINE int get_number() const; - - void make_egg(); - void connect_egg(); - - LwoToEggConverter *_converter; - CPT(LwoLayer) _layer; - PT(EggGroup) _egg_group; -}; - -#include "cLwoLayer.I" - -#endif diff --git a/pandatool/src/lwoegg/cLwoPoints.I b/pandatool/src/lwoegg/cLwoPoints.I deleted file mode 100644 index 2d785c07..00000000 --- a/pandatool/src/lwoegg/cLwoPoints.I +++ /dev/null @@ -1,24 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoPoints.I - * @author drose - * @date 2001-04-25 - */ - -/** - * - */ -INLINE CLwoPoints:: -CLwoPoints(LwoToEggConverter *converter, const LwoPoints *points, - CLwoLayer *layer) : - _converter(converter), - _points(points), - _layer(layer) -{ -} diff --git a/pandatool/src/lwoegg/cLwoPoints.cxx b/pandatool/src/lwoegg/cLwoPoints.cxx deleted file mode 100644 index 93a89f79..00000000 --- a/pandatool/src/lwoegg/cLwoPoints.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoPoints.cxx - * @author drose - * @date 2001-04-25 - */ - -#include "cLwoPoints.h" -#include "lwoToEggConverter.h" -#include "cLwoLayer.h" - -#include "pta_stdfloat.h" -#include "lwoVertexMap.h" -#include "string_utils.h" - -/** - * Associates the indicated VertexMap with the points set. This may define - * such niceties as UV coordinates or per-vertex color. - */ -void CLwoPoints:: -add_vmap(const LwoVertexMap *lwo_vmap) { - IffId map_type = lwo_vmap->_map_type; - const std::string &name = lwo_vmap->_name; - - bool inserted; - if (map_type == IffId("TXUV")) { - inserted = - _txuv.insert(VMap::value_type(name, lwo_vmap)).second; - - } else if (map_type == IffId("PICK")) { - inserted = - _pick.insert(VMap::value_type(name, lwo_vmap)).second; - - } else { - return; - } - - if (!inserted) { - nout << "Multiple vertex maps on the same points of type " - << map_type << " named " << name << "\n"; - } -} - -/** - * Returns true if there is a UV of the indicated name associated with the - * given vertex, false otherwise. If true, fills in uv with the value. - */ -bool CLwoPoints:: -get_uv(const std::string &uv_name, int n, LPoint2 &uv) const { - VMap::const_iterator ni = _txuv.find(uv_name); - if (ni == _txuv.end()) { - return false; - } - - const LwoVertexMap *vmap = (*ni).second; - if (vmap->_dimension != 2) { - nout << "Unexpected dimension of " << vmap->_dimension - << " for UV map " << uv_name << "\n"; - return false; - } - - if (!vmap->has_value(n)) { - return false; - } - - PTA_stdfloat value = vmap->get_value(n); - - uv.set(value[0], value[1]); - return true; -} - -/** - * Creates the egg structures associated with this Lightwave object. - */ -void CLwoPoints:: -make_egg() { - // Generate a vpool name based on the layer index, for lack of anything - // better. - std::string vpool_name = "layer" + format_string(_layer->get_number()); - _egg_vpool = new EggVertexPool(vpool_name); -} - -/** - * Connects all the egg structures together. - */ -void CLwoPoints:: -connect_egg() { - if (!_egg_vpool->empty()) { - _layer->_egg_group->add_child(_egg_vpool.p()); - } -} diff --git a/pandatool/src/lwoegg/cLwoPoints.h b/pandatool/src/lwoegg/cLwoPoints.h deleted file mode 100644 index a4dbf642..00000000 --- a/pandatool/src/lwoegg/cLwoPoints.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoPoints.h - * @author drose - * @date 2001-04-25 - */ - -#ifndef CLWOPOINTS_H -#define CLWOPOINTS_H - -#include "pandatoolbase.h" - -#include "lwoPoints.h" -#include "eggVertexPool.h" -#include "pointerTo.h" - -#include "pmap.h" - -class LwoToEggConverter; -class LwoVertexMap; -class CLwoLayer; - -/** - * This class is a wrapper around LwoPoints and stores additional information - * useful during the conversion-to-egg process. - */ -class CLwoPoints { -public: - INLINE CLwoPoints(LwoToEggConverter *converter, const LwoPoints *points, - CLwoLayer *layer); - - void add_vmap(const LwoVertexMap *lwo_vmap); - bool get_uv(const std::string &uv_name, int n, LPoint2 &uv) const; - - void make_egg(); - void connect_egg(); - - LwoToEggConverter *_converter; - CPT(LwoPoints) _points; - CLwoLayer *_layer; - PT(EggVertexPool) _egg_vpool; - - // A number of vertex maps of different types may be associated, but we only - // care about some of the types here. - typedef pmap VMap; - VMap _txuv; - VMap _pick; -}; - -#include "cLwoPoints.I" - -#endif diff --git a/pandatool/src/lwoegg/cLwoPolygons.I b/pandatool/src/lwoegg/cLwoPolygons.I deleted file mode 100644 index 94908deb..00000000 --- a/pandatool/src/lwoegg/cLwoPolygons.I +++ /dev/null @@ -1,26 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoPolygons.I - * @author drose - * @date 2001-04-25 - */ - -/** - * - */ -INLINE CLwoPolygons:: -CLwoPolygons(LwoToEggConverter *converter, const LwoPolygons *polygons, - CLwoPoints *points) : - _converter(converter), - _polygons(polygons), - _points(points) -{ - _tags = nullptr; - _surf_ptags = nullptr; -} diff --git a/pandatool/src/lwoegg/cLwoPolygons.cxx b/pandatool/src/lwoegg/cLwoPolygons.cxx deleted file mode 100644 index e6a0fac4..00000000 --- a/pandatool/src/lwoegg/cLwoPolygons.cxx +++ /dev/null @@ -1,284 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoPolygons.cxx - * @author drose - * @date 2001-04-25 - */ - -#include "cLwoPolygons.h" -#include "lwoToEggConverter.h" -#include "cLwoPoints.h" -#include "cLwoLayer.h" -#include "cLwoSurface.h" - -#include "lwoPolygonTags.h" -#include "lwoTags.h" -#include "lwoDiscontinuousVertexMap.h" -#include "eggData.h" -#include "eggPolygon.h" -#include "eggPoint.h" -#include "deg_2_rad.h" - -using std::string; - -/** - * Associates the indicated PolygonTags and Tags with the polygons in this - * chunk. This may define features such as per-polygon surfaces, parts, and - * smoothing groups. - */ -void CLwoPolygons:: -add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags) { - if (_tags != nullptr && _tags != tags) { - nout << "Multiple Tags fields in effect on the same polygons.\n"; - } - _tags = tags; - - IffId type = lwo_ptags->_tag_type; - - bool inserted = _ptags.insert(PTags::value_type(type, lwo_ptags)).second; - if (!inserted) { - nout << "Multiple polygon tags on the same polygons of type " - << type << "\n"; - - } else { - if (type == IffId("SURF")) { - _surf_ptags = lwo_ptags; - } - } -} - -/** - * Associates the indicated DiscontinousVertexMap with the polygons. This can - * be used in conjunction with (or in place of) the VertexMap associated with - * the points set, to define per-polygon UV's etc. - */ -void CLwoPolygons:: -add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad) { - IffId map_type = lwo_vmad->_map_type; - const string &name = lwo_vmad->_name; - - bool inserted; - if (map_type == IffId("TXUV")) { - inserted = - _txuv.insert(VMad::value_type(name, lwo_vmad)).second; - - } else { - return; - } - - if (!inserted) { - nout << "Multiple discontinous vertex maps on the same polygons of type " - << map_type << " named " << name << "\n"; - } -} - -/** - * Returns the surface associated with the given polygon, or NULL if no - * surface is associated. - */ -CLwoSurface *CLwoPolygons:: -get_surface(int polygon_index) const { - if (_surf_ptags == nullptr) { - // No surface definitions. - return nullptr; - } - - if (!_surf_ptags->has_tag(polygon_index)) { - // The polygon isn't tagged. - return nullptr; - } - - int tag_index = _surf_ptags->get_tag(polygon_index); - if (_tags == nullptr || tag_index < 0 || - tag_index >= _tags->get_num_tags()) { - // The tag index is out-of-bounds. - nout << "Invalid polygon tag index " << tag_index << "\n"; - return nullptr; - } - - string tag = _tags->get_tag(tag_index); - - // Now look up the surface name in the header. - CLwoSurface *surface = _converter->get_surface(tag); - if (surface == nullptr) { - nout << "Unknown surface " << tag << "\n"; - return nullptr; - } - - return surface; -} - -/** - * Returns true if there is a UV of the indicated name associated with the - * given vertex of the indicated polygon, false otherwise. If true, fills in - * uv with the value. - * - * This performs a lookup in the optional "discontinuous" vertex mapping, - * which provides the ability to map different UV's per each polygon for the - * same vertex. If the UV is not defined here, it may also be defined in the - * standard vertex map, which is associated with the points themselves. - */ -bool CLwoPolygons:: -get_uv(const string &uv_name, int pi, int vi, LPoint2 &uv) const { - VMad::const_iterator ni = _txuv.find(uv_name); - if (ni == _txuv.end()) { - return false; - } - - const LwoDiscontinuousVertexMap *vmad = (*ni).second; - if (vmad->_dimension != 2) { - nout << "Unexpected dimension of " << vmad->_dimension - << " for discontinuous UV map " << uv_name << "\n"; - return false; - } - - if (!vmad->has_value(pi, vi)) { - return false; - } - - PTA_stdfloat value = vmad->get_value(pi, vi); - - uv.set(value[0], value[1]); - return true; -} - -/** - * Creates the egg structures associated with this Lightwave object. - */ -void CLwoPolygons:: -make_egg() { - // First, we need a temporary group to hold all of the polygons we'll - // create. - _egg_group = new EggGroup; - - if (_polygons->_polygon_type == IffId("CURV")) { - nout << "Ignoring Catmull-Rom splines.\n"; - - } else if (_polygons->_polygon_type == IffId("PTCH")) { - nout << "Treating subdivision patches as ordinary polygons.\n"; - make_faces(); - - } else if (_polygons->_polygon_type == IffId("MBAL")) { - nout << "Ignoring metaballs.\n"; - - } else if (_polygons->_polygon_type == IffId("BONE")) { - nout << "Ignoring bones.\n"; - - } else if (_polygons->_polygon_type == IffId("FACE")) { - make_faces(); - - } else { - nout << "Ignoring unknown geometry type " << _polygons->_polygon_type - << ".\n"; - } -} - -/** - * Connects all the egg structures together. - */ -void CLwoPolygons:: -connect_egg() { - nassertv(_points->_layer->_egg_group != nullptr); - nassertv(_egg_group != nullptr); - _points->_layer->_egg_group->steal_children(*_egg_group); -} - - -/** - * Generates "face" polygons, i.e. actual polygons. - */ -void CLwoPolygons:: -make_faces() { - PN_stdfloat smooth_angle = -1.0; - - int num_polygons = _polygons->get_num_polygons(); - for (int pindex = 0; pindex < num_polygons; pindex++) { - LwoPolygons::Polygon *poly = _polygons->get_polygon(pindex); - CLwoSurface *surface = get_surface(pindex); - - bool is_valid = true; - - // Set up the vertices. - const LwoPoints *points = _points->_points; - int num_points = points->get_num_points(); - EggVertexPool *egg_vpool = _points->_egg_vpool; - - // We reverse the vertex ordering to compensate for Lightwave's clockwise - // ordering convention. We also want to start with the last vertex, so - // that the first convex angle is the first angle in the EggPolygon (for - // determining correct normals). - PT(EggPrimitive) egg_prim; - - if (poly->_vertices.size() == 1) { - egg_prim = new EggPoint; - } else { - egg_prim = new EggPolygon; - } - - // First, we have to create a temporary vector of vertices for the - // polygon, so we can possibly adjust the properties of these vertices - // (like the UV's) in the shader before we create them. - vector_PT_EggVertex egg_vertices; - - int num_vertices = poly->_vertices.size(); - for (int vi = num_vertices; vi > 0; vi--) { - int vindex = poly->_vertices[vi % num_vertices]; - if (vindex < 0 || vindex >= num_points) { - nout << "Invalid vertex index " << vindex << " in polygon.\n"; - is_valid = false; - } else { - PT(EggVertex) egg_vertex = new EggVertex; - LPoint3d pos = LCAST(double, points->get_point(vindex)); - egg_vertex->set_pos(pos); - - // Does the vertex used named UV's? - if (surface != nullptr && surface->has_named_uvs()) { - string uv_name = surface->get_uv_name(); - LPoint2 uv; - if (get_uv(uv_name, pindex, vindex, uv)) { - // This UV is defined in a "discontinuous" map, that associated a - // particular UV per each polygon. - egg_vertex->set_uv(LCAST(double, uv)); - - } else if (_points->get_uv(uv_name, vindex, uv)) { - // The UV does not appear in a discontinuous map, but it is - // defined in the points set. - egg_vertex->set_uv(LCAST(double, uv)); - } - } - - egg_vertices.push_back(egg_vertex); - } - } - - if (is_valid) { - if (surface != nullptr) { - surface->apply_properties(egg_prim, egg_vertices, smooth_angle); - } - - // Now add all the vertices officially to the primitive. - vector_PT_EggVertex::const_iterator evi; - for (evi = egg_vertices.begin(); evi != egg_vertices.end(); ++evi) { - EggVertex *egg_vertex = (*evi); - EggVertex *new_vertex = egg_vpool->create_unique_vertex(*egg_vertex); - egg_prim->add_vertex(new_vertex); - } - - // And add the primitive to its parent. - _egg_group->add_child(egg_prim.p()); - } - } - - CoordinateSystem cs = _converter->get_egg_data()->get_coordinate_system(); - if (smooth_angle > 0.0) { - _egg_group->recompute_vertex_normals(rad_2_deg(smooth_angle), cs); - } else { - _egg_group->recompute_polygon_normals(cs); - } -} diff --git a/pandatool/src/lwoegg/cLwoPolygons.h b/pandatool/src/lwoegg/cLwoPolygons.h deleted file mode 100644 index d5c4b4af..00000000 --- a/pandatool/src/lwoegg/cLwoPolygons.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoPolygons.h - * @author drose - * @date 2001-04-25 - */ - -#ifndef CLWOPOLYGONS_H -#define CLWOPOLYGONS_H - -#include "pandatoolbase.h" - -#include "lwoPolygons.h" -#include "eggGroup.h" -#include "pointerTo.h" - -#include "pmap.h" - -class LwoToEggConverter; -class CLwoPoints; -class CLwoSurface; -class LwoTags; -class LwoPolygonTags; -class LwoDiscontinuousVertexMap; - -/** - * This class is a wrapper around LwoPolygons and stores additional - * information useful during the conversion-to-egg process. - */ -class CLwoPolygons { -public: - INLINE CLwoPolygons(LwoToEggConverter *converter, - const LwoPolygons *polygons, - CLwoPoints *points); - - void add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags); - void add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad); - - CLwoSurface *get_surface(int polygon_index) const; - bool get_uv(const std::string &uv_name, int pi, int vi, LPoint2 &uv) const; - - void make_egg(); - void connect_egg(); - - LwoToEggConverter *_converter; - CPT(LwoPolygons) _polygons; - CLwoPoints *_points; - PT(EggGroup) _egg_group; - - const LwoTags *_tags; - typedef pmap PTags; - PTags _ptags; - - const LwoPolygonTags *_surf_ptags; - - // There might be named maps associated with the polygons to bring a per- - // polygon mapping to the UV's. - typedef pmap VMad; - VMad _txuv; - -private: - void make_faces(); -}; - -#include "cLwoPolygons.I" - -#endif diff --git a/pandatool/src/lwoegg/cLwoSurface.I b/pandatool/src/lwoegg/cLwoSurface.I deleted file mode 100644 index 8c39871a..00000000 --- a/pandatool/src/lwoegg/cLwoSurface.I +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurface.I - * @author drose - * @date 2001-04-25 - */ - -/** - * Returns the name of the surface. Each surface in a given Lightwave file - * should have a unique name. - */ -INLINE const std::string &CLwoSurface:: -get_name() const { - return _surface->_name; -} - -/** - * Returns true if the surface is set up to reference UV's stored on the - * vertices, by name (as opposed to generated UV's, which is the more common - * Lightwave case). In this case, get_uv_name() can be called to return the - * name of the UV's. - */ -INLINE bool CLwoSurface:: -has_named_uvs() const { - return (_block != nullptr && - _block->_projection_mode == LwoSurfaceBlockProjection::M_uv); -} - -/** - * Returns the name of the set of UV's that are associated with this surface, - * if has_named_uvs() is true. - */ -INLINE const std::string &CLwoSurface:: -get_uv_name() const { - return _block->_uv_name; -} diff --git a/pandatool/src/lwoegg/cLwoSurface.cxx b/pandatool/src/lwoegg/cLwoSurface.cxx deleted file mode 100644 index 1bb0c146..00000000 --- a/pandatool/src/lwoegg/cLwoSurface.cxx +++ /dev/null @@ -1,495 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurface.cxx - * @author drose - * @date 2001-04-25 - */ - -#include "cLwoSurface.h" -#include "cLwoSurfaceBlock.h" -#include "cLwoClip.h" -#include "lwoToEggConverter.h" - -#include "lwoSurfaceColor.h" -#include "lwoSurfaceParameter.h" -#include "lwoSurfaceSmoothingAngle.h" -#include "lwoSurfaceSidedness.h" -#include "lwoSurfaceBlock.h" -#include "eggPrimitive.h" -#include "string_utils.h" -#include "mathNumbers.h" -#include "dcast.h" - - -/** - * - */ -CLwoSurface:: -CLwoSurface(LwoToEggConverter *converter, const LwoSurface *surface) : - _converter(converter), - _surface(surface) -{ - _flags = 0; - _rgb.set(1.0, 1.0, 1.0); - _checked_material = false; - _checked_texture = false; - _map_uvs = nullptr; - _block = nullptr; - - // Walk through the chunk list, looking for some basic properties. - int num_chunks = _surface->get_num_chunks(); - for (int i = 0; i < num_chunks; i++) { - const IffChunk *chunk = _surface->get_chunk(i); - - if (chunk->is_of_type(LwoSurfaceColor::get_class_type())) { - const LwoSurfaceColor *color = DCAST(LwoSurfaceColor, chunk); - _flags |= F_rgb; - _rgb = color->_color; - - } else if (chunk->is_of_type(LwoSurfaceParameter::get_class_type())) { - const LwoSurfaceParameter *param = DCAST(LwoSurfaceParameter, chunk); - IffId type = param->get_id(); - - if (type == IffId("DIFF")) { - _flags |= F_diffuse; - _diffuse = param->_value; - - } else if (type == IffId("LUMI")) { - _flags |= F_luminosity; - _luminosity = param->_value; - - } else if (type == IffId("SPEC")) { - _flags |= F_specular; - _specular = param->_value; - - } else if (type == IffId("REFL")) { - _flags |= F_reflection; - _reflection = param->_value; - - } else if (type == IffId("TRAN")) { - _flags |= F_transparency; - _transparency = param->_value; - - } else if (type == IffId("GLOS")) { - _flags |= F_gloss; - _gloss = param->_value; - - } else if (type == IffId("TRNL")) { - _flags |= F_translucency; - _translucency = param->_value; - } - - } else if (chunk->is_of_type(LwoSurfaceSmoothingAngle::get_class_type())) { - const LwoSurfaceSmoothingAngle *sa = DCAST(LwoSurfaceSmoothingAngle, chunk); - _flags |= F_smooth_angle; - _smooth_angle = sa->_angle; - - } else if (chunk->is_of_type(LwoSurfaceSidedness::get_class_type())) { - const LwoSurfaceSidedness *sn = DCAST(LwoSurfaceSidedness, chunk); - _flags |= F_backface; - _backface = (sn->_sidedness == LwoSurfaceSidedness::S_front_and_back); - - } else if (chunk->is_of_type(LwoSurfaceBlock::get_class_type())) { - const LwoSurfaceBlock *lwo_block = DCAST(LwoSurfaceBlock, chunk); - // One of possibly several blocks in the texture that define additional - // fancy rendering properties. - - CLwoSurfaceBlock *block = new CLwoSurfaceBlock(_converter, lwo_block); - - // We only consider enabled "IMAP" type blocks that affect "COLR". - if (block->_block_type == IffId("IMAP") && - block->_channel_id == IffId("COLR") && - block->_enabled) { - // Now save the block with the lowest ordinal. - if (_block == nullptr) { - _block = block; - - } else if (block->_ordinal < _block->_ordinal) { - delete _block; - _block = block; - - } else { - delete block; - } - - } else { - delete block; - } - } - } - - // Now get the four-component color, based on combining the RGB and the - // transparency. - _color.set(1.0, 1.0, 1.0, 1.0); - - if ((_flags & F_rgb) != 0) { - _color[0] = _rgb[0]; - _color[1] = _rgb[1]; - _color[2] = _rgb[2]; - } - - if ((_flags & F_transparency) != 0) { - _color[3] = 1.0 - _transparency; - } - - _diffuse_color = _color; -} - -/** - * - */ -CLwoSurface:: -~CLwoSurface() { - delete _block; -} - -/** - * Applies the color, texture, etc. described by the surface to the indicated - * egg primitive. - * - * If the surface defines a smoothing angle, smooth_angle may be updated to - * reflect it if the angle is greater than that specified. - */ -void CLwoSurface:: -apply_properties(EggPrimitive *egg_prim, vector_PT_EggVertex &egg_vertices, - PN_stdfloat &smooth_angle) { - if (!_surface->_source.empty()) { - // This surface is derived from another surface; apply that one first. - CLwoSurface *parent = _converter->get_surface(_surface->_source); - if (parent != nullptr && parent != this) { - parent->apply_properties(egg_prim, egg_vertices, smooth_angle); - } - } - - bool has_texture = check_texture(); - bool has_material = check_material(); - - egg_prim->set_color(_diffuse_color); - - if (has_material) { - egg_prim->set_material(_egg_material); - } - - if (has_texture) { - egg_prim->set_texture(_egg_texture); - - // Assign UV's to the vertices. - generate_uvs(egg_vertices); - } - - if ((_flags & F_backface) != 0) { - egg_prim->set_bface_flag(_backface); - } - - if ((_flags & F_smooth_angle) != 0) { - smooth_angle = std::max(smooth_angle, _smooth_angle); - } -} - -/** - * Checks whether the surface demands a texture or not. Returns true if so, - * false otherwise. - * - * If the surface demands a texture, this also sets up _egg_texture and - * _compute_uvs as appropriate for the texture. - */ -bool CLwoSurface:: -check_texture() { - if (_checked_texture) { - return (_egg_texture != nullptr); - } - _checked_texture = true; - _egg_texture = nullptr; - _map_uvs = nullptr; - - if (_block == nullptr) { - // No texture. Not even a shader block. - return false; - } - - int clip_index = _block->_clip_index; - if (clip_index < 0) { - // No image file associated with the texture. - return false; - } - - CLwoClip *clip = _converter->get_clip(clip_index); - if (clip == nullptr) { - nout << "No clip image with index " << clip_index << "\n"; - return false; - } - - if (!clip->is_still_image()) { - // Can't do anything with an animated image right now. - return false; - } - - Filename pathname = _converter->convert_model_path(clip->_filename); - - _egg_texture = new EggTexture("clip" + format_string(clip_index), pathname); - - // Do we need to generate UV's? - switch (_block->_projection_mode) { - case LwoSurfaceBlockProjection::M_planar: - _map_uvs = &CLwoSurface::map_planar; - break; - - case LwoSurfaceBlockProjection::M_cylindrical: - _map_uvs = &CLwoSurface::map_cylindrical; - break; - - case LwoSurfaceBlockProjection::M_spherical: - _map_uvs = &CLwoSurface::map_spherical; - break; - - case LwoSurfaceBlockProjection::M_cubic: - _map_uvs = &CLwoSurface::map_cubic; - break; - - case LwoSurfaceBlockProjection::M_front: - // Cannot generate "front" UV's, since this depends on a camera. Is it - // supposed to be updated in real time, like a projected texture? - break; - - case LwoSurfaceBlockProjection::M_uv: - // "uv" projection means to use the existing UV's already defined for the - // vertex. This case was already handled in the code that created the - // EggVertex pointers. - break; - }; - - // Texture overrides the primitive's natural color. - _color[0] = 1.0; - _color[1] = 1.0; - _color[2] = 1.0; - - return true; -} - -/** - * Checks whether the surface demands a material or not. Returns true if so, - * false otherwise. - */ -bool CLwoSurface:: -check_material() { - if (_checked_material) { - return (_egg_material != nullptr); - } - _checked_material = true; - _egg_material = nullptr; - - if (!_converter->_make_materials) { - // If we aren't making materials, then don't make a material. - return false; - } - - _egg_material = new EggMaterial(get_name()); - - if ((_flags & F_diffuse) != 0) { - _diffuse_color.set(_color[0] * _diffuse, - _color[1] * _diffuse, - _color[2] * _diffuse, - _color[3]); - // We want to avoid setting the diffuse color on the material. We're - // already setting the color explicitly on the object, so there's no need - // to also set a diffuse color on the material, and doing so prevents nice - // features like set_color() and set_color_scale() from working in Panda. - - // _egg_material->set_diff(_diffuse_color); - } - - if ((_flags & F_luminosity) != 0) { - LColor luminosity(_color[0] * _luminosity, - _color[1] * _luminosity, - _color[2] * _luminosity, - 1.0); - _egg_material->set_emit(luminosity); - } - - if ((_flags & F_specular) != 0) { - LColor specular(_color[0] * _specular, - _color[1] * _specular, - _color[2] * _specular, - 1.0); - _egg_material->set_spec(specular); - } - - if ((_flags & F_gloss) != 0) { - _egg_material->set_shininess(_gloss * 128.0); - } - - return true; -} - - -/** - * Computes all the UV's for the polygon's vertices, according to the - * _projection_mode defined in the block. - */ -void CLwoSurface:: -generate_uvs(vector_PT_EggVertex &egg_vertices) { - if (_map_uvs == nullptr) { - return; - } - - // To do this properly near seams and singularities (for instance, the back - // seam and the poles of the spherical map), we will need to know the - // polygon's centroid. - LPoint3d centroid(0.0, 0.0, 0.0); - - vector_PT_EggVertex::const_iterator vi; - for (vi = egg_vertices.begin(); vi != egg_vertices.end(); ++vi) { - EggVertex *egg_vertex = (*vi); - centroid += egg_vertex->get_pos3(); - } - - centroid /= (double)egg_vertices.size(); - centroid = centroid * _block->_inv_transform; - - // Now go back through and actually compute the UV's. - for (vi = egg_vertices.begin(); vi != egg_vertices.end(); ++vi) { - EggVertex *egg_vertex = (*vi); - LPoint3d pos = egg_vertex->get_pos3() * _block->_inv_transform; - LPoint2d uv = (this->*_map_uvs)(pos, centroid); - egg_vertex->set_uv(uv); - } -} - -/** - * Computes a UV based on the given point in space, using a planar projection. - */ -LPoint2d CLwoSurface:: -map_planar(const LPoint3d &pos, const LPoint3d &) const { - // A planar projection is about as easy as can be. We ignore the Y axis, - // and project the point into the XZ plane. Done. - double u = (pos[0] + 0.5); - double v = (pos[2] + 0.5); - - return LPoint2d(u, v); -} - -/** - * Computes a UV based on the given point in space, using a spherical - * projection. - */ -LPoint2d CLwoSurface:: -map_spherical(const LPoint3d &pos, const LPoint3d ¢roid) const { - // To compute the x position on the frame, we only need to consider the - // angle of the vector about the Y axis. Project the vector into the XZ - // plane to do this. - - LVector2d xz_orig(pos[0], pos[2]); - LVector2d xz = xz_orig; - double u_offset = 0.0; - - if (xz == LVector2d::zero()) { - // If we have a point on either pole, we've got problems. This point maps - // to the entire bottom edge of the image, so which U value should we - // choose? It does make a difference, especially if we have a number of - // polygons around the south pole that all share the common vertex. - - // We choose the U value based on the polygon's centroid. - xz.set(centroid[0], centroid[2]); - - } else if (xz[1] >= 0.0 && ((xz[0] < 0.0) != (centroid[0] < 0.))) { - // Now, if our polygon crosses the seam along the back of the sphere--that - // is, the point is on the back of the sphere (xz[1] >= 0.0) and not on - // the same side of the XZ plane as the centroid, we've got problems too. - // We need to add an offset to the computed U value, either 1 or -1, to - // keep all the vertices of the polygon on the same side of the seam. - - u_offset = (xz[0] < 0.0) ? 1.0 : -1.0; - } - - // The U value is based on the longitude: the angle about the Y axis. - double u = - (atan2(xz[0], -xz[1]) / (2.0 * MathNumbers::pi) + 0.5 + u_offset) * _block->_w_repeat; - - // Now rotate the vector into the YZ plane, and the V value is based on the - // latitude: the angle about the X axis. - LVector2d yz(pos[1], xz_orig.length()); - double v = - (atan2(yz[0], yz[1]) / MathNumbers::pi + 0.5) * _block->_h_repeat; - - return LPoint2d(u, v); -} - -/** - * Computes a UV based on the given point in space, using a cylindrical - * projection. - */ -LPoint2d CLwoSurface:: -map_cylindrical(const LPoint3d &pos, const LPoint3d ¢roid) const { - // This is almost identical to the spherical projection, except for the - // computation of V. - - LVector2d xz(pos[0], pos[2]); - double u_offset = 0.0; - - if (xz == LVector2d::zero()) { - // Although a cylindrical mapping does not really have a singularity at - // the pole, it's still possible to put a point there, and we'd like to do - // the right thing with the polygon that shares that point. So the - // singularity logic remains. - xz.set(centroid[0], centroid[2]); - - } else if (xz[1] >= 0.0 && ((xz[0] < 0.0) != (centroid[0] < 0.))) { - // And cylinders do still have a seam at the back. - u_offset = (xz[0] < 0.0) ? 1.0 : -1.0; - } - - double u = - (atan2(xz[0], -xz[1]) / (2.0 * MathNumbers::pi) + 0.5 + u_offset) * _block->_w_repeat; - - // For a cylindrical mapping, the V value comes almost directly from Y. - // Easy. - double v = (pos[1] + 0.5); - - return LPoint2d(u, v); -} - -/** - * Computes a UV based on the given point in space, using a cubic projection. - */ -LPoint2d CLwoSurface:: -map_cubic(const LPoint3d &pos, const LPoint3d ¢roid) const { - // A cubic projection is a planar projection, but we eliminate the dominant - // axis (based on the polygon's centroid) instead of arbitrarily eliminating - // Y. - - double x = fabs(centroid[0]); - double y = fabs(centroid[1]); - double z = fabs(centroid[2]); - - double u, v; - - if (x > y) { - if (x > z) { - // X is dominant. - u = (pos[2] + 0.5); - v = (pos[1] + 0.5); - } else { - // Z is dominant. - u = (pos[0] + 0.5); - v = (pos[1] + 0.5); - } - } else { - if (y > z) { - // Y is dominant. - u = (pos[0] + 0.5); - v = (pos[2] + 0.5); - } else { - // Z is dominant. - u = (pos[0] + 0.5); - v = (pos[1] + 0.5); - } - } - - return LPoint2d(u, v); -} diff --git a/pandatool/src/lwoegg/cLwoSurface.h b/pandatool/src/lwoegg/cLwoSurface.h deleted file mode 100644 index ec098f18..00000000 --- a/pandatool/src/lwoegg/cLwoSurface.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurface.h - * @author drose - * @date 2001-04-25 - */ - -#ifndef CLWOSURFACE_H -#define CLWOSURFACE_H - -#include "pandatoolbase.h" - -#include "cLwoSurfaceBlock.h" - -#include "lwoSurface.h" -#include "luse.h" -#include "eggTexture.h" -#include "eggMaterial.h" -#include "pt_EggTexture.h" -#include "pt_EggMaterial.h" -#include "vector_PT_EggVertex.h" - -#include "pmap.h" - -class LwoToEggConverter; -class LwoSurfaceBlock; -class EggPrimitive; - -/** - * This class is a wrapper around LwoSurface and stores additional information - * useful during the conversion-to-egg process. - */ -class CLwoSurface { -public: - CLwoSurface(LwoToEggConverter *converter, const LwoSurface *surface); - ~CLwoSurface(); - - INLINE const std::string &get_name() const; - - void apply_properties(EggPrimitive *egg_prim, - vector_PT_EggVertex &egg_vertices, - PN_stdfloat &smooth_angle); - bool check_texture(); - bool check_material(); - - INLINE bool has_named_uvs() const; - INLINE const std::string &get_uv_name() const; - - - enum Flags { - F_rgb = 0x0001, - F_diffuse = 0x0002, - F_luminosity = 0x0004, - F_specular = 0x0008, - F_reflection = 0x0010, - F_transparency = 0x0020, - F_gloss = 0x0040, - F_translucency = 0x0080, - F_smooth_angle = 0x0100, - F_backface = 0x0200, - }; - - int _flags; - LRGBColor _rgb; - PN_stdfloat _diffuse; - PN_stdfloat _luminosity; - PN_stdfloat _specular; - PN_stdfloat _reflection; - PN_stdfloat _transparency; - PN_stdfloat _gloss; - PN_stdfloat _translucency; - PN_stdfloat _smooth_angle; - bool _backface; - - LColor _color; - LColor _diffuse_color; - - LwoToEggConverter *_converter; - CPT(LwoSurface) _surface; - - bool _checked_material; - PT_EggMaterial _egg_material; - - bool _checked_texture; - PT_EggTexture _egg_texture; - - CLwoSurfaceBlock *_block; - -private: - void generate_uvs(vector_PT_EggVertex &egg_vertices); - - LPoint2d map_planar(const LPoint3d &pos, const LPoint3d ¢roid) const; - LPoint2d map_spherical(const LPoint3d &pos, const LPoint3d ¢roid) const; - LPoint2d map_cylindrical(const LPoint3d &pos, const LPoint3d ¢roid) const; - LPoint2d map_cubic(const LPoint3d &pos, const LPoint3d ¢roid) const; - - // Define a pointer to one of the above member functions. - LPoint2d (CLwoSurface::*_map_uvs)(const LPoint3d &pos, const LPoint3d ¢roid) const; -}; - -#include "cLwoSurface.I" - -#endif diff --git a/pandatool/src/lwoegg/cLwoSurfaceBlock.I b/pandatool/src/lwoegg/cLwoSurfaceBlock.I deleted file mode 100644 index dde99337..00000000 --- a/pandatool/src/lwoegg/cLwoSurfaceBlock.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurfaceBlock.I - * @author drose - * @date 2001-04-26 - */ diff --git a/pandatool/src/lwoegg/cLwoSurfaceBlock.cxx b/pandatool/src/lwoegg/cLwoSurfaceBlock.cxx deleted file mode 100644 index ebf5a5ac..00000000 --- a/pandatool/src/lwoegg/cLwoSurfaceBlock.cxx +++ /dev/null @@ -1,148 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurfaceBlock.cxx - * @author drose - * @date 2001-04-26 - */ - -#include "cLwoSurfaceBlock.h" -#include "cLwoSurfaceBlockTMap.h" -#include "lwoToEggConverter.h" - -#include "lwoSurfaceBlockChannel.h" -#include "lwoSurfaceBlockEnabled.h" -#include "lwoSurfaceBlockImage.h" -#include "lwoSurfaceBlockRepeat.h" -#include "lwoSurfaceBlockVMapName.h" -#include "dcast.h" - - -/** - * - */ -CLwoSurfaceBlock:: -CLwoSurfaceBlock(LwoToEggConverter *converter, const LwoSurfaceBlock *block) : - _converter(converter), - _block(block) -{ - _block_type = _block->_header->get_id(); - _ordinal = _block->_header->_ordinal; - _enabled = true; - _opacity_type = LwoSurfaceBlockOpacity::T_additive; - _opacity = 1.0; - _transform = LMatrix4d::ident_mat(); - _inv_transform = LMatrix4d::ident_mat(); - _projection_mode = LwoSurfaceBlockProjection::M_uv; - _axis = LwoSurfaceBlockAxis::A_y; - _clip_index = -1; - _w_wrap = LwoSurfaceBlockWrap::M_repeat; - _h_wrap = LwoSurfaceBlockWrap::M_repeat; - _w_repeat = 1.0; - _h_repeat = 1.0; - _tmap = nullptr; - - // Scan the chunks in the header. - int num_hchunks = _block->_header->get_num_chunks(); - for (int hi = 0; hi < num_hchunks; hi++) { - const IffChunk *hchunk = _block->_header->get_chunk(hi); - - if (hchunk->is_of_type(LwoSurfaceBlockChannel::get_class_type())) { - const LwoSurfaceBlockChannel *bc = - DCAST(LwoSurfaceBlockChannel, hchunk); - _channel_id = bc->_channel_id; - - } else if (hchunk->is_of_type(LwoSurfaceBlockEnabled::get_class_type())) { - const LwoSurfaceBlockEnabled *ec = - DCAST(LwoSurfaceBlockEnabled, hchunk); - _enabled = ec->_enabled; - } - } - - // Scan the chunks in the body. - int num_chunks = _block->get_num_chunks(); - for (int i = 0; i < num_chunks; i++) { - const IffChunk *chunk = _block->get_chunk(i); - - if (chunk->is_of_type(LwoSurfaceBlockTMap::get_class_type())) { - const LwoSurfaceBlockTMap *lwo_tmap = DCAST(LwoSurfaceBlockTMap, chunk); - if (_tmap != nullptr) { - nout << "Two TMAP chunks encountered within surface block.\n"; - delete _tmap; - } - _tmap = new CLwoSurfaceBlockTMap(_converter, lwo_tmap); - - } else if (chunk->is_of_type(LwoSurfaceBlockProjection::get_class_type())) { - const LwoSurfaceBlockProjection *proj = DCAST(LwoSurfaceBlockProjection, chunk); - _projection_mode = proj->_mode; - - } else if (chunk->is_of_type(LwoSurfaceBlockAxis::get_class_type())) { - const LwoSurfaceBlockAxis *axis = DCAST(LwoSurfaceBlockAxis, chunk); - _axis = axis->_axis; - - } else if (chunk->is_of_type(LwoSurfaceBlockImage::get_class_type())) { - const LwoSurfaceBlockImage *image = DCAST(LwoSurfaceBlockImage, chunk); - _clip_index = image->_index; - - } else if (chunk->is_of_type(LwoSurfaceBlockWrap::get_class_type())) { - const LwoSurfaceBlockWrap *wrap = DCAST(LwoSurfaceBlockWrap, chunk); - _w_wrap = wrap->_width; - _h_wrap = wrap->_height; - - } else if (chunk->is_of_type(LwoSurfaceBlockWrap::get_class_type())) { - const LwoSurfaceBlockWrap *wrap = DCAST(LwoSurfaceBlockWrap, chunk); - _w_wrap = wrap->_width; - _h_wrap = wrap->_height; - - } else if (chunk->is_of_type(LwoSurfaceBlockVMapName::get_class_type())) { - const LwoSurfaceBlockVMapName *vmap = DCAST(LwoSurfaceBlockVMapName, chunk); - _uv_name = vmap->_name; - - } else if (chunk->is_of_type(LwoSurfaceBlockRepeat::get_class_type())) { - const LwoSurfaceBlockRepeat *repeat = DCAST(LwoSurfaceBlockRepeat, chunk); - if (repeat->get_id() == IffId("WRPW")) { - _w_repeat = repeat->_cycles; - } else if (repeat->get_id() == IffId("WRPH")) { - _h_repeat = repeat->_cycles; - } - } - } - - if (_tmap != nullptr) { - _tmap->get_transform(_transform); - } - - // Also rotate the transform if we specify some axis other than Y. (All the - // map_* uv mapping functions are written to assume Y is the dominant axis.) - switch (_axis) { - case LwoSurfaceBlockAxis::A_x: - _transform = LMatrix4d::rotate_mat(90.0, - LVecBase3d::unit_z(), - CS_yup_left) * _transform; - break; - - case LwoSurfaceBlockAxis::A_y: - break; - - case LwoSurfaceBlockAxis::A_z: - _transform = LMatrix4d::rotate_mat(-90.0, - LVecBase3d::unit_x(), - CS_yup_left) * _transform; - break; - } - - _inv_transform.invert_from(_transform); -} - -/** - * - */ -CLwoSurfaceBlock:: -~CLwoSurfaceBlock() { - delete _tmap; -} diff --git a/pandatool/src/lwoegg/cLwoSurfaceBlock.h b/pandatool/src/lwoegg/cLwoSurfaceBlock.h deleted file mode 100644 index cf86126f..00000000 --- a/pandatool/src/lwoegg/cLwoSurfaceBlock.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurfaceBlock.h - * @author drose - * @date 2001-04-26 - */ - -#ifndef CLWOSURFACEBLOCK_H -#define CLWOSURFACEBLOCK_H - -#include "pandatoolbase.h" - -#include "lwoSurfaceBlock.h" -#include "lwoSurfaceBlockOpacity.h" -#include "lwoSurfaceBlockProjection.h" -#include "lwoSurfaceBlockAxis.h" -#include "lwoSurfaceBlockWrap.h" - -#include "luse.h" - -class LwoToEggConverter; -class CLwoSurfaceBlockTMap; - -/** - * This class is a wrapper around LwoSurfaceBlock and stores additional - * information useful during the conversion-to-egg process. - */ -class CLwoSurfaceBlock { -public: - CLwoSurfaceBlock(LwoToEggConverter *converter, const LwoSurfaceBlock *block); - ~CLwoSurfaceBlock(); - - IffId _block_type; - IffId _channel_id; - std::string _ordinal; - bool _enabled; - - LwoSurfaceBlockOpacity::Type _opacity_type; - PN_stdfloat _opacity; - - LMatrix4d _transform; - LMatrix4d _inv_transform; - LwoSurfaceBlockProjection::Mode _projection_mode; - LwoSurfaceBlockAxis::Axis _axis; - - int _clip_index; - LwoSurfaceBlockWrap::Mode _w_wrap; - LwoSurfaceBlockWrap::Mode _h_wrap; - PN_stdfloat _w_repeat; - PN_stdfloat _h_repeat; - std::string _uv_name; - - LwoToEggConverter *_converter; - CPT(LwoSurfaceBlock) _block; - CLwoSurfaceBlockTMap *_tmap; -}; - -#include "cLwoSurfaceBlock.I" - -#endif diff --git a/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.I b/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.I deleted file mode 100644 index f267006f..00000000 --- a/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurfaceBlockTMap.I - * @author drose - * @date 2001-04-30 - */ diff --git a/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.cxx b/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.cxx deleted file mode 100644 index 649fd803..00000000 --- a/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.cxx +++ /dev/null @@ -1,73 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurfaceBlockTMap.cxx - * @author drose - * @date 2001-04-30 - */ - -#include "cLwoSurfaceBlockTMap.h" -#include "lwoToEggConverter.h" - -#include "lwoSurfaceBlockTransform.h" -#include "lwoSurfaceBlockRefObj.h" -#include "compose_matrix.h" -#include "dcast.h" - -/** - * - */ -CLwoSurfaceBlockTMap:: -CLwoSurfaceBlockTMap(LwoToEggConverter *converter, const LwoSurfaceBlockTMap *tmap) : - _converter(converter), - _tmap(tmap) -{ - _center.set(0.0, 0.0, 0.0); - _size.set(1.0, 1.0, 1.0); - _rotation.set(0.0, 0.0, 0.0); - _csys = LwoSurfaceBlockCoordSys::T_object; - _reference_object = "(none)"; - - // Scan the chunks in the body. - int num_chunks = _tmap->get_num_chunks(); - for (int i = 0; i < num_chunks; i++) { - const IffChunk *chunk = _tmap->get_chunk(i); - - if (chunk->is_of_type(LwoSurfaceBlockTransform::get_class_type())) { - const LwoSurfaceBlockTransform *trans = DCAST(LwoSurfaceBlockTransform, chunk); - if (trans->get_id() == IffId("CNTR")) { - _center = trans->_vec; - } else if (trans->get_id() == IffId("SIZE")) { - _size = trans->_vec; - } else if (trans->get_id() == IffId("ROTA")) { - _rotation = trans->_vec; - } - - } else if (chunk->is_of_type(LwoSurfaceBlockRefObj::get_class_type())) { - const LwoSurfaceBlockRefObj *ref = DCAST(LwoSurfaceBlockRefObj, chunk); - _reference_object = ref->_name; - - } else if (chunk->is_of_type(LwoSurfaceBlockCoordSys::get_class_type())) { - const LwoSurfaceBlockCoordSys *csys = DCAST(LwoSurfaceBlockCoordSys, chunk); - _csys = csys->_type; - } - } -} - -/** - * Fills up the indicated matrix with the net transform indicated by the TMAP - * chunk, accounting for scale, rotate, and translate. - */ -void CLwoSurfaceBlockTMap:: -get_transform(LMatrix4d &mat) const { - LPoint3d hpr(rad_2_deg(_rotation[0]), - rad_2_deg(-_rotation[1]), - rad_2_deg(-_rotation[2])); - compose_matrix(mat, LCAST(double, _size), hpr, - LCAST(double, _center), CS_yup_left); -} diff --git a/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.h b/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.h deleted file mode 100644 index 075ed418..00000000 --- a/pandatool/src/lwoegg/cLwoSurfaceBlockTMap.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cLwoSurfaceBlockTMap.h - * @author drose - * @date 2001-04-30 - */ - -#ifndef CLWOSURFACEBLOCKTMAP_H -#define CLWOSURFACEBLOCKTMAP_H - -#include "pandatoolbase.h" - -#include "lwoSurfaceBlockTMap.h" -#include "lwoSurfaceBlockCoordSys.h" - -#include "luse.h" - -class LwoToEggConverter; - -/** - * This class is a wrapper around LwoSurfaceBlockTMap and stores additional - * information useful during the conversion-to-egg process. - */ -class CLwoSurfaceBlockTMap { -public: - CLwoSurfaceBlockTMap(LwoToEggConverter *converter, const LwoSurfaceBlockTMap *tmap); - - void get_transform(LMatrix4d &mat) const; - - LPoint3 _center; - LVecBase3 _size; - LVecBase3 _rotation; - - std::string _reference_object; - - LwoSurfaceBlockCoordSys::Type _csys; - - LwoToEggConverter *_converter; - CPT(LwoSurfaceBlockTMap) _tmap; -}; - -#include "cLwoSurfaceBlockTMap.I" - -#endif diff --git a/pandatool/src/lwoegg/lwoToEggConverter.I b/pandatool/src/lwoegg/lwoToEggConverter.I deleted file mode 100644 index 2e766681..00000000 --- a/pandatool/src/lwoegg/lwoToEggConverter.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoToEggConverter.I - * @author drose - * @date 2001-04-25 - */ diff --git a/pandatool/src/lwoegg/lwoToEggConverter.cxx b/pandatool/src/lwoegg/lwoToEggConverter.cxx deleted file mode 100644 index 524d60a8..00000000 --- a/pandatool/src/lwoegg/lwoToEggConverter.cxx +++ /dev/null @@ -1,443 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoToEggConverter.cxx - * @author drose - * @date 2001-04-25 - */ - -#include "lwoToEggConverter.h" -#include "cLwoLayer.h" -#include "cLwoClip.h" -#include "cLwoPoints.h" -#include "cLwoPolygons.h" -#include "cLwoSurface.h" - -#include "eggData.h" -#include "lwoHeader.h" -#include "lwoLayer.h" -#include "lwoClip.h" -#include "lwoPoints.h" -#include "lwoPolygons.h" -#include "lwoVertexMap.h" -#include "lwoDiscontinuousVertexMap.h" -#include "lwoTags.h" -#include "lwoPolygonTags.h" -#include "lwoInputFile.h" -#include "dcast.h" - - -/** - * - */ -LwoToEggConverter:: -LwoToEggConverter() { - _generic_layer = nullptr; - _make_materials = true; -} - -/** - * - */ -LwoToEggConverter:: -LwoToEggConverter(const LwoToEggConverter ©) : - SomethingToEggConverter(copy) -{ -} - -/** - * - */ -LwoToEggConverter:: -~LwoToEggConverter() { - cleanup(); -} - -/** - * Allocates and returns a new copy of the converter. - */ -SomethingToEggConverter *LwoToEggConverter:: -make_copy() { - return new LwoToEggConverter(*this); -} - -/** - * Returns the English name of the file type this converter supports. - */ -std::string LwoToEggConverter:: -get_name() const { - return "Lightwave"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -std::string LwoToEggConverter:: -get_extension() const { - return "lwo"; -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. - */ -bool LwoToEggConverter:: -supports_compressed() const { - return true; -} - -/** - * Handles the reading of the input file and converting it to egg. Returns - * true if successful, false otherwise. - * - * This is designed to be as generic as possible, generally in support of run- - * time loading. Command-line converters may choose to use convert_lwo() - * instead, as it provides more control. - */ -bool LwoToEggConverter:: -convert_file(const Filename &filename) { - LwoInputFile in; - - nout << "Reading " << filename << "\n"; - if (!in.open_read(filename)) { - nout << "Unable to open " << filename << "\n"; - return false; - } - - PT(IffChunk) chunk = in.get_chunk(); - if (chunk == nullptr) { - nout << "Unable to read " << filename << "\n"; - return false; - } - - if (!chunk->is_of_type(LwoHeader::get_class_type())) { - nout << "File " << filename << " is not a Lightwave Object file.\n"; - return false; - } - - LwoHeader *header = DCAST(LwoHeader, chunk); - if (!header->is_valid()) { - nout << "File " << filename - << " is not recognized as a Lightwave Object file. " - << "Perhaps the version is too recent.\n"; - return false; - } - - return convert_lwo(header); -} - -/** - * Fills up the egg_data structure according to the indicated lwo structure. - */ -bool LwoToEggConverter:: -convert_lwo(const LwoHeader *lwo_header) { - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_yup_left); - } - - _error = false; - _lwo_header = lwo_header; - - collect_lwo(); - make_egg(); - connect_egg(); - - _egg_data->remove_unused_vertices(true); - cleanup(); - - return !had_error(); -} - -/** - * Returns a pointer to the layer with the given index number, or NULL if - * there is no such layer. - */ -CLwoLayer *LwoToEggConverter:: -get_layer(int number) const { - if (number >= 0 && number < (int)_layers.size()) { - return _layers[number]; - } - return nullptr; -} - -/** - * Returns a pointer to the clip with the given index number, or NULL if there - * is no such clip. - */ -CLwoClip *LwoToEggConverter:: -get_clip(int number) const { - if (number >= 0 && number < (int)_clips.size()) { - return _clips[number]; - } - return nullptr; -} - -/** - * Returns a pointer to the surface definition with the given name, or NULL if - * there is no such surface. - */ -CLwoSurface *LwoToEggConverter:: -get_surface(const std::string &name) const { - Surfaces::const_iterator si; - si = _surfaces.find(name); - if (si != _surfaces.end()) { - return (*si).second; - } - return nullptr; -} - -/** - * Frees all the internal data structures after we're done converting, and - * resets the converter to its initial state. - */ -void LwoToEggConverter:: -cleanup() { - _lwo_header.clear(); - - delete _generic_layer; - _generic_layer = nullptr; - - for (CLwoLayer *layer : _layers) { - delete layer; - } - _layers.clear(); - - for (CLwoClip *clip : _clips) { - delete clip; - } - _clips.clear(); - - for (CLwoPoints *points : _points) { - delete points; - } - _points.clear(); - - for (CLwoPolygons *polygons : _polygons) { - delete polygons; - } - _polygons.clear(); - - Surfaces::iterator si; - for (si = _surfaces.begin(); si != _surfaces.end(); ++si) { - CLwoSurface *surface = (*si).second; - delete surface; - } - _surfaces.clear(); -} - -/** - * Walks through the chunks in the Lightwave data and creates wrapper objects - * for each relevant piece. - */ -void LwoToEggConverter:: -collect_lwo() { - CLwoLayer *last_layer = nullptr; - CLwoPoints *last_points = nullptr; - CLwoPolygons *last_polygons = nullptr; - - const LwoTags *tags = nullptr; - - int num_chunks = _lwo_header->get_num_chunks(); - for (int i = 0; i < num_chunks; i++) { - const IffChunk *chunk = _lwo_header->get_chunk(i); - - if (chunk->is_of_type(LwoLayer::get_class_type())) { - const LwoLayer *lwo_layer = DCAST(LwoLayer, chunk); - CLwoLayer *layer = new CLwoLayer(this, lwo_layer); - int number = layer->get_number(); - slot_layer(number); - - if (_layers[number] != nullptr) { - nout << "Warning: multiple layers with number " << number << "\n"; - } - _layers[number] = layer; - last_layer = layer; - last_points = nullptr; - last_polygons = nullptr; - - } else if (chunk->is_of_type(LwoClip::get_class_type())) { - const LwoClip *lwo_clip = DCAST(LwoClip, chunk); - CLwoClip *clip = new CLwoClip(this, lwo_clip); - - int index = clip->get_index(); - slot_clip(index); - - if (_clips[index] != nullptr) { - nout << "Warning: multiple clips with index " << index << "\n"; - } - _clips[index] = clip; - - } else if (chunk->is_of_type(LwoPoints::get_class_type())) { - if (last_layer == nullptr) { - last_layer = make_generic_layer(); - } - - const LwoPoints *lwo_points = DCAST(LwoPoints, chunk); - CLwoPoints *points = new CLwoPoints(this, lwo_points, last_layer); - _points.push_back(points); - last_points = points; - - } else if (chunk->is_of_type(LwoVertexMap::get_class_type())) { - if (last_points == nullptr) { - nout << "Vertex map chunk encountered without a preceding points chunk.\n"; - } else { - const LwoVertexMap *lwo_vmap = DCAST(LwoVertexMap, chunk); - last_points->add_vmap(lwo_vmap); - } - - } else if (chunk->is_of_type(LwoDiscontinuousVertexMap::get_class_type())) { - if (last_polygons == nullptr) { - nout << "Discontinous vertex map chunk encountered without a preceding polygons chunk.\n"; - } else { - const LwoDiscontinuousVertexMap *lwo_vmad = DCAST(LwoDiscontinuousVertexMap, chunk); - last_polygons->add_vmad(lwo_vmad); - } - - } else if (chunk->is_of_type(LwoTags::get_class_type())) { - tags = DCAST(LwoTags, chunk); - - } else if (chunk->is_of_type(LwoPolygons::get_class_type())) { - if (last_points == nullptr) { - nout << "Polygon chunk encountered without a preceding points chunk.\n"; - } else { - const LwoPolygons *lwo_polygons = DCAST(LwoPolygons, chunk); - CLwoPolygons *polygons = - new CLwoPolygons(this, lwo_polygons, last_points); - _polygons.push_back(polygons); - last_polygons = polygons; - } - - } else if (chunk->is_of_type(LwoPolygonTags::get_class_type())) { - if (last_polygons == nullptr) { - nout << "Polygon tags chunk encountered without a preceding polygons chunk.\n"; - } else if (tags == nullptr) { - nout << "Polygon tags chunk encountered without a preceding tags chunk.\n"; - } else { - const LwoPolygonTags *lwo_ptags = DCAST(LwoPolygonTags, chunk); - last_polygons->add_ptags(lwo_ptags, tags); - } - - } else if (chunk->is_of_type(LwoSurface::get_class_type())) { - if (last_layer == nullptr) { - last_layer = make_generic_layer(); - } - - const LwoSurface *lwo_surface = DCAST(LwoSurface, chunk); - CLwoSurface *surface = new CLwoSurface(this, lwo_surface); - - bool inserted = _surfaces.insert(Surfaces::value_type(surface->get_name(), surface)).second; - if (!inserted) { - nout << "Multiple surface definitions named " << surface->get_name() << "\n"; - delete surface; - } - } - } -} - -/** - * Makes egg structures for all of the conversion wrapper objects. - */ -void LwoToEggConverter:: -make_egg() { - if (_generic_layer != nullptr) { - _generic_layer->make_egg(); - } - - Layers::iterator li; - for (li = _layers.begin(); li != _layers.end(); ++li) { - CLwoLayer *layer = (*li); - if (layer != nullptr) { - layer->make_egg(); - } - } - - Points::iterator pi; - for (pi = _points.begin(); pi != _points.end(); ++pi) { - CLwoPoints *points = (*pi); - points->make_egg(); - } - - Polygons::iterator gi; - for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) { - CLwoPolygons *polygons = (*gi); - polygons->make_egg(); - } -} - -/** - * Connects together all of the egg structures. - */ -void LwoToEggConverter:: -connect_egg() { - if (_generic_layer != nullptr) { - _generic_layer->connect_egg(); - } - - Layers::iterator li; - for (li = _layers.begin(); li != _layers.end(); ++li) { - CLwoLayer *layer = (*li); - if (layer != nullptr) { - layer->connect_egg(); - } - } - - Points::iterator pi; - for (pi = _points.begin(); pi != _points.end(); ++pi) { - CLwoPoints *points = (*pi); - points->connect_egg(); - } - - Polygons::iterator gi; - for (gi = _polygons.begin(); gi != _polygons.end(); ++gi) { - CLwoPolygons *polygons = (*gi); - polygons->connect_egg(); - } -} - -/** - * Ensures that there is space in the _layers array to store an element at - * position number. - */ -void LwoToEggConverter:: -slot_layer(int number) { - nassertv(number - (int)_layers.size() < 1000); - while (number >= (int)_layers.size()) { - _layers.push_back(nullptr); - } - nassertv(number >= 0 && number < (int)_layers.size()); -} - -/** - * Ensures that there is space in the _clips array to store an element at - * position number. - */ -void LwoToEggConverter:: -slot_clip(int number) { - nassertv(number - (int)_clips.size() < 1000); - while (number >= (int)_clips.size()) { - _clips.push_back(nullptr); - } - nassertv(number >= 0 && number < (int)_clips.size()); -} - -/** - * If a geometry definition is encountered in the Lightwave file before a - * layer definition, we should make a generic layer to hold the geometry. - * This makes and returns a single layer for this purpose. It should not be - * called twice. - */ -CLwoLayer *LwoToEggConverter:: -make_generic_layer() { - nassertr(_generic_layer == nullptr, _generic_layer); - - PT(LwoLayer) layer = new LwoLayer; - layer->make_generic(); - - _generic_layer = new CLwoLayer(this, layer); - return _generic_layer; -} diff --git a/pandatool/src/lwoegg/lwoToEggConverter.h b/pandatool/src/lwoegg/lwoToEggConverter.h deleted file mode 100644 index c4380a21..00000000 --- a/pandatool/src/lwoegg/lwoToEggConverter.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoToEggConverter.h - * @author drose - * @date 2001-04-17 - */ - -#ifndef LWOTOEGGCONVERTER_H -#define LWOTOEGGCONVERTER_H - -#include "pandatoolbase.h" - -#include "somethingToEggConverter.h" -#include "lwoHeader.h" -#include "pointerTo.h" - -#include "pvector.h" -#include "pmap.h" - -class CLwoLayer; -class CLwoClip; -class CLwoPoints; -class CLwoPolygons; -class CLwoSurface; -class LwoClip; - -/** - * This class supervises the construction of an EggData structure from the - * data represented by the LwoHeader. Reading and writing the egg and lwo - * structures is left to the user. - */ -class LwoToEggConverter : public SomethingToEggConverter { -public: - LwoToEggConverter(); - LwoToEggConverter(const LwoToEggConverter ©); - virtual ~LwoToEggConverter(); - - virtual SomethingToEggConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - - virtual bool convert_file(const Filename &filename); - bool convert_lwo(const LwoHeader *lwo_header); - virtual bool supports_compressed() const; - - CLwoLayer *get_layer(int number) const; - CLwoClip *get_clip(int number) const; - - CLwoSurface *get_surface(const std::string &name) const; - - bool _make_materials; - -private: - void cleanup(); - - void collect_lwo(); - void make_egg(); - void connect_egg(); - - void slot_layer(int number); - void slot_clip(int number); - CLwoLayer *make_generic_layer(); - - CPT(LwoHeader) _lwo_header; - - CLwoLayer *_generic_layer; - typedef pvector Layers; - Layers _layers; - - typedef pvector Clips; - Clips _clips; - - typedef pvector Points; - Points _points; - - typedef pvector Polygons; - Polygons _polygons; - - typedef pmap Surfaces; - Surfaces _surfaces; -}; - -#include "lwoToEggConverter.I" - -#endif diff --git a/pandatool/src/lwoegg/p3lwoegg_composite1.cxx b/pandatool/src/lwoegg/p3lwoegg_composite1.cxx deleted file mode 100644 index b5106cfd..00000000 --- a/pandatool/src/lwoegg/p3lwoegg_composite1.cxx +++ /dev/null @@ -1,11 +0,0 @@ - -#include "cLwoClip.cxx" -#include "cLwoLayer.cxx" -#include "cLwoPoints.cxx" -#include "cLwoPolygons.cxx" -#include "cLwoSurface.cxx" -#include "cLwoSurfaceBlock.cxx" -#include "cLwoSurfaceBlockTMap.cxx" -#include "lwoToEggConverter.cxx" -#include "lwoToEggConverter.h" - diff --git a/pandatool/src/lwoprogs/CMakeLists.txt b/pandatool/src/lwoprogs/CMakeLists.txt deleted file mode 100644 index 39210c50..00000000 --- a/pandatool/src/lwoprogs/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(lwo-scan lwoScan.cxx lwoScan.h) -target_link_libraries(lwo-scan p3progbase p3lwo) -install(TARGETS lwo-scan EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -if(HAVE_EGG) - - add_executable(lwo2egg lwoToEgg.cxx lwoToEgg.h) - target_link_libraries(lwo2egg p3lwoegg p3eggbase p3progbase) - install(TARGETS lwo2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -endif() diff --git a/pandatool/src/lwoprogs/lwoScan.cxx b/pandatool/src/lwoprogs/lwoScan.cxx deleted file mode 100644 index c299a3a7..00000000 --- a/pandatool/src/lwoprogs/lwoScan.cxx +++ /dev/null @@ -1,84 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoScan.cxx - * @author drose - * @date 2001-04-24 - */ - -#include "lwoScan.h" - -#include "lwoInputFile.h" -#include "lwoChunk.h" -#include "config_lwo.h" - -/** - * - */ -LwoScan:: -LwoScan() { - clear_runlines(); - add_runline("[opts] input.lwo"); - - set_program_brief("describe the contents of a Lightwave object file"); - set_program_description - ("This program simply reads a Lightwave object file and dumps its " - "contents to standard output. It's mainly useful for debugging " - "problems with lwo2egg."); -} - -/** - * - */ -void LwoScan:: -run() { - LwoInputFile in; - if (!in.open_read(_input_filename)) { - nout << "Unable to open " << _input_filename << "\n"; - exit(1); - } - - PT(IffChunk) chunk = in.get_chunk(); - if (chunk == nullptr) { - nout << "Unable to read file.\n"; - } else { - while (chunk != nullptr) { - chunk->write(std::cout, 0); - chunk = in.get_chunk(); - } - } -} - -/** - * - */ -bool LwoScan:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the Lightwave object file to read on the command line.\n"; - return false; - } - if (args.size() != 1) { - nout << "You may specify only one Lightwave object file to read on the command line.\n"; - return false; - } - - _input_filename = args[0]; - - return true; -} - - -int -main(int argc, char *argv[]) { - init_liblwo(); - LwoScan prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/lwoprogs/lwoScan.h b/pandatool/src/lwoprogs/lwoScan.h deleted file mode 100644 index a602e785..00000000 --- a/pandatool/src/lwoprogs/lwoScan.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoScan.h - * @author drose - * @date 2001-04-30 - */ - -#ifndef LWOSCAN_H -#define LWOSCAN_H - -#include "programBase.h" -#include "filename.h" - -/** - * A program to read a Lightwave file and report its structure and contents. - */ -class LwoScan : public ProgramBase { -public: - LwoScan(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - - Filename _input_filename; -}; - -#endif diff --git a/pandatool/src/lwoprogs/lwoToEgg.cxx b/pandatool/src/lwoprogs/lwoToEgg.cxx deleted file mode 100644 index a2e54b48..00000000 --- a/pandatool/src/lwoprogs/lwoToEgg.cxx +++ /dev/null @@ -1,87 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoToEgg.cxx - * @author drose - * @date 2001-04-17 - */ - -#include "lwoToEgg.h" - -#include "lwoToEggConverter.h" -#include "lwoHeader.h" -#include "lwoInputFile.h" -#include "config_lwo.h" - -/** - * - */ -LwoToEgg:: -LwoToEgg() : - SomethingToEgg("Lightwave", ".lwo") -{ - add_path_replace_options(); - add_path_store_options(); - add_units_options(); - add_normals_options(); - add_transform_options(); - - set_program_brief("convert a Lightwave Object file to .egg"); - set_program_description - ("This program converts Lightwave Object (.lwo) files to egg. Many " - "rendering characteristics of Lightwave (like layered shaders, etc.) " - "are not supported, but fundamental things like polygons and texture " - "maps are. This program is primarily designed to support files written " - "by Lightwave version 6.x (LWO2 files), but it also has some limited " - "support for version 5.x files (LWOB files)."); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. Normally, this is y-up-left."); - - redescribe_option - ("ui", - "Specify the units of the input Lightwave file. By convention, " - "this is assumed to be meters if it is unspecified."); - - _coordinate_system = CS_yup_left; -} - -/** - * - */ -void LwoToEgg:: -run() { - _data->set_coordinate_system(_coordinate_system); - - if (_input_units == DU_invalid) { - _input_units = DU_meters; - } - - LwoToEggConverter converter; - converter.set_egg_data(_data); - apply_parameters(converter); - - if (!converter.convert_file(_input_filename)) { - nout << "Errors in conversion.\n"; - exit(1); - } - - write_egg_file(); - nout << "\n"; -} - - -int main(int argc, char *argv[]) { - init_liblwo(); - LwoToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/lwoprogs/lwoToEgg.h b/pandatool/src/lwoprogs/lwoToEgg.h deleted file mode 100644 index 44342fce..00000000 --- a/pandatool/src/lwoprogs/lwoToEgg.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file lwoToEgg.h - * @author drose - * @date 2001-04-17 - */ - -#ifndef LWOTOEGG_H -#define LWOTOEGG_H - -#include "pandatoolbase.h" - -#include "somethingToEgg.h" -#include "lwoToEggConverter.h" - -#include "dSearchPath.h" - -/** - * A program to read a Lightwave file and generate an egg file. - */ -class LwoToEgg : public SomethingToEgg { -public: - LwoToEgg(); - - void run(); -}; - -#endif diff --git a/pandatool/src/mac-stats/CMakeLists.txt b/pandatool/src/mac-stats/CMakeLists.txt deleted file mode 100644 index 23c54ef9..00000000 --- a/pandatool/src/mac-stats/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT APPLE OR NOT HAVE_NET) - return() -endif() - -set(MACSTATS_HEADERS - macStats.h - macStatsAppDelegate.h - macStatsChartMenu.h - macStatsChartMenuDelegate.h - macStatsFlameGraph.h - macStatsGraph.h - macStatsGraphView.h - macStatsGraphViewController.h - macStatsLabel.h - macStatsLabelStack.h - macStatsMonitor.h - macStatsPianoRoll.h - macStatsScaleArea.h - macStatsServer.h - macStatsStripChart.h - macStatsTimeline.h -) - -set(MACSTATS_SOURCES - macStats.mm - macStatsAppDelegate.mm - macStatsChartMenu.mm - macStatsChartMenuDelegate.mm - macStatsFlameGraph.mm - macStatsGraph.mm - macStatsGraphView.mm - macStatsGraphViewController.mm - macStatsLabel.mm - macStatsLabelStack.mm - macStatsMonitor.mm - macStatsPianoRoll.mm - macStatsScaleArea.mm - macStatsServer.mm - macStatsStripChart.mm - macStatsTimeline.mm -) - -composite_sources(mac-stats MACSTATS_SOURCES) -add_executable(mac-stats ${MACSTATS_HEADERS} ${MACSTATS_SOURCES}) -target_link_libraries(mac-stats p3progbase p3pstatserver) -target_link_libraries(mac-stats "-framework Cocoa") -target_link_libraries(mac-stats "-framework Carbon") -target_link_libraries(mac-stats "-framework Quartz") - -# This program is NOT actually called win-stats. It's just pstats -set_target_properties(mac-stats PROPERTIES OUTPUT_NAME "pstats") - -install(TARGETS mac-stats EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/mac-stats/Info.plist b/pandatool/src/mac-stats/Info.plist deleted file mode 100644 index 2550b7e5..00000000 --- a/pandatool/src/mac-stats/Info.plist +++ /dev/null @@ -1,47 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - org.panda3d.pstats - CFBundleExecutable - pstats - CFBundleName - PStats - CFBundleDisplayName - PStats - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - APPL - LSHasLocalizedDisplayName - - NSAppleScriptEnabled - - NSPrincipalClass - NSApplication - CFBundleDocumentTypes - - - CFBundleTypeName - PStats session file - CFBundleTypeRole - Editor - LSHandlerRank - Owner - LSTypeIsPackage - - CFBundleTypeExtensions - - pstats - - CFBundleTypeMIMETypes - - application/vnd.panda3d.pstats - - - - - diff --git a/pandatool/src/mac-stats/cocoa_compat.h b/pandatool/src/mac-stats/cocoa_compat.h deleted file mode 100644 index b535b08d..00000000 --- a/pandatool/src/mac-stats/cocoa_compat.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file cocoa_compat.h - * @author rdb - * @date 2023-08-28 - */ - -#ifndef COCOA_COMPAT_H -#define COCOA_COMPAT_H - -#import - -// Allow building with older SDKs. -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 110000 -typedef NS_ENUM(NSInteger, NSWindowToolbarStyle) { - NSWindowToolbarStyleAutomatic, - NSWindowToolbarStyleExpanded, - NSWindowToolbarStylePreference, - NSWindowToolbarStyleUnified, - NSWindowToolbarStyleUnifiedCompact -} API_AVAILABLE(macos(11.0)); - -API_AVAILABLE(macos(11.0)) API_UNAVAILABLE(ios) -@interface NSTrackingSeparatorToolbarItem : NSToolbarItem -+ (instancetype)trackingSeparatorToolbarItemWithIdentifier:(NSString *)identifier splitView:(NSSplitView *)splitView dividerIndex:(NSInteger)dividerIndex API_UNAVAILABLE(ios); -@property (strong) NSSplitView *splitView API_UNAVAILABLE(ios); -@property NSInteger dividerIndex API_UNAVAILABLE(ios); -@end - -#endif // __MAC_OS_X_VERSION_MAX_ALLOWED - -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101400 -@protocol NSViewToolTipOwner -- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(nullable void *)data; -@end - -#endif // __MAC_OS_X_VERSION_MAX_ALLOWED - -#endif // COCOA_COMPAT_H diff --git a/pandatool/src/mac-stats/macStats.h b/pandatool/src/mac-stats/macStats.h deleted file mode 100644 index a5e2371b..00000000 --- a/pandatool/src/mac-stats/macStats.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStats.h - * @author rdb - * @date 2023-08-17 - */ - -#ifndef MACSTATS_H -#define MACSTATS_H - -#include "pStatServer.h" - -#endif diff --git a/pandatool/src/mac-stats/macStats.mm b/pandatool/src/mac-stats/macStats.mm deleted file mode 100644 index cbaee082..00000000 --- a/pandatool/src/mac-stats/macStats.mm +++ /dev/null @@ -1,73 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStats.mm - * @author rdb - * @date 2023-08-17 - */ - -#include "pandatoolbase.h" -#include "macStats.h" -#include "macStatsServer.h" -#include "config_pstatclient.h" - -#include -#include - -extern "C" { - OSStatus CPSSetProcessName(ProcessSerialNumber *psn, char *name); -}; - -@implementation NSBundle(swizzle) -- (NSString *)__bundleIdentifier { - if (self == [NSBundle mainBundle]) { - return @"org.panda3d.pstats"; - } else { - return [self __bundleIdentifier]; - } -} -@end - -void -keyboard_interrupt(int sig) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { - [NSApp terminate:NSApp]; - }); -} - -int -main(int argc, char *argv[]) { - // This hack is necessary to allow showing notifications when run as a console app. - Class cls = objc_getClass("NSBundle"); - if (cls) { - method_exchangeImplementations(class_getInstanceMethod(cls, @selector(bundleIdentifier)), - class_getInstanceMethod(cls, @selector(__bundleIdentifier))); - } - - // Set the bundle name of the application. - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - CPSSetProcessName(&psn, (char *)"PStats"); - - @autoreleasepool { - // Create the server application. - MacStatsServer *server = new MacStatsServer; - - // Register a SIGINT handler to terminate the application correctly. - // Otherwise, notifications may linger in the notification center. - struct sigaction act = {}; - act.sa_handler = &keyboard_interrupt; - act.sa_flags = SA_RESETHAND; - sigaction(SIGINT, &act, nullptr); - - // Get lost in the Cocoa main loop. - server->run(argc, argv); - } - - return 0; -} diff --git a/pandatool/src/mac-stats/macStatsAppDelegate.h b/pandatool/src/mac-stats/macStatsAppDelegate.h deleted file mode 100644 index e7921178..00000000 --- a/pandatool/src/mac-stats/macStatsAppDelegate.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsAppDelegate.h - * @author rdb - * @date 2023-08-17 - */ - -#ifndef MACSTATSAPPDELEGATE_H -#define MACSTATSAPPDELEGATE_H - -#import -#import - -class MacStatsServer; - -@interface MacStatsAppDelegate : NSObject { - @private - MacStatsServer *_server; - NSTimer *_timer; -} - -- (id)initWithServer:(MacStatsServer *)server; -- (void)applicationDidFinishLaunching:(NSApplication *)sender; -- (BOOL)applicationShouldTerminate:(NSApplication *)sender; -- (void)applicationWillTerminate:(NSApplication *)sender; -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center - shouldPresentNotification:(NSUserNotification *)notification; - -@end - -#endif diff --git a/pandatool/src/mac-stats/macStatsAppDelegate.mm b/pandatool/src/mac-stats/macStatsAppDelegate.mm deleted file mode 100644 index 7831549c..00000000 --- a/pandatool/src/mac-stats/macStatsAppDelegate.mm +++ /dev/null @@ -1,201 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsAppDelegate.mm - * @author rdb - * @date 2023-08-17 - */ - -#include "macStatsAppDelegate.h" -#include "macStatsServer.h" -#include "pStatGraph.h" - -@implementation MacStatsAppDelegate - -- (id)initWithServer:(MacStatsServer *)server { - if (self = [super init]) { - _server = server; - _timer = nil; - } - - return self; -} - -- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app { - // Squelches an annoying warning. - return YES; -} - -- (BOOL)application:(NSApplication *)sender - openFile:(NSString *)filename { - Filename fn([filename UTF8String]); - fn.set_binary(); - return _server->open_session(fn); -} - -- (void)applicationDidFinishLaunching:(NSApplication *)sender { - // Set this object as delegate for user notifications. - { - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - center.delegate = self; - } - - // Register default preferences. - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSDictionary *dict = [NSDictionary - dictionaryWithObjects:@[@"", [NSNumber numberWithBool:YES], [NSNumber numberWithInt:PStatGraph::GBU_ms]] - forKeys:@[@"Appearance", @"ShowStatusItem", @"TimeUnits"]]; - [defaults registerDefaults:dict]; - - if (_server != nil) { - // Apply preferences. - [self applyDefaults:nil]; - - // Create a timer to poll the server. - _timer = [NSTimer scheduledTimerWithTimeInterval:0.2 - target:self - selector:@selector(pollServer) - userInfo:nil - repeats:YES]; - - // Start new session if we don't have one yet. - if (_server->get_monitor() == nullptr) { - _server->new_session(); - } - } - - // Watch for defaults change. - { - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:self - selector:@selector(applyDefaults:) - name:NSUserDefaultsDidChangeNotification - object:nil]; - } -} - -- (void)applyDefaults:(NSNotification *)notification { - if (_server != nil) { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - _server->set_show_status_item([defaults boolForKey:@"ShowStatusItem"]); - _server->set_appearance([defaults stringForKey:@"Appearance"]); - _server->set_time_units([defaults integerForKey:@"TimeUnits"]); - } -} - -- (void)pollServer { - _server->poll(); -} - -- (BOOL)applicationShouldTerminate:(NSApplication *)sender { - if (_server != nil) { - return _server->close_session(); - } - return YES; -} - -- (void)applicationWillTerminate:(NSApplication *)sender { - if (_timer != nil) { - [_timer invalidate]; - _timer = nil; - } - - if (_server != nil) { - delete _server; - _server = nil; - } -} - -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center - shouldPresentNotification:(NSUserNotification *)notification { - return YES; -} - -- (void)userNotificationCenter:(NSUserNotificationCenter *)center - didActivateNotification:(NSUserNotification *)notification { - NSUserNotificationAction *action = notification.additionalActivationAction; - if (action != nil) { - NSString *ident = action.identifier; - if ([ident isEqual:@"quit"]) { - [NSApp terminate:self]; - } - else if ([ident isEqual:@"new"]) { - _server->new_session(); - } - else if ([ident isEqual:@"open"]) { - _server->open_session(); - } - else if ([ident isEqual:@"openLast"]) { - _server->open_last_session(); - } - } -} - -- (void)handleNewSession:(NSMenuItem *)item { - _server->new_session(); -} - -- (void)handleOpenSession:(NSMenuItem *)item { - _server->open_session(); -} - -- (void)handleOpenLastSession:(NSMenuItem *)item { - _server->open_last_session(); -} - -- (void)handleSaveSession:(NSMenuItem *)item { - _server->save_session(); -} - -- (void)handleCloseSession:(NSMenuItem *)item { - _server->close_session(); -} - -- (void)handleExportSession:(NSMenuItem *)item { - _server->export_session(); -} - -- (void)handleToggleSettingsBool:(NSMenuItem *)item { - [[NSUserDefaults standardUserDefaults] setBool:(item.state != NSOnState) forKey:item.representedObject]; -} - -- (void)handleSettingsInteger:(NSMenuItem *)item { - [[NSUserDefaults standardUserDefaults] setInteger:item.tag forKey:item.representedObject]; -} - -- (void)handleSettingsAppearance:(NSMenuItem *)item { - [[NSUserDefaults standardUserDefaults] setObject:item.representedObject forKey:@"Appearance"]; -} - -- (void)handleSpeed:(NSMenuItem *)item { - MacStatsMonitor *monitor = _server->get_monitor(); - if (monitor != nullptr) { - monitor->set_scroll_speed(item.tag); - } -} - -- (void)handlePause:(NSMenuItem *)item { - MacStatsMonitor *monitor = _server->get_monitor(); - if (monitor != nullptr) { - monitor->set_pause(!item.state); - } -} - -- (void)handleClickStatusItem:(id)sender { - [NSApp activateIgnoringOtherApps:YES]; -} - -- (void)handleChooseCollectorColor:(NSColorPanel *)panel { - MacStatsMonitor *monitor = _server->get_monitor(); - if (monitor != nullptr) { - NSColor *color = panel.color; - monitor->handle_choose_collector_color(LRGBColor(color.redComponent, color.greenComponent, color.blueComponent)); - } -} - -@end diff --git a/pandatool/src/mac-stats/macStatsChartMenu.h b/pandatool/src/mac-stats/macStatsChartMenu.h deleted file mode 100644 index a8b3bcea..00000000 --- a/pandatool/src/mac-stats/macStatsChartMenu.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsChartMenu.h - * @author rdb - * @date 2023-08-18 - */ - -#ifndef MACSTATSCHARTMENU_H -#define MACSTATSCHARTMENU_H - -#include "pandatoolbase.h" -#include "macStatsMonitor.h" - -#include - -class PStatView; -class PStatViewLevel; - -/** - * A pulldown menu of charts available for a particular thread. - */ -class MacStatsChartMenu { -public: - MacStatsChartMenu(MacStatsMonitor *monitor, int thread_index); - ~MacStatsChartMenu(); - - int get_thread_index() const { return _thread_index; } - - void add_to_menu(NSMenu *menu, int position); - void remove_from_menu(NSMenu *menu); - - void check_update(); - void do_update(); - -private: - bool add_view(NSMenu *parent_menu, const PStatViewLevel *view_level, - bool show_level, int insert_at); - NSMenuItem *make_menu_item(NSMenu *parent_menu, int insert_at, - const char *label, SEL action, - int collector_index = -1); - - MacStatsMonitor *_monitor; - int _thread_index; - - int _last_level_index; - NSMenu *_menu; - - // Pair of menu item, submenu - std::vector > _collector_items; - int _time_items_end = 0; - int _level_items_end = 0; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsChartMenu.mm b/pandatool/src/mac-stats/macStatsChartMenu.mm deleted file mode 100644 index 8df12743..00000000 --- a/pandatool/src/mac-stats/macStatsChartMenu.mm +++ /dev/null @@ -1,246 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsChartMenu.mm - * @author rdb - * @date 2023-08-18 - */ - -#include "macStatsChartMenu.h" -#include "macStatsChartMenuDelegate.h" -#include "macStatsMonitor.h" - -/** - * - */ -MacStatsChartMenu:: -MacStatsChartMenu(MacStatsMonitor *monitor, int thread_index) : - _monitor(monitor), - _thread_index(thread_index) -{ - _menu = [[NSMenu alloc] init]; - _menu.delegate = [[MacStatsChartMenuDelegate alloc] initWithMonitor:monitor threadIndex:thread_index]; - - if (thread_index == 0) { - _menu.title = @"Graphs"; - - // Timeline goes first. - make_menu_item(_menu, -1, "Timeline", @selector(handleOpenTimeline:)); - - // Then the piano roll (even though it's not very useful nowadays) - make_menu_item(_menu, -1, "Piano Roll", @selector(handleOpenPianoRoll:)); - } - else { - make_menu_item(_menu, -1, "Open Strip Chart", @selector(handleOpenStripChart:), 0); - make_menu_item(_menu, -1, "Open Flame Graph", @selector(handleOpenFlameGraph:)); - } - - [_menu addItem:[NSMenuItem separatorItem]]; - _time_items_end = 3; - - // Put a separator between time items and level items. - [_menu addItem:[NSMenuItem separatorItem]]; - _level_items_end = _time_items_end + 1; - - // For the main thread menu, also some options relating to all graph windows. - if (thread_index == 0) { - [_menu addItem:[NSMenuItem separatorItem]]; - make_menu_item(_menu, -1, "Close All Graphs", @selector(handleCloseAllGraphs:)); - make_menu_item(_menu, -1, "Reopen Default Graphs", @selector(handleReopenDefaultGraphs:)); - make_menu_item(_menu, -1, "Save Current Layout as Default", @selector(handleSaveDefaultGraphs:)); - } - - do_update(); -} - -/** - * - */ -MacStatsChartMenu:: -~MacStatsChartMenu() { - MacStatsChartMenuDelegate *delegate = (MacStatsChartMenuDelegate *)_menu.delegate; - [_menu release]; - [delegate release]; -} - -/** - * Adds the menu to the end of the indicated menu bar. - */ -void MacStatsChartMenu:: -add_to_menu(NSMenu *menu, int position) { - NSMenuItem *item = [[NSMenuItem alloc] init]; - [menu insertItem:item atIndex:position]; - [menu setSubmenu:_menu forItem:item]; - [item release]; -} - -/** - * Removes the menu from the menu bar. - */ -void MacStatsChartMenu:: -remove_from_menu(NSMenu *menu) { - int index = [menu indexOfItemWithSubmenu:_menu]; - if (index >= 0) { - [menu removeItemAtIndex:index]; - } -} - -/** - * Checks to see if the menu needs to be updated (e.g. because of new data - * from the client), and updates it if necessary. - */ -void MacStatsChartMenu:: -check_update() { - PStatView &view = _monitor->get_view(_thread_index); - if (view.get_level_index() != _last_level_index) { - do_update(); - } -} - -/** - * Unconditionally updates the menu with the latest data from the client. - */ -void MacStatsChartMenu:: -do_update() { - PStatView &view = _monitor->get_view(_thread_index); - _last_level_index = view.get_level_index(); - - const PStatClientData *client_data = _monitor->get_client_data(); - if (_thread_index != 0) { - std::string thread_name = client_data->get_thread_name(_thread_index); - _menu.title = [NSString stringWithUTF8String:thread_name.c_str()]; - } - - if (client_data->get_num_collectors() > _collector_items.size()) { - _collector_items.resize(client_data->get_num_collectors(), std::make_pair(nullptr, nullptr)); - } - - // The menu item(s) for the thread's frame time goes second. - const PStatViewLevel *view_level = view.get_top_level(); - if (_thread_index == 0) { - if (add_view(_menu, view_level, false, _time_items_end)) { - ++_time_items_end; - ++_level_items_end; - } - } else { - for (int c = 0; c < view_level->get_num_children(); ++c) { - if (add_view(_menu, view_level->get_child(c), false, _time_items_end)) { - ++_time_items_end; - ++_level_items_end; - } - } - } - - // And then the menu item(s) for each of the level values. - int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); - for (int tc = 0; tc < num_toplevel_collectors; tc++) { - int collector = client_data->get_toplevel_collector(tc); - if (client_data->has_collector(collector) && - client_data->get_collector_has_level(collector, _thread_index)) { - - PStatView &level_view = _monitor->get_level_view(collector, _thread_index); - add_view(_menu, level_view.get_top_level(), true, _level_items_end); - } - } -} - -/** - * Adds a new entry or entries to the menu for the indicated view and its - * children. Returns true if an item was added, false if not. - */ -bool MacStatsChartMenu:: -add_view(NSMenu *parent_menu, const PStatViewLevel *view_level, - bool show_level, int insert_at) { - int collector = view_level->get_collector(); - - NSMenuItem *&menu_item = _collector_items[collector].first; - NSMenu *&menu = _collector_items[collector].second; - - const PStatClientData *client_data = _monitor->get_client_data(); - - int num_children = view_level->get_num_children(); - if (menu == nullptr && num_children == 0) { - // For a collector without children, no point in making a submenu. We just - // have the item open a strip chart directly (no point in creating a flame - // graph if there are no children). - if (menu_item != nullptr) { - // Already exists. - return false; - } - - std::string collector_name = client_data->get_collector_name(collector); - if (show_level) { - menu_item = make_menu_item(parent_menu, insert_at, - collector_name.c_str(), @selector(handleOpenStripChartLevel:), collector); - } else { - menu_item = make_menu_item(parent_menu, insert_at, - collector_name.c_str(), @selector(handleOpenStripChart:), collector); - } - return true; - } - else if (menu_item != nullptr && menu == nullptr) { - // Unhook the signal handler, we are creating a submenu. - menu_item.action = nil; - } - - // Create a submenu. - bool added_item = false; - if (menu_item == nullptr) { - std::string collector_name = client_data->get_collector_name(collector); - menu_item = make_menu_item(parent_menu, insert_at, collector_name.c_str(), nil); - added_item = true; - } - - if (menu == nullptr) { - menu = [[NSMenu alloc] init]; - [parent_menu setSubmenu:menu forItem:menu_item]; - - if (show_level) { - make_menu_item(menu, -1, "Open Strip Chart", - @selector(handleOpenStripChartLevel:), collector); - } else { - make_menu_item(menu, -1, "Open Strip Chart", - @selector(handleOpenStripChart:), collector); - - if (collector == 0) { - collector = -1; - } - - make_menu_item(menu, -1, "Open Flame Graph", - @selector(handleOpenFlameGraph:), collector); - } - - [menu addItem:[NSMenuItem separatorItem]]; - [menu release]; - } - - for (int c = 0; c < num_children; ++c) { - add_view(menu, view_level->get_child(c), show_level, 2 + !show_level); - } - - return added_item; -} - -/** - * - */ -NSMenuItem *MacStatsChartMenu:: -make_menu_item(NSMenu *parent_menu, int insert_at, const char *label, SEL action, int collector_index) { - NSMenuItem *menu_item = [[NSMenuItem alloc] init]; - menu_item.title = [NSString stringWithUTF8String:label]; - menu_item.target = _menu.delegate; - menu_item.action = action; - menu_item.tag = collector_index; - if (insert_at >= 0) { - [parent_menu insertItem:menu_item atIndex:insert_at]; - } else { - [parent_menu addItem:menu_item]; - } - [menu_item release]; - return menu_item; -} diff --git a/pandatool/src/mac-stats/macStatsChartMenuDelegate.h b/pandatool/src/mac-stats/macStatsChartMenuDelegate.h deleted file mode 100644 index 05f86302..00000000 --- a/pandatool/src/mac-stats/macStatsChartMenuDelegate.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsChartMenuDelegate.h - * @author rdb - * @date 2023-08-18 - */ - -#ifndef MACSTATSCHARTMENUDELEGATE_H -#define MACSTATSCHARTMENUDELEGATE_H - -#import -#import - -class MacStatsMonitor; - -@interface MacStatsChartMenuDelegate : NSObject { - @private - MacStatsMonitor *_monitor; - int _thread_index; -} - -- (id)initWithMonitor:(MacStatsMonitor *)monitor threadIndex:(int)index; - -@end - -#endif diff --git a/pandatool/src/mac-stats/macStatsChartMenuDelegate.mm b/pandatool/src/mac-stats/macStatsChartMenuDelegate.mm deleted file mode 100644 index 67c12fca..00000000 --- a/pandatool/src/mac-stats/macStatsChartMenuDelegate.mm +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsChartMenuDelegate.mm - * @author rdb - * @date 2023-08-18 - */ - -#include "macStatsChartMenuDelegate.h" -#include "macStatsMonitor.h" - -@implementation MacStatsChartMenuDelegate - -- (id)initWithMonitor:(MacStatsMonitor *)monitor threadIndex:(int)index { - if (self = [super init]) { - _monitor = monitor; - _thread_index = index; - } - - return self; -} - -- (void)handleOpenTimeline:(NSMenuItem *)item { - _monitor->open_timeline(); -} - -- (void)handleOpenStripChart:(NSMenuItem *)item { - _monitor->open_strip_chart(_thread_index, item.tag, NO); -} - -- (void)handleOpenStripChartLevel:(NSMenuItem *)item { - _monitor->open_strip_chart(_thread_index, item.tag, YES); -} - -- (void)handleOpenFlameGraph:(NSMenuItem *)item { - _monitor->open_flame_graph(_thread_index, item.tag); -} - -- (void)handleOpenPianoRoll:(NSMenuItem *)item { - _monitor->open_piano_roll(_thread_index); -} - -- (void)handleCloseAllGraphs:(NSMenuItem *)item { - _monitor->close_all_graphs(); -} - -- (void)handleReopenDefaultGraphs:(NSMenuItem *)item { - _monitor->close_all_graphs(); - _monitor->open_default_graphs(); -} - -- (void)handleSaveDefaultGraphs:(NSMenuItem *)item { - _monitor->save_default_graphs(); -} - -@end diff --git a/pandatool/src/mac-stats/macStatsFlameGraph.h b/pandatool/src/mac-stats/macStatsFlameGraph.h deleted file mode 100644 index a678e887..00000000 --- a/pandatool/src/mac-stats/macStatsFlameGraph.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsFlameGraph.h - * @author rdb - * @date 2023-08-18 - */ - -#ifndef MACSTATSFLAMEGRAPH_H -#define MACSTATSFLAMEGRAPH_H - -#include "macStatsGraph.h" -#include "pStatFlameGraph.h" -#include "macStatsChartMenuDelegate.h" - -/** - * A window that draws a flame chart, which shows the collectors explicitly - * stopping and starting, one frame at a time. - */ -class MacStatsFlameGraph final : public PStatFlameGraph, public MacStatsGraph { -public: - MacStatsFlameGraph(MacStatsMonitor *monitor, int thread_index, - int collector_index=-1, int frame_number=-1); - virtual ~MacStatsFlameGraph(); - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void on_click_label(int collector_index); - virtual void on_enter_label(int collector_index); - virtual void on_leave_label(int collector_index); - virtual NSMenu *get_label_menu(int collector_index) const; - -protected: - virtual void normal_guide_bars(); - - void clear_region(); - virtual void begin_draw(); - virtual void draw_bar(int depth, int from_x, int to_x, - int collector_index, int parent_index); - virtual void end_draw(); - virtual void idle(); - - virtual bool animate(double time, double dt); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual NSMenu *get_graph_menu(int mouse_x, int mouse_y) const; - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - - virtual bool handle_key(int graph_x, int graph_y, bool pressed, - UniChar c, unsigned short key_code); - virtual void handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual void handle_button_release(int graph_x, int graph_y); - virtual void handle_motion(int graph_x, int graph_y); - virtual void handle_leave(); - virtual void handle_wheel(int graph_x, int graph_y, double dx, double dy); - virtual void handle_draw_graph(CGContextRef ctx, NSRect rect); - virtual void handle_back(); - -public: - void handle_toggle_average(bool state); - -private: - int pixel_to_depth(int y) const; - void draw_guide_bar(CGContextRef ctx, const PStatGraph::GuideBar &bar); - void draw_guide_labels(CGContextRef ctx); - void draw_guide_label(CGContextRef ctx, const PStatGraph::GuideBar &bar); - -private: - NSToolbarItem *_total_item; - - MacStatsChartMenuDelegate *_menu_delegate; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsFlameGraph.mm b/pandatool/src/mac-stats/macStatsFlameGraph.mm deleted file mode 100644 index 003629d4..00000000 --- a/pandatool/src/mac-stats/macStatsFlameGraph.mm +++ /dev/null @@ -1,919 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsFlameGraph.mm - * @author rdb - * @date 2023-08-18 - */ - -#include "macStatsFlameGraph.h" -#include "macStatsMonitor.h" -#include "macStatsGraphView.h" -#include "macStatsScaleArea.h" -#include "pStatCollectorDef.h" -#include "cocoa_compat.h" - -@interface MacStatsFlameGraphViewController : MacStatsGraphViewController -@end - -static const int default_flame_graph_width = 800; -static const int default_flame_graph_height = 250; - -/** - * - */ -MacStatsFlameGraph:: -MacStatsFlameGraph(MacStatsMonitor *monitor, int thread_index, - int collector_index, int frame_number) : - PStatFlameGraph(monitor, thread_index, collector_index, frame_number, 0, 0), - MacStatsGraph(monitor, [MacStatsFlameGraphViewController alloc]) -{ - // Used for popup menus. - _menu_delegate = [[MacStatsChartMenuDelegate alloc] initWithMonitor:monitor threadIndex:thread_index]; - - // Set the initial size of the graph. - int height = default_flame_graph_height + _window.frame.size.height - _window.contentLayoutRect.size.height; - _graph_view.frame = NSMakeRect(0, 0, default_flame_graph_width, height); - _graph_view_controller.view.frame = NSMakeRect(0, 0, default_flame_graph_width, height); - - _total_item = nil; - if (@available(macOS 11.0, *)) { - NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""]; - toolbar.delegate = _graph_view_controller; - toolbar.displayMode = NSToolbarDisplayModeIconOnly; - _window.toolbar = toolbar; - [_window setToolbarStyle:NSWindowToolbarStyleUnifiedCompact]; - - for (NSToolbarItem *item in toolbar.items) { - if ([item.itemIdentifier isEqual:@"total"]) { - _total_item = item; - break; - } - } - [toolbar release]; - } - - //MacStatsScaleAreaController *scale_area_controller = [[MacStatsScaleAreaController alloc] initWithGraph:this]; - //scale_area_controller.layoutAttribute = NSLayoutAttributeRight; - //_scale_area = scale_area_controller.view; - //[_window addTitlebarAccessoryViewController:scale_area_controller]; - - _window.contentViewController = _graph_view_controller; - - _graph_view_controller.backToolbarItemVisible = NO; - - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - if (get_average_mode()) { - start_animation(); - } - - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } - - if (@available(macOS 11.0, *)) { - std::string text = format_number(get_horizontal_scale(), get_guide_bar_units(), get_guide_bar_unit_name()); - [_total_item setTitle:[NSString stringWithUTF8String:text.c_str()]]; - } - - [_window makeKeyAndOrderFront:nil]; -} - -/** - * - */ -MacStatsFlameGraph:: -~MacStatsFlameGraph() { - [_menu_delegate release]; -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void MacStatsFlameGraph:: -new_collector(int collector_index) { - MacStatsGraph::new_collector(collector_index); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void MacStatsFlameGraph:: -new_data(int thread_index, int frame_number) { - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } - - if (!_pause) { - update(); - - if (@available(macOS 11.0, *)) { - std::string text = format_number(get_horizontal_scale(), get_guide_bar_units(), get_guide_bar_unit_name()); - [_total_item setTitle:[NSString stringWithUTF8String:text.c_str()]]; - } - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void MacStatsFlameGraph:: -force_redraw() { - if (_ctx) { - PStatFlameGraph::force_redraw(); - } -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void MacStatsFlameGraph:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatFlameGraph::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void MacStatsFlameGraph:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - if (@available(macOS 11.0, *)) { - std::string text = format_number(get_horizontal_scale(), get_guide_bar_units(), get_guide_bar_unit_name()); - [_total_item setTitle:[NSString stringWithUTF8String:text.c_str()]]; - } - - //_scale_area.needsDisplay = YES; - } -} - -/** - * Called when the user single-clicks on a label. - */ -void MacStatsFlameGraph:: -on_click_label(int collector_index) { - int current = get_collector_index(); - if (collector_index != current) { - if (get_history_depth() == 0) { - _graph_view_controller.backToolbarItemVisible = YES; - } - push_collector_index(collector_index); - - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } -} - -/** - * Called when the user hovers the mouse over a label. - */ -void MacStatsFlameGraph:: -on_enter_label(int collector_index) { - if (collector_index != _highlighted_index) { - _highlighted_index = collector_index; - - if (!get_average_mode()) { - PStatFlameGraph::force_redraw(); - } - } -} - -/** - * Called when the user's mouse cursor leaves a label. - */ -void MacStatsFlameGraph:: -on_leave_label(int collector_index) { - if (collector_index == _highlighted_index && collector_index != -1) { - _highlighted_index = -1; - - if (!get_average_mode()) { - PStatFlameGraph::force_redraw(); - } - } -} - -/** - * Called when the mouse right-clicks on a label, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsFlameGraph:: -get_label_menu(int collector_index) const { - NSMenu *menu = [[[NSMenu alloc] init] autorelease]; - - std::string label = get_label_tooltip(collector_index); - if (!label.empty()) { - if (@available(macOS 14.0, *)) { - [menu addItem:[NSMenuItem sectionHeaderWithTitle:[NSString stringWithUTF8String:label.c_str()]]]; - } else { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithUTF8String:label.c_str()] action:nil keyEquivalent:@""]; - item.enabled = NO; - [menu addItem:item]; - [item release]; - } - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Set as Focus" action:@selector(handleSetAsFocus:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - item.enabled = (collector_index != 0 || get_collector_index() != 0); - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Strip Chart" action:@selector(handleOpenStripChart:) keyEquivalent:@""]; - item.target = _menu_delegate; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Flame Graph" action:@selector(handleOpenFlameGraph:) keyEquivalent:@""]; - item.target = _menu_delegate; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - [menu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Change Color\u2026" action:@selector(handleChangeColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Reset Color" action:@selector(handleResetColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - return menu; -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void MacStatsFlameGraph:: -normal_guide_bars() { - // We want vaguely 100 pixels between guide bars. - int num_bars = get_xsize() / 100; - - _guide_bars.clear(); - - double dist = get_horizontal_scale() / num_bars; - - for (int i = 1; i < num_bars; ++i) { - _guide_bars.push_back(make_guide_bar(i * dist)); - } - - _guide_bars_changed = true; - - //nassertv_always(_scale_area != nullptr); - //_scale_area.needsDisplay = YES; -} - -/** - * Erases the chart area. - */ -void MacStatsFlameGraph:: -clear_region() { - if (_ctx) { - CGContextSetFillColorWithColor(_ctx, _background_color); - CGContextFillRect(_ctx, CGRectMake(0, 0, get_xsize(), get_ysize())); - } -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void MacStatsFlameGraph:: -begin_draw() { - if (!_ctx) { - return; - } - - clear_region(); - - // isFlipped is true in the NSView, so flip the text again - CGContextSetTextMatrix(_ctx, CGAffineTransformMakeScale(1, -1)); - - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - const GuideBar &bar = get_guide_bar(i); - draw_guide_bar(_ctx, bar); - draw_guide_label(_ctx, bar); - } -} - -/** - * Should be overridden by the user class. Should draw a single bar at the - * indicated location. - */ -void MacStatsFlameGraph:: -draw_bar(int depth, int from_x, int to_x, int collector_index, int parent_index) { - double bottom = get_ysize() - depth * 4.000 * 5; - double top = bottom - 4.000 * 5; - - top += 1; - - MacStatsMonitor *monitor = MacStatsGraph::_monitor; - - bool is_highlighted = collector_index == _highlighted_index; - CGContextSetFillColorWithColor(_ctx, - monitor->get_collector_color(collector_index, is_highlighted)); - - if (to_x < from_x + 3) { - // It's just a tiny sliver. This is a more reliable way to draw it. - CGRect rect = CGRectMake(from_x, top, to_x - from_x, bottom - top); - CGContextFillRect(_ctx, rect); - } - else { - double radius = std::min((double)4.000, (to_x - from_x) / 2.0); - CGContextBeginPath(_ctx); - CGContextAddArc(_ctx, to_x - radius, top + radius, radius, -0.5 * M_PI, 0.0, NO); - CGContextAddArc(_ctx, to_x - radius, bottom - radius, radius, 0.0, 0.5 * M_PI, NO); - CGContextAddArc(_ctx, from_x + radius, bottom - radius, radius, 0.5 * M_PI, M_PI, NO); - CGContextAddArc(_ctx, from_x + radius, top + radius, radius, M_PI, 1.5 * M_PI, NO); - CGContextClosePath(_ctx); - CGContextFillPath(_ctx); - - if ((to_x - from_x) >= 4.000 * 4) { - // Only bother drawing the text if we've got some space to draw on. - int left = std::max(from_x, 0) + 4.000 / 2; - int right = std::min(to_x, get_xsize()) - 4.000 / 2; - - const PStatClientData *client_data = monitor->get_client_data(); - const PStatCollectorDef &def = client_data->get_collector_def(collector_index); - - const CFStringRef keys[] = { - (__bridge CFStringRef)NSForegroundColorAttributeName, - (__bridge CFStringRef)NSFontAttributeName, - }; - const void *values[] = { - monitor->get_collector_text_color(collector_index, is_highlighted), - [NSFont systemFontOfSize:0.0], - }; - CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, def._name.c_str(), kCFStringEncodingUTF8); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - - CTLineRef line = CTLineCreateWithAttributedString(astr); - CGRect bounds = CTLineGetImageBounds(line, _ctx); - CFRelease(astr); - CFRelease(str); - - if (bounds.size.width < right - left) { - // We have room for more. Show the collector's actual parent, if it's - // different than the block it's shown above. - if (def._parent_index > 0 && def._parent_index != parent_index) { - const PStatCollectorDef &parent_def = client_data->get_collector_def(def._parent_index); - std::string long_name = parent_def._name + ":" + def._name; - - CFStringRef long_str = CFStringCreateWithCString(kCFAllocatorDefault, long_name.c_str(), kCFStringEncodingUTF8); - CFAttributedStringRef long_astr = CFAttributedStringCreate(kCFAllocatorDefault, long_str, attribs); - - CTLineRef long_line = CTLineCreateWithAttributedString((CFAttributedStringRef)long_astr); - CGRect long_bounds = CTLineGetImageBounds(long_line, _ctx); - - if (long_bounds.size.width < right - left) { - CFRelease(line); - line = long_line; - bounds = long_bounds; - } else { - CFRelease(long_line); - } - CFRelease(long_astr); - CFRelease(long_str); - } - } - else { - static CFStringRef token_str = CFSTR("\u2026"); - CFAttributedStringRef token_astr = CFAttributedStringCreate(kCFAllocatorDefault, token_str, attribs); - CTLineRef token_line = CTLineCreateWithAttributedString(token_astr); - CTLineRef trunc_line = CTLineCreateTruncatedLine(line, right - left, kCTLineTruncationEnd, token_line); - CFRelease(line); - CFRelease(token_astr); - CFRelease(token_line); - line = trunc_line; - } - - // Center the text vertically in the bar. - if (line != nullptr) { - CGContextSetTextPosition(_ctx, left, top + (bottom - top + bounds.size.height) / 2); - CTLineDraw(line, _ctx); - CFRelease(line); - } - CFRelease(attribs); - } - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void MacStatsFlameGraph:: -end_draw() { - _graph_view.needsDisplay = YES; -} - -/** - * Called at the end of the draw cycle. - */ -void MacStatsFlameGraph:: -idle() { -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool MacStatsFlameGraph:: -animate(double time, double dt) { - return PStatFlameGraph::animate(time, dt); -} - -/** - * Returns the current window dimensions. - */ -bool MacStatsFlameGraph:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - MacStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void MacStatsFlameGraph:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - MacStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * Called when the mouse right-clicks on the graph, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsFlameGraph:: -get_graph_menu(int mouse_x, int mouse_y) const { - int collector_index = get_bar_collector(pixel_to_depth(mouse_y), mouse_x); - if (collector_index != -1) { - return get_label_menu(collector_index); - } - return nil; -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsFlameGraph:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return get_bar_tooltip(pixel_to_depth(mouse_y), mouse_x); -} - -/** - * Based on the mouse position within the window's client area, look for - * draggable things the mouse might be hovering over and return the - * apprioprate DragMode enum or DM_none if nothing is indicated. - */ -MacStatsGraph::DragMode MacStatsFlameGraph:: -consider_drag_start(int graph_x, int graph_y) { - if (graph_y >= 0 && graph_y < get_ysize()) { - if (graph_x >= 0 && graph_x < get_xsize()) { - // See if the mouse is over a user-defined guide bar. - int x = graph_x; - double from_height = pixel_to_height(x - 2); - double to_height = pixel_to_height(x + 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else { - // The mouse is left or right of the graph; maybe create a new guide - // bar. - return DM_new_guide_bar; - } - } - - return DM_none; -} - -/** - * - */ -bool MacStatsFlameGraph:: -handle_key(int graph_x, int graph_y, bool pressed, UniChar c, unsigned short key_code) { - bool changed = false; - - if (pressed) { - switch (c) { - case NSLeftArrowFunctionKey: - changed = prev_frame(); - break; - - case NSRightArrowFunctionKey: - changed = next_frame(); - break; - - case NSHomeFunctionKey: - changed = first_frame(); - break; - - case NSEndFunctionKey: - changed = last_frame(); - break; - } - } - - if (changed) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } - - return changed; -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -void MacStatsFlameGraph:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - int depth = pixel_to_depth(graph_y); - int collector_index = get_bar_collector(depth, graph_x); - if (double_click && button == 0) { - // Double-clicking on a color bar in the graph will zoom the graph into - // that collector. - if (collector_index >= 0) { - on_click_label(collector_index); - } else { - if (get_history_depth() > 0) { - clear_history(); - _graph_view_controller.backToolbarItemVisible = NO; - } - set_collector_index(-1); - - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } - return; - } - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - _drag_scale_start = pixel_to_height(graph_x); - // SetCapture(_graph_window); - return; - } - else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - _drag_start_x = graph_x; - // SetCapture(_graph_window); - return; - } - - return MacStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -void MacStatsFlameGraph:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_x < 0 || graph_x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return MacStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -void MacStatsFlameGraph:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none && - graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - // When the mouse is over a color bar, highlight it. - int depth = pixel_to_depth(graph_y); - int collector_index = get_bar_collector(depth, graph_x); - on_enter_label(collector_index); - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - if (graph_x >= 0 && graph_x < get_xsize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_x)); - return; - } - } - else if (_drag_mode == DM_guide_bar) { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - return; - } - - return MacStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -void MacStatsFlameGraph:: -handle_leave() { - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - return; -} - -/** - * - */ -void MacStatsFlameGraph:: -handle_wheel(int graph_x, int graph_y, double dx, double dy) { - if (dx != 0.0) { - if ((dx > 0.0) ? prev_frame() : next_frame()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } - } -} - -/** - * Fills in the graph window. - */ -void MacStatsFlameGraph:: -handle_draw_graph(CGContextRef ctx, NSRect rect) { - MacStatsGraph::handle_draw_graph(ctx, rect); - - CGContextSetTextMatrix(ctx, CGAffineTransformMakeScale(1, -1)); - - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - const GuideBar &bar = get_user_guide_bar(i); - draw_guide_bar(ctx, bar); - draw_guide_label(ctx, bar); - } -} - -/** - * Called when the mouse clicks the back button in the toolbar. - */ -void MacStatsFlameGraph:: -handle_back() { - if (pop_collector_index()) { - if (get_history_depth() == 0) { - _graph_view_controller.backToolbarItemVisible = NO; - } - - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } -} - -/** - * Called when the mouse toggles the "Average" checkbox in the toolbar. - */ -void MacStatsFlameGraph:: -handle_toggle_average(bool state) { - set_average_mode(state); - if (state) { - start_animation(); - } -} - - -/** - * Converts a pixel to a depth index. - */ -int MacStatsFlameGraph:: -pixel_to_depth(int y) const { - return (get_ysize() - 1 - y) / (4.000 * 5); -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void MacStatsFlameGraph:: -draw_guide_bar(CGContextRef ctx, const PStatGraph::GuideBar &bar) { - int x = height_to_pixel(bar._height); - - if (x > 0 && x < get_xsize() - 1) { - // Only draw it if it's not too close to the top. - CGContextSetStrokeColorWithColor(ctx, [NSColor gridColor].CGColor); - /*switch (bar._style) { - case GBS_target: - CGContextSetRGBStrokeColor(ctx, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2], 1.0); - break; - - case GBS_user: - CGContextSetRGBStrokeColor(ctx, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2], 1.0); - break; - - default: - CGContextSetRGBStrokeColor(ctx, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2], 1.0); - break; - }*/ - CGContextBeginPath(ctx); - CGContextMoveToPoint(ctx, x, 0); - CGContextAddLineToPoint(ctx, x, get_ysize()); - CGContextStrokePath(ctx); - } -} - -/** - * This is called during the servicing of the draw event. - */ -void MacStatsFlameGraph:: -draw_guide_labels(CGContextRef ctx) { - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_label(ctx, get_guide_bar(i)); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_label(ctx, get_user_guide_bar(i)); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void MacStatsFlameGraph:: -draw_guide_label(CGContextRef ctx, const PStatGraph::GuideBar &bar) { - NSColor *color; - color = [NSColor tertiaryLabelColor]; - /*switch (bar._style) { - case GBS_target: - color = [NSColor colorWithDeviceRed:rgb_light_gray[0] green:rgb_light_gray[1] blue:rgb_light_gray[2] alpha:1.0]; - break; - - case GBS_user: - color = [NSColor colorWithDeviceRed:rgb_user_guide_bar[0] green:rgb_user_guide_bar[1] blue:rgb_user_guide_bar[2] alpha:1.0]; - break; - - default: - color = [NSColor colorWithDeviceRed:rgb_dark_gray[0] green:rgb_dark_gray[1] blue:rgb_dark_gray[2] alpha:1.0]; - break; - }*/ - - int x = height_to_pixel(bar._height); - const std::string &label = bar._label; - - const CFStringRef keys[] = { - (__bridge CFStringRef)NSForegroundColorAttributeName, - (__bridge CFStringRef)NSFontAttributeName, - }; - const void *values[] = { - color, - [NSFont systemFontOfSize:0.0], - }; - CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, label.c_str(), kCFStringEncodingUTF8); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - CFRelease(attribs); - CFRelease(str); - - CTLineRef line = CTLineCreateWithAttributedString(astr); - CFRelease(astr); - CGRect bounds = CTLineGetImageBounds(line, ctx); - int width = bounds.size.width; - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(x - width); - double to_height = pixel_to_height(x + width); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - CFRelease(line); - return; - } - } - - if (x >= 0 && x < get_xsize()) { - int y = bounds.size.height; - if (@available(macOS 11.0, *)) { - // Account for underlap of title bar - y += _window.frame.size.height - _window.contentLayoutRect.size.height; - } - CGContextSetTextPosition(ctx, x + 6, y + 6); - CTLineDraw(line, ctx); - } - - CFRelease(line); -} - -@implementation MacStatsFlameGraphViewController - -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar { - return @[@"back", @"average", @"total"]; -} - -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar { - return @[@"average", @"total"]; -} - -- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar - itemForItemIdentifier:(NSString *)ident - willBeInsertedIntoToolbar:(BOOL)flag { - - if (@available(macOS 11.0, *)) { - if ([ident isEqual:@"average"]) { - NSButton *button = [NSButton buttonWithTitle:@"Average" target:self action:@selector(handleToggleAverage:)]; - button.image = [NSImage imageWithSystemSymbolName:@"sum" accessibilityDescription:@""]; - button.bezelStyle = NSBezelStyleTexturedRounded; - button.buttonType = NSButtonTypePushOnPushOff; - button.bordered = YES; - button.toolTip = @"Average"; - button.state = NSOffState; - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:ident] autorelease]; - item.label = @"Average"; - item.view = button; - return item; - } - if ([ident isEqual:@"total"]) { - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:ident] autorelease]; - item.label = @"Total"; - item.enabled = NO; - [item setBordered:YES]; - return item; - } - } - - return [super toolbar:toolbar itemForItemIdentifier:ident willBeInsertedIntoToolbar:flag]; -} - -- (void)handleToggleAverage:(NSButton *)button { - MacStatsFlameGraph *graph = (MacStatsFlameGraph *)_graph; - graph->handle_toggle_average(button.state == NSOnState); -} - -@end diff --git a/pandatool/src/mac-stats/macStatsGraph.h b/pandatool/src/mac-stats/macStatsGraph.h deleted file mode 100644 index 2905f60d..00000000 --- a/pandatool/src/mac-stats/macStatsGraph.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsGraph.h - * @author rdb - * @date 2023-08-17 - */ - -#ifndef MACSTATSGRAPH_H -#define MACSTATSGRAPH_H - -#include "pandatoolbase.h" -#include "macStatsGraphViewController.h" -#include "macStatsLabelStack.h" -#include "pmap.h" -#include "luse.h" - -class MacStatsMonitor; - -/** - * This is just an abstract base class to provide a common pointer type for - * the various kinds of graphs that may be created for a MacStatsMonitor. - */ -class MacStatsGraph { -public: - // What is the user adjusting by dragging the mouse in a window? - enum DragMode { - DM_none, - DM_scale, - DM_guide_bar, - DM_new_guide_bar, - DM_sizing, - DM_pan, - }; - -public: - MacStatsGraph(MacStatsMonitor *monitor, MacStatsGraphViewController *controller); - virtual ~MacStatsGraph(); - - void close(); - - MacStatsMonitor *get_monitor() { return _monitor; } - NSSplitView *get_split_view() { return _split_view; } - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw()=0; - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void set_scroll_speed(double scroll_speed); - void set_pause(bool pause); - - void user_guide_bars_changed(); - virtual void on_click_label(int collector_index); - virtual void on_enter_label(int collector_index); - virtual void on_leave_label(int collector_index); - virtual NSMenu *get_label_menu(int collector_index) const; - virtual std::string get_label_tooltip(int collector_index) const; - - void reset_collector_color(int collector_index); - -protected: - void start_animation(); - virtual bool animate(double time, double dt); - - void get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - -public: - // These must be public, because we can't declare Objective-C friends here. - virtual NSMenu *get_graph_menu(int mouse_x, int mouse_y) const; - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - virtual void set_drag_mode(DragMode drag_mode); - - virtual bool handle_key(int graph_x, int graph_y, bool pressed, - UniChar c, unsigned short key_code); - virtual void handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual void handle_button_release(int graph_x, int graph_y); - virtual void handle_motion(int graph_x, int graph_y); - virtual void handle_leave(); - virtual void handle_scroll(); - virtual void handle_wheel(int graph_x, int graph_y, double dx, double dy); - virtual void handle_magnify(int graph_x, int graph_y, double scale); - virtual void handle_draw_graph(CGContextRef ctx, NSRect rect); - virtual void handle_draw_graph_overhang(CGContextRef ctx, NSRect rect); - virtual void handle_draw_scale_area(CGContextRef ctx, NSRect rect); - virtual void handle_back(); - virtual void handle_timer(); - -protected: - CGColorRef _background_color; - - MacStatsMonitor *_monitor; - NSWindow *_window; - NSView *_graph_view; - MacStatsGraphViewController *_graph_view_controller; - NSView *_scale_area = nullptr; - NSSplitView *_split_view = nullptr; - NSScrollView *_sidebar_view = nullptr; - MacStatsLabelStack _label_stack; - - CGContextRef _ctx = nullptr; - int _bitmap_xsize, _bitmap_ysize; - - DragMode _drag_mode; - DragMode _potential_drag_mode; - int _drag_start_x, _drag_start_y; - double _drag_scale_start; - int _drag_guide_bar; - - int _highlighted_index = -1; - - bool _pause; - - NSTimer *_animation_timer = nil; - double _time = 0.0; - - static const CGFloat rgb_white[4]; - static const CGFloat rgb_light_gray[4]; - static const CGFloat rgb_dark_gray[4]; - static const CGFloat rgb_black[4]; - static const CGFloat rgb_user_guide_bar[4]; - -private: - void setup_bitmap(int xsize, int ysize, double scale); - void release_bitmap(); -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsGraph.mm b/pandatool/src/mac-stats/macStatsGraph.mm deleted file mode 100644 index 466d875d..00000000 --- a/pandatool/src/mac-stats/macStatsGraph.mm +++ /dev/null @@ -1,491 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsGraph.mm - * @author rdb - * @date 2023-08-17 - */ - -#include "macStatsGraph.h" -#include "macStatsGraphView.h" -#include "macStatsMonitor.h" -#include "macStatsLabelStack.h" - -const CGFloat MacStatsGraph::rgb_light_gray[4] = { - 0x9a / (CGFloat)0xff, 0x9a / (CGFloat)0xff, 0x9a / (CGFloat)0xff, 1.0, -}; -const CGFloat MacStatsGraph::rgb_dark_gray[4] = { - 0xb0 / (CGFloat)0xff, 0xb0 / (CGFloat)0xff, 0xb0 / (CGFloat)0xff, 1.0, -}; -const CGFloat MacStatsGraph::rgb_user_guide_bar[4] = { - 0x82 / (CGFloat)0xff, 0x96 / (CGFloat)0xff, 0xff / (CGFloat)0xff, 1.0, -}; - -static const NSInteger style_mask = NSWindowStyleMaskTitled - | NSWindowStyleMaskClosable - | NSWindowStyleMaskMiniaturizable - | NSWindowStyleMaskResizable; - -/** - * - */ -MacStatsGraph:: -MacStatsGraph(MacStatsMonitor *monitor, MacStatsGraphViewController *controller) : - _monitor(monitor) -{ - _background_color = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 0.0); - - _drag_mode = DM_none; - _potential_drag_mode = DM_none; - _drag_scale_start = 0.0f; - - _pause = false; - - NSInteger this_style_mask = style_mask; - if (@available(macOS 11.0, *)) { - this_style_mask |= NSWindowStyleMaskFullSizeContentView; - } - - _window = [NSWindow alloc]; - [_window initWithContentRect:NSMakeRect(100, 500, 500, 150) - styleMask:this_style_mask - backing:NSBackingStoreBuffered - defer:NO]; - _window.releasedWhenClosed = NO; - _window.titlebarAppearsTransparent = NO; - _window.excludedFromWindowsMenu = NO; - - _window.contentMinSize = NSMakeSize(68, _window.contentView.frame.size.height - _window.contentLayoutRect.size.height); - - _graph_view_controller = [controller initWithGraph:this]; - _graph_view = ((MacStatsGraphViewController *)_graph_view_controller).graphView; - - // Get notified when the window closes. - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:_graph_view_controller - selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification - object:_window]; -} - -/** - * - */ -MacStatsGraph:: -~MacStatsGraph() { - if (_animation_timer != nil) { - [_animation_timer invalidate]; - [_animation_timer release]; - _animation_timer = nil; - } - - _monitor = nullptr; - release_bitmap(); - - _label_stack.clear_labels(); - - [_graph_view_controller release]; - [_window release]; - - CGColorRelease(_background_color); -} - -/** - * - */ -void MacStatsGraph:: -close() { - [_window close]; -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void MacStatsGraph:: -new_collector(int new_collector) { -} - -/** - * Called whenever new data arrives. - */ -void MacStatsGraph:: -new_data(int thread_index, int frame_number) { -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void MacStatsGraph:: -changed_graph_size(int graph_xsize, int graph_ysize) { -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void MacStatsGraph:: -set_time_units(int unit_mask) { -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speed for the graph to the indicated value. - */ -void MacStatsGraph:: -set_scroll_speed(double scroll_speed) { -} - -/** - * Changes the pause flag for the graph. When this flag is true, the graph - * does not update in response to new data. - */ -void MacStatsGraph:: -set_pause(bool pause) { - _pause = pause; -} - -/** - * Called when the user guide bars have been changed. - */ -void MacStatsGraph:: -user_guide_bars_changed() { - if (_scale_area != nullptr) { - _scale_area.needsDisplay = YES; - } - _graph_view.needsDisplay = YES; -} - -/** - * Called when the user single-clicks on a label. - */ -void MacStatsGraph:: -on_click_label(int collector_index) { -} - -/** - * Called when the user hovers the mouse over a label. - */ -void MacStatsGraph:: -on_enter_label(int collector_index) { - if (collector_index != _highlighted_index) { - _highlighted_index = collector_index; - force_redraw(); - } -} - -/** - * Called when the user's mouse cursor leaves a label. - */ -void MacStatsGraph:: -on_leave_label(int collector_index) { - if (collector_index == _highlighted_index && collector_index != -1) { - _highlighted_index = -1; - force_redraw(); - } -} - -/** - * Called when the mouse right-clicks on a label, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsGraph:: -get_label_menu(int collector_index) const { - return nil; -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsGraph:: -get_label_tooltip(int collector_index) const { - return std::string(); -} - -/** - * Turns on the animation timer, if it hasn't already been turned on. - */ -void MacStatsGraph:: -start_animation() { - if (_animation_timer != nil) { - return; - } - - _time = 0.0; - _animation_timer = [NSTimer scheduledTimerWithTimeInterval:1 / 60.0 target:_graph_view selector:@selector(handleTimer:) userInfo:nil repeats:YES]; - [_animation_timer retain]; -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool MacStatsGraph:: -animate(double time, double dt) { - return false; -} - -/** - * Returns the current window dimensions. - */ -void MacStatsGraph:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - - NSRect screen_frame = _window.screen.visibleFrame; - - NSRect frame = _window.frame; - x = frame.origin.x - screen_frame.origin.x; - y = (screen_frame.origin.y + screen_frame.size.height) - (frame.origin.y + frame.size.height); - width = frame.size.width; - height = frame.size.height; - maximized = _window.zoomed; - minimized = _window.miniaturized; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void MacStatsGraph:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - - NSRect screen_frame = _window.screen.visibleFrame; - - NSRect frame; - frame.origin.x = screen_frame.origin.x + x; - frame.origin.y = (screen_frame.origin.y + screen_frame.size.height) - (y + height); - frame.size.width = width; - frame.size.height = height; - [_window setFrame:frame display:NO]; - - if (maximized != _window.zoomed) { - [_window zoom:_window]; - } - - if (minimized != _window.miniaturized) { - if (minimized) { - [_window miniaturize:_window]; - } else { - [_window deminiaturize:_window]; - } - } -} - -/** - * Called when the given collector has changed colors. - */ -void MacStatsGraph:: -reset_collector_color(int collector_index) { - force_redraw(); - _label_stack.update_label_color(collector_index); -} - -/** - * Called when the mouse right-clicks on the graph, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsGraph:: -get_graph_menu(int mouse_x, int mouse_y) const { - return nil; -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsGraph:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return std::string(); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -MacStatsGraph::DragMode MacStatsGraph:: -consider_drag_start(int graph_x, int graph_y) { - return DM_none; -} - -/** - * This should be called whenever the drag mode needs to change state. It - * provides hooks for a derived class to do something special. - */ -void MacStatsGraph:: -set_drag_mode(MacStatsGraph::DragMode drag_mode) { - _drag_mode = drag_mode; -} - -/** - * - */ -bool MacStatsGraph:: -handle_key(int graph_x, int graph_y, bool pressed, UniChar c, unsigned short key_code) { - return false; -} - -/** - * Called when the mouse button is depressed within the window, or any nested - * window. - */ -void MacStatsGraph:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (_potential_drag_mode != DM_none && button == 1) { - set_drag_mode(_potential_drag_mode); - _drag_start_x = graph_x; - _drag_start_y = graph_y; - // SetCapture(_window); - } -} - -/** - * Called when the mouse button is released within the window, or any nested - * window. - */ -void MacStatsGraph:: -handle_button_release(int graph_x, int graph_y) { - set_drag_mode(DM_none); - // ReleaseCapture(); - - return handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the window, or any nested window. - */ -void MacStatsGraph:: -handle_motion(int graph_x, int graph_y) { - _potential_drag_mode = consider_drag_start(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -void MacStatsGraph:: -handle_leave() { -} - -/** - * Called when the mouse is moved within the graph window. - */ -void MacStatsGraph:: -handle_scroll() { - force_redraw(); -} - -/** - * - */ -void MacStatsGraph:: -handle_wheel(int graph_x, int graph_y, double dx, double dy) { -} - -/** - * - */ -void MacStatsGraph:: -handle_magnify(int graph_x, int graph_y, double scale) { -} - -/** - * - */ -void MacStatsGraph:: -handle_timer() { - _time += 1.0 / 60.0; - - if (!animate(_time, 1.0 / 60.0)) { - [_animation_timer invalidate]; - [_animation_timer release]; - _animation_timer = nil; - } -} - -/** - * Fills in the graph window. - */ -void MacStatsGraph:: -handle_draw_graph(CGContextRef ctx, NSRect rect) { - CGContextSetBlendMode(ctx, kCGBlendModeCopy); - CGContextSetInterpolationQuality(ctx, kCGInterpolationNone); - - // Quantize this so that changed_graph_size will always call force_redraw() - NSRect full_rect = _graph_view.bounds; - full_rect.size.width = (int)full_rect.size.width; - full_rect.size.height = (int)full_rect.size.height; - - CGSize size = CGContextConvertSizeToDeviceSpace(ctx, full_rect.size); - int width = abs((int)size.width); - int height = abs((int)size.height); - - if (_ctx == nullptr || _bitmap_xsize != width || _bitmap_ysize != height) { - if (_ctx == nullptr && _scale_area != nullptr) { - _scale_area.needsDisplay = YES; - } - setup_bitmap(width, height, _window.backingScaleFactor); - - changed_graph_size(full_rect.size.width, full_rect.size.height); - } - - CGImageRef image = CGBitmapContextCreateImage(_ctx); - CGContextDrawImage(ctx, CGRectMake(0, 0, full_rect.size.width, full_rect.size.height), image); - CGImageRelease(image); -} - -/** - * Fills in the graph window overhang, which is the area outside the graph - * bounds that may become visible momentarily due to scroll elasticity. - */ -void MacStatsGraph:: -handle_draw_graph_overhang(CGContextRef ctx, NSRect rect) { -} - -/** - * Fills in the scale area. - */ -void MacStatsGraph:: -handle_draw_scale_area(CGContextRef ctx, NSRect rect) { -} - -/** - * Called when the mouse clicks the back button in the toolbar. - */ -void MacStatsGraph:: -handle_back() { -} - -/** - * Sets up a backing-store bitmap of the indicated size. - */ -void MacStatsGraph:: -setup_bitmap(int xsize, int ysize, double scale) { - release_bitmap(); - - _bitmap_xsize = xsize; - _bitmap_ysize = ysize; - - // Ostensibly, a layer context is more efficient, but I tried it and the - // performance was horrible compared to a bitmap context. - _ctx = CGBitmapContextCreate(nullptr, xsize, ysize, 8, 0, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), kCGImageAlphaPremultipliedLast); - CGContextSetBlendMode(_ctx, kCGBlendModeCopy); - CGContextScaleCTM(_ctx, scale, scale); -} - -/** - * Frees the backing-store bitmap created by setup_bitmap(). - */ -void MacStatsGraph:: -release_bitmap() { - if (_ctx != nullptr) { - CGContextRelease(_ctx); - _ctx = nullptr; - } -} diff --git a/pandatool/src/mac-stats/macStatsGraphView.h b/pandatool/src/mac-stats/macStatsGraphView.h deleted file mode 100644 index efd0d0c6..00000000 --- a/pandatool/src/mac-stats/macStatsGraphView.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsGraphView.h - * @author rdb - * @date 2023-08-18 - */ - -#ifndef MACSTATSGRAPHVIEW_H -#define MACSTATSGRAPHVIEW_H - -#include "cocoa_compat.h" - -class MacStatsGraph; - -@interface MacStatsGraphView : NSView { - @public - MacStatsGraph *_graph; -} - -- (id)initWithGraph:(MacStatsGraph *)graph; -- (void)drawRect:(NSRect)dirtyRect; - -@end - -#endif diff --git a/pandatool/src/mac-stats/macStatsGraphView.mm b/pandatool/src/mac-stats/macStatsGraphView.mm deleted file mode 100644 index 82b2d5d8..00000000 --- a/pandatool/src/mac-stats/macStatsGraphView.mm +++ /dev/null @@ -1,156 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsGraphView.mm - * @author rdb - * @date 2023-08-18 - */ - -#include "macStatsGraphView.h" -#include "macStatsGraph.h" -#include "macStatsStripChart.h" -#include "macStatsFlameGraph.h" -#include "macStatsTimeline.h" -#include "macStatsScaleArea.h" - -@implementation MacStatsGraphView - -- (id)initWithGraph:(MacStatsGraph *)graph { - if (self = [super init]) { - _graph = graph; - - self.translatesAutoresizingMaskIntoConstraints = NO; - - NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect) owner:self userInfo:nil]; - [self addTrackingArea:area]; - [area release]; - - [self addToolTipRect:NSMakeRect(0, 0, 1000, 1000) owner:self userData:nil]; - } - - return self; -} - -- (BOOL)isFlipped { - return YES; -} - -- (BOOL)acceptsFirstResponder { - return YES; -} - -- (void)keyDown:(NSEvent *)event { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - UniChar c = 0; - NSString *str = [event charactersIgnoringModifiers]; - if (str != nil && str.length == 1) { - c = [str characterAtIndex:0]; - } - _graph->handle_key(pos.x, pos.y, true, c, event.keyCode); -} - -- (void)keyUp:(NSEvent *)event { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - UniChar c = 0; - NSString *str = [event charactersIgnoringModifiers]; - if (str != nil && str.length == 1) { - c = [str characterAtIndex:0]; - } - _graph->handle_key(pos.x, pos.y, false, c, event.keyCode); -} - -- (void)mouseDown:(NSEvent *)event { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - _graph->handle_button_press(pos.x, pos.y, event.clickCount > 1, event.buttonNumber); -} - -- (void)mouseUp:(NSEvent *)event { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - _graph->handle_button_release(pos.x, pos.y); -} - -- (void)mouseDragged:(NSEvent *)event { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - _graph->handle_motion(pos.x, pos.y); -} - -- (void)mouseMoved:(NSEvent *)event { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - _graph->handle_motion(pos.x, pos.y); -} - -- (void)mouseExited:(NSEvent *)event { - _graph->handle_leave(); -} - -- (void)scrollWheel:(NSEvent *)event { - [super scrollWheel:event]; - if (event.deltaX != 0) { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - _graph->handle_wheel(pos.x, pos.y, event.deltaX, event.deltaY); - } -} - -- (void)magnifyWithEvent:(NSEvent *)event { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - _graph->handle_magnify(pos.x, pos.y, event.magnification); -} - -- (void)handleTimer:(NSTimer *)timer { - _graph->handle_timer(); -} - -- (void)viewDidChangeEffectiveAppearance { - if (_graph != nullptr) { - // Don't call this initially - if (self.window != nil) { - [NSAppearance setCurrentAppearance:self.effectiveAppearance]; - _graph->force_redraw(); - } - } -} - -- (void)drawRect:(NSRect)dirtyRect { - if (_graph != nullptr) { - CGContextRef ctx = [NSGraphicsContext currentContext].CGContext; - _graph->handle_draw_graph(ctx, dirtyRect); - } -} - -// Not called when building with macOS 14 SDK due to change in clipsToBounds -// (but there it simply calls drawRect with the overhang region) -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 140000 -- (void)drawBackgroundOverhangInRect:(NSRect)dirtyRect { - if (_graph != nullptr) { - CGContextRef ctx = [NSGraphicsContext currentContext].CGContext; - _graph->handle_draw_graph_overhang(ctx, dirtyRect); - } -} -#endif - -- (NSMenu *)menuForEvent:(NSEvent *)event { - if (_graph != nullptr) { - NSPoint pos = [self convertPoint:event.locationInWindow fromView:nil]; - return _graph->get_graph_menu(pos.x, pos.y); - } - return nil; -} - -- (NSString *)view:(NSView *)view - stringForToolTip:(NSToolTipTag)tag - point:(NSPoint)point - userData:(void *)data { - - if (_graph != nullptr) { - std::string text = _graph->get_graph_tooltip(point.x, point.y); - return [NSString stringWithUTF8String:text.c_str()]; - } - return @""; -} - -@end diff --git a/pandatool/src/mac-stats/macStatsGraphViewController.h b/pandatool/src/mac-stats/macStatsGraphViewController.h deleted file mode 100644 index d688a656..00000000 --- a/pandatool/src/mac-stats/macStatsGraphViewController.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsGraphViewController.h - * @author rdb - * @date 2023-08-28 - */ - -#ifndef MACSTATSGRAPHVIEWCONTROLLER_H -#define MACSTATSGRAPHVIEWCONTROLLER_H - -#include "macStatsGraphView.h" - -#import - -class MacStatsGraph; - -@interface MacStatsGraphViewController : NSViewController { - @protected - MacStatsGraph *_graph; -} - -- (id)initWithGraph:(MacStatsGraph *)graph; -- (MacStatsGraphView *)graphView; -- (BOOL)backToolbarItemVisible; -- (void)setBackToolbarItemVisible:(BOOL)show; - -@end - -@interface MacStatsScrollableGraphViewController : MacStatsGraphViewController - -- (MacStatsGraphView *)graphView; -- (NSClipView *)clipView; - -@end - -#endif diff --git a/pandatool/src/mac-stats/macStatsGraphViewController.mm b/pandatool/src/mac-stats/macStatsGraphViewController.mm deleted file mode 100644 index 84f450f7..00000000 --- a/pandatool/src/mac-stats/macStatsGraphViewController.mm +++ /dev/null @@ -1,224 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsGraphViewController.mm - * @author rdb - * @date 2023-08-28 - */ - -#include "macStatsGraphViewController.h" -#include "macStatsGraph.h" -#include "macStatsMonitor.h" -#include "cocoa_compat.h" - -@implementation MacStatsGraphViewController - -- (id)initWithGraph:(MacStatsGraph *)graph { - if (self = [super init]) { - _graph = graph; - } - - return self; -} - -- (void)windowWillClose:(NSNotification *)notification { - MacStatsGraph *graph = _graph; - if (graph != nullptr) { - MacStatsMonitor *monitor = graph->get_monitor(); - if (monitor != nullptr) { - _graph = nullptr; - monitor->remove_graph(graph); - } - } -} - -- (void)loadView { - NSView *graph_view = [[MacStatsGraphView alloc] initWithGraph:_graph]; - NSView *background; - if (@available(macOS 10.14, *)) { - NSVisualEffectView *effect_view = [[NSVisualEffectView alloc] init]; - effect_view.material = (NSVisualEffectMaterial)18;//NSVisualEffectMaterialContentBackground; - background = effect_view; - } else { - background = [[NSView alloc] init]; - background.wantsLayer = YES; - background.layer.backgroundColor = [NSColor controlBackgroundColor].CGColor; - } - [background addSubview:graph_view]; - self.view = background; - - [graph_view.widthAnchor constraintEqualToAnchor:background.widthAnchor].active = YES; - [graph_view.heightAnchor constraintEqualToAnchor:background.heightAnchor].active = YES; - [graph_view release]; - [background release]; -} - -- (MacStatsGraphView *)graphView { - return (MacStatsGraphView *)self.view.subviews[0]; -} - -- (void)handleSplitViewResize:(NSNotification *)notification { - NSSplitView *split_view = (NSSplitView *)notification.object; - NSWindow *window = split_view.window; - NSToolbar *toolbar = window.toolbar; - if ([split_view isSubviewCollapsed:split_view.arrangedSubviews[0]]) { - if (toolbar.items[0].itemIdentifier != NSToolbarToggleSidebarItemIdentifier) { - [toolbar insertItemWithItemIdentifier:NSToolbarToggleSidebarItemIdentifier atIndex:0]; - } - } else { - if (toolbar.items[0].itemIdentifier == NSToolbarToggleSidebarItemIdentifier) { - [toolbar removeItemAtIndex:0]; - } - } -} - -- (BOOL)backToolbarItemVisible { - NSToolbar *toolbar = self.view.window.toolbar; - if ([toolbar.items[0].itemIdentifier isEqual:@"back"] || - [toolbar.items[1].itemIdentifier isEqual:@"back"]) { - return YES; - } else { - return NO; - } -} - -- (void)setBackToolbarItemVisible:(BOOL)show { - NSToolbar *toolbar = self.view.window.toolbar; - if ([toolbar.items[1].itemIdentifier isEqual:@"back"]) { - if (!show) { - [toolbar removeItemAtIndex:1]; - } - } - else if ([toolbar.items[0].itemIdentifier isEqual:@"back"]) { - if (!show) { - [toolbar removeItemAtIndex:0]; - } - } - else if (show) { - // Insert it after the sidebar toggle, if we have one. - int index = ([toolbar.items[0].itemIdentifier isEqual:NSToolbarToggleSidebarItemIdentifier]); - [toolbar insertItemWithItemIdentifier:@"back" atIndex:index]; - } -} - -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar { - return @[]; -} - -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar { - return @[]; -} - -- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar - itemForItemIdentifier:(NSString *)ident - willBeInsertedIntoToolbar:(BOOL)flag { - - if (@available(macOS 11.0, *)) { - if ([ident isEqual:@"sep"]) { - return [NSTrackingSeparatorToolbarItem trackingSeparatorToolbarItemWithIdentifier:@"sep" splitView:_graph->get_split_view() dividerIndex:0]; - } - - if ([ident isEqual:@"back"]) { - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:ident] autorelease]; - item.label = @"Back"; - item.image = [NSImage imageWithSystemSymbolName:@"chevron.left" accessibilityDescription:@""]; - item.target = self; - item.action = @selector(handleBack:); - [item setNavigational:YES]; - [item setBordered:YES]; - return item; - } - } - - return nil; -} - -- (void)handleSetAsFocus:(NSMenuItem *)item { - _graph->on_click_label(item.tag); -} - -- (void)handleChangeColor:(NSMenuItem *)item { - _graph->get_monitor()->choose_collector_color(item.tag); -} - -- (void)handleResetColor:(NSMenuItem *)item { - _graph->get_monitor()->reset_collector_color(item.tag); -} - -- (void)handleBack:(id)sender { - _graph->handle_back(); -} - -@end - -@implementation MacStatsScrollableGraphViewController - -- (void)loadView { - NSView *graph_view = [[MacStatsGraphView alloc] initWithGraph:_graph]; - NSScrollView *scroll = [[NSScrollView alloc] init]; - scroll.hasHorizontalScroller = NO; - scroll.hasVerticalScroller = YES; - scroll.horizontalScrollElasticity = NSScrollElasticityNone; - scroll.usesPredominantAxisScrolling = NO; - scroll.drawsBackground = YES; - scroll.scrollerStyle = NSScrollerStyleOverlay; - scroll.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - //scroll.translatesAutoresizingMaskIntoConstraints = NO; - scroll.automaticallyAdjustsContentInsets = YES; - scroll.documentView = graph_view; - self.view = scroll; - - [graph_view.widthAnchor constraintEqualToAnchor:scroll.widthAnchor].active = YES; - - if (@available(macOS 11.0, *)) { - [graph_view.heightAnchor constraintGreaterThanOrEqualToAnchor:((NSLayoutGuide *)[scroll safeAreaLayoutGuide]).heightAnchor].active = YES; - } else { - [graph_view.heightAnchor constraintGreaterThanOrEqualToAnchor:scroll.heightAnchor].active = YES; - } - - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:self - selector:@selector(handleScroll:) - name:NSScrollViewDidLiveScrollNotification - object:scroll]; - [scroll release]; - [graph_view release]; -} - -- (MacStatsGraphView *)graphView { - return (MacStatsGraphView *)((NSScrollView *)self.view).documentView; -} - -- (NSClipView *)clipView { - return ((NSScrollView *)self.view).contentView; -} - -- (void)viewDidLayout { - if (_graph != nullptr) { - _graph->handle_scroll(); - } -} - -- (void)handleScroll:(NSNotification *)notification { - if (_graph != nullptr) { - _graph->handle_scroll(); - } -} - -- (void)handleSideScroll:(NSNotification *)notification { - // Graph view is flipped, side bar isn't, so we need to convert coordinates - NSScrollView *side_sv = ((NSScrollView *)notification.object); - NSScrollView *graph_sv = (NSScrollView *)self.view; - NSPoint point; - point.x = 0; - point.y = self.graphView.frame.size.height - (side_sv.documentVisibleRect.size.height + side_sv.documentVisibleRect.origin.y) - graph_sv.contentInsets.top; - [graph_sv.contentView scrollToPoint:point]; - [graph_sv reflectScrolledClipView:graph_sv.contentView]; -} - -@end diff --git a/pandatool/src/mac-stats/macStatsLabel.h b/pandatool/src/mac-stats/macStatsLabel.h deleted file mode 100644 index 1171ba25..00000000 --- a/pandatool/src/mac-stats/macStatsLabel.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsLabel.h - * @author rdb - * @date 2023-08-18 - */ - -#ifndef MACSTATSLABEL_H -#define MACSTATSLABEL_H - -#include "pandatoolbase.h" -#include "luse.h" - -#include "cocoa_compat.h" - -class MacStatsMonitor; -class MacStatsGraph; - -/** - * A text label that will draw in color appropriate for a particular - * collector. It also responds when the user double-clicks on it. This is - * handy for putting colored labels on strip charts. - */ -@interface MacStatsLabel : NSTextField { - @private - MacStatsGraph *_graph; - int _thread_index; - int _collector_index; - bool _highlight; - bool _mouse_within; - NSColor *_fg_color; - NSColor *_highlight_fg_color; - NSColor *_bg_color; - NSColor *_highlight_bg_color; -} - -- (id)initWithText:(NSString *)text - graph:(MacStatsGraph *)graph - threadIndex:(int)thread_index - collectorIndex:(int)collector_index; - -- (int)threadIndex; -- (int)collectorIndex; - -- (void)updateColor; - -- (BOOL)highlight; -- (void)setHighlight:(BOOL)highlight; - -@end - -#endif diff --git a/pandatool/src/mac-stats/macStatsLabel.mm b/pandatool/src/mac-stats/macStatsLabel.mm deleted file mode 100644 index 3169c58f..00000000 --- a/pandatool/src/mac-stats/macStatsLabel.mm +++ /dev/null @@ -1,137 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsLabel.mm - * @author rdb - * @date 2023-08-18 - */ - -#include "macStatsLabel.h" -#include "macStatsMonitor.h" -#include "macStatsGraph.h" - -@implementation MacStatsLabel - -- (id)initWithText:(NSString *)text - graph:(MacStatsGraph *)graph - threadIndex:(int)thread_index - collectorIndex:(int)collector_index { - if (self = [super init]) { - _graph = graph; - _thread_index = thread_index; - _collector_index = collector_index; - _bg_color = nil; - _highlight_bg_color = nil; - - [self setStringValue:text]; - self.bezeled = NO; - self.drawsBackground = YES; - self.selectable = NO; - self.editable = NO; - self.lineBreakMode = NSLineBreakByTruncatingTail; - //self.autoresizingMask = NSViewWidthSizable | NSViewMaxXMargin | NSViewMinXMargin; - //self.translatesAutoresizingMaskIntoConstraints = NO; - - NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect) owner:self userInfo:nil]; - [self addTrackingArea:area]; - [area release]; - - [self addToolTipRect:NSMakeRect(0, 0, 1000, 1000) owner:self userData:nil]; - - [self updateColor]; - } - - return self; -} - -- (void)dealloc { - [_bg_color release]; - [_highlight_bg_color release]; - [super dealloc]; -} - -- (NSSize)intrinsicContentSize { - // Allow resizing down. - NSSize size = [super intrinsicContentSize]; - return NSMakeSize(NSViewNoIntrinsicMetric, size.height); -} - -- (int)threadIndex { - return _thread_index; -} - -- (int)collectorIndex { - return _collector_index; -} - -- (void)updateColor { - if (_bg_color != nil) { - [_bg_color release]; - } - if (_highlight_bg_color != nil) { - [_highlight_bg_color release]; - } - - _bg_color = [NSColor colorWithCGColor:_graph->get_monitor()->get_collector_color(_collector_index, false)]; - _highlight_bg_color = [NSColor colorWithCGColor:_graph->get_monitor()->get_collector_color(_collector_index, true)]; - - [_bg_color retain]; - [_highlight_bg_color retain]; - - _fg_color = _graph->get_monitor()->get_collector_text_color(_collector_index, false); - _highlight_fg_color = _graph->get_monitor()->get_collector_text_color(_collector_index, true); - - [self setHighlight:_highlight]; -} - -- (BOOL)highlight { - return _highlight; -} - -- (void)setHighlight:(BOOL)highlight { - _highlight = highlight; - if (highlight || _mouse_within) { - self.backgroundColor = _highlight_bg_color; - self.textColor = _highlight_fg_color; - } else { - self.backgroundColor = _bg_color; - self.textColor = _fg_color; - } -} - -- (void)mouseEntered:(NSEvent *)event { - _mouse_within = true; - self.backgroundColor = _highlight_bg_color; - self.textColor = _highlight_fg_color; -} - -- (void)mouseExited:(NSEvent *)event { - _mouse_within = false; - [self setHighlight:_highlight]; -} - -- (void)mouseDown:(NSEvent *)event { - if (event.buttonNumber == 0 && event.clickCount == 2) { - _graph->on_click_label(_collector_index); - } -} - -- (NSMenu *)menuForEvent:(NSEvent *)event { - return _graph->get_label_menu(_collector_index); -} - -- (NSString *)view:(NSView *)view - stringForToolTip:(NSToolTipTag)tag - point:(NSPoint)point - userData:(void *)data { - - std::string text = _graph->get_label_tooltip(_collector_index); - return [NSString stringWithUTF8String:text.c_str()]; -} - -@end diff --git a/pandatool/src/mac-stats/macStatsLabelStack.h b/pandatool/src/mac-stats/macStatsLabelStack.h deleted file mode 100644 index 9aabb3b2..00000000 --- a/pandatool/src/mac-stats/macStatsLabelStack.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsLabelStack.h - * @author rdb - * @date 2023-08-17 - */ - -#ifndef MACSTATSLABELSTACK_H -#define MACSTATSLABELSTACK_H - -#include "pandatoolbase.h" -#include "pvector.h" -#include "macStatsLabel.h" - -#include - -class MacStatsMonitor; -class MacStatsGraph; - -/** - * A widget that contains a stack of labels from bottom to top. - */ -class MacStatsLabelStack { -public: - MacStatsLabelStack(); - ~MacStatsLabelStack(); - - NSView *get_view() const; - - int get_label_y(int label_index, NSView *target_view) const; - int get_label_height(int label_index) const; - int get_label_collector_index(int label_index) const; - - void clear_labels(); - int add_label(MacStatsMonitor *monitor, MacStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname); - int get_num_labels() const; - - void highlight_label(int collector_index); - void update_label_color(int collector_index); - -private: - NSStackView *_stack_view; - NSLayoutConstraint *_constraint; - int _highlight_label; - - typedef pvector Labels; - Labels _labels; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsLabelStack.mm b/pandatool/src/mac-stats/macStatsLabelStack.mm deleted file mode 100644 index 6bfa9c3f..00000000 --- a/pandatool/src/mac-stats/macStatsLabelStack.mm +++ /dev/null @@ -1,174 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsLabelStack.mm - * @author rdb - * @date 2023-08-17 - */ - -#include "macStatsLabelStack.h" -#include "macStatsLabel.h" -#include "macStatsMonitor.h" - -static const NSEdgeInsets insets = {8, 8, 8, 8}; - -/** - * - */ -MacStatsLabelStack:: -MacStatsLabelStack() { - _stack_view = [[NSStackView alloc] init]; - _stack_view.edgeInsets = insets; - _stack_view.orientation = NSUserInterfaceLayoutOrientationVertical; - _stack_view.alignment = NSLayoutAttributeRight;//NSLayoutAttributeCenterX; - _stack_view.distribution = NSStackViewDistributionGravityAreas; - _stack_view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - _stack_view.translatesAutoresizingMaskIntoConstraints = NO; - _stack_view.spacing = 0; - _highlight_label = -1; - - // May never be wider than the widest label, or 68, whichever is larger - //FIXME - _constraint = [_stack_view.widthAnchor constraintLessThanOrEqualToConstant:68]; - _constraint.active = NO; - [_constraint retain]; -} - -/** - * - */ -MacStatsLabelStack:: -~MacStatsLabelStack() { - clear_labels(); - [_constraint release]; - [_stack_view release]; -} - -/** - * Returns the view for this stack. - */ -NSView *MacStatsLabelStack:: -get_view() const { - return _stack_view; -} - -/** - * Returns the y position of the indicated label's bottom edge, relative to - * the indicated target widget. - */ -int MacStatsLabelStack:: -get_label_y(int label_index, NSView *target_view) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0); - - MacStatsLabel *label = _labels[label_index]; - NSPoint pos = [target_view convertPoint:NSMakePoint(0, label.frame.size.height) fromView:label]; - return pos.y; -} - -/** - * Returns the height of the indicated label. - */ -int MacStatsLabelStack:: -get_label_height(int label_index) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0); - return _labels[label_index].frame.size.height; -} - -/** - * Returns the collector index associated with the indicated label. - */ -int MacStatsLabelStack:: -get_label_collector_index(int label_index) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), -1); - return _labels[label_index].collectorIndex; -} - -/** - * Removes the set of labels and starts a new set. - */ -void MacStatsLabelStack:: -clear_labels() { - for (MacStatsLabel *label : _labels) { - [_stack_view removeView:label]; - [label release]; - } - _labels.clear(); - - _constraint.constant = 68; - - NSRect frame = _stack_view.frame; - frame.size.width = 0; - _stack_view.frame = frame; -} - -/** - * Adds a new label to the top of the stack; returns the new label index. - */ -int MacStatsLabelStack:: -add_label(MacStatsMonitor *monitor, MacStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname) { - const PStatClientData *client_data = monitor->get_client_data(); - std::string text; - if (use_fullname) { - text = client_data->get_collector_fullname(collector_index); - } else { - text = client_data->get_collector_name(collector_index); - } - - MacStatsLabel *label = [MacStatsLabel alloc]; - [label initWithText:[NSString stringWithUTF8String:text.c_str()] - graph:graph - threadIndex:thread_index - collectorIndex:collector_index]; - - [_stack_view insertView:label atIndex:0 inGravity:NSStackViewGravityBottom]; - [label.leadingAnchor constraintEqualToAnchor:_stack_view.leadingAnchor constant:8].active = YES; - [label.trailingAnchor constraintLessThanOrEqualToAnchor:_stack_view.trailingAnchor constant:-8].active = YES; - - _constraint.constant = std::max(_constraint.constant, label.intrinsicContentSize.width); - - int label_index = (int)_labels.size(); - _labels.push_back(label); - - return label_index; -} - -/** - * Returns the number of labels in the stack. - */ -int MacStatsLabelStack:: -get_num_labels() const { - return _labels.size(); -} - -/** - * Draws a highlight around the label representing the indicated collector, - * and removes the highlight from any other label. Specify -1 to remove the - * highlight from all labels. - */ -void MacStatsLabelStack:: -highlight_label(int collector_index) { - if (_highlight_label != collector_index) { - _highlight_label = collector_index; - for (MacStatsLabel *label : _labels) { - label.highlight = (label.collectorIndex == _highlight_label); - } - } -} - -/** - * Refreshes the color of the label with the given index. - */ -void MacStatsLabelStack:: -update_label_color(int collector_index) { - for (MacStatsLabel *label : _labels) { - if (label.collectorIndex == collector_index) { - [label updateColor]; - } - } -} diff --git a/pandatool/src/mac-stats/macStatsMonitor.h b/pandatool/src/mac-stats/macStatsMonitor.h deleted file mode 100644 index 8c5d0c31..00000000 --- a/pandatool/src/mac-stats/macStatsMonitor.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsMonitor.h - * @author rdb - * @date 2023-08-17 - */ - -#ifndef MACSTATSMONITOR_H -#define MACSTATSMONITOR_H - -#include "pandatoolbase.h" - -#include "pStatMonitor.h" -#include "pointerTo.h" -#include "pset.h" -#include "pvector.h" -#include "pmap.h" - -#import - -class MacStatsGraph; -class MacStatsServer; -class MacStatsChartMenu; - -/** - * This class represents a connection to a PStatsClient and manages the data - * exchange with the client. - */ -class MacStatsMonitor : public PStatMonitor { -public: - MacStatsMonitor(MacStatsServer *server); - virtual ~MacStatsMonitor(); - - void close(); - - virtual std::string get_monitor_name(); - - virtual void initialized(); - virtual void got_hello(); - virtual void got_bad_version(int client_major, int client_minor, - int server_major, int server_minor); - virtual void new_collector(int collector_index); - virtual void new_thread(int thread_index); - virtual void new_data(int thread_index, int frame_number); - virtual void remove_thread(int thread_index); - virtual void lost_connection(); - virtual void idle(); - virtual bool has_idle(); - - virtual void user_guide_bars_changed(); - - PStatGraph *open_timeline(); - PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); - PStatGraph *open_piano_roll(int thread_index); - - CGColorRef get_collector_color(int collector_index, bool highlight = false); - NSColor *get_collector_text_color(int collector_index, bool highlight = false); - - void choose_collector_color(int collector_index); - void handle_choose_collector_color(const LRGBColor &color); - void reset_collector_color(int collector_index); - - void set_show_status_item(bool show); - void set_time_units(int unit_mask); - void set_scroll_speed(double scroll_speed); - void set_pause(bool pause); - - void add_graph(MacStatsGraph *graph); - void remove_graph(MacStatsGraph *graph); - void close_all_graphs(); - -private: - void setup_speed_menu(); - void update_status_bar(); - -private: - typedef pset Graphs; - Graphs _graphs; - - typedef pvector ChartMenus; - ChartMenus _chart_menus; - - NSUserNotification *_notification = nullptr; - NSMenu *_main_menu; - NSMenuItem *_speed_menu_item = nullptr; - NSMenuItem *_speed_menu_item_1; - NSMenuItem *_speed_menu_item_2; - NSMenuItem *_speed_menu_item_3; - NSMenuItem *_speed_menu_item_6; - NSMenuItem *_speed_menu_item_12; - NSMenuItem *_speed_menu_item_pause; - int _next_chart_index; - NSStatusItem *_frame_rate_status_item = nullptr; - double _scroll_speed; - bool _pause; - bool _have_data = false; - int _choosing_color_collector_index; - - struct ColorSet { - CGColorRef _bg[2]; - NSColor *_fg[2]; - }; - typedef pmap Colors; - Colors _colors; - - friend class MacStatsGraph; - friend class MacStatsServer; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsMonitor.mm b/pandatool/src/mac-stats/macStatsMonitor.mm deleted file mode 100644 index 57245e02..00000000 --- a/pandatool/src/mac-stats/macStatsMonitor.mm +++ /dev/null @@ -1,647 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsMonitor.mm - * @author rdb - * @date 2023-08-17 - */ - -#include "macStatsMonitor.h" -#include "macStats.h" -#include "macStatsServer.h" -#include "macStatsStripChart.h" -#include "macStatsChartMenu.h" -#include "macStatsPianoRoll.h" -#include "macStatsFlameGraph.h" -#include "macStatsTimeline.h" -#include "pStatGraph.h" -#include "pStatCollectorDef.h" - -#include "convert_srgb.h" - -/** - * - */ -MacStatsMonitor:: -MacStatsMonitor(MacStatsServer *server) : PStatMonitor(server) { - _main_menu = NSApp.mainMenu; - - // These will be filled in later when the menu is created. - _scroll_speed = 0.0; - _pause = false; - _next_chart_index = 2; - - setup_speed_menu(); - - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"ShowStatusItem"]) { - set_show_status_item(true); - } -} - -/** - * - */ -MacStatsMonitor:: -~MacStatsMonitor() { - close(); -} - -/** - * Closes all the graphs associated with this monitor. - */ -void MacStatsMonitor:: -close() { - PStatMonitor::close(); - - if (_notification != nil) { - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - [center removeDeliveredNotification:_notification]; - [_notification release]; - _notification = nil; - } - - close_all_graphs(); - - if (_speed_menu_item != nullptr) { - [_main_menu removeItem:_speed_menu_item]; - [_speed_menu_item release]; - _speed_menu_item = nullptr; - } - - for (MacStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->remove_from_menu(_main_menu); - delete chart_menu; - } - _chart_menus.clear(); - - set_show_status_item(false); - - for (auto &item : _colors) { - CGColorRelease(item.second._bg[0]); - CGColorRelease(item.second._bg[1]); - } - _colors.clear(); - - _next_chart_index = 2; -} - -/** - * Should be redefined to return a descriptive name for the type of - * PStatsMonitor this is. - */ -std::string MacStatsMonitor:: -get_monitor_name() { - return "MacStats"; -} - -/** - * Called after the monitor has been fully set up. At this time, it will have - * a valid _client_data pointer, and things like is_alive() and close() will - * be meaningful. However, we may not yet know who we're connected to - * (is_client_known() may return false), and we may not know anything about - * the threads or collectors we're about to get data on. - */ -void MacStatsMonitor:: -initialized() { -} - -/** - * Called when the "hello" message has been received from the client. At this - * time, the client's hostname and program name will be known. - */ -void MacStatsMonitor:: -got_hello() { - std::string progname = get_client_progname(); - std::string hostname = get_client_hostname(); - - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - _notification = [[NSUserNotification alloc] init]; - _notification.title = @"PStats Server"; - _notification.informativeText = [NSString - stringWithFormat:@"Connected to %s on %s", progname.c_str(), hostname.c_str()]; - - [center deliverNotification:_notification]; -} - -/** - * Like got_hello(), this is called when the "hello" message has been received - * from the client. At this time, the client's hostname and program name will - * be known. However, the client appears to be an incompatible version and - * the connection will be terminated; the monitor should issue a message to - * that effect. - */ -void MacStatsMonitor:: -got_bad_version(int client_major, int client_minor, - int server_major, int server_minor) { - std::ostringstream str; - str << "Unable to honor connection attempt from " - << get_client_progname() << " on " << get_client_hostname() - << ": unsupported PStats version " - << client_major << "." << client_minor; - - if (server_minor == 0) { - str << " (server understands version " << server_major - << "." << server_minor << " only)."; - } else { - str << " (server understands versions " << server_major - << ".0 through " << server_major << "." << server_minor << ")."; - } - - std::string message = str.str(); - - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"PStats Error"; - alert.informativeText = [NSString stringWithUTF8String:message.c_str()]; - alert.alertStyle = NSCriticalAlertStyle; - [alert runModal]; - [alert release]; -} - -/** - * Called whenever a new Collector definition is received from the client. - * Generally, the client will send all of its collectors over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Collector definitions midstream. - */ -void MacStatsMonitor:: -new_collector(int collector_index) { - for (MacStatsGraph *graph : _graphs) { - graph->new_collector(collector_index); - } -} - -/** - * Called whenever a new Thread definition is received from the client. - * Generally, the client will send all of its threads over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Thread definitions midstream. - */ -void MacStatsMonitor:: -new_thread(int thread_index) { - MacStatsChartMenu *chart_menu = new MacStatsChartMenu(this, thread_index); - chart_menu->add_to_menu(_main_menu, _next_chart_index); - ++_next_chart_index; - _chart_menus.push_back(chart_menu); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void MacStatsMonitor:: -new_data(int thread_index, int frame_number) { - PStatMonitor::new_data(thread_index, frame_number); - - for (MacStatsGraph *graph : _graphs) { - graph->new_data(thread_index, frame_number); - } - - if (!_have_data) { - open_default_graphs(); - _have_data = true; - } -} - -/** - * Called when a thread should be removed from the list of threads. - */ -void MacStatsMonitor:: -remove_thread(int thread_index) { - for (ChartMenus::iterator it = _chart_menus.begin(); it != _chart_menus.end(); ++it) { - MacStatsChartMenu *chart_menu = *it; - if (chart_menu->get_thread_index() == thread_index) { - chart_menu->remove_from_menu(_main_menu); - delete chart_menu; - _chart_menus.erase(it); - --_next_chart_index; - return; - } - } -} - -/** - * Called whenever the connection to the client has been lost. This is a - * permanent state change. The monitor should update its display to represent - * this, and may choose to close down automatically. - */ -void MacStatsMonitor:: -lost_connection() { - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - - if (_notification != nil) { - [center removeDeliveredNotification:_notification]; - [_notification release]; - } - - std::string hostname = get_client_hostname(); - - _notification = [[NSUserNotification alloc] init]; - _notification.title = @"PStats Server"; - _notification.informativeText = [NSString - stringWithFormat:@"Lost connection to %s", hostname.c_str()]; - - _notification.additionalActions = @[ - [NSUserNotificationAction actionWithIdentifier:@"new" title:@"New Session"], - [NSUserNotificationAction actionWithIdentifier:@"quit" title:@"Quit PStats"] - ]; - - [center deliverNotification:_notification]; -} - -/** - * If has_idle() returns true, this will be called periodically to allow the - * monitor to update its display or whatever it needs to do. - */ -void MacStatsMonitor:: -idle() { - // Check if any of our chart menus need updating. - for (MacStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->check_update(); - } - - // Update the frame rate label from the main thread (thread 0). - if (_frame_rate_status_item != nil) { - const PStatThreadData *thread_data = get_client_data()->get_thread_data(0); - double frame_rate = thread_data->get_frame_rate(); - if (frame_rate != 0.0f) { - _frame_rate_status_item.button.title = - [NSString stringWithFormat:@"%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate]; - } - } -} - -/** - * Should be redefined to return true if you want to redefine idle() and - * expect it to be called. - */ -bool MacStatsMonitor:: -has_idle() { - return true; -} - -/** - * Called when the user guide bars have been changed. - */ -void MacStatsMonitor:: -user_guide_bars_changed() { - for (MacStatsGraph *graph : _graphs) { - graph->user_guide_bars_changed(); - } -} - -/** - * Opens a new timeline. - */ -PStatGraph *MacStatsMonitor:: -open_timeline() { - MacStatsTimeline *graph = new MacStatsTimeline(this); - add_graph(graph); - return graph; -} - -/** - * Opens a new flame graph showing the indicated data. - */ -PStatGraph *MacStatsMonitor:: -open_flame_graph(int thread_index, int collector_index, int frame_number) { - MacStatsFlameGraph *graph = - new MacStatsFlameGraph(this, thread_index, collector_index, frame_number); - add_graph(graph); - return graph; -} - -/** - * Opens a new strip chart showing the indicated data. - */ -PStatGraph *MacStatsMonitor:: -open_strip_chart(int thread_index, int collector_index, bool show_level) { - MacStatsStripChart *graph = - new MacStatsStripChart(this, thread_index, collector_index, show_level); - add_graph(graph); - return graph; -} - -/** - * Opens a new piano roll showing the indicated data. - */ -PStatGraph *MacStatsMonitor:: -open_piano_roll(int thread_index) { - MacStatsPianoRoll *graph = new MacStatsPianoRoll(this, thread_index); - add_graph(graph); - return graph; -} - -/** - * Returns a color suitable for drawing the indicated collector. - */ -CGColorRef MacStatsMonitor:: -get_collector_color(int collector_index, bool highlight) { - Colors::iterator bi; - bi = _colors.find(collector_index); - if (bi != _colors.end()) { - return (*bi).second._bg[highlight]; - } - - LRGBColor rgb = PStatMonitor::get_collector_color(collector_index); - rgb[0] = encode_sRGB_float((float)rgb[0]); - rgb[1] = encode_sRGB_float((float)rgb[1]); - rgb[2] = encode_sRGB_float((float)rgb[2]); - - PN_stdfloat bright = rgb.dot(LRGBColor(0.2126, 0.7152, 0.0722)); - CGColorRef color = CGColorCreateGenericRGB(rgb[0], rgb[1], rgb[2], 1.0); - - rgb *= 0.75; - CGColorRef hcolor = CGColorCreateGenericRGB(rgb[0], rgb[1], rgb[2], 1.0); - - ColorSet &set = _colors[collector_index]; - set._bg[0] = color; - set._bg[1] = hcolor; - - if (bright >= 0.5) { - set._fg[0] = [NSColor blackColor]; - } else { - set._fg[0] = [NSColor whiteColor]; - } - - if (bright * 0.75 >= 0.5) { - set._fg[1] = [NSColor blackColor]; - } else { - set._fg[1] = [NSColor whiteColor]; - } - - return highlight ? hcolor : color; -} - -/** - * Returns a color suitable for drawing text on the indicated collector. - */ -NSColor *MacStatsMonitor:: -get_collector_text_color(int collector_index, bool highlight) { - get_collector_color(collector_index, false); - return _colors[collector_index]._fg[highlight]; -} - -/** - * Opens a dialog to change the given collector color. - */ -void MacStatsMonitor:: -choose_collector_color(int collector_index) { - _choosing_color_collector_index = collector_index; - - const LRGBColor &rgb = PStatMonitor::get_collector_color(collector_index); - NSColor *color = [NSColor colorWithSRGBRed:rgb[0] green:rgb[1] blue:rgb[2] alpha:1.0]; - - NSColorPanel *panel = [NSColorPanel sharedColorPanel]; - panel.target = [NSApp delegate]; - panel.action = @selector(handleChooseCollectorColor:); - panel.showsAlpha = NO; - panel.color = color; - [NSApp orderFrontColorPanel:panel]; -} - -/** - * Sets a custom color associated with the given collector. - */ -void MacStatsMonitor:: -handle_choose_collector_color(const LRGBColor &color) { - int collector_index = _choosing_color_collector_index; - - PStatMonitor::set_collector_color(collector_index, color); - - if (_colors.erase(collector_index)) { - for (MacStatsGraph *graph : _graphs) { - graph->reset_collector_color(collector_index); - } - } -} - -/** - * Resets the color of the given collector to the default. - */ -void MacStatsMonitor:: -reset_collector_color(int collector_index) { - PStatMonitor::clear_collector_color(collector_index); - - if (_colors.erase(collector_index)) { - for (MacStatsGraph *graph : _graphs) { - graph->reset_collector_color(collector_index); - } - } -} - -/** - * Enables the frame rate label on the right end of the menu bar. This is - * used as a text label to display the main thread's frame rate to the user, - * although it is implemented as a right-justified toplevel menu item that - * doesn't open to anything. - */ -void MacStatsMonitor:: -set_show_status_item(bool show) { - if (show && _frame_rate_status_item == nil) { - _frame_rate_status_item = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; - _frame_rate_status_item.button.action = @selector(handleClickStatusItem:); - [_frame_rate_status_item retain]; - - const PStatClientData *client_data = get_client_data(); - if (client_data != nullptr) { - const PStatThreadData *thread_data = client_data->get_thread_data(0); - if (thread_data != nullptr) { - double frame_rate = thread_data->get_frame_rate(); - if (frame_rate != 0.0f) { - _frame_rate_status_item.button.title = - [NSString stringWithFormat:@"%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate]; - } - } - } - } - if (!show && _frame_rate_status_item != nil) { - // Careful: for some reason, this can get called recursively. - NSStatusItem *status_item = _frame_rate_status_item; - _frame_rate_status_item = nil; - [[NSStatusBar systemStatusBar] removeStatusItem:status_item]; - [status_item release]; - status_item = nil; - } -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for all graphs to the indicated mask if - * it is a time-based graph. - */ -void MacStatsMonitor:: -set_time_units(int unit_mask) { - for (MacStatsGraph *graph : _graphs) { - graph->set_time_units(unit_mask); - } -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speeds for all graphs to the indicated value. - */ -void MacStatsMonitor:: -set_scroll_speed(double scroll_speed) { - _scroll_speed = scroll_speed; - - // First, change all of the open graphs appropriately. - for (MacStatsGraph *graph : _graphs) { - graph->set_scroll_speed(_scroll_speed); - } - - // Then, change the state of the menu items. - _speed_menu_item_1.state = (scroll_speed == 1.0); - _speed_menu_item_2.state = (scroll_speed == 2.0); - _speed_menu_item_3.state = (scroll_speed == 3.0); - _speed_menu_item_6.state = (scroll_speed == 6.0); - _speed_menu_item_12.state = (scroll_speed == 12.0); -} - -/** - * Called when the user selects a pause on or pause off option from the menu. - */ -void MacStatsMonitor:: -set_pause(bool pause) { - _pause = pause; - - // First, change all of the open graphs appropriately. - for (MacStatsGraph *graph : _graphs) { - graph->set_pause(_pause); - } - - // Then, change the state of the menu item. - _speed_menu_item_pause.state = pause; -} - -/** - * Adds the newly-created graph to the list of managed graphs. - */ -void MacStatsMonitor:: -add_graph(MacStatsGraph *graph) { - _graphs.insert(graph); - - int units = [[NSUserDefaults standardUserDefaults] integerForKey:@"TimeUnits"]; - graph->set_time_units(units); - graph->set_scroll_speed(_scroll_speed); - graph->set_pause(_pause); -} - -/** - * Deletes the indicated graph. - */ -void MacStatsMonitor:: -remove_graph(MacStatsGraph *graph) { - Graphs::iterator gi = _graphs.find(graph); - if (gi != _graphs.end()) { - _graphs.erase(gi); - delete graph; - } -} - -/** - * Asks all open graphs to close. - */ -void MacStatsMonitor:: -close_all_graphs() { - while (!_graphs.empty()) { - (*_graphs.begin())->close(); - } -} - -/** - * Creates the "Speed" pulldown menu. - */ -void MacStatsMonitor:: -setup_speed_menu() { - NSMenu *menu = [[NSMenu alloc] init]; - menu.title = @"Speed"; - menu.autoenablesItems = NO; - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSpeed:); - item.title = @"1"; - item.tag = 1; - [menu addItem:item]; - [item release]; - - _speed_menu_item_1 = item; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSpeed:); - item.title = @"2"; - item.tag = 2; - [menu addItem:item]; - [item release]; - - _speed_menu_item_2 = item; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSpeed:); - item.title = @"3"; - item.tag = 3; - item.state = NSOnState; - [menu addItem:item]; - [item release]; - - _speed_menu_item_3 = item; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSpeed:); - item.title = @"6"; - item.tag = 6; - [menu addItem:item]; - [item release]; - - _speed_menu_item_6 = item; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSpeed:); - item.title = @"12"; - item.tag = 12; - [menu addItem:item]; - [item release]; - - _speed_menu_item_12 = item; - } - - [menu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handlePause:); - item.title = @"pause"; - [menu addItem:item]; - [item release]; - - _speed_menu_item_pause = item; - } - - NSMenuItem *item = [[NSMenuItem alloc] init]; - _speed_menu_item = item; - [_main_menu addItem:item]; - [_main_menu setSubmenu:menu forItem:item]; - [menu release]; - - set_scroll_speed(3); - set_pause(false); - - ++_next_chart_index; -} diff --git a/pandatool/src/mac-stats/macStatsPianoRoll.h b/pandatool/src/mac-stats/macStatsPianoRoll.h deleted file mode 100644 index df156619..00000000 --- a/pandatool/src/mac-stats/macStatsPianoRoll.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsPianoRoll.h - * @author rdb - * @date 2023-08-19 - */ - -#ifndef MACSTATSPIANOROLL_H -#define MACSTATSPIANOROLL_H - -#include "macStatsGraph.h" -#include "pStatPianoRoll.h" -#include "macStatsChartMenuDelegate.h" - -class MacStatsMonitor; - -/** - * A window that draws a piano-roll style chart, which shows the collectors - * explicitly stopping and starting, one frame at a time. - */ -class MacStatsPianoRoll final : public PStatPianoRoll, public MacStatsGraph { -public: - MacStatsPianoRoll(MacStatsMonitor *monitor, int thread_index); - virtual ~MacStatsPianoRoll(); - - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void on_click_label(int collector_index); - virtual NSMenu *get_label_menu(int collector_index) const; - virtual std::string get_label_tooltip(int collector_index) const; - void set_horizontal_scale(double time_width); - -protected: - void clear_region(); - virtual void begin_draw(); - virtual void begin_row(int row); - virtual void draw_bar(int row, int from_x, int to_x); - virtual void end_draw(); - virtual void idle(); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual NSMenu *get_graph_menu(int mouse_x, int mouse_y) const; - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - - virtual void handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual void handle_button_release(int graph_x, int graph_y); - virtual void handle_motion(int graph_x, int graph_y); - virtual void handle_leave(); - virtual void handle_scroll(); - virtual void handle_magnify(int graph_x, int graph_y, double scale); - virtual void handle_draw_graph(CGContextRef ctx, NSRect rect); - virtual void handle_draw_graph_overhang(CGContextRef ctx, NSRect rect); - virtual void handle_draw_scale_area(CGContextRef ctx, NSRect rect); - -private: - int get_collector_under_pixel(int xpoint, int ypoint) const; - void update_labels(); - void draw_guide_bars(CGContextRef ctx, int y, int height); - void draw_guide_bar(CGContextRef ctx, const PStatGraph::GuideBar &bar, - int y, int height); - void draw_guide_labels(CGContextRef ctx); - void draw_guide_label(CGContextRef ctx, const PStatGraph::GuideBar &bar); - -private: - MacStatsChartMenuDelegate *_menu_delegate; - NSScrollView *_sidebar_scroll_view; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsPianoRoll.mm b/pandatool/src/mac-stats/macStatsPianoRoll.mm deleted file mode 100644 index fe620b7f..00000000 --- a/pandatool/src/mac-stats/macStatsPianoRoll.mm +++ /dev/null @@ -1,764 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsPianoRoll.mm - * @author rdb - * @date 2023-08-19 - */ - -#include "macStatsPianoRoll.h" -#include "macStatsMonitor.h" -#include "macStatsLabelStack.h" -#include "macStatsScaleArea.h" - -static const int default_piano_roll_width = 800; -static const int default_piano_roll_height = 400; - -static const int minimum_piano_roll_sidebar_width = 68; -static const int default_piano_roll_sidebar_width = 200; - -/** - * - */ -MacStatsPianoRoll:: -MacStatsPianoRoll(MacStatsMonitor *monitor, int thread_index) : - PStatPianoRoll(monitor, thread_index, 0, 0), - MacStatsGraph(monitor, [MacStatsScrollableGraphViewController alloc]) -{ - // Used for popup menus. - _menu_delegate = [[MacStatsChartMenuDelegate alloc] initWithMonitor:monitor threadIndex:thread_index]; - - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - const PStatClientData *client_data = - MacStatsGraph::_monitor->get_client_data(); - std::string thread_name = client_data->get_thread_name(_thread_index); - std::string window_title = thread_name + " thread piano roll"; - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - - if (@available(macOS 11.0, *)) { - _window.titleVisibility = NSWindowTitleHidden; - } - - // Set the initial size of the graph. - _graph_view.frame = NSMakeRect(0, 0, default_piano_roll_width, default_piano_roll_height); - _graph_view_controller.view.frame = NSMakeRect(0, 0, default_piano_roll_width, default_piano_roll_height); - - // It's put inside a scroll view that tracks the main scroll view. - NSScrollView *scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, default_piano_roll_sidebar_width, 0)]; - scroll_view.documentView = _label_stack.get_view(); - scroll_view.drawsBackground = NO; - scroll_view.automaticallyAdjustsContentInsets = YES; - //scroll_view.translatesAutoresizingMaskIntoConstraints = NO; - scroll_view.hasHorizontalScroller = NO; - scroll_view.hasVerticalScroller = NO; - _sidebar_scroll_view = scroll_view; - - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:_graph_view_controller - selector:@selector(handleSideScroll:) - name:NSScrollViewDidLiveScrollNotification - object:scroll_view]; - - NSViewController *sidebar_controller = [[NSViewController alloc] init]; - sidebar_controller.view = scroll_view; - - NSSplitViewController *svc = [[NSSplitViewController alloc] init]; - [svc addSplitViewItem:[NSSplitViewItem sidebarWithViewController:sidebar_controller]]; - [svc addSplitViewItem:[NSSplitViewItem splitViewItemWithViewController:_graph_view_controller]]; - - svc.splitViewItems[0].minimumThickness = minimum_piano_roll_sidebar_width; - svc.splitViewItems[0].canCollapse = NO; - - NSSplitView *split_view = svc.splitView; - split_view.vertical = YES; - split_view.dividerStyle = NSSplitViewDividerStyleThin; - split_view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - _split_view = split_view; - - _window.contentViewController = svc; - - [svc release]; - [sidebar_controller release]; - - // Scale area goes on top, as a titlebar accessory view. - MacStatsScaleAreaController *scale_area_controller = [[MacStatsScaleAreaController alloc] initWithGraph:this]; - scale_area_controller.fullScreenMinHeight = 20; - scale_area_controller.layoutAttribute = NSLayoutAttributeRight; - _scale_area = scale_area_controller.view; - [_window addTitlebarAccessoryViewController:scale_area_controller]; - [scale_area_controller release]; - - [_label_stack.get_view().widthAnchor constraintEqualToAnchor:scroll_view.widthAnchor].active = YES; - [_label_stack.get_view().heightAnchor constraintEqualToAnchor:_graph_view.heightAnchor].active = YES; - - idle(); - - [_window makeKeyAndOrderFront:nil]; -} - -/** - * - */ -MacStatsPianoRoll:: -~MacStatsPianoRoll() { - [_sidebar_scroll_view release]; - [_menu_delegate release]; -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void MacStatsPianoRoll:: -new_data(int thread_index, int frame_number) { - if (!_pause) { - update(); - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void MacStatsPianoRoll:: -force_redraw() { - if (_ctx) { - PStatPianoRoll::force_redraw(); - } -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void MacStatsPianoRoll:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatPianoRoll::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void MacStatsPianoRoll:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void MacStatsPianoRoll:: -on_click_label(int collector_index) { - if (collector_index >= 0) { - MacStatsGraph::_monitor->open_strip_chart(_thread_index, collector_index, false); - } -} - -/** - * Called when the mouse right-clicks on a label, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsPianoRoll:: -get_label_menu(int collector_index) const { - NSMenu *menu = [[[NSMenu alloc] init] autorelease]; - - std::string label = get_label_tooltip(collector_index); - if (!label.empty()) { - if (@available(macOS 14.0, *)) { - [menu addItem:[NSMenuItem sectionHeaderWithTitle:[NSString stringWithUTF8String:label.c_str()]]]; - } else { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithUTF8String:label.c_str()] action:nil keyEquivalent:@""]; - item.enabled = NO; - [menu addItem:item]; - [item release]; - } - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Strip Chart" action:@selector(handleOpenStripChart:) keyEquivalent:@""]; - item.target = _menu_delegate; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Flame Graph" action:@selector(handleOpenFlameGraph:) keyEquivalent:@""]; - item.target = _menu_delegate; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - [menu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Change Color\u2026" action:@selector(handleChangeColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Reset Color" action:@selector(handleResetColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - return menu; -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsPianoRoll:: -get_label_tooltip(int collector_index) const { - return PStatPianoRoll::get_label_tooltip(collector_index); -} - -/** - * Changes the amount of time the width of the horizontal axis represents. - * This may force a redraw. - */ -void MacStatsPianoRoll:: -set_horizontal_scale(double time_width) { - PStatPianoRoll::set_horizontal_scale(time_width); - - _graph_view.needsDisplay = YES; -} - -/** - * Erases the chart area. - */ -void MacStatsPianoRoll:: -clear_region() { - if (_ctx) { - CGContextSetFillColorWithColor(_ctx, _background_color); - CGContextFillRect(_ctx, CGRectMake(0, 0, get_xsize(), get_ysize())); - } -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void MacStatsPianoRoll:: -begin_draw() { - clear_region(); - - // Draw in the guide bars. - CGContextSetStrokeColorWithColor(_ctx, [NSColor gridColor].CGColor); - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; ++i) { - draw_guide_bar(_ctx, get_guide_bar(i), 0, get_ysize()); - } -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any one row of bars. These bars correspond to the collector whose - * index is get_row_collector(row), and in the color get_row_color(row). - */ -void MacStatsPianoRoll:: -begin_row(int row) { - int collector_index = get_label_collector(row); - bool is_highlighted = collector_index == _highlighted_index; - CGContextSetFillColorWithColor(_ctx, - MacStatsGraph::_monitor->get_collector_color(collector_index, is_highlighted)); -} - -/** - * Draws a single bar on the chart. - */ -void MacStatsPianoRoll:: -draw_bar(int row, int from_x, int to_x) { - if (row >= 0 && row < _label_stack.get_num_labels()) { - int y = _label_stack.get_label_y(row, _graph_view); - int height = _label_stack.get_label_height(row); - - CGContextFillRect(_ctx, CGRectMake(from_x, (y - height + 2), to_x - from_x, (height - 4))); - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void MacStatsPianoRoll:: -end_draw() { - _graph_view.needsDisplay = YES; - - if (_guide_bars_changed) { - _scale_area.needsDisplay = YES; - _guide_bars_changed = false; - } -} - -/** - * Called at the end of the draw cycle. - */ -void MacStatsPianoRoll:: -idle() { - if (_labels_changed) { - update_labels(); - } -} - -/** - * Returns the current window dimensions. - */ -bool MacStatsPianoRoll:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - MacStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void MacStatsPianoRoll:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - MacStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * Called when the mouse right-clicks on the graph, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsPianoRoll:: -get_graph_menu(int mouse_x, int mouse_y) const { - int collector_index = get_collector_under_pixel(mouse_x, mouse_y); - if (collector_index >= 0) { - return get_label_menu(collector_index); - } - return nil; -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsPianoRoll:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - int collector_index = get_collector_under_pixel(mouse_x, mouse_y); - if (collector_index >= 0) { - return get_label_tooltip(collector_index); - } - return std::string(); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -MacStatsGraph::DragMode MacStatsPianoRoll:: -consider_drag_start(int graph_x, int graph_y) { - if (graph_y >= 0 && graph_y < get_ysize()) { - if (graph_x >= 0 && graph_x < get_xsize()) { - // See if the mouse is over a user-defined guide bar. - int x = graph_x; - double from_height = pixel_to_height(x - 2); - double to_height = pixel_to_height(x + 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else { - // The mouse is left or right of the graph; maybe create a new guide - // bar. - return DM_new_guide_bar; - } - } - - return MacStatsGraph::consider_drag_start(graph_x, graph_y); -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -void MacStatsPianoRoll:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - if (double_click && button == 1) { - // Double-clicking on a color bar in the graph is the same as double- - // clicking on the corresponding label. - on_click_label(get_collector_under_pixel(graph_x, graph_y)); - return; - } - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - _drag_scale_start = pixel_to_height(graph_x); - // SetCapture(_graph_window); - return; - - } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - _drag_start_x = graph_x; - // SetCapture(_graph_window); - return; - } - - return MacStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -void MacStatsPianoRoll:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_x < 0 || graph_x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return MacStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -void MacStatsPianoRoll:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { - // When the mouse is over a color bar, highlight it. - int collector_index = get_collector_under_pixel(graph_x, graph_y); - _label_stack.highlight_label(collector_index); - on_enter_label(collector_index); - - /* - // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph - // window. - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - _graph_window, - 0 - }; - TrackMouseEvent(&tme); - */ - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_scale) { - double ratio = (double)graph_x / (double)get_xsize(); - if (ratio > 0.0f) { - set_horizontal_scale(_drag_scale_start / ratio); - } - return; - } - else if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - if (graph_x >= 0 && graph_x < get_xsize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_x)); - return; - } - - } else if (_drag_mode == DM_guide_bar) { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - return; - } - - return MacStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -void MacStatsPianoRoll:: -handle_leave() { - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); -} - -/** - * Called when the mouse is moved within the graph window. - */ -void MacStatsPianoRoll:: -handle_scroll() { - // Graph view is flipped, side bar isn't, so we need to convert coordinates - NSPoint point; - point.x = 0; - point.y = _graph_view.frame.size.height - (((NSScrollView *)_graph_view_controller.view).documentVisibleRect.size.height + ((NSScrollView *)_graph_view_controller.view).documentVisibleRect.origin.y); - [_sidebar_scroll_view.contentView scrollToPoint:point]; - [_sidebar_scroll_view reflectScrolledClipView:_sidebar_scroll_view.contentView]; -} - -/** - * - */ -void MacStatsPianoRoll:: -handle_magnify(int graph_x, int graph_y, double scale) { - set_horizontal_scale(get_horizontal_scale() * (1.0 - scale)); -} - -/** - * Fills in the graph window. - */ -void MacStatsPianoRoll:: -handle_draw_graph(CGContextRef ctx, NSRect rect) { -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 140000 - draw_guide_bars(ctx, rect.origin.y, rect.size.height); -#endif - - // Copy the drawn bars into the graph. - MacStatsGraph::handle_draw_graph(ctx, rect); - - // Draw the scale area. -/* - CGContextSetRGBStrokeColor(ctx, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2], 1.0); - CGContextSetStrokeColor(ctx, rgb_dark_gray); - CGContextBeginPath(ctx); - CGContextMoveToPoint(ctx, 0, header_height); - CGContextAddLineToPoint(ctx, get_xsize(), header_height); - CGContextStrokePath(ctx);*/ - - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; ++i) { - draw_guide_bar(ctx, get_user_guide_bar(i), rect.origin.y, rect.size.height); - } - - NSRect scale_frame = _scale_area.frame; - NSRect graph_frame = _graph_view.frame; - if (scale_frame.size.width != graph_frame.size.width) { - scale_frame.size.width = graph_frame.size.width; - _scale_area.frame = scale_frame; - } -} - -/** - * Fills in the graph window overhang, which is the area outside the graph - * bounds that may become visible momentarily due to scroll elasticity. - */ -void MacStatsPianoRoll:: -handle_draw_graph_overhang(CGContextRef ctx, NSRect rect) { - CGContextSetFillColorWithColor(ctx, _background_color); - CGContextFillRect(ctx, rect); - - draw_guide_bars(ctx, rect.origin.y, rect.size.height); -} - -/** - * Fills in the scale area. - */ -void MacStatsPianoRoll:: -handle_draw_scale_area(CGContextRef ctx, NSRect rect) { -/* - CGContextSetRGBStrokeColor(ctx, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2], 1.0); - CGContextSetStrokeColor(ctx, rgb_dark_gray); - CGContextBeginPath(ctx); - CGContextMoveToPoint(ctx, 0, header_height); - CGContextAddLineToPoint(ctx, get_xsize(), header_height); - CGContextStrokePath(ctx);*/ - - draw_guide_bars(ctx, rect.origin.y, rect.size.height); - draw_guide_labels(ctx); -} - -/** - * Returns the collector index associated with the indicated vertical row, or - * -1. - */ -int MacStatsPianoRoll:: -get_collector_under_pixel(int xpoint, int ypoint) const { - if (_label_stack.get_num_labels() == 0) { - return -1; - } - - // Assume all of the labels are the same height. - int origin = _label_stack.get_label_y(0, _graph_view); - int height = _label_stack.get_label_height(0); - int row = (origin - ypoint) / height; - if (row >= 0 && row < _label_stack.get_num_labels()) { - return _label_stack.get_label_collector_index(row); - } else { - return -1; - } -} - -/** - * Resets the list of labels. - */ -void MacStatsPianoRoll:: -update_labels() { - _label_stack.clear_labels(); - for (int i = 0; i < get_num_labels(); ++i) { - _label_stack.add_label(MacStatsGraph::_monitor, this, - _thread_index, - get_label_collector(i), true); - } - _labels_changed = false; -} - -/** - * - */ -void MacStatsPianoRoll:: -draw_guide_bars(CGContextRef ctx, int y, int height) { - CGContextSetStrokeColorWithColor(ctx, [NSColor gridColor].CGColor); - - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; ++i) { - draw_guide_bar(ctx, get_guide_bar(i), y, height); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; ++i) { - draw_guide_bar(ctx, get_user_guide_bar(i), y, height); - } -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void MacStatsPianoRoll:: -draw_guide_bar(CGContextRef ctx, const PStatGraph::GuideBar &bar, - int y, int height) { - int x = height_to_pixel(bar._height); - - if (x > 0 && x < get_xsize() - 1) { - // Only draw it if it's not too close to the top. - /*switch (bar._style) { - case GBS_target: - CGContextSetRGBStrokeColor(ctx, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2], 1.0); - break; - - case GBS_user: - CGContextSetRGBStrokeColor(ctx, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2], 1.0); - break; - - default: - CGContextSetRGBStrokeColor(ctx, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2], 1.0); - break; - }*/ - CGContextBeginPath(ctx); - CGContextMoveToPoint(ctx, x, y); - CGContextAddLineToPoint(ctx, x, y + height); - CGContextStrokePath(ctx); - } -} - -/** - * This is called during the servicing of the draw event. - */ -void MacStatsPianoRoll:: -draw_guide_labels(CGContextRef ctx) { - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; ++i) { - draw_guide_label(ctx, get_guide_bar(i)); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; ++i) { - draw_guide_label(ctx, get_user_guide_bar(i)); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void MacStatsPianoRoll:: -draw_guide_label(CGContextRef ctx, const PStatGraph::GuideBar &bar) { - NSColor *color; - if (@available(macOS 11.0, *)) { - color = [NSColor tertiaryLabelColor]; - } else { - // Otherwise it's hard to see on the dark titlebars - color = [NSColor windowFrameTextColor]; - } - /* - switch (bar._style) { - case GBS_target: - color = [NSColor colorWithDeviceRed:rgb_light_gray[0] green:rgb_light_gray[1] blue:rgb_light_gray[2] alpha:1.0]; - break; - - case GBS_user: - color = [NSColor colorWithDeviceRed:rgb_user_guide_bar[0] green:rgb_user_guide_bar[1] blue:rgb_user_guide_bar[2] alpha:1.0]; - break; - - default: - color = [NSColor colorWithDeviceRed:rgb_dark_gray[0] green:rgb_dark_gray[1] blue:rgb_dark_gray[2] alpha:1.0]; - break; - }*/ - - int x = height_to_pixel(bar._height); - const std::string &label = bar._label; - - const CFStringRef keys[] = { - (__bridge CFStringRef)NSForegroundColorAttributeName, - (__bridge CFStringRef)NSFontAttributeName, - }; - const void *values[] = { - color, - [NSFont systemFontOfSize:0.0], - }; - CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, label.c_str(), kCFStringEncodingUTF8); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - CFRelease(attribs); - CFRelease(str); - - CTLineRef line = CTLineCreateWithAttributedString(astr); - CFRelease(astr); - CGRect bounds = CTLineGetImageBounds(line, ctx); - int width = bounds.size.width; - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(x - width); - double to_height = pixel_to_height(x + width); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - CFRelease(line); - return; - } - } - - if (x >= 0 && x < get_xsize()) { - CGContextSetTextPosition(ctx, x + 6, 6); - CTLineDraw(line, ctx); - } - - CFRelease(line); -} diff --git a/pandatool/src/mac-stats/macStatsScaleArea.h b/pandatool/src/mac-stats/macStatsScaleArea.h deleted file mode 100644 index cf7ae2f0..00000000 --- a/pandatool/src/mac-stats/macStatsScaleArea.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsScaleArea.h - * @author rdb - * @date 2023-08-18 - */ - -#ifndef MACSTATSSCALEAREA_H -#define MACSTATSSCALEAREA_H - -#import - -class MacStatsGraph; - -@interface MacStatsScaleArea : NSView { - @private - MacStatsGraph *_graph; -} - -- (id)initWithGraph:(MacStatsGraph *)graph frame:(NSRect)rect; -- (void)drawRect:(NSRect)dirtyRect; - -@end - -@interface MacStatsScaleAreaController : NSTitlebarAccessoryViewController { - @private - MacStatsGraph *_graph; -} - -- (id)initWithGraph:(MacStatsGraph *)graph; -- (void)loadView; - -@end - -#endif diff --git a/pandatool/src/mac-stats/macStatsScaleArea.mm b/pandatool/src/mac-stats/macStatsScaleArea.mm deleted file mode 100644 index 4502946f..00000000 --- a/pandatool/src/mac-stats/macStatsScaleArea.mm +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsScaleArea.mm - * @author rdb - * @date 2023-08-18 - */ - -#include "macStatsScaleArea.h" -#include "macStatsGraph.h" -#include "macStatsStripChart.h" - -@implementation MacStatsScaleArea - -- (id)initWithGraph:(MacStatsGraph *)graph frame:(NSRect)rect { - if (self = [super initWithFrame:rect]) { - _graph = graph; - - [self addTrackingArea:[[NSTrackingArea alloc] initWithRect:NSZeroRect options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect) owner:self userInfo:nil]]; - } - - return self; -} - -- (void)drawRect:(NSRect)dirtyRect { - _graph->handle_draw_scale_area([NSGraphicsContext currentContext].CGContext, dirtyRect); -} - -@end - -@implementation MacStatsScaleAreaController - -- (id)initWithGraph:(MacStatsGraph *)graph { - if (self = [super init]) { - _graph = graph; - } - - return self; -} - -- (void)loadView { - self.view = [[MacStatsScaleArea alloc] initWithGraph:_graph frame:NSMakeRect(0, 0, 100, 100)]; -} - -@end diff --git a/pandatool/src/mac-stats/macStatsServer.h b/pandatool/src/mac-stats/macStatsServer.h deleted file mode 100644 index 8c5ba47e..00000000 --- a/pandatool/src/mac-stats/macStatsServer.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsServer.h - * @author rdb - * @date 2023-08-17 - */ - -#ifndef MACSTATSSERVER_H -#define MACSTATSSERVER_H - -#include "pandatoolbase.h" -#include "programBase.h" -#include "pStatServer.h" -#include "macStatsMonitor.h" -#include "macStatsAppDelegate.h" - -#include - -/** - * The class that owns the main loop, waiting for client connections. - */ -class MacStatsServer : public PStatServer, public ProgramBase { -public: - MacStatsServer(); - - MacStatsMonitor *get_monitor() { return _monitor; } - - void run(int argc, char *argv[]); - -protected: - virtual bool handle_args(Args &args) override; - - virtual PStatMonitor *make_monitor(const NetAddress &address) override; - virtual void lost_connection(PStatMonitor *monitor) override; - -public: - bool new_session(); - bool open_session(const Filename &fn); - bool open_session(); - bool open_last_session(); - bool save_session(); - bool export_session(); - bool close_session(); - - void set_show_status_item(bool show); - void set_appearance(NSString *name); - void set_time_units(int unit_mask); - -private: - void create_app(); - void setup_session_menu(); - -private: - PT(MacStatsMonitor) _monitor; - - Filename _last_session; - Filename _save_filename; - - int _port = -1; - NSApplication *_app = nil; - NSUserNotification *_listening_notification = nil; - NSMenu *_main_menu = nil; - NSMenuItem *_show_status_item_menu_item = nil; - NSMenuItem *_appearance_system_menu_item = nil; - NSMenuItem *_appearance_aqua_menu_item = nil; - NSMenuItem *_appearance_dark_aqua_menu_item = nil; - NSMenuItem *_units_ms_menu_item = nil; - NSMenuItem *_units_hz_menu_item = nil; - NSMenuItem *_new_session_menu_item = nil; - NSMenuItem *_open_last_session_menu_item = nil; - NSMenuItem *_save_session_menu_item = nil; - NSMenuItem *_close_session_menu_item = nil; - NSMenuItem *_export_session_menu_item = nil; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsServer.mm b/pandatool/src/mac-stats/macStatsServer.mm deleted file mode 100644 index 8b7611fe..00000000 --- a/pandatool/src/mac-stats/macStatsServer.mm +++ /dev/null @@ -1,732 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsServer.mm - * @author rdb - * @date 2023-08-17 - */ - -#include "macStatsServer.h" -#include "macStatsMonitor.h" -#include "macStatsAppDelegate.h" -#include "pandaVersion.h" -#include "pStatGraph.h" -#include "config_pstatclient.h" - -#include - -/** - * - */ -MacStatsServer:: -MacStatsServer() : _port(pstats_port) { - set_program_brief("macOS PStats client"); - set_program_description - ("This is a GUI-based PStats server that listens on a TCP port for a " - "connection from a PStatClient in a Panda3D application. It offers " - "various graphs for showing the timing information sent by the client." - "\n\n" - "The full documentation is available online:\n " -#ifdef HAVE_PYTHON - "https://docs.panda3d.org/" PANDA_ABI_VERSION_STR "/python/optimization/pstats" -#else - "https://docs.panda3d.org/" PANDA_ABI_VERSION_STR "/cpp/optimization/pstats" -#endif - ""); - - add_option - ("p", "port", 0, - "Specify the TCP port to listen for connections on. By default, this " - "is taken from the pstats-port Config variable.", - &ProgramBase::dispatch_int, nullptr, &_port); - - add_runline("[-p 5185]"); - add_runline("session.pstats"); - - _last_session = Filename::expand_from( - "$HOME/Library/Caches/Panda3D-" PANDA_ABI_VERSION_STR "/last-session.pstats"); - _last_session.set_binary(); - - create_app(); -} - -/** - * Runs the server. - */ -void MacStatsServer:: -run(int argc, char *argv[]) { - if (parse_command_line(argc, argv, isatty(STDERR_FILENO)) == ProgramBase::EC_failure) { - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"PStats Error"; - alert.informativeText = @"Failed to parse command-line options."; - alert.alertStyle = NSCriticalAlertStyle; - [alert runModal]; - [alert release]; - return; - } - - [_app run]; -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool MacStatsServer:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - // applicationDidFinishLaunching will call new_session(). - return true; - } - else if (args.size() == 1) { - // Handled by application:openFile: - return true; - } - else { - nout << "At most one filename may be specified on the command-line.\n"; - return false; - } -} - -/** - * - */ -PStatMonitor *MacStatsServer:: -make_monitor(const NetAddress &address) { - // Enable the "New Session", "Save Session" and "Close Session" menu items. - _new_session_menu_item.enabled = YES; - _save_session_menu_item.enabled = YES; - _close_session_menu_item.enabled = YES; - _export_session_menu_item.enabled = YES; - - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - if (_listening_notification != nil) { - [center removeDeliveredNotification:_listening_notification]; - [_listening_notification release]; - _listening_notification = nil; - } - - _monitor = new MacStatsMonitor(this); - return _monitor; -} - -/** - * Called when connection has been lost. - */ -void MacStatsServer:: -lost_connection(PStatMonitor *monitor) { - if (_monitor != nullptr && !_monitor->_have_data) { - // We didn't have any data yet. Just silently restart the session. - _monitor->close(); - _monitor = nullptr; - if (new_session()) { - return; - } - } else { - // Store a backup now, in case PStats crashes or something. - _last_session.make_dir(); - if (monitor->write(_last_session)) { - nout << "Wrote to " << _last_session << "\n"; - } else { - nout << "Failed to write to " << _last_session << "\n"; - } - } - - stop_listening(); -} - -/** - * Starts a new session. - */ -bool MacStatsServer:: -new_session() { - if (!close_session()) { - return false; - } - - if (listen(_port)) { - NSUserNotification *notification = [[NSUserNotification alloc] init]; - notification.title = @"PStats Server"; - notification.informativeText = [NSString stringWithFormat:@"Waiting for client to connect on port %d\u2026", _port]; - - // Quick way to do something else if the user prefers. - notification.additionalActions = @[ - [NSUserNotificationAction actionWithIdentifier:@"open" title:@"Open Session\u2026"], - [NSUserNotificationAction actionWithIdentifier:@"openLast" title:@"Open Last Session"], - [NSUserNotificationAction actionWithIdentifier:@"quit" title:@"Quit PStats"] - ]; - - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - [center deliverNotification:notification]; - _listening_notification = notification; - - _new_session_menu_item.enabled = NO; - _save_session_menu_item.enabled = NO; - _close_session_menu_item.enabled = YES; - _export_session_menu_item.enabled = NO; - - return true; - } - - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"PStats Error"; - alert.informativeText = [NSString stringWithFormat:@"Unable to open port %d. Try specifying a different port number using pstats-port in your Config file or the -p option on the command-line.", _port]; - alert.alertStyle = NSCriticalAlertStyle; - [alert runModal]; - [alert release]; - - return false; -} - -/** - * Opens a session with the given filename. - */ -bool MacStatsServer:: -open_session(const Filename &fn) { - if (!close_session()) { - return false; - } - - MacStatsMonitor *monitor = new MacStatsMonitor(this); - if (!monitor->read(fn)) { - delete monitor; - return false; - } - - _save_filename = fn; - _new_session_menu_item.enabled = YES; - _save_session_menu_item.enabled = YES; - _close_session_menu_item.enabled = YES; - _export_session_menu_item.enabled = YES; - - _monitor = monitor; - - // If the file contained no graphs, open the default graphs. - if (monitor->_graphs.empty()) { - monitor->open_default_graphs(); - } - - return true; -} - -/** - * Offers to open an existing session. - */ -bool MacStatsServer:: -open_session() { - if (!close_session()) { - return false; - } - - NSOpenPanel *panel = [NSOpenPanel openPanel]; - panel.title = @"Open Session"; - - if ([panel runModal] == NSModalResponseOK) { - NSString *path = [[panel.URLs firstObject] path]; - Filename fn([path UTF8String]); - fn.set_binary(); - if (open_session(fn)) { - return true; - } - - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"PStats Error"; - alert.informativeText = [NSString stringWithFormat:@"Failed to load session file: %s", fn.c_str()]; - alert.alertStyle = NSCriticalAlertStyle; - [alert runModal]; - [alert release]; - } - - return false; -} - -/** - * Opens the last session, if any. - */ -bool MacStatsServer:: -open_last_session() { - if (open_session(_last_session)) { - return true; - } - - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"PStats Error"; - alert.informativeText = [NSString stringWithFormat:@"Failed to load session file: %s", _last_session.c_str()]; - alert.alertStyle = NSCriticalAlertStyle; - [alert runModal]; - [alert release]; - - return false; -} - -/** - * Offers to save the current session. - */ -bool MacStatsServer:: -save_session() { - nassertr_always(_monitor != nullptr, true); - - NSSavePanel *panel = [NSSavePanel savePanel]; - panel.title = @"Save Session"; - - if (_save_filename.empty()) { - panel.nameFieldStringValue = @"session.pstats"; - } else { - std::string dirname = _save_filename.get_dirname(); - std::string basename = _save_filename.get_basename(); - panel.nameFieldStringValue = [NSString stringWithUTF8String:basename.c_str()]; - panel.directoryURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:dirname.c_str()]]; - } - - if ([panel runModal] == NSModalResponseOK) { - NSString *path = [panel.URL path]; - Filename fn([path UTF8String]); - fn.set_binary(); - - if (!_monitor->write(fn)) { - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"PStats Error"; - alert.informativeText = [NSString stringWithFormat:@"Failed to save session file: %s", fn.c_str()]; - alert.alertStyle = NSCriticalAlertStyle; - [alert runModal]; - [alert release]; - - return false; - } - _save_filename = fn; - _monitor->get_client_data()->clear_dirty(); - return true; - } - - return false; -} - -/** - * Offers to export the current session as a JSON file. - */ -bool MacStatsServer:: -export_session() { - nassertr_always(_monitor != nullptr, true); - - NSSavePanel *panel = [NSSavePanel savePanel]; - panel.title = @"Export Session"; - panel.nameFieldStringValue = @"session.json"; - - if ([panel runModal] == NSModalResponseOK) { - NSString *path = [panel.URL path]; - Filename fn([path UTF8String]); - fn.set_binary(); - - std::ofstream stream; - if (!fn.open_write(stream)) { - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"PStats Error"; - alert.informativeText = [NSString stringWithFormat:@"Failed to open file for export: %s", fn.c_str()]; - alert.alertStyle = NSCriticalAlertStyle; - [alert runModal]; - [alert release]; - - return false; - } - - int pid = _monitor->get_client_pid(); - _monitor->get_client_data()->write_json(stream, std::max(0, pid)); - stream.close(); - return true; - } - - return false; -} - -/** - * Closes the current session. - */ -bool MacStatsServer:: -close_session() { - bool wrote_last_session = false; - - if (_monitor != nullptr) { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data != nullptr && client_data->is_dirty()) { - if (!_monitor->has_read_filename()) { - _last_session.make_dir(); - if (_monitor->write(_last_session)) { - nout << "Wrote to " << _last_session << "\n"; - wrote_last_session = true; - } - else { - nout << "Failed to write to " << _last_session << "\n"; - } - } - - // Make sure the alert goes on top. - [_app activateIgnoringOtherApps:YES]; - - NSAlert *alert = [[NSAlert alloc] init]; - alert.messageText = @"Unsaved Data"; - alert.informativeText = @"Would you like to save the currently open session?"; - [alert addButtonWithTitle:@"Save\u2026"]; - [alert addButtonWithTitle:@"Don't Save"]; - [alert addButtonWithTitle:@"Cancel"]; - int response = [alert runModal]; - [alert release]; - - if ((response != 1000 && response != 1001) || - (response == 1000 && !save_session())) { - return false; - } - } - - _monitor->close(); - _monitor = nullptr; - } - - _save_filename = Filename(); - stop_listening(); - - if (_listening_notification != nil) { - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - [center removeDeliveredNotification:_listening_notification]; - [_listening_notification release]; - _listening_notification = nil; - } - - _new_session_menu_item.enabled = YES; - if (wrote_last_session) { - _open_last_session_menu_item.enabled = YES; - } - _save_session_menu_item.enabled = NO; - _close_session_menu_item.enabled = NO; - _export_session_menu_item.enabled = NO; - return true; -} - -/** - * Enables the frame rate label on the right end of the menu bar. This is - * used as a text label to display the main thread's frame rate to the user, - * although it is implemented as a right-justified toplevel menu item that - * doesn't open to anything. - */ -void MacStatsServer:: -set_show_status_item(bool show) { - if (_monitor != nullptr) { - _monitor->set_show_status_item(show); - } - - _show_status_item_menu_item.state = show ? NSOnState : NSOffState; -} - -/** - * - */ -void MacStatsServer:: -set_appearance(NSString *name) { - if (@available(macOS 10.14, *)) { - if (name == nil || name.length == 0) { - [_app setAppearance:nil]; - _appearance_system_menu_item.state = NSOnState; - } else { - [_app setAppearance:[NSAppearance appearanceNamed:name]]; - _appearance_system_menu_item.state = NSOffState; - } - - _appearance_aqua_menu_item.state = (name != nil && [name isEqual:@"NSAppearanceNameAqua"]) ? NSOnState : NSOffState; - _appearance_dark_aqua_menu_item.state = (name != nil && [name isEqual:@"NSAppearanceNameDarkAqua"]) ? NSOnState : NSOffState; - } -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for all graphs to the indicated mask if - * it is a time-based graph. - */ -void MacStatsServer:: -set_time_units(int unit_mask) { - if (_monitor != nullptr) { - _monitor->set_time_units(unit_mask); - } - - _units_ms_menu_item.state = (unit_mask & PStatGraph::GBU_ms) ? NSOnState : NSOffState; - _units_hz_menu_item.state = (unit_mask & PStatGraph::GBU_hz) ? NSOnState : NSOffState; -} - -/** - * Creates the menu bar for this monitor. - */ -void MacStatsServer:: -create_app() { - _app = [NSApplication sharedApplication]; - - MacStatsAppDelegate *delegate = [[MacStatsAppDelegate alloc] initWithServer:this]; - [_app setDelegate:delegate]; - [_app setActivationPolicy:NSApplicationActivationPolicyRegular]; - - _main_menu = [[NSMenu alloc] init]; - - NSMenu *app_menu = [[NSMenu alloc] init]; - - NSMenu *settings_menu = [[NSMenu alloc] init]; - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleToggleSettingsBool:); - item.representedObject = @"ShowStatusItem"; - item.title = @"Show in Status Bar"; - item.state = NSOnState; - [settings_menu addItem:item]; - - _show_status_item_menu_item = item; - [item release]; - } - - NSMenu *units_menu; - if (@available(macOS 14.0, *)) { - // On Sonnoma, use a section with header. - [settings_menu addItem:[NSMenuItem separatorItem]]; - [settings_menu addItem:[NSMenuItem sectionHeaderWithTitle:@"Time Units"]]; - units_menu = settings_menu; - } else { - // On older versions, create a sub-menu. - units_menu = [[NSMenu alloc] init]; - units_menu.autoenablesItems = NO; - - NSMenuItem *units_item = [[NSMenuItem alloc] init]; - units_item.title = @"Time Units"; - - [settings_menu addItem:units_item]; - [settings_menu setSubmenu:units_menu forItem:units_item]; - [units_item release]; - [units_menu release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSettingsInteger:); - item.representedObject = @"TimeUnits"; - item.tag = PStatGraph::GBU_ms; - item.title = @"ms"; - item.state = NSOnState; - [units_menu addItem:item]; - - _units_ms_menu_item = item; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSettingsInteger:); - item.representedObject = @"TimeUnits"; - item.tag = PStatGraph::GBU_hz; - item.title = @"Hz"; - item.state = NSOffState; - [units_menu addItem:item]; - - _units_hz_menu_item = item; - [item release]; - } - - // Dark mode available from Mojave. - if (@available(macOS 10.14, *)) { - NSMenu *appearance_menu; - if (@available(macOS 14.0, *)) { - // On Sonnoma, use a section with header. - [settings_menu addItem:[NSMenuItem separatorItem]]; - [settings_menu addItem:[NSMenuItem sectionHeaderWithTitle:@"Appearance"]]; - appearance_menu = settings_menu; - } else { - // On older versions, create a sub-menu. - appearance_menu = [[NSMenu alloc] init]; - appearance_menu.autoenablesItems = NO; - - NSMenuItem *appearance_item = [[NSMenuItem alloc] init]; - appearance_item.title = @"Appearance"; - - [settings_menu addItem:appearance_item]; - [settings_menu setSubmenu:appearance_menu forItem:appearance_item]; - [appearance_item release]; - [appearance_menu release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSettingsAppearance:); - item.representedObject = @""; - item.title = @"System"; - item.state = NSOnState; - [appearance_menu addItem:item]; - _appearance_system_menu_item = item; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSettingsAppearance:); - item.representedObject = @"NSAppearanceNameAqua"; - item.title = @"Aqua"; - item.state = NSOffState; - [appearance_menu addItem:item]; - _appearance_aqua_menu_item = item; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSettingsAppearance:); - item.representedObject = @"NSAppearanceNameDarkAqua"; - item.title = @"Dark Aqua"; - item.state = NSOffState; - [appearance_menu addItem:item]; - _appearance_dark_aqua_menu_item = item; - [item release]; - } - } - - NSMenuItem *settings_item = [[NSMenuItem alloc] init]; - settings_item.title = @"Settings"; - [app_menu addItem:settings_item]; - [app_menu setSubmenu:settings_menu forItem:settings_item]; - [settings_item release]; - [settings_menu release]; - - [app_menu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(hide:); - item.keyEquivalent = @"h"; - item.title = @"Hide PStats"; - [app_menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(hideOtherApplications:); - item.keyEquivalent = @"h"; - item.keyEquivalentModifierMask |= NSAlternateKeyMask; - item.title = @"Hide Others"; - [app_menu addItem:item]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(unhideAllApplications:); - item.title = @"Show All"; - [app_menu addItem:item]; - [item release]; - } - - [app_menu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(terminate:); - item.keyEquivalent = @"q"; - item.title = @"Quit PStats"; - [app_menu addItem:item]; - [item release]; - } - - NSMenuItem *app_menu_item = [[NSMenuItem alloc] init]; - [_main_menu addItem:app_menu_item]; - [_main_menu setSubmenu:app_menu forItem:app_menu_item]; - [app_menu_item release]; - [app_menu release]; - - setup_session_menu(); - - [_app setMainMenu:_main_menu]; - [_main_menu release]; - - //[_app activateIgnoringOtherApps:YES]; - //[_app finishLaunching]; - - set_time_units(PStatGraph::GBU_ms); -} - -/** - * Creates the "Session" pulldown menu. - */ -void MacStatsServer:: -setup_session_menu() { - NSMenu *submenu = [[NSMenu alloc] init]; - submenu.title = @"Session"; - submenu.autoenablesItems = NO; - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleNewSession:); - item.keyEquivalent = @"n"; - item.title = @"New Session"; - [submenu addItem:item]; - - _new_session_menu_item = item; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleOpenSession:); - item.keyEquivalent = @"o"; - item.title = @"Open Session\u2026"; - [submenu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleOpenLastSession:); - item.title = @"Open Last Session"; - item.enabled = _last_session.exists(); - [submenu addItem:item]; - - _open_last_session_menu_item = item; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleSaveSession:); - item.keyEquivalent = @"s"; - item.title = @"Save Session\u2026"; - item.enabled = NO; - [submenu addItem:item]; - - _save_session_menu_item = item; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleCloseSession:); - item.keyEquivalent = @"w"; - item.title = @"Close Session"; - item.enabled = NO; - [submenu addItem:item]; - - _close_session_menu_item = item; - [item release]; - } - - [submenu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.action = @selector(handleExportSession:); - item.title = @"Export as JSON\u2026"; - item.enabled = NO; - [submenu addItem:item]; - - _export_session_menu_item = item; - [item release]; - } - - NSMenuItem *item = [[NSMenuItem alloc] init]; - [_main_menu addItem:item]; - [_main_menu setSubmenu:submenu forItem:item]; -} diff --git a/pandatool/src/mac-stats/macStatsStripChart.h b/pandatool/src/mac-stats/macStatsStripChart.h deleted file mode 100644 index 685a5f66..00000000 --- a/pandatool/src/mac-stats/macStatsStripChart.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsStripChart.h - * @author rdb - * @date 2023-08-18 - */ - -#ifndef MACSTATSSTRIPCHART_H -#define MACSTATSSTRIPCHART_H - -#include "macStatsGraph.h" -#include "pStatStripChart.h" -#include "macStatsChartMenuDelegate.h" - -class MacStatsMonitor; - -/** - * A window that draws a strip chart, given a view. - */ -class MacStatsStripChart final : public PStatStripChart, public MacStatsGraph { -public: - MacStatsStripChart(MacStatsMonitor *monitor, - int thread_index, int collector_index, bool show_level); - virtual ~MacStatsStripChart(); - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void set_scroll_speed(double scroll_speed); - virtual void on_click_label(int collector_index); - virtual NSMenu *get_label_menu(int collector_index) const; - virtual std::string get_label_tooltip(int collector_index) const; - void set_vertical_scale(double value_height); - void set_auto_vertical_scale(); - -protected: - virtual void update_labels(); - - virtual void clear_region(); - virtual void draw_slice(int x, int w, - const PStatStripChart::FrameData &fdata); - virtual void draw_empty(int x, int w); - virtual void draw_cursor(int x); - virtual void end_draw(int from_x, int to_x); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual NSMenu *get_graph_menu(int mouse_x, int mouse_y) const; - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - virtual void set_drag_mode(DragMode drag_mode); - - virtual void handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual void handle_button_release(int graph_x, int graph_y); - virtual void handle_motion(int graph_x, int graph_y); - virtual void handle_leave(); - virtual void handle_magnify(int graph_x, int graph_y, double scale); - virtual void handle_draw_graph(CGContextRef ctx, NSRect rect); - virtual void handle_draw_scale_area(CGContextRef ctx, NSRect rect); - virtual void handle_back(); - -private: - void draw_guide_bar(CGContextRef ctx, int from_x, int to_x, - const PStatGraph::GuideBar &bar); - void draw_guide_labels(CGContextRef ctx); - int draw_guide_label(CGContextRef ctx, const PStatGraph::GuideBar &bar, int last_y); - -private: - MacStatsChartMenuDelegate *_menu_delegate; - //NSButton *_smooth_checkbox; - //NSTextField *_total_label; - NSToolbarItem *_total_item; - - std::vector _back_stack; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsStripChart.mm b/pandatool/src/mac-stats/macStatsStripChart.mm deleted file mode 100644 index 068c41ea..00000000 --- a/pandatool/src/mac-stats/macStatsStripChart.mm +++ /dev/null @@ -1,964 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsStripChart.mm - * @author rdb - * @date 2023-08-18 - */ - -#include "macStatsStripChart.h" -#include "macStatsMonitor.h" -#include "macStatsScaleArea.h" -#include "pStatCollectorDef.h" -#include "cocoa_compat.h" - -@interface MacStatsStripChartViewController : MacStatsGraphViewController -@end - -static const int default_strip_chart_width = 400; -static const int default_strip_chart_height = 200; - -static const int minimum_strip_chart_sidebar_width = 116; -static const int default_strip_chart_sidebar_width = 116; - -/** - * - */ -MacStatsStripChart:: -MacStatsStripChart(MacStatsMonitor *monitor, int thread_index, - int collector_index, bool show_level) : - PStatStripChart(monitor, thread_index, collector_index, show_level, 0, 0), - MacStatsGraph(monitor, [MacStatsStripChartViewController alloc]) -{ - // Used for popup menus. - _menu_delegate = [[MacStatsChartMenuDelegate alloc] initWithMonitor:monitor threadIndex:thread_index]; - - // Set the initial size of the graph. - int height = default_strip_chart_height + _window.frame.size.height - _window.contentLayoutRect.size.height; - _graph_view.frame = NSMakeRect(0, 0, default_strip_chart_width, height); - _graph_view_controller.view.frame = NSMakeRect(0, 0, default_strip_chart_width, height); - - // It's put inside a scroll view that tracks the main scroll view. - NSScrollView *scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, default_strip_chart_sidebar_width, 0)]; - scroll_view.documentView = _label_stack.get_view(); - scroll_view.drawsBackground = NO; - scroll_view.automaticallyAdjustsContentInsets = YES; - scroll_view.hasHorizontalScroller = NO; - scroll_view.hasVerticalScroller = NO; - - NSViewController *sidebar_controller = [[NSViewController alloc] init]; - sidebar_controller.view = scroll_view; - - // Add a view to the right of the graph, to display all of the scale units. - // Calculate how wide it should be to display a typical label. - CGFloat width = [NSTextField labelWithString:@"999 ms"].frame.size.width + 8; - _scale_area = [[MacStatsScaleArea alloc] initWithGraph:this frame:NSMakeRect(0, 0, width, 0)]; - _scale_area.autoresizingMask = NSViewHeightSizable; - - NSViewController *scale_area_controller = [[NSViewController alloc] init]; - scale_area_controller.view = _scale_area; - - NSSplitViewController *svc = [[NSSplitViewController alloc] init]; - [svc addSplitViewItem:[NSSplitViewItem sidebarWithViewController:sidebar_controller]]; - [svc addSplitViewItem:[NSSplitViewItem splitViewItemWithViewController:_graph_view_controller]]; - [svc addSplitViewItem:[NSSplitViewItem splitViewItemWithViewController:scale_area_controller]]; - - svc.splitViewItems[0].minimumThickness = minimum_strip_chart_sidebar_width; - svc.splitViewItems[2].minimumThickness = width; - svc.splitViewItems[2].maximumThickness = width; - - NSSplitView *split_view = svc.splitView; - split_view.vertical = YES; - split_view.dividerStyle = NSSplitViewDividerStyleThin; - split_view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - _split_view = split_view; - - // When sidebar collapses, show a sidebar icon in the menu bar - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:_graph_view_controller - selector:@selector(handleSplitViewResize:) - name:NSSplitViewDidResizeSubviewsNotification - object:split_view]; - - _window.contentViewController = svc; - - _graph_view_controller.backToolbarItemVisible = NO; - - [svc release]; - [sidebar_controller release]; - - _total_item = nil; - if (@available(macOS 11.0, *)) { - NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""]; - toolbar.delegate = _graph_view_controller; - toolbar.displayMode = NSToolbarDisplayModeIconOnly; - _window.toolbar = toolbar; - [_window setToolbarStyle:NSWindowToolbarStyleUnifiedCompact]; - - for (NSToolbarItem *item in toolbar.items) { - if ([item.itemIdentifier isEqual:@"total"]) { - _total_item = item; - break; - } - } - [toolbar release]; - } - - /*{ - _smooth_checkbox = [NSButton checkboxWithTitle:@"Smooth" - target:_graph_view_controller - action:@selector(handleToggleAverageMode:)]; - - NSStackView *stack_view = [NSStackView stackViewWithViews:@[_smooth_checkbox]]; - stack_view.translatesAutoresizingMaskIntoConstraints = NO; - - NSTitlebarAccessoryViewController *accessory_controller = [[NSTitlebarAccessoryViewController alloc] init]; - //accessory_controller.layoutAttribute = NSLayoutAttributeLeft; - [accessory_controller.view addSubview:stack_view]; - //accessory_controller.automaticallyAdjustsSize = NO; - [_window addTitlebarAccessoryViewController:accessory_controller]; - [accessory_controller release]; - - [stack_view.leftAnchor constraintEqualToAnchor:_graph_view.leftAnchor constant:8].active = YES; - [stack_view.bottomAnchor constraintEqualToAnchor:((NSLayoutGuide *)_window.contentLayoutGuide).topAnchor constant:-8].active = YES; - //[stack_view.topAnchor constraintEqualToAnchor:svc.view.topAnchor constant:-8].active = YES; - }*/ - /*{ - _total_label = [NSTextField labelWithString:@""]; - - NSStackView *stack_view = [NSStackView stackViewWithViews:@[_total_label]]; - stack_view.translatesAutoresizingMaskIntoConstraints = NO; - - NSTitlebarAccessoryViewController *accessory_controller = [[NSTitlebarAccessoryViewController alloc] init]; - accessory_controller.layoutAttribute = NSLayoutAttributeRight; - [accessory_controller.view addSubview:stack_view]; - //accessory_controller.automaticallyAdjustsSize = NO; - [_window addTitlebarAccessoryViewController:accessory_controller]; - [accessory_controller release]; - - [stack_view.rightAnchor constraintEqualToAnchor:_graph_view.rightAnchor].active = YES; - [stack_view.bottomAnchor constraintEqualToAnchor:((NSLayoutGuide *)_window.contentLayoutGuide).topAnchor].active = YES; - [stack_view.topAnchor constraintEqualToAnchor:svc.view.topAnchor].active = YES; - }*/ - - if (show_level) { - // If it's a level-type graph, show the appropriate units. - if (_unit_name.empty()) { - set_guide_bar_units(GBU_named); - } else { - set_guide_bar_units(GBU_named | GBU_show_units); - } - } else { - // If it's a time-type graph, show the ms / Hz units. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - } - - [_label_stack.get_view().widthAnchor constraintEqualToAnchor:scroll_view.widthAnchor].active = YES; - - // Update window title and total label. - new_data(0, 0); - - [_window makeKeyAndOrderFront:nil]; -} - -/** - * - */ -MacStatsStripChart:: -~MacStatsStripChart() { - [_menu_delegate release]; -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void MacStatsStripChart:: -new_collector(int collector_index) { - MacStatsGraph::new_collector(collector_index); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void MacStatsStripChart:: -new_data(int thread_index, int frame_number) { - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - _window.title = [NSString stringWithUTF8String:window_title.c_str()]; - } - } - - if (!_pause) { - update(); - - if (@available(macOS 10.15, *)) { - std::string text = get_total_text(); - [_total_item setTitle:[NSString stringWithUTF8String:text.c_str()]]; - } - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void MacStatsStripChart:: -force_redraw() { - if (_ctx) { - PStatStripChart::force_redraw(); - } - - _scale_area.needsDisplay = YES; -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void MacStatsStripChart:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatStripChart::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void MacStatsStripChart:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - if (@available(macOS 10.15, *)) { - std::string text = get_total_text(); - [_total_item setTitle:[NSString stringWithUTF8String:text.c_str()]]; - } - - _scale_area.needsDisplay = YES; - } -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speed for the graph to the indicated value. - */ -void MacStatsStripChart:: -set_scroll_speed(double scroll_speed) { - // The speed factor indicates chart widths per minute. - if (scroll_speed != 0.0f) { - set_horizontal_scale(60.0f / scroll_speed); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void MacStatsStripChart:: -on_click_label(int collector_index) { - if (collector_index < 0) { - // Clicking on whitespace in the graph is the same as clicking on the top - // label. - collector_index = get_collector_index(); - } - - if (collector_index == get_collector_index()) { - // Clicking on the top label means to go up to the parent level. - if (collector_index != 0) { - const PStatClientData *client_data = - MacStatsGraph::_monitor->get_client_data(); - if (client_data->has_collector(collector_index)) { - const PStatCollectorDef &def = - client_data->get_collector_def(collector_index); - if (def._parent_index == 0 && get_view().get_show_level()) { - // Unless the parent is "Frame", and we're not a time collector. - } - else if (def._parent_index != get_collector_index()) { - // If we were previously at the parent, pop it from the stack. - if (!_back_stack.empty() && _back_stack.back() == def._parent_index) { - _back_stack.pop_back(); - if (_back_stack.empty()) { - _graph_view_controller.backToolbarItemVisible = NO; - } - } else { - if (_back_stack.empty()) { - _graph_view_controller.backToolbarItemVisible = YES; - } - _back_stack.push_back(get_collector_index()); - } - - set_collector_index(def._parent_index); - } - } - } - } - else { - if (_back_stack.empty()) { - _graph_view_controller.backToolbarItemVisible = YES; - } - _back_stack.push_back(get_collector_index()); - - // Clicking on any other label means to focus on that. - set_collector_index(collector_index); - } - - // Update window title and total label. - new_data(0, 0); - - _scale_area.needsDisplay = YES; -} - -/** - * Called when the mouse right-clicks on a label, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsStripChart:: -get_label_menu(int collector_index) const { - NSMenu *menu = [[[NSMenu alloc] init] autorelease]; - - std::string label = get_label_tooltip(collector_index); - if (!label.empty()) { - if (@available(macOS 14.0, *)) { - [menu addItem:[NSMenuItem sectionHeaderWithTitle:[NSString stringWithUTF8String:label.c_str()]]]; - } else { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithUTF8String:label.c_str()] action:nil keyEquivalent:@""]; - item.enabled = NO; - [menu addItem:item]; - [item release]; - } - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Set as Focus" action:@selector(handleSetAsFocus:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - item.enabled = (collector_index != 0 || get_collector_index() != 0); - [menu addItem:item]; - [item release]; - } - - { - SEL action = get_view().get_show_level() ? @selector(handleOpenStripChartLevel:) : @selector(handleOpenStripChart:); - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Strip Chart" action:action keyEquivalent:@""]; - item.target = _menu_delegate; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - if (!get_view().get_show_level()) { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Flame Graph" action:@selector(handleOpenFlameGraph:) keyEquivalent:@""]; - item.target = _menu_delegate; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - [menu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Change Color\u2026" action:@selector(handleChangeColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Reset Color" action:@selector(handleResetColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = collector_index; - [menu addItem:item]; - [item release]; - } - - return menu; -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsStripChart:: -get_label_tooltip(int collector_index) const { - return PStatStripChart::get_label_tooltip(collector_index); -} - -/** - * Changes the value the height of the vertical axis represents. This may - * force a redraw. - */ -void MacStatsStripChart:: -set_vertical_scale(double value_height) { - PStatStripChart::set_vertical_scale(value_height); - - _graph_view.needsDisplay = YES; - _scale_area.needsDisplay = YES; -} - -/** - * Sets the vertical scale to make all the data visible. - */ -void MacStatsStripChart:: -set_auto_vertical_scale() { - PStatStripChart::set_auto_vertical_scale(); - set_vertical_scale(get_vertical_scale() * 1.5); - - _graph_view.needsDisplay = YES; - _scale_area.needsDisplay = YES; -} - -/** - * Resets the list of labels. - */ -void MacStatsStripChart:: -update_labels() { - PStatStripChart::update_labels(); - - _label_stack.clear_labels(); - for (int i = 0; i < get_num_labels(); i++) { - _label_stack.add_label(MacStatsGraph::_monitor, this, _thread_index, - get_label_collector(i), false); - } - _labels_changed = false; -} - -/** - * Erases the chart area. - */ -void MacStatsStripChart:: -clear_region() { - if (_ctx) { - //CGContextSetFillColorWithColor(_ctx, _background_color); - //CGContextFillRect(_ctx, CGRectMake(0, 0, get_xsize(), get_ysize())); - } -} - -/** - * Draws a single vertical slice of the strip chart, at the given pixel - * position, and corresponding to the indicated level data. - */ -void MacStatsStripChart:: -draw_slice(int x, int w, const PStatStripChart::FrameData &fdata) { - if (!_ctx) { - return; - } - - // Start by clearing the band first. - CGContextSetFillColorWithColor(_ctx, _background_color); - CGContextFillRect(_ctx, CGRectMake(x, 0, w, get_ysize())); - - double overall_time = 0.0; - int y = get_ysize(); - - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - overall_time += cd._net_value; - - bool is_highlighted = cd._collector_index == _highlighted_index; - CGContextSetFillColorWithColor(_ctx, - MacStatsGraph::_monitor->get_collector_color(cd._collector_index, is_highlighted)); - - if (overall_time > get_vertical_scale()) { - // Off the top. Go ahead and clamp it by hand, in case it's so far off - // the top we'd overflow the 16-bit pixel value. - CGContextFillRect(_ctx, CGRectMake(x, 0, w, y)); - // And we can consider ourselves done now. - return; - } - - int top_y = height_to_pixel(overall_time); - CGContextFillRect(_ctx, CGRectMake(x, top_y, w, y - top_y)); - y = top_y; - } -} - -/** - * Draws a single vertical slice of background color. - */ -void MacStatsStripChart:: -draw_empty(int x, int w) { - if (!_ctx) { - return; - } - - CGContextSetFillColorWithColor(_ctx, _background_color); - CGContextFillRect(_ctx, CGRectMake(x, 0, w, get_ysize())); -} - -/** - * Draws a single vertical slice of foreground color. - */ -void MacStatsStripChart:: -draw_cursor(int x) { - if (!_ctx) { - return; - } - - CGContextBeginPath(_ctx); - CGContextMoveToPoint(_ctx, x, 0); - CGContextAddLineToPoint(_ctx, x, get_ysize()); - CGContextStrokePath(_ctx); -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars in the strip chart; it gives the pixel range - * that was just redrawn. - */ -void MacStatsStripChart:: -end_draw(int from_x, int to_x) { - _graph_view.needsDisplay = YES; -} - -/** - * Returns the current window dimensions. - */ -bool MacStatsStripChart:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - MacStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void MacStatsStripChart:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - MacStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * Called when the mouse right-clicks on the graph, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsStripChart:: -get_graph_menu(int mouse_x, int mouse_y) const { - NSMenu *menu = nullptr; - if (_highlighted_index != -1) { - menu = get_label_menu(_highlighted_index); - } -/* - if (menu != nullptr) { - [menu addItem:[NSMenuItem separatorItem]]; - } else { - menu = [[[NSMenu alloc] init] autorelease]; - } - - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Smooth" action:@selector(handleToggleStripChartAverage:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.state = get_average_mode() ? NSOnState : NSOffState; - [menu addItem:item]; - [item release];*/ - return menu; -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsStripChart:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - if (_highlighted_index != -1) { - return get_label_tooltip(_highlighted_index); - } - return std::string(); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -MacStatsGraph::DragMode MacStatsStripChart:: -consider_drag_start(int graph_x, int graph_y) { - // See if the mouse is over a user-defined guide bar. - int y = graph_y; - double from_height = pixel_to_height(y + 2); - double to_height = pixel_to_height(y - 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - return MacStatsGraph::consider_drag_start(graph_x, graph_y); -} - -/** - * This should be called whenever the drag mode needs to change state. It - * provides hooks for a derived class to do something special. - */ -void MacStatsStripChart:: -set_drag_mode(MacStatsGraph::DragMode drag_mode) { - MacStatsGraph::set_drag_mode(drag_mode); -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -void MacStatsStripChart:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - if (double_click && button == 0) { - // Double-clicking on a color bar in the graph is the same as double- - // clicking on the corresponding label. - on_click_label(get_collector_under_pixel(graph_x, graph_y)); - return; - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - _drag_scale_start = pixel_to_height(graph_y); - // SetCapture(_graph_window); - return; - } - } - - if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - _drag_start_y = graph_y; - // SetCapture(_graph_window); - return; - } - - return MacStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -void MacStatsStripChart:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_y < 0 || graph_y >= get_ysize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_y)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return MacStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -void MacStatsStripChart:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none && - graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - // When the mouse is over a color bar, highlight it. - int collector_index = get_collector_under_pixel(graph_x, graph_y); - _label_stack.highlight_label(collector_index); - on_enter_label(collector_index); - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_scale) { - double ratio = 1.0 - ((double)graph_y / (double)get_ysize()); - if (ratio > 0.0) { - double new_scale = _drag_scale_start / ratio; - if (!IS_NEARLY_EQUAL(get_vertical_scale(), new_scale)) { - // Disable smoothing while we do this expensive operation. - set_vertical_scale(_drag_scale_start / ratio); - } - } - return; - } - else if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - if (graph_y >= 0 && graph_y < get_ysize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_y)); - return; - } - } - else if (_drag_mode == DM_guide_bar) { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_y)); - return; - } - - MacStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -void MacStatsStripChart:: -handle_leave() { - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - return; -} - -/** - * - */ -void MacStatsStripChart:: -handle_magnify(int graph_x, int graph_y, double scale) { - set_vertical_scale(get_vertical_scale() * (1.0 - scale)); -} - -/** - * Fills in the graph window. - */ -void MacStatsStripChart:: -handle_draw_graph(CGContextRef ctx, NSRect rect) { - MacStatsGraph::handle_draw_graph(ctx, rect); - - int width = get_xsize(); - - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_bar(ctx, 0, width, get_guide_bar(i)); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_bar(ctx, 0, width, get_user_guide_bar(i)); - } -} - -/** - * Fills in the scale area. - */ -void MacStatsStripChart:: -handle_draw_scale_area(CGContextRef ctx, NSRect rect) { - MacStatsGraph::handle_draw_scale_area(ctx, rect); - draw_guide_labels(ctx); -} - -/** - * Called when the mouse clicks the back button in the toolbar. - */ -void MacStatsStripChart:: -handle_back() { - if (!_back_stack.empty()) { - int collector_index = _back_stack.back(); - _back_stack.pop_back(); - set_collector_index(collector_index); - - // Update window title and total label. - new_data(0, 0); - _scale_area.needsDisplay = YES; - } - - if (_back_stack.empty()) { - _graph_view_controller.backToolbarItemVisible = NO; - } -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void MacStatsStripChart:: -draw_guide_bar(CGContextRef ctx, int from_x, int to_x, - const PStatGraph::GuideBar &bar) { - int y = height_to_pixel(bar._height); - - if (y > 1) { - // Only draw it if it's not too close to the top. - /*switch (bar._style) { - case GBS_target: - CGContextSetRGBStrokeColor(ctx, rgb_light_gray[0], rgb_light_gray[1], rgb_light_gray[2], 1.0); - break; - - case GBS_user: - CGContextSetRGBStrokeColor(ctx, rgb_user_guide_bar[0], rgb_user_guide_bar[1], rgb_user_guide_bar[2], 1.0); - break; - - default: - CGContextSetRGBStrokeColor(ctx, rgb_dark_gray[0], rgb_dark_gray[1], rgb_dark_gray[2], 1.0); - break; - }*/ - CGContextSetStrokeColorWithColor(ctx, [NSColor gridColor].CGColor); - CGContextBeginPath(ctx); - CGContextMoveToPoint(ctx, from_x, y); - CGContextAddLineToPoint(ctx, to_x, y); - CGContextStrokePath(ctx); - } -} - -/** - * This is called during the servicing of the draw event. - */ -void MacStatsStripChart:: -draw_guide_labels(CGContextRef ctx) { - // Draw in the labels for the guide bars. - int last_y = 0; - - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; i++) { - last_y = draw_guide_label(ctx, get_guide_bar(i), last_y); - } - - GuideBar top_value = make_guide_bar(get_vertical_scale()); - draw_guide_label(ctx, top_value, last_y); - - last_y = 0; - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; i++) { - last_y = draw_guide_label(ctx, get_user_guide_bar(i), last_y); - } -} - -/** - * Draws the text for the indicated guide bar label to the right of the graph, - * unless it would overlap with the indicated last label, whose top pixel - * value is given. Returns the top pixel value of the new label. - */ -int MacStatsStripChart:: -draw_guide_label(CGContextRef ctx, const PStatGraph::GuideBar &bar, int last_y) { - NSColor *color; - switch (bar._style) { - case GBS_target: - color = [NSColor secondaryLabelColor]; - break; - - case GBS_user: - color = [NSColor tertiaryLabelColor]; - break; - - default: - color = [NSColor labelColor]; - break; - } - - int y = height_to_pixel(bar._height); - const std::string &label = bar._label; - - const CFStringRef keys[] = { - (__bridge CFStringRef)NSForegroundColorAttributeName, - (__bridge CFStringRef)NSFontAttributeName, - }; - const void *values[] = { - color, - [NSFont systemFontOfSize:0.0], - }; - CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, label.c_str(), kCFStringEncodingUTF8); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - CFRelease(attribs); - CFRelease(str); - - CTLineRef line = CTLineCreateWithAttributedString(astr); - CFRelease(astr); - CGRect bounds = CTLineGetImageBounds(line, ctx); - int height = bounds.size.height; - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(y + height); - double to_height = pixel_to_height(y - height); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - CFRelease(line); - return last_y; - } - } - - if (y > height && y < get_ysize() - height) { - // Now convert our y to a coordinate within our drawing area. - - int this_y = y - height / 2; - if (last_y < this_y || last_y > this_y + height) { - CGContextSetTextPosition(ctx, 4, get_ysize() - this_y - height); - CTLineDraw(line, ctx); - - last_y = this_y; - } - } - - CFRelease(line); - return last_y; -} - -@implementation MacStatsStripChartViewController - -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar { - if (@available(macOS 10.15, *)) { - return @[@"smooth", @"sep", @"total"]; - } else { - return @[@"smooth", @"sep"]; - } -} - -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar { - if (@available(macOS 10.15, *)) { - return @[@"smooth", @"sep", @"total"]; - } else { - return @[@"smooth", @"sep"]; - } -} - -- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar - itemForItemIdentifier:(NSString *)ident - willBeInsertedIntoToolbar:(BOOL)flag { - - if (@available(macOS 11.0, *)) { - if ([ident isEqual:@"smooth"]) { - NSButton *button = [NSButton buttonWithTitle:@"Smooth" target:self action:@selector(handleToggleSmooth:)]; - button.image = [NSImage imageWithSystemSymbolName:@"alternatingcurrent" accessibilityDescription:@""]; - button.bezelStyle = NSBezelStyleTexturedRounded; - button.buttonType = NSButtonTypePushOnPushOff; - button.bordered = YES; - button.toolTip = @"Smooth"; - button.state = NSOffState; - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:ident] autorelease]; - item.label = @"Smooth"; - item.view = button; - return item; - } - if ([ident isEqual:@"total"]) { - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:ident] autorelease]; - item.label = @"Total"; - item.action = @selector(handleClickTotal:); - item.target = self; - [item setBordered:YES]; - return item; - } - } - - return [super toolbar:toolbar itemForItemIdentifier:ident willBeInsertedIntoToolbar:flag]; -} - -- (void)handleToggleSmooth:(NSMenuItem *)item { - MacStatsStripChart *graph = (MacStatsStripChart *)_graph; - graph->set_average_mode(item.state == NSOnState); -} - -- (void)handleClickTotal:(NSButton *)button { - MacStatsStripChart *graph = (MacStatsStripChart *)_graph; - graph->set_auto_vertical_scale(); -} - -@end diff --git a/pandatool/src/mac-stats/macStatsTimeline.h b/pandatool/src/mac-stats/macStatsTimeline.h deleted file mode 100644 index e26d5e7c..00000000 --- a/pandatool/src/mac-stats/macStatsTimeline.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsTimeline.h - * @author rdb - * @date 2023-08-19 - */ - -#ifndef MACSTATSTIMELINE_H -#define MACSTATSTIMELINE_H - -#include "macStatsGraph.h" -#include "pStatTimeline.h" - -class MacStatsMonitor; - -/** - * A window that draws all of the start/stop event pairs on each thread on a - * horizontal scrolling timeline, with concurrent start/stop pairs stacked - * underneath each other. - */ -class MacStatsTimeline final : public PStatTimeline, public MacStatsGraph { -public: - MacStatsTimeline(MacStatsMonitor *monitor); - virtual ~MacStatsTimeline(); - - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - -protected: - virtual void clear_region(); - virtual void begin_draw(); - virtual void draw_separator(int row); - virtual void draw_guide_bar(int x, GuideBarStyle style); - virtual void draw_bar(int row, int from_x, int to_x, int collector_index, - const std::string &collector_name); - virtual void end_draw(); - virtual void idle(); - - virtual bool animate(double time, double dt); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - virtual NSMenu *get_graph_menu(int mouse_x, int mouse_y) const; - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int graph_x, int graph_y); - - virtual bool handle_key(int graph_x, int graph_y, bool pressed, - UniChar c, unsigned short key_code); - virtual void handle_button_press(int graph_x, int graph_y, - bool double_click, int button); - virtual void handle_button_release(int graph_x, int graph_y); - virtual void handle_motion(int graph_x, int graph_y); - virtual void handle_leave(); - virtual void handle_scroll(); - virtual void handle_wheel(int graph_x, int graph_y, double dx, double dy); - virtual void handle_magnify(int graph_x, int graph_y, double scale); - virtual void handle_draw_graph(CGContextRef ctx, NSRect rect); - virtual void handle_draw_graph_overhang(CGContextRef ctx, NSRect rect); - virtual void handle_draw_scale_area(CGContextRef ctx, NSRect rect); - -public: - void handle_zoom_to(); - void handle_open_strip_chart(); - void handle_open_flame_graph(); - void handle_open_piano_roll(); - -private: - void draw_guide_bar(CGContextRef ctx, GuideBarStyle style, int x, int y, int height); - void draw_guide_labels(CGContextRef ctx); - void draw_guide_label(CGContextRef ctx, const GuideBar &bar); - - int row_to_pixel(int row) const { - return row * 4 * 5 + 4 - _scroll; - } - int pixel_to_row(int y) const { - return (y + _scroll - 4) / (4 * 5); - } - - NSView *_thread_area; - pvector > _thread_labels; - NSLayoutConstraint *_graph_height_constraint; - NSScrollView *_sidebar_scroll_view; - - int _highlighted_row = -1; - int _highlighted_x = 0; - int _scroll = 0; - mutable ColorBar _popup_bar; -}; - -#endif diff --git a/pandatool/src/mac-stats/macStatsTimeline.mm b/pandatool/src/mac-stats/macStatsTimeline.mm deleted file mode 100644 index 85f5c89e..00000000 --- a/pandatool/src/mac-stats/macStatsTimeline.mm +++ /dev/null @@ -1,949 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file macStatsTimeline.mm - * @author rdb - * @date 2023-08-19 - */ - -#include "macStatsTimeline.h" -#include "macStatsMonitor.h" -#include "macStatsLabelStack.h" -#include "macStatsScaleArea.h" -#include "pStatCollectorDef.h" - -@interface MacStatsTimelineViewController : MacStatsScrollableGraphViewController -@end - -static const int default_timeline_width = 1000; -static const int default_timeline_height = 300; - -static const int minimum_timeline_sidebar_width = 68; -static const int default_timeline_sidebar_width = 100; - -/** - * - */ -MacStatsTimeline:: -MacStatsTimeline(MacStatsMonitor *monitor) : - PStatTimeline(monitor, 0, 0), - MacStatsGraph(monitor, [MacStatsTimelineViewController alloc]) -{ - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - _window.title = @"Timeline"; - - if (@available(macOS 11.0, *)) { - _window.titleVisibility = NSWindowTitleHidden; - } - - // Set the initial size of the graph. - const ThreadRow &last_thread_row = _threads.back(); - int height = row_to_pixel(last_thread_row._row_offset + last_thread_row._rows.size()); - if (height < default_timeline_height) { - height = default_timeline_height; - } - height += _window.frame.size.height - _window.contentLayoutRect.size.height; - _graph_view.frame = NSMakeRect(0, 0, default_timeline_width, height); - _graph_view_controller.view.frame = NSMakeRect(0, 0, default_timeline_width, height); - - // Add a drawing area to the left of the graph to show the thread labels. - _thread_area = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, default_timeline_sidebar_width, 0)]; - _thread_area.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - _thread_area.translatesAutoresizingMaskIntoConstraints = NO; - - // It's put inside a scroll view that tracks the main scroll view. - NSScrollView *scroll_view = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, default_timeline_sidebar_width, 0)]; - scroll_view.documentView = _thread_area; - scroll_view.drawsBackground = NO; - scroll_view.automaticallyAdjustsContentInsets = YES; - //scroll_view.translatesAutoresizingMaskIntoConstraints = NO; - scroll_view.hasHorizontalScroller = NO; - scroll_view.hasVerticalScroller = NO; - _sidebar_scroll_view = scroll_view; - - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - [center addObserver:_graph_view_controller - selector:@selector(handleSideScroll:) - name:NSScrollViewDidLiveScrollNotification - object:scroll_view]; - - NSViewController *sidebar_controller = [[NSViewController alloc] init]; - sidebar_controller.view = scroll_view; - - NSSplitViewController *svc = [[NSSplitViewController alloc] init]; - [svc addSplitViewItem:[NSSplitViewItem sidebarWithViewController:sidebar_controller]]; - [svc addSplitViewItem:[NSSplitViewItem splitViewItemWithViewController:_graph_view_controller]]; - - svc.splitViewItems[0].minimumThickness = minimum_timeline_sidebar_width; - svc.splitViewItems[0].canCollapse = NO; - - NSSplitView *split_view = svc.splitView; - split_view.vertical = YES; - split_view.dividerStyle = NSSplitViewDividerStyleThin; - split_view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - _split_view = split_view; - - _window.contentViewController = svc; - - [svc release]; - [sidebar_controller release]; - - // Scale area goes on top, as a titlebar accessory view. - MacStatsScaleAreaController *scale_area_controller = [[MacStatsScaleAreaController alloc] initWithGraph:this]; - scale_area_controller.fullScreenMinHeight = 20; - scale_area_controller.layoutAttribute = NSLayoutAttributeRight; - _scale_area = scale_area_controller.view; - [_window addTitlebarAccessoryViewController:scale_area_controller]; - [scale_area_controller release]; - - [_thread_area.widthAnchor constraintEqualToAnchor:scroll_view.widthAnchor].active = YES; - [_thread_area.heightAnchor constraintEqualToAnchor:_graph_view.heightAnchor].active = YES; - - _graph_height_constraint = [_graph_view.heightAnchor constraintGreaterThanOrEqualToConstant:0]; - _graph_height_constraint.active = YES; - - [_window makeKeyAndOrderFront:nil]; -} - -/** - * - */ -MacStatsTimeline:: -~MacStatsTimeline() { - [_thread_area release]; - [_sidebar_scroll_view release]; -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void MacStatsTimeline:: -new_data(int thread_index, int frame_number) { - PStatTimeline::new_data(thread_index, frame_number); -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void MacStatsTimeline:: -force_redraw() { - if (_ctx) { - PStatTimeline::force_redraw(); - } -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void MacStatsTimeline:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatTimeline::changed_size(graph_xsize, graph_ysize); -} - -/** - * Erases the chart area. - */ -void MacStatsTimeline:: -clear_region() { - if (_ctx) { - CGContextSetFillColorWithColor(_ctx, _background_color); - CGContextFillRect(_ctx, CGRectMake(0, 0, get_xsize(), get_ysize())); - - CGContextSetTextMatrix(_ctx, CGAffineTransformMakeScale(1, -1)); - //draw_guide_labels(_ctx); - } -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void MacStatsTimeline:: -begin_draw() { -} - -/** - * Draws a horizontal separator. - */ -void MacStatsTimeline:: -draw_separator(int row) { - if (_ctx) { - CGContextSetFillColorWithColor(_ctx, [NSColor gridColor].CGColor); - CGContextFillRect(_ctx, CGRectMake(0, (row_to_pixel(row) + row_to_pixel(row + 1)) / 2.0, get_xsize(), 4.0 / 3.0)); - } -} - -/** - * Draws a vertical guide bar. If the row is -1, draws it in all rows. - */ -void MacStatsTimeline:: -draw_guide_bar(int x, GuideBarStyle style) { - draw_guide_bar(_ctx, style, x, 0, get_ysize()); -} - -/** - * Draws a single bar in the chart for the indicated row, in the color for the - * given collector, for the indicated horizontal pixel range. - */ -void MacStatsTimeline:: -draw_bar(int row, int from_x, int to_x, int collector_index, - const std::string &collector_name) { - int top = row_to_pixel(row); - int bottom = row_to_pixel(row + 1); - int scale = 4; - - top += 1; - - MacStatsMonitor *monitor = MacStatsGraph::_monitor; - - bool is_highlighted = row == _highlighted_row && _highlighted_x >= from_x && _highlighted_x < to_x; - CGContextSetFillColorWithColor(_ctx, - monitor->get_collector_color(collector_index, is_highlighted)); - - if (to_x < from_x + 1) { - // Too tiny to draw. - } - else if (to_x < from_x + scale) { - // It's just a tiny sliver. This is a more reliable way to draw it. - CGRect rect = CGRectMake(from_x, top, to_x - from_x, bottom - top); - CGContextFillRect(_ctx, rect); - } - else { - int left = std::max(from_x, -scale - 1); - int right = std::min(std::max(to_x, from_x + 1), get_xsize() + scale); - - double radius = std::min((double)scale, (right - left) / 2.0); - CGContextBeginPath(_ctx); - CGContextAddArc(_ctx, right - radius - 0.5, top + radius, radius, -0.5 * M_PI, 0.0, NO); - CGContextAddArc(_ctx, right - radius - 0.5, bottom - radius, radius, 0.0, 0.5 * M_PI, NO); - CGContextAddArc(_ctx, left + radius, bottom - radius, radius, 0.5 * M_PI, M_PI, NO); - CGContextAddArc(_ctx, left + radius, top + radius, radius, M_PI, 1.5 * M_PI, NO); - CGContextClosePath(_ctx); - CGContextFillPath(_ctx); - - if ((to_x - from_x) >= scale * 4) { - // Only bother drawing the text if we've got some space to draw on. - const CFStringRef keys[] = { - (__bridge CFStringRef)NSForegroundColorAttributeName, - (__bridge CFStringRef)NSFontAttributeName, - }; - const void *values[] = { - monitor->get_collector_text_color(collector_index, is_highlighted), - [NSFont systemFontOfSize:0.0], - }; - CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, collector_name.c_str(), kCFStringEncodingUTF8); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - - CTLineRef line = CTLineCreateWithAttributedString(astr); - CGRect bounds = CTLineGetImageBounds(line, _ctx); - CFRelease(astr); - CFRelease(str); - - int text_width = bounds.size.width; - int text_height = bounds.size.height; - - double center = (from_x + to_x) / 2.0; - double text_left = std::max(from_x, 0) + scale / 2.0; - double text_right = std::min(to_x, get_xsize()) - scale / 2.0; - double text_top = top + (bottom - top - text_height) / 2.0 + text_height; - - if (text_width >= text_right - text_left) { - size_t c = collector_name.rfind(':'); - if (text_right - text_left < scale * 6) { - // It's a really tiny space. Draw a single letter. - UniChar ch = *(collector_name.data() + (c != std::string::npos ? c + 1 : 0)); - - CFStringRef str = CFStringCreateWithCharacters(kCFAllocatorDefault, &ch, 1); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - - CTLineRef new_line = CTLineCreateWithAttributedString((CFAttributedStringRef)astr); - bounds = CTLineGetImageBounds(new_line, _ctx); - text_width = bounds.size.width; - - CFRelease(line); - CFRelease(astr); - CFRelease(str); - line = new_line; - } - else { - // Maybe just use everything after the last colon. - if (c != std::string::npos) { - const char *short_name = collector_name.data() + c + 1; - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, short_name, kCFStringEncodingUTF8); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - - CTLineRef new_line = CTLineCreateWithAttributedString((CFAttributedStringRef)astr); - bounds = CTLineGetImageBounds(new_line, _ctx); - text_width = bounds.size.width; - - CFRelease(line); - CFRelease(astr); - CFRelease(str); - line = new_line; - } - } - } - - if (text_width >= text_right - text_left) { - // Have CoreText truncate to the correct length. - static CFStringRef token_str = CFSTR("\u2026"); - CFAttributedStringRef token_astr = CFAttributedStringCreate(kCFAllocatorDefault, token_str, attribs); - CTLineRef token_line = CTLineCreateWithAttributedString(token_astr); - CTLineRef trunc_line = CTLineCreateTruncatedLine(line, text_right - text_left, kCTLineTruncationEnd, token_line); - CFRelease(line); - CFRelease(token_astr); - CFRelease(token_line); - line = trunc_line; - CGContextSetTextPosition(_ctx, text_left, text_top); - } - else if (center - text_width / 2.0 < 0.0) { - // Put it against the left-most edge. - CGContextSetTextPosition(_ctx, scale, text_top); - } - else if (center + text_width / 2.0 >= get_xsize()) { - // Put it against the right-most edge. - CGContextSetTextPosition(_ctx, get_xsize() - scale - text_width, text_top); - } - else { - // It fits just fine, center it. - CGContextSetTextPosition(_ctx, center - text_width / 2.0, text_top); - } - - if (line != nullptr) { - CTLineDraw(line, _ctx); - CFRelease(line); - } - CFRelease(attribs); - } - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void MacStatsTimeline:: -end_draw() { - // Recalculate the size of the graph. - if (!_threads.empty()) { - const ThreadRow &last_thread_row = _threads.back(); - int new_height = row_to_pixel(last_thread_row._row_offset + last_thread_row._rows.size()); - _graph_height_constraint.constant = new_height; - } - - _graph_view.needsDisplay = YES; - - // If we scroll sideways while we're also scrolling vertically such that the - // overhang becomes visible due to elasticity, the overhang doesn't update. - // I could only find this private method for fixing this problem. - // Not needed as of macOS 14 and up, since the normal drawRect DTRT there. -#if __MAC_OS_X_VERSION_MAX_ALLOWED < 140000 - NSClipView *clip_view = ((MacStatsScrollableGraphViewController *)_graph_view_controller).clipView; - if ([clip_view respondsToSelector:@selector(_setNeedsDisplayInOverhang:)]) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wobjc-method-access" - [clip_view _setNeedsDisplayInOverhang:YES]; -#pragma clang diagnostic pop - } -#endif - - if (_threads_changed) { - while (_thread_labels.size() < _threads.size()) { - NSTextField *label = [NSTextField labelWithString:@"Thread"]; - label.translatesAutoresizingMaskIntoConstraints = NO; - [_thread_area addSubview:label]; - - [label.rightAnchor constraintEqualToAnchor:_thread_area.rightAnchor constant:-8].active = YES; - [_thread_area.widthAnchor constraintGreaterThanOrEqualToAnchor:label.widthAnchor constant:16].active = YES; - - NSLayoutConstraint *constraint; - if (@available(macOS 11.0, *)) { - constraint = [label.topAnchor constraintEqualToAnchor:_thread_area.topAnchor]; - } else { - constraint = [label.topAnchor constraintEqualToAnchor:_thread_area.topAnchor]; - } - constraint.active = YES; - - _thread_labels.push_back(std::make_pair(label, constraint)); - } - - for (size_t i = 0; i < _threads.size(); ++i) { - const ThreadRow &thread_row = _threads[i]; - NSTextField *label = _thread_labels[i].first; - NSLayoutConstraint *label_constraint = _thread_labels[i].second; - - label.stringValue = [NSString stringWithUTF8String:thread_row._label.c_str()]; - label_constraint.constant = row_to_pixel(thread_row._row_offset); - } - - _thread_area.needsDisplay = YES; - _threads_changed = false; - } - - if (_guide_bars_changed) { - _scale_area.needsDisplay = YES; - _guide_bars_changed = false; - } -} - -/** - * Called at the end of the draw cycle. - */ -void MacStatsTimeline:: -idle() { -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool MacStatsTimeline:: -animate(double time, double dt) { - return PStatTimeline::animate(time, dt); -} - -/** - * Returns the current window dimensions. - */ -bool MacStatsTimeline:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - MacStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void MacStatsTimeline:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - MacStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * Called when the mouse right-clicks on the graph, and should return the menu - * that should pop up. - */ -NSMenu *MacStatsTimeline:: -get_graph_menu(int graph_x, int graph_y) const { - int row = pixel_to_row(graph_y); - ColorBar bar; - if (!find_bar(row, graph_x, bar)) { - return nil; - } - - _popup_bar = bar; - - NSMenu *menu = [[[NSMenu alloc] init] autorelease]; - - std::string label = get_bar_tooltip(row, graph_x); - if (!label.empty()) { - if (@available(macOS 14.0, *)) { - [menu addItem:[NSMenuItem sectionHeaderWithTitle:[NSString stringWithUTF8String:label.c_str()]]]; - } else { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithUTF8String:label.c_str()] action:nil keyEquivalent:@""]; - item.enabled = NO; - [menu addItem:item]; - [item release]; - } - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Zoom To" action:@selector(handleZoomTo:) keyEquivalent:@""]; - item.target = _graph_view_controller; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Strip Chart" action:@selector(handleOpenStripChart:) keyEquivalent:@""]; - item.target = _graph_view_controller; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Flame Graph" action:@selector(handleOpenFlameGraph:) keyEquivalent:@""]; - item.target = _graph_view_controller; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Open Piano Roll" action:@selector(handleOpenPianoRoll:) keyEquivalent:@""]; - item.target = _graph_view_controller; - [menu addItem:item]; - [item release]; - } - - [menu addItem:[NSMenuItem separatorItem]]; - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Change Color\u2026" action:@selector(handleChangeColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = bar._collector_index; - [menu addItem:item]; - [item release]; - } - - { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Reset Color" action:@selector(handleResetColor:) keyEquivalent:@""]; - item.target = _graph_view_controller; - item.tag = bar._collector_index; - [menu addItem:item]; - [item release]; - } - - return menu; -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string MacStatsTimeline:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return PStatTimeline::get_bar_tooltip(pixel_to_row(mouse_y), mouse_x); -} - -/** - * Based on the mouse position within the graph window, look for draggable - * things the mouse might be hovering over and return the appropriate DragMode - * enum or DM_none if nothing is indicated. - */ -MacStatsGraph::DragMode MacStatsTimeline:: -consider_drag_start(int graph_x, int graph_y) { - return MacStatsGraph::consider_drag_start(graph_x, graph_y); -} - -/** - * - */ -bool MacStatsTimeline:: -handle_key(int graph_x, int graph_y, bool pressed, UniChar c, unsigned short key_code) { - // Accept WASD based on their position rather than their mapping - int flag = 0; - switch (key_code) { - case 13: - flag = F_w; - break; - case 0: - flag = F_a; - break; - case 1: - flag = F_s; - break; - case 2: - flag = F_d; - break; - } - if (flag == 0) { - switch (c) { - case 0x1c: - case NSLeftArrowFunctionKey: - flag = F_left; - break; - case 0x1d: - case NSRightArrowFunctionKey: - flag = F_right; - break; - case 'w': - flag = F_w; - break; - case 'a': - flag = F_a; - break; - case 's': - flag = F_s; - break; - case 'd': - flag = F_d; - break; - } - } - if (flag != 0) { - if (pressed) { - if (flag & (F_w | F_s)) { - _zoom_center = pixel_to_timestamp(graph_x); - } - if (_keys_held == 0) { - start_animation(); - } - _keys_held |= flag; - } - else if (_keys_held != 0) { - _keys_held &= ~flag; - } - return true; - } - return false; -} - -/** - * Called when the mouse button is depressed within the graph window. - */ -void MacStatsTimeline:: -handle_button_press(int graph_x, int graph_y, bool double_click, int button) { - if (graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - if (double_click && button == 0) { - // Double-clicking on a color bar in the graph will zoom the graph into - // that collector. - int row = pixel_to_row(graph_y); - ColorBar bar; - if (find_bar(row, graph_x, bar)) { - double width = bar._end - bar._start; - zoom_to(width * 1.5, pixel_to_timestamp(graph_x)); - scroll_to(bar._start - width / 4.0); - } else { - // Double-clicking the white area zooms out. - _zoom_speed -= 100.0; - } - start_animation(); - } - - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_pan); - _drag_start_x = graph_x; - _scroll_speed = 0.0; - _zoom_center = pixel_to_timestamp(graph_x); - return; - } - } - - return MacStatsGraph::handle_button_press(graph_x, graph_y, - double_click, button); -} - -/** - * Called when the mouse button is released within the graph window. - */ -void MacStatsTimeline:: -handle_button_release(int graph_x, int graph_y) { - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - else if (_drag_mode == DM_guide_bar) { - if (graph_x < 0 || graph_x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x)); - } - set_drag_mode(DM_none); - // ReleaseCapture(); - return handle_motion(graph_x, graph_y); - } - - return MacStatsGraph::handle_button_release(graph_x, graph_y); -} - -/** - * Called when the mouse is moved within the graph window. - */ -void MacStatsTimeline:: -handle_motion(int graph_x, int graph_y) { - if (_drag_mode == DM_none && _potential_drag_mode == DM_none && - graph_x >= 0 && graph_y >= 0 && graph_x < get_xsize() && graph_y < get_ysize()) { - // When the mouse is over a color bar, highlight it. - int row = pixel_to_row(graph_y); - std::swap(_highlighted_x, graph_x); - std::swap(_highlighted_row, row); - - if (row >= 0) { - PStatTimeline::force_redraw(row, graph_x, graph_x); - } - PStatTimeline::force_redraw(_highlighted_row, _highlighted_x, _highlighted_x); - - if ((_keys_held & (F_w | F_s)) != 0) { - // Update the zoom center if we move the mouse while zooming with the - // keyboard. - _zoom_center = pixel_to_timestamp(graph_x); - } - } - else { - // If the mouse is in some drag mode, stop highlighting. - if (_highlighted_row != -1) { - int row = _highlighted_row; - _highlighted_row = -1; - PStatTimeline::force_redraw(row, _highlighted_x, _highlighted_x); - } - } - - if (_drag_mode == DM_pan) { - int delta = _drag_start_x - graph_x; - _drag_start_x = graph_x; - set_horizontal_scroll(get_horizontal_scroll() + pixel_to_height(delta)); - return; - } - - return MacStatsGraph::handle_motion(graph_x, graph_y); -} - -/** - * Called when the mouse has left the graph window. - */ -void MacStatsTimeline:: -handle_leave() { - if (_highlighted_row != -1) { - int row = _highlighted_row; - _highlighted_row = -1; - PStatTimeline::force_redraw(row, _highlighted_x, _highlighted_x); - } -} - -/** - * Called when the mouse is moved within the graph window. - */ -void MacStatsTimeline:: -handle_scroll() { - // Graph view is flipped, side bar isn't, so we need to convert coordinates - NSPoint point; - point.x = 0; - point.y = _graph_view.frame.size.height - (((NSScrollView *)_graph_view_controller.view).documentVisibleRect.size.height + ((NSScrollView *)_graph_view_controller.view).documentVisibleRect.origin.y); - [_sidebar_scroll_view.contentView scrollToPoint:point]; - [_sidebar_scroll_view reflectScrolledClipView:_sidebar_scroll_view.contentView]; -} - -/** - * - */ -void MacStatsTimeline:: -handle_wheel(int graph_x, int graph_y, double dx, double dy) { - if (dx != 0.0) { - _scroll_speed -= dx; - start_animation(); - } -} - -/** - * - */ -void MacStatsTimeline:: -handle_magnify(int graph_x, int graph_y, double scale) { - zoom_by(scale * 4.0, pixel_to_timestamp(graph_x)); - start_animation(); -} - -/** - * Fills in the graph window. - */ -void MacStatsTimeline:: -handle_draw_graph(CGContextRef ctx, NSRect rect) { -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 140000 - for (const GuideBar &bar : _guide_bars) { - int x = timestamp_to_pixel(bar._height); - draw_guide_bar(ctx, bar._style, x, rect.origin.y, rect.size.height); - } -#endif - - MacStatsGraph::handle_draw_graph(ctx, rect); - - NSRect scale_frame = _scale_area.frame; - NSRect graph_frame = _graph_view.frame; - if (scale_frame.size.width != graph_frame.size.width) { - scale_frame.size.width = graph_frame.size.width; - _scale_area.frame = scale_frame; - } -} - -/** - * Fills in the graph window overhang, which is the area outside the graph - * bounds that may become visible momentarily due to scroll elasticity. - */ -void MacStatsTimeline:: -handle_draw_graph_overhang(CGContextRef ctx, NSRect rect) { - CGContextSetFillColorWithColor(ctx, _background_color); - CGContextFillRect(ctx, rect); - - for (const GuideBar &bar : _guide_bars) { - int x = timestamp_to_pixel(bar._height); - draw_guide_bar(ctx, bar._style, x, rect.origin.y, rect.size.height); - } -} - -/** - * Fills in the scale area. - */ -void MacStatsTimeline:: -handle_draw_scale_area(CGContextRef ctx, NSRect rect) { - MacStatsGraph::handle_draw_scale_area(ctx, rect); - - draw_guide_labels(ctx); - - CGContextSetFillColorWithColor(ctx, [NSColor gridColor].CGColor); - - for (const GuideBar &bar : _guide_bars) { - int x = timestamp_to_pixel(bar._height); - x = [_scale_area convertPoint:NSMakePoint(x, 0) fromView:_graph_view].x; - draw_guide_bar(ctx, bar._style, x, rect.origin.y, rect.size.height); - } -} - -/** - * - */ -void MacStatsTimeline:: -handle_zoom_to() { - const ColorBar &bar = _popup_bar; - double width = bar._end - bar._start; - zoom_to(width * 1.5, (bar._end + bar._start) / 2.0); - scroll_to(bar._start - width / 4.0); - start_animation(); -} - -/** - * - */ -void MacStatsTimeline:: -handle_open_strip_chart() { - const ColorBar &bar = _popup_bar; - MacStatsGraph::_monitor->open_strip_chart(bar._thread_index, bar._collector_index, false); -} - -/** - * - */ -void MacStatsTimeline:: -handle_open_flame_graph() { - const ColorBar &bar = _popup_bar; - MacStatsGraph::_monitor->open_flame_graph(bar._thread_index, bar._collector_index, bar._frame_number); -} - -/** - * - */ -void MacStatsTimeline:: -handle_open_piano_roll() { - const ColorBar &bar = _popup_bar; - MacStatsGraph::_monitor->open_piano_roll(bar._thread_index); -} - -/** - * Draws a vertical guide bar. If the row is -1, draws it in all rows. - */ -void MacStatsTimeline:: -draw_guide_bar(CGContextRef ctx, GuideBarStyle style, int x, int y, int height) { - double width = 1.0; - if (style == GBS_frame) { - width *= 2; - } - - CGContextSetFillColorWithColor(ctx, [NSColor gridColor].CGColor); - CGContextFillRect(ctx, CGRectMake(x - width / 2.0, y, width, height)); -} - -/** - * This is called during the servicing of the draw event. - */ -void MacStatsTimeline:: -draw_guide_labels(CGContextRef ctx) { - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_label(ctx, get_guide_bar(i)); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void MacStatsTimeline:: -draw_guide_label(CGContextRef ctx, const PStatGraph::GuideBar &bar) { - const std::string &label = bar._label; - if (label.empty()) { - return; - } - - NSColor *color; - if (@available(macOS 11.0, *)) { - color = [NSColor tertiaryLabelColor]; - } else { - // Otherwise it's hard to see on the dark titlebars - color = [NSColor windowFrameTextColor]; - } - /*switch (bar._style) { - case GBS_target: - color = [NSColor colorWithDeviceRed:rgb_light_gray[0] green:rgb_light_gray[1] blue:rgb_light_gray[2] alpha:1.0]; - break; - - case GBS_user: - color = [NSColor colorWithDeviceRed:rgb_user_guide_bar[0] green:rgb_user_guide_bar[1] blue:rgb_user_guide_bar[2] alpha:1.0]; - break; - - case GBS_normal: - color = [NSColor colorWithDeviceRed:rgb_light_gray[0] green:rgb_light_gray[1] blue:rgb_light_gray[2] alpha:1.0]; - break; - - case GBS_frame: - color = [NSColor colorWithDeviceRed:rgb_dark_gray[0] green:rgb_dark_gray[1] blue:rgb_dark_gray[2] alpha:1.0]; - break; - }*/ - - const CFStringRef keys[] = { - (__bridge CFStringRef)NSForegroundColorAttributeName, - (__bridge CFStringRef)NSFontAttributeName, - }; - const void *values[] = { - color, - [NSFont systemFontOfSize:0.0], - }; - CFDictionaryRef attribs = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, label.c_str(), kCFStringEncodingUTF8); - CFAttributedStringRef astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attribs); - CFRelease(attribs); - CFRelease(str); - - CTLineRef line = CTLineCreateWithAttributedString(astr); - CFRelease(astr); - CGRect bounds = CTLineGetImageBounds(line, ctx); - //int height = bounds.size.height; - int width = bounds.size.width; - - NSRect graph_bounds = _graph_view.bounds; - - int x = timestamp_to_pixel(bar._height); - x = [_scale_area convertPoint:NSMakePoint(x, 0) fromView:_graph_view].x; - - if (x + width >= 0 && x + width < get_xsize()) { - if (x + width < graph_bounds.size.width) { - CGContextSetTextPosition(ctx, x + 6, 6); - CTLineDraw(line, ctx); - } - } - - CFRelease(line); -} - -@implementation MacStatsTimelineViewController - -- (void)handleZoomTo:(NSMenuItem *)item { - ((MacStatsTimeline *)_graph)->handle_zoom_to(); -} - -- (void)handleOpenStripChart:(NSMenuItem *)item { - ((MacStatsTimeline *)_graph)->handle_open_strip_chart(); -} - -- (void)handleOpenFlameGraph:(NSMenuItem *)item { - ((MacStatsTimeline *)_graph)->handle_open_flame_graph(); -} - -- (void)handleOpenPianoRoll:(NSMenuItem *)item { - ((MacStatsTimeline *)_graph)->handle_open_piano_roll(); -} - -@end - diff --git a/pandatool/src/mac-stats/macstats_composite1.mm b/pandatool/src/mac-stats/macstats_composite1.mm deleted file mode 100644 index 5ae8136a..00000000 --- a/pandatool/src/mac-stats/macstats_composite1.mm +++ /dev/null @@ -1,16 +0,0 @@ -#include "macStats.mm" -#include "macStatsAppDelegate.mm" -#include "macStatsChartMenu.mm" -#include "macStatsChartMenuDelegate.mm" -#include "macStatsFlameGraph.mm" -#include "macStatsGraph.mm" -#include "macStatsGraphView.mm" -#include "macStatsGraphViewController.mm" -#include "macStatsLabel.mm" -#include "macStatsLabelStack.mm" -#include "macStatsMonitor.mm" -#include "macStatsPianoRoll.mm" -#include "macStatsScaleArea.mm" -#include "macStatsServer.mm" -#include "macStatsStripChart.mm" -#include "macStatsTimeline.mm" diff --git a/pandatool/src/miscprogs/CMakeLists.txt b/pandatool/src/miscprogs/CMakeLists.txt deleted file mode 100644 index 64ce488e..00000000 --- a/pandatool/src/miscprogs/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(bin2c binToC.cxx binToC.h) -target_link_libraries(bin2c p3progbase) -install(TARGETS bin2c EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/miscprogs/binToC.cxx b/pandatool/src/miscprogs/binToC.cxx deleted file mode 100644 index ae9fbc40..00000000 --- a/pandatool/src/miscprogs/binToC.cxx +++ /dev/null @@ -1,149 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file binToC.cxx - * @author drose - * @date 2003-07-18 - */ - -#include "binToC.h" - -// The number of bytes across the page to write. -static const int col_width = 11; - -/** - * - */ -BinToC:: -BinToC() : - WithOutputFile(true, true, false) -{ - clear_runlines(); - add_runline("input output.c"); - add_runline("input -o output.c"); - add_runline("input >output.c"); - - set_program_brief("convert binary data to a compilable C table"); - set_program_description - ("bin2c is a simple utility program to read a disk file, presumably " - "one with binary contents, and output a table that can be " - "compiled via a C compiler to generate the same data. It's handy " - "for portably importing binary data into a library or executable."); - - add_option - ("n", "name", 0, - "Specify the name of the table that is generated.", - &BinToC::dispatch_string, nullptr, &_table_name); - - add_option - ("static", "", 0, - "Flag the table with the keyword 'static'.", - &BinToC::dispatch_none, &_static_table); - - add_option - ("string", "", 0, - "Define the table suitablly to pass to a string constructor.", - &BinToC::dispatch_none, &_for_string); - - add_option - ("o", "filename", 0, - "Specify the filename to which the resulting C code will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file, or standard output is used if there are no " - "other parameters.", - &BinToC::dispatch_filename, &_got_output_filename, &_output_filename); - - _table_name = "data"; -} - -/** - * - */ -void BinToC:: -run() { - std::ifstream in; - if (!_input_filename.open_read(in)) { - nout << "Unable to read " << _input_filename << ".\n"; - exit(1); - } - - std::ostream &out = get_output(); - std::string static_keyword; - if (_static_table) { - static_keyword = "static "; - } - - std::string table_type = "const unsigned char "; - std::string length_type = "const int "; - if (_for_string) { - // Actually, declaring the table as "const char" causes VC7 to yell about - // truncating all of the values >= 0x80. table_type = "const char "; - length_type = "const size_t "; - } - - out << "\n" - << "/*\n" - << " * This table was generated by the command:\n" - << " *\n" - << " * " << get_exec_command() << "\n" - << " */\n" - << "\n" - << "#include \n" - << "\n" - << static_keyword << table_type << _table_name << "[] = {"; - out << std::hex << std::setfill('0'); - int count = 0; - int col = 0; - int ch = in.get(); - while (!in.fail() && ch != EOF) { - if (col == 0) { - out << "\n "; - } else if (col == col_width) { - out << ",\n "; - col = 0; - } else { - out << ", "; - } - out << "0x" << std::setw(2) << (unsigned int)ch; - col++; - count++; - ch = in.get(); - } - out << "\n};\n\n" - << static_keyword << length_type << _table_name << "_len = " - << std::dec << count << ";\n\n"; -} - -/** - * - */ -bool BinToC:: -handle_args(ProgramBase::Args &args) { - if (args.size() == 2 && !_got_output_filename) { - // The second argument, if present, is implicitly the output file. - _got_output_filename = true; - _output_filename = args[1]; - args.pop_back(); - } - - if (args.size() != 1) { - nout << "You must specify exactly one input file to read on the command line.\n"; - return false; - } - - _input_filename = Filename::binary_filename(args[0]); - return true; -} - - -int main(int argc, char *argv[]) { - BinToC prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/miscprogs/binToC.h b/pandatool/src/miscprogs/binToC.h deleted file mode 100644 index f1ba6599..00000000 --- a/pandatool/src/miscprogs/binToC.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file binToC.h - * @author drose - * @date 2003-07-18 - */ - -#ifndef BINTOC_H -#define BINTOC_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "withOutputFile.h" - -/** - * A utility program to read a (binary) file and output a table that can be - * compiled via a C compiler to generate the same data. Handy for portably - * importing binary data into a library or executable. - */ -class BinToC : public ProgramBase, public WithOutputFile { -public: - BinToC(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - - Filename _input_filename; - std::string _table_name; - bool _static_table; - bool _for_string; -}; - -#endif diff --git a/pandatool/src/objegg/CMakeLists.txt b/pandatool/src/objegg/CMakeLists.txt deleted file mode 100644 index c6106815..00000000 --- a/pandatool/src/objegg/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3OBJEGG_HEADERS - config_objegg.h - eggToObjConverter.h - objToEggConverter.h - objToEggConverter.I -) - -set(P3OBJEGG_SOURCES - config_objegg.cxx - eggToObjConverter.cxx - objToEggConverter.cxx -) - -composite_sources(p3objegg P3OBJEGG_SOURCES) -add_library(p3objegg STATIC ${P3OBJEGG_HEADERS} ${P3OBJEGG_SOURCES}) -target_link_libraries(p3objegg p3eggbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/objegg/config_objegg.cxx b/pandatool/src/objegg/config_objegg.cxx deleted file mode 100644 index 7896ab30..00000000 --- a/pandatool/src/objegg/config_objegg.cxx +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_objegg.cxx - * @author drose - * @date 2010-12-07 - */ - -#include "config_objegg.h" -#include "dconfig.h" - -Configure(config_objegg); -NotifyCategoryDef(objegg, ""); - -ConfigureFn(config_objegg) { - init_libobjegg(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libobjegg() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; -} diff --git a/pandatool/src/objegg/config_objegg.h b/pandatool/src/objegg/config_objegg.h deleted file mode 100644 index 179d647a..00000000 --- a/pandatool/src/objegg/config_objegg.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_objegg.h - * @author drose - * @date 2010-12-07 - */ - -#ifndef CONFIG_OBJEGG_H -#define CONFIG_OBJEGG_H - -#include "pandatoolbase.h" -#include "notifyCategoryProxy.h" - -NotifyCategoryDeclNoExport(objegg); - -extern void init_libobjegg(); - -#endif diff --git a/pandatool/src/objegg/eggToObjConverter.cxx b/pandatool/src/objegg/eggToObjConverter.cxx deleted file mode 100644 index a0363069..00000000 --- a/pandatool/src/objegg/eggToObjConverter.cxx +++ /dev/null @@ -1,411 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToObjConverter.cxx - * @author drose - * @date 2012-12-19 - */ - -#include "eggToObjConverter.h" -#include "config_objegg.h" -#include "config_egg.h" -#include "eggData.h" -#include "string_utils.h" -#include "streamReader.h" -#include "virtualFileSystem.h" -#include "eggPolygon.h" -#include "eggPoint.h" -#include "eggLine.h" -#include "dcast.h" - -using std::ostream; -using std::string; - -/** - * - */ -EggToObjConverter:: -EggToObjConverter() { -} - -/** - * - */ -EggToObjConverter:: -EggToObjConverter(const EggToObjConverter ©) : - EggToSomethingConverter(copy) -{ -} - -/** - * - */ -EggToObjConverter:: -~EggToObjConverter() { -} - -/** - * Allocates and returns a new copy of the converter. - */ -EggToSomethingConverter *EggToObjConverter:: -make_copy() { - return new EggToObjConverter(*this); -} - - -/** - * Returns the English name of the file type this converter supports. - */ -string EggToObjConverter:: -get_name() const { - return "obj"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -string EggToObjConverter:: -get_extension() const { - return "obj"; -} - -/** - * Returns true if this file type can transparently save compressed files - * (with a .pz extension), false otherwise. - */ -bool EggToObjConverter:: -supports_compressed() const { - return true; -} - -/** - * Handles the conversion of the internal EggData to the target file format, - * written to the specified filename. - */ -bool EggToObjConverter:: -write_file(const Filename &filename) { - clear_error(); - - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_zup_right); - } - - if (!process(filename)) { - _error = true; - } - return !had_error(); -} - -/** - * - */ -bool EggToObjConverter:: -process(const Filename &filename) { - _egg_data->flatten_transforms(); - collect_vertices(_egg_data); - - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - Filename obj_filename = Filename::text_filename(filename); - vfs->delete_file(obj_filename); - ostream *file = vfs->open_write_file(obj_filename, true, true); - if (file == nullptr) { - return false; - } - if (egg_precision != 0) { - file->precision(egg_precision); - } - - _current_group = nullptr; - - /* - (*file) << "\n#\n" - << "# obj file generated by the following command:\n" - << "# " << get_exec_command() << "\n" - << "#\n\n"; - */ - - write_vertices(*file, "v", 3, _unique_vert3); - write_vertices(*file, "v", 4, _unique_vert4); - write_vertices(*file, "vt", 2, _unique_uv2); - write_vertices(*file, "vt", 3, _unique_uv3); - write_vertices(*file, "vn", 3, _unique_norm); - - write_faces(*file, _egg_data); - - bool success = (file != nullptr); - vfs->close_write_file(file); - - return success; -} - -/** - * Recursively walks the egg structure, looking for vertices referenced by - * polygons or points. Any such vertices are added to the vertex tables for - * writing to the obj file. - */ -void EggToObjConverter:: -collect_vertices(EggNode *egg_node) { - if (egg_node->is_of_type(EggPrimitive::get_class_type())) { - EggPrimitive *egg_prim = DCAST(EggPrimitive, egg_node); - EggPrimitive::iterator pi; - for (pi = egg_prim->begin(); pi != egg_prim->end(); ++pi) { - record_vertex(*pi); - } - - } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); - - EggGroupNode::iterator ci; - for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { - collect_vertices(*ci); - } - } -} - -/** - * Recursively walks the egg structure again, this time writing out the face - * records for any polygons, points, or lines encountered. - */ -void EggToObjConverter:: -write_faces(ostream &out, EggNode *egg_node) { - if (egg_node->is_of_type(EggPrimitive::get_class_type())) { - const char *prim_type = nullptr; - if (egg_node->is_of_type(EggPolygon::get_class_type())) { - prim_type = "f"; - } else if (egg_node->is_of_type(EggPoint::get_class_type())) { - prim_type = "p"; - } else if (egg_node->is_of_type(EggLine::get_class_type())) { - prim_type = "l"; - } - - if (prim_type != nullptr) { - write_group_reference(out, egg_node); - - EggPrimitive *egg_prim = DCAST(EggPrimitive, egg_node); - - out << prim_type; - EggPrimitive::iterator pi; - for (pi = egg_prim->begin(); pi != egg_prim->end(); ++pi) { - VertexDef &vdef = _vmap[(*pi)]; - int vert_index = -1; - int uv_index = -1; - int norm_index = -1; - - if (vdef._vert3_index != -1) { - vert_index = vdef._vert3_index + 1; - } else if (vdef._vert4_index != -1) { - vert_index = vdef._vert4_index + 1 + (int)_unique_vert3.size(); - } - - if (vdef._uv2_index != -1) { - uv_index = vdef._uv2_index + 1; - } else if (vdef._uv3_index != -1) { - uv_index = vdef._uv3_index + 1 + (int)_unique_uv2.size(); - } - - if (vdef._norm_index != -1) { - norm_index = vdef._norm_index + 1; - } - - if (vert_index == -1) { - continue; - } - - if (norm_index != -1) { - if (uv_index != -1) { - out << " " << vert_index << "/" << uv_index << "/" << norm_index; - } else { - out << " " << vert_index << "//" << norm_index; - } - } else if (uv_index != -1) { - out << " " << vert_index << "/" << uv_index; - } else { - out << " " << vert_index; - } - } - out << "\n"; - } - } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); - - EggGroupNode::iterator ci; - for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) { - write_faces(out, *ci); - } - } -} - -/** - * Writes the "g" tag to describe this polygon's group, if needed. - */ -void EggToObjConverter:: -write_group_reference(ostream &out, EggNode *egg_node) { - EggGroupNode *egg_group = egg_node->get_parent(); - if (egg_group == _current_group) { - // Same group we wrote last time. - return; - } - - string group_name; - get_group_name(group_name, egg_group); - if (group_name.empty()) { - out << "g default\n"; - } else { - out << "g" << group_name << "\n"; - } - _current_group = egg_group; -} - -/** - * Recursively determines the appropriate string to write for the "g" tag to - * describe a particular EggGroupNode. - */ -void EggToObjConverter:: -get_group_name(string &group_name, EggGroupNode *egg_group) { - string name = trim(egg_group->get_name()); - if (!name.empty()) { - group_name += ' '; - - // Remove nonstandard characters. - for (string::const_iterator ni = name.begin(); ni != name.end(); ++ni) { - char c = (*ni); - if (!isalnum(c)) { - c = '_'; - } - group_name += c; - } - } - - // Now recurse. - EggGroupNode *egg_parent = egg_group->get_parent(); - if (egg_parent != nullptr) { - get_group_name(group_name, egg_parent); - } -} - -/** - * Adds the indicated EggVertex to the unique vertex tables, for writing later - * by write_vertices(). - */ -void EggToObjConverter:: -record_vertex(EggVertex *vertex) { - VertexDef &vdef = _vmap[vertex]; - - switch (vertex->get_num_dimensions()) { - case 1: - vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos1()); - break; - case 2: - vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos2()); - break; - case 3: - vdef._vert3_index = record_unique(_unique_vert3, vertex->get_pos3()); - break; - case 4: - vdef._vert4_index = record_unique(_unique_vert4, vertex->get_pos4()); - break; - } - - if (vertex->has_uv("")) { - vdef._uv2_index = record_unique(_unique_uv2, vertex->get_uv("")); - } else if (vertex->has_uvw("")) { - vdef._uv3_index = record_unique(_unique_uv3, vertex->get_uvw("")); - } - - if (vertex->has_normal()) { - vdef._norm_index = record_unique(_unique_norm, vertex->get_normal()); - } -} - -/** - * Records the indicated vertex value, returning the shared index if this - * value already appears elsewhere in the table, or the new unique index if - * this is the first time this value appears. - */ -int EggToObjConverter:: -record_unique(UniqueVertices &unique, const LVecBase4d &vec) { - // We record a zero-based index. Note that we will actually write out a - // one-based index to the obj file, as required by the standard. - int index = unique.size(); - UniqueVertices::iterator ui = unique.insert(UniqueVertices::value_type(vec, index)).first; - return (*ui).second; -} - -/** - * Records the indicated vertex value, returning the shared index if this - * value already appears elsewhere in the table, or the new unique index if - * this is the first time this value appears. - */ -int EggToObjConverter:: -record_unique(UniqueVertices &unique, const LVecBase3d &vec) { - return record_unique(unique, LVecBase4d(vec[0], vec[1], vec[2], 0.0)); -} - -/** - * Records the indicated vertex value, returning the shared index if this - * value already appears elsewhere in the table, or the new unique index if - * this is the first time this value appears. - */ -int EggToObjConverter:: -record_unique(UniqueVertices &unique, const LVecBase2d &vec) { - return record_unique(unique, LVecBase4d(vec[0], vec[1], 0.0, 0.0)); -} - -/** - * Records the indicated vertex value, returning the shared index if this - * value already appears elsewhere in the table, or the new unique index if - * this is the first time this value appears. - */ -int EggToObjConverter:: -record_unique(UniqueVertices &unique, double pos) { - return record_unique(unique, LVecBase4d(pos, 0.0, 0.0, 0.0)); -} - -/** - * Actually writes the vertex values recorded in the indicated table to the - * obj output stream. - */ -void EggToObjConverter:: -write_vertices(ostream &out, const string &prefix, int num_components, - const UniqueVertices &unique) { - // First, sort the list into numeric order. - int num_vertices = (int)unique.size(); - const LVecBase4d **vertices = (const LVecBase4d **)PANDA_MALLOC_ARRAY(num_vertices * sizeof(LVecBase4d *)); - memset(vertices, 0, num_vertices * sizeof(LVecBase4d *)); - UniqueVertices::const_iterator ui; - for (ui = unique.begin(); ui != unique.end(); ++ui) { - int index = (*ui).second; - const LVecBase4d &vec = (*ui).first; - nassertv(index >= 0 && index < num_vertices); - nassertv(vertices[index] == nullptr); - vertices[index] = &vec; - } - - for (int i = 0; i < num_vertices; ++i) { - out << prefix; - const LVecBase4d &vec = *(vertices[i]); - for (int ci = 0; ci < num_components; ++ci) { - out << " " << vec[ci]; - } - out << "\n"; - } - PANDA_FREE_ARRAY(vertices); -} - -/** - * - */ -EggToObjConverter::VertexDef:: -VertexDef() : - _vert3_index(-1), - _vert4_index(-1), - _uv2_index(-1), - _uv3_index(-1), - _norm_index(-1) -{ -} diff --git a/pandatool/src/objegg/eggToObjConverter.h b/pandatool/src/objegg/eggToObjConverter.h deleted file mode 100644 index 51f940d5..00000000 --- a/pandatool/src/objegg/eggToObjConverter.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToObjConverter.h - * @author drose - * @date 2012-12-19 - */ - -#ifndef EGGTOOBJCONVERTER_H -#define EGGTOOBJCONVERTER_H - -#include "pandatoolbase.h" - -#include "eggToSomethingConverter.h" -#include "eggVertexPool.h" -#include "eggGroup.h" - -/** - * Convert an obj file to egg data. - */ -class EggToObjConverter : public EggToSomethingConverter { -public: - EggToObjConverter(); - EggToObjConverter(const EggToObjConverter ©); - ~EggToObjConverter(); - - virtual EggToSomethingConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual bool supports_compressed() const; - - virtual bool write_file(const Filename &filename); - -private: - typedef pmap UniqueVertices; - class VertexDef { - public: - VertexDef(); - int _vert3_index; - int _vert4_index; - int _uv2_index; - int _uv3_index; - int _norm_index; - }; - typedef pmap VertexMap; - - bool process(const Filename &filename); - - void collect_vertices(EggNode *egg_node); - void write_faces(std::ostream &out, EggNode *egg_node); - void write_group_reference(std::ostream &out, EggNode *egg_node); - void get_group_name(std::string &group_name, EggGroupNode *egg_group); - - void record_vertex(EggVertex *vertex); - int record_unique(UniqueVertices &unique, const LVecBase4d &vec); - int record_unique(UniqueVertices &unique, const LVecBase3d &vec); - int record_unique(UniqueVertices &unique, const LVecBase2d &vec); - int record_unique(UniqueVertices &unique, double pos); - - void write_vertices(std::ostream &out, const std::string &prefix, int num_components, - const UniqueVertices &unique); - -private: - UniqueVertices _unique_vert3, _unique_vert4, _unique_uv2, _unique_uv3, _unique_norm; - VertexMap _vmap; - EggGroupNode *_current_group; -}; - -#endif diff --git a/pandatool/src/objegg/objToEggConverter.I b/pandatool/src/objegg/objToEggConverter.I deleted file mode 100644 index c8a2d629..00000000 --- a/pandatool/src/objegg/objToEggConverter.I +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file objToEggConverter.I - * @author drose - * @date 2013-01-03 - */ - -/** - * Provides a unique but arbitrary ordering for VertexEntry objects in a map. - */ -INLINE bool ObjToEggConverter::VertexEntry:: -operator < (const VertexEntry &other) const { - if (_vi != other._vi) { - return _vi < other._vi; - } - if (_vti != other._vti) { - return _vti < other._vti; - } - - // It's important that these two tests are made last, so we can find the - // first vertex that has any normal but also matches the above properties. - if (_vni != other._vni) { - return _vni < other._vni; - } - if (_synth_vni != other._synth_vni) { - return _synth_vni < other._synth_vni; - } - return false; -} - -/** - * - */ -INLINE bool ObjToEggConverter::VertexEntry:: -operator == (const VertexEntry &other) const { - return (_vi == other._vi && _vti == other._vti && - _vni == other._vni && _synth_vni == other._synth_vni); -} - -/** - * Returns true if all the properties except _vni and _synth_vni are - * equivalent. - */ -INLINE bool ObjToEggConverter::VertexEntry:: -matches_except_normal(const VertexEntry &other) const { - return (_vi == other._vi && _vti == other._vti); -} diff --git a/pandatool/src/objegg/objToEggConverter.cxx b/pandatool/src/objegg/objToEggConverter.cxx deleted file mode 100644 index 7044409c..00000000 --- a/pandatool/src/objegg/objToEggConverter.cxx +++ /dev/null @@ -1,1106 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file objToEggConverter.cxx - * @author drose - * @date 2010-12-07 - */ - -#include "objToEggConverter.h" -#include "config_objegg.h" -#include "eggData.h" -#include "string_utils.h" -#include "streamReader.h" -#include "virtualFileSystem.h" -#include "eggPolygon.h" -#include "nodePath.h" -#include "geomTriangles.h" -#include "geomPoints.h" -#include "colorAttrib.h" -#include "shadeModelAttrib.h" -#include "dcast.h" -#include "triangulator3.h" -#include "config_egg2pg.h" - -using std::string; - -/** - * - */ -ObjToEggConverter:: -ObjToEggConverter() { -} - -/** - * - */ -ObjToEggConverter:: -ObjToEggConverter(const ObjToEggConverter ©) : - SomethingToEggConverter(copy) -{ -} - -/** - * - */ -ObjToEggConverter:: -~ObjToEggConverter() { -} - -/** - * Allocates and returns a new copy of the converter. - */ -SomethingToEggConverter *ObjToEggConverter:: -make_copy() { - return new ObjToEggConverter(*this); -} - - -/** - * Returns the English name of the file type this converter supports. - */ -string ObjToEggConverter:: -get_name() const { - return "obj"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -string ObjToEggConverter:: -get_extension() const { - return "obj"; -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. - */ -bool ObjToEggConverter:: -supports_compressed() const { - return true; -} - -/** - * Returns true if this converter can directly convert the model type to - * internal Panda memory structures, given the indicated options, or false - * otherwise. If this returns true, then convert_to_node() may be called to - * perform the conversion, which may be faster than calling convert_file() if - * the ultimate goal is a PandaNode anyway. - */ -bool ObjToEggConverter:: -supports_convert_to_node(const LoaderOptions &options) const { - return true; -} - -/** - * Handles the reading of the input file and converting it to egg. Returns - * true if successful, false otherwise. - */ -bool ObjToEggConverter:: -convert_file(const Filename &filename) { - clear_error(); - - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_zup_right); - } - - if (!process(filename)) { - _error = true; - } - return !had_error(); -} - -/** - * Reads the input file and directly produces a ready-to-render model file as - * a PandaNode. Returns NULL on failure, or if it is not supported. (This - * functionality is not supported by all converter types; see - * supports_convert_to_node()). - */ -PT(PandaNode) ObjToEggConverter:: -convert_to_node(const LoaderOptions &options, const Filename &filename) { - clear_error(); - - _root_node = new PandaNode(""); - _current_vertex_data = new VertexData(_root_node, "root"); - - if (!process_node(filename)) { - _error = true; - } - - _current_vertex_data->close_geom(this); - delete _current_vertex_data; - - if (had_error()) { - return nullptr; - } - - return _root_node; -} - -/** - * Reads the file and converts it to egg structures. - */ -bool ObjToEggConverter:: -process(const Filename &filename) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - std::istream *strm = vfs->open_read_file(filename, true); - if (strm == nullptr) { - objegg_cat.error() - << "Couldn't read " << filename << "\n"; - return false; - } - - _v_table.clear(); - _vn_table.clear(); - _rgb_table.clear(); - _vt_table.clear(); - _xvt_table.clear(); - _ref_plane_res.set(1.0, 1.0); - _v4_given = false; - _vt3_given = false; - _f_given = false; - - _vpool = new EggVertexPool("vpool"); - _egg_data->add_child(_vpool); - _root_group = new EggGroup("root"); - _egg_data->add_child(_root_group); - _current_group = _root_group; - - StreamReader sr(strm, true); - string line = sr.readline(); - _line_number = 1; - while (!line.empty()) { - line = trim(line); - if (line.empty()) { - line = sr.readline(); - continue; - } - - while (line[line.length() - 1] == '\\') { - // If it ends on a backslash, it's a continuation character. - string line2 = sr.readline(); - ++_line_number; - if (line2.empty()) { - break; - } - line = line.substr(0, line.length() - 1) + trim(line2); - } - - if (line.substr(0, 15) == "#_ref_plane_res") { - process_ref_plane_res(line); - line = sr.readline(); - continue; - } - - if (line[0] == '#') { - line = sr.readline(); - continue; - } - - if (!process_line(line)) { - return false; - } - line = sr.readline(); - ++_line_number; - } - - if (!_f_given) { - generate_egg_points(); - } - - return true; -} - -/** - * - */ -bool ObjToEggConverter:: -process_line(const string &line) { - vector_string words; - tokenize(line, words, " \t", true); - nassertr(!words.empty(), false); - - string tag = words[0]; - if (tag == "v") { - return process_v(words); - } else if (tag == "vt") { - return process_vt(words); - } else if (tag == "xvt") { - return process_xvt(words); - } else if (tag == "xvc") { - return process_xvc(words); - } else if (tag == "vn") { - return process_vn(words); - } else if (tag == "f") { - return process_f(words); - } else if (tag == "g") { - return process_g(words); - } else { - bool inserted = _ignored_tags.insert(tag).second; - if (inserted) { - objegg_cat.info() - << "Ignoring tag " << tag << "\n"; - } - } - - return true; -} - -/** - * - */ -bool ObjToEggConverter:: -process_ref_plane_res(const string &line) { - // the #_ref_plane_res line is a DRZ extension that defines the pixel - // resolution of the projector device. It's needed to properly scale the - // xvt lines. - - vector_string words; - tokenize(line, words, " \t", true); - nassertr(!words.empty(), false); - - if (words.size() != 3) { - objegg_cat.error() - << "Wrong number of tokens at line " << _line_number << "\n"; - return false; - } - - bool okflag = true; - okflag &= string_to_double(words[1], _ref_plane_res[0]); - okflag &= string_to_double(words[2], _ref_plane_res[1]); - - if (!okflag) { - objegg_cat.error() - << "Invalid number at line " << _line_number << ":\n"; - return false; - } - - return true; -} - -/** - * - */ -bool ObjToEggConverter:: -process_v(vector_string &words) { - if (words.size() != 4 && words.size() != 5 && - words.size() != 7 && words.size() != 8) { - objegg_cat.error() - << "Wrong number of tokens at line " << _line_number << "\n"; - return false; - } - - bool okflag = true; - LPoint4d pos; - okflag &= string_to_double(words[1], pos[0]); - okflag &= string_to_double(words[2], pos[1]); - okflag &= string_to_double(words[3], pos[2]); - if (words.size() == 5 || words.size() == 8) { - okflag &= string_to_double(words[4], pos[3]); - _v4_given = true; - } else { - pos[3] = 1.0; - } - - if (!okflag) { - objegg_cat.error() - << "Invalid number at line " << _line_number << "\n"; - return false; - } - - _v_table.push_back(pos); - - // Meshlab format might include an RGB color following the vertex position. - if (words.size() == 7 && words.size() == 8) { - size_t si = words.size(); - LVecBase3d rgb; - okflag &= string_to_double(words[si - 3], rgb[0]); - okflag &= string_to_double(words[si - 2], rgb[1]); - okflag &= string_to_double(words[si - 1], rgb[2]); - - if (!okflag) { - objegg_cat.error() - << "Invalid number at line " << _line_number << "\n"; - return false; - } - while (_rgb_table.size() + 1 < _v_table.size()) { - _rgb_table.push_back(LVecBase3d(1.0, 1.0, 1.0)); - } - _rgb_table.push_back(rgb); - } - - return true; -} - -/** - * - */ -bool ObjToEggConverter:: -process_vt(vector_string &words) { - if (words.size() != 3 && words.size() != 4) { - objegg_cat.error() - << "Wrong number of tokens at line " << _line_number << "\n"; - return false; - } - - bool okflag = true; - LTexCoord3d uvw; - okflag &= string_to_double(words[1], uvw[0]); - okflag &= string_to_double(words[2], uvw[1]); - if (words.size() == 4) { - okflag &= string_to_double(words[3], uvw[2]); - _vt3_given = true; - } else { - uvw[2] = 0.0; - } - - if (!okflag) { - objegg_cat.error() - << "Invalid number at line " << _line_number << "\n"; - return false; - } - - _vt_table.push_back(uvw); - - return true; -} - -/** - * "xvt" is an extended column invented by DRZ. It includes texture - * coordinates in pixel space of the projector device, as well as for each - * camera. We map it to the nominal texture coordinates here. - */ -bool ObjToEggConverter:: -process_xvt(vector_string &words) { - if (words.size() < 3) { - objegg_cat.error() - << "Wrong number of tokens at line " << _line_number << "\n"; - return false; - } - - bool okflag = true; - LTexCoordd uv; - okflag &= string_to_double(words[1], uv[0]); - okflag &= string_to_double(words[2], uv[1]); - - if (!okflag) { - objegg_cat.error() - << "Invalid number at line " << _line_number << "\n"; - return false; - } - - uv[0] /= _ref_plane_res[0]; - uv[1] = 1.0 - uv[1] / _ref_plane_res[1]; - - _xvt_table.push_back(uv); - - return true; -} - -/** - * "xvc" is another extended column invented by DRZ. We quietly ignore it. - */ -bool ObjToEggConverter:: -process_xvc(vector_string &words) { - return true; -} - -/** - * - */ -bool ObjToEggConverter:: -process_vn(vector_string &words) { - if (words.size() != 4) { - objegg_cat.error() - << "Wrong number of tokens at line " << _line_number << "\n"; - return false; - } - - bool okflag = true; - LVector3d normal; - okflag &= string_to_double(words[1], normal[0]); - okflag &= string_to_double(words[2], normal[1]); - okflag &= string_to_double(words[3], normal[2]); - - if (!okflag) { - objegg_cat.error() - << "Invalid number at line " << _line_number << "\n"; - return false; - } - normal.normalize(); - - _vn_table.push_back(normal); - - return true; -} - -/** - * Defines a face in the obj file. - */ -bool ObjToEggConverter:: -process_f(vector_string &words) { - _f_given = true; - - PT(EggPolygon) poly = new EggPolygon; - for (size_t i = 1; i < words.size(); ++i) { - EggVertex *vertex = get_face_vertex(words[i]); - if (vertex == nullptr) { - return false; - } - poly->add_vertex(vertex); - } - _current_group->add_child(poly); - - return true; -} - -/** - * Defines a group in the obj file. - */ -bool ObjToEggConverter:: -process_g(vector_string &words) { - EggGroup *group = _root_group; - - // We assume the group names define a hierarchy of more-specific to less- - // specific group names, so that the first group name is the bottommost - // node, and the last group name is the topmost node. - - // Thus, iterate from the back to the front. - size_t i = words.size(); - while (i > 1) { - --i; - EggNode *child = group->find_child(words[i]); - if (child == nullptr || !child->is_of_type(EggGroup::get_class_type())) { - child = new EggGroup(words[i]); - group->add_child(child); - } - group = DCAST(EggGroup, child); - } - - _current_group = group; - return true; -} - -/** - * Returns or creates a vertex in the vpool according to the indicated face - * reference. - */ -EggVertex *ObjToEggConverter:: -get_face_vertex(const string &reference) { - VertexEntry entry(this, reference); - - // Synthesize a vertex. - EggVertex synth; - - if (entry._vi != 0) { - if (_v4_given) { - synth.set_pos(LCAST(double, _v_table[entry._vi - 1])); - } else { - LPoint4d pos = _v_table[entry._vi - 1]; - synth.set_pos(LPoint3d(pos[0], pos[1], pos[2])); - } - - if (entry._vi - 1 < (int)_rgb_table.size()) { - // We have a per-vertex color too. - LRGBColord rgb = _rgb_table[entry._vi - 1]; - LColor rgba(rgb[0], rgb[1], rgb[2], 1.0); - synth.set_color(rgba); - } - } - - if (entry._vti != 0) { - // We have a texture coordinate; apply it. - if (_vt3_given) { - synth.set_uvw("", _vt_table[entry._vti - 1]); - } else { - LTexCoord3d uvw = _vt_table[entry._vti - 1]; - synth.set_uv("", LTexCoordd(uvw[0], uvw[1])); - } - } else if (entry._vi - 1 < (int)_xvt_table.size()) { - // We have an xvt texture coordinate. - synth.set_uv("", _xvt_table[entry._vi - 1]); - } - - if (entry._vni != 0) { - // We have a normal; apply it. - synth.set_normal(_vn_table[entry._vni - 1]); - } - - return _vpool->create_unique_vertex(synth); -} - -/** - * If an obj file defines no faces, create a bunch of EggVertex objects to - * illustrate the vertex positions at least. - */ -void ObjToEggConverter:: -generate_egg_points() { - for (size_t vi = 0; vi < _v_table.size(); ++vi) { - const LVecBase4d &p = _v_table[vi]; - _vpool->make_new_vertex(LVecBase3d(p[0], p[1], p[2])); - } -} - - -/** - * Reads the file and converts it to PandaNode structures. - */ -bool ObjToEggConverter:: -process_node(const Filename &filename) { - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - std::istream *strm = vfs->open_read_file(filename, true); - if (strm == nullptr) { - objegg_cat.error() - << "Couldn't read " << filename << "\n"; - return false; - } - - _v_table.clear(); - _vn_table.clear(); - _rgb_table.clear(); - _vt_table.clear(); - _xvt_table.clear(); - _ref_plane_res.set(1.0, 1.0); - _v4_given = false; - _vt3_given = false; - _f_given = false; - - StreamReader sr(strm, true); - string line = sr.readline(); - _line_number = 1; - while (!line.empty()) { - line = trim(line); - if (line.empty()) { - line = sr.readline(); - continue; - } - - if (line.substr(0, 15) == "#_ref_plane_res") { - process_ref_plane_res(line); - line = sr.readline(); - continue; - } - - if (line[0] == '#') { - line = sr.readline(); - continue; - } - - if (!process_line_node(line)) { - return false; - } - line = sr.readline(); - ++_line_number; - } - - if (!_f_given) { - generate_points(); - } - - return true; -} - -/** - * - */ -bool ObjToEggConverter:: -process_line_node(const string &line) { - vector_string words; - tokenize(line, words, " \t", true); - nassertr(!words.empty(), false); - - string tag = words[0]; - if (tag == "v") { - return process_v(words); - } else if (tag == "vt") { - return process_vt(words); - } else if (tag == "xvt") { - return process_xvt(words); - } else if (tag == "xvc") { - return process_xvc(words); - } else if (tag == "vn") { - return process_vn(words); - } else if (tag == "f") { - return process_f_node(words); - } else if (tag == "g") { - return process_g_node(words); - } else { - bool inserted = _ignored_tags.insert(tag).second; - if (inserted) { - objegg_cat.info() - << "Ignoring tag " << tag << "\n"; - } - } - - return true; -} - -/** - * Defines a face in the obj file. - */ -bool ObjToEggConverter:: -process_f_node(vector_string &words) { - _f_given = true; - - bool all_vn = true; - //int non_vn_index = -1; - - pvector verts; - verts.reserve(words.size() - 1); - for (size_t i = 1; i < words.size(); ++i) { - VertexEntry entry(this, words[i]); - verts.push_back(entry); - if (entry._vni == 0) { - all_vn = false; - //non_vn_index = i; - } - } - - if (verts.size() < 3) { - // Not enough vertices. - objegg_cat.error() - << "Degenerate face at " << _line_number << "\n"; - return false; - } - - int synth_vni = 0; - if (!all_vn) { - // Synthesize a normal if we need it. - LNormald normal = LNormald::zero(); - for (size_t i = 0; i < verts.size(); ++i) { - int vi0 = verts[i]._vi; - int vi1 = verts[(i + 1) % verts.size()]._vi; - if (vi0 == 0 || vi1 == 0) { - continue; - } - const LVecBase4d &p0 = _v_table[vi0 - 1]; - const LVecBase4d &p1 = _v_table[vi1 - 1]; - - normal[0] += p0[1] * p1[2] - p0[2] * p1[1]; - normal[1] += p0[2] * p1[0] - p0[0] * p1[2]; - normal[2] += p0[0] * p1[1] - p0[1] * p1[0]; - } - normal.normalize(); - synth_vni = add_synth_normal(normal); - } - - Triangulator3 tri; - int num_tris = 1; - - if (verts.size() != 3) { - // We have to triangulate a higher-order polygon. - for (size_t i = 0; i < verts.size(); ++i) { - const LVecBase4d &p = _v_table[verts[i]._vi - 1]; - tri.add_vertex(p[0], p[1], p[2]); - tri.add_polygon_vertex(i); - } - - tri.triangulate(); - num_tris = tri.get_num_triangles(); - } - - if (_current_vertex_data->_prim->get_num_vertices() + 3 * num_tris > egg_max_indices || - _current_vertex_data->_entries.size() + verts.size() > (size_t)egg_max_vertices) { - // We'll exceed our specified limit with these triangles; start a new - // Geom. - _current_vertex_data->close_geom(this); - } - - if (verts.size() == 3) { - // It's already a triangle; add it directly. - _current_vertex_data->add_triangle(this, verts[0], verts[1], verts[2], synth_vni); - - } else { - // Get the triangulated results. - for (int ti = 0; ti < num_tris; ++ti) { - int i0 = tri.get_triangle_v0(ti); - int i1 = tri.get_triangle_v1(ti); - int i2 = tri.get_triangle_v2(ti); - _current_vertex_data->add_triangle(this, verts[i0], verts[i1], verts[i2], synth_vni); - } - } - - return true; -} - -/** - * Defines a group in the obj file. - */ -bool ObjToEggConverter:: -process_g_node(vector_string &words) { - _current_vertex_data->close_geom(this); - delete _current_vertex_data; - _current_vertex_data = nullptr; - - NodePath np(_root_node); - - // We assume the group names define a hierarchy of more-specific to less- - // specific group names, so that the first group name is the bottommost - // node, and the last group name is the topmost node. - - // Thus, iterate from the back to the front. - size_t i = words.size(); - string name; - while (i > 2) { - --i; - name = words[i]; - NodePath child = np.find(name); - if (!child) { - child = np.attach_new_node(name); - } - np = child; - } - - if (i > 1) { - --i; - name = words[i]; - } - - _current_vertex_data = new VertexData(np.node(), name); - - return true; -} - -/** - * If an obj file defines no faces, create a bunch of GeomPoints to illustrate - * the vertex positions at least. - */ -void ObjToEggConverter:: -generate_points() { - CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3(); - PT(GeomVertexData) vdata = new GeomVertexData("points", format, GeomEnums::UH_static); - vdata->set_num_rows(_v_table.size()); - GeomVertexWriter vertex_writer(vdata, InternalName::get_vertex()); - - for (size_t vi = 0; vi < _v_table.size(); ++vi) { - const LVecBase4d &p = _v_table[vi]; - vertex_writer.add_data3d(p[0], p[1], p[2]); - } - - PT(GeomPrimitive) prim = new GeomPoints(GeomEnums::UH_static); - prim->add_next_vertices(_v_table.size()); - prim->close_primitive(); - - PT(Geom) geom = new Geom(vdata); - geom->add_primitive(prim); - - PT(GeomNode) geom_node = new GeomNode("points"); - geom_node->add_geom(geom); - _root_node->add_child(geom_node); -} - -/** - * Adds a new normal to the synth_vn table, or returns an existing normal. In - * either case returns the 1-based index number to the normal. - */ -int ObjToEggConverter:: -add_synth_normal(const LVecBase3d &normal) { - std::pair result = _unique_synth_vn_table.insert(UniqueVec3Table::value_type(normal, _unique_synth_vn_table.size())); - UniqueVec3Table::iterator ni = result.first; - int index = (*ni).second; - - if (result.second) { - // If the normal was added to the table, it's a unique normal, and now we - // have to add it to the table too. - _synth_vn_table.push_back(normal); - } - - return index + 1; -} - -/** - * Creates a VertexEntry from the n/n/n string format in the obj file face - * reference. - */ -ObjToEggConverter::VertexEntry:: -VertexEntry(const ObjToEggConverter *converter, const string &obj_vertex) { - _vi = 0; - _vti = 0; - _vni = 0; - _synth_vni = 0; - - vector_string words; - tokenize(obj_vertex, words, "/", false); - nassertv(!words.empty()); - - for (size_t i = 0; i < words.size(); ++i) { - int index; - if (trim(words[i]).empty()) { - index = 0; - } else { - if (!string_to_int(words[i], index)) { - index = 0; - } - } - - switch (i) { - case 0: - _vi = index; - if (_vi < 0) { - _vi = (int)converter->_v_table.size() + _vi; - } - if (_vi < 0 || _vi - 1 >= (int)converter->_v_table.size()) { - _vi = 0; - } - break; - - case 1: - _vti = index; - if (_vti < 0) { - _vti = (int)converter->_vt_table.size() + _vti; - } - if (_vti < 0 || _vti - 1 >= (int)converter->_vt_table.size()) { - _vti = 0; - } - break; - - case 2: - _vni = index; - if (_vni < 0) { - _vni = (int)converter->_vn_table.size() + _vni; - } - if (_vni < 0 || _vni - 1 >= (int)converter->_vn_table.size()) { - _vni = 0; - } - break; - } - } -} - -/** - * - */ -ObjToEggConverter::VertexData:: -VertexData(PandaNode *parent, const string &name) : - _parent(parent), _name(name) -{ - _geom_node = nullptr; - - _v4_given = false; - _vt3_given = false; - _vt_given = false; - _rgb_given = false; - _vn_given = false; - - _prim = new GeomTriangles(GeomEnums::UH_static); -} - -/** - * Adds a new entry to the vertex data for the indicated VertexEntry, or - * returns an equivalent vertex already present. - */ -int ObjToEggConverter::VertexData:: -add_vertex(const ObjToEggConverter *converter, const VertexEntry &entry) { - std::pair result; - UniqueVertexEntries::iterator ni; - int index; - - if (entry._vni != 0 || entry._synth_vni != 0) { - // If we are storing a vertex with a normal, see if we have already stored - // a vertex without a normal first. - VertexEntry no_normal(entry); - no_normal._vni = 0; - no_normal._synth_vni = 0; - ni = _unique_entries.find(no_normal); - if (ni != _unique_entries.end()) { - // We did have such a vertex! In this case, repurpose this vertex, - // resetting it to contain this normal. - index = (*ni).second; - _unique_entries.erase(ni); - result = _unique_entries.insert(UniqueVertexEntries::value_type(entry, index)); - nassertr(result.second, index); - nassertr(_entries[index] == no_normal, index); - _entries[index]._vni = entry._vni; - _entries[index]._synth_vni = entry._synth_vni; - return index; - } - } else if (entry._vni == 0 && entry._synth_vni == 0) { - // If we are storing a vertex *without* any normal, see if we have already - // stored a vertex with a normal first. - ni = _unique_entries.lower_bound(entry); - if (ni != _unique_entries.end() && (*ni).first.matches_except_normal(entry)) { - // We had such a vertex, so use it. - index = (*ni).second; - return index; - } - } - - // We didn't already have a vertex we could repurpose, so try to add exactly - // the desired vertex. - result = _unique_entries.insert(UniqueVertexEntries::value_type(entry, _entries.size())); - ni = result.first; - index = (*ni).second; - - if (result.second) { - // If the vertex was added to the table, it's a unique vertex, and now we - // have to add it to the vertex data too. - _entries.push_back(entry); - - if (converter->_v4_given) { - _v4_given = true; - } - if (converter->_vt3_given) { - _vt3_given = true; - } - if (entry._vti != 0) { - _vt_given = true; - } else if (entry._vi - 1 < (int)converter->_xvt_table.size()) { - // We have an xvt texture coordinate. - _vt_given = true; - } - if (entry._vi - 1 < (int)converter->_rgb_table.size()) { - // We have a per-vertex color too. - _rgb_given = true; - } - if (entry._vni != 0) { - _vn_given = true; - } - } - - return index; -} - -/** - * Adds a triangle to the primitive, as a triple of three VertexEntry objects, - * which are each added to the vertex pool. If synth_vni is not 0, it is - * assigned to the last vertex. - */ -void ObjToEggConverter::VertexData:: -add_triangle(const ObjToEggConverter *converter, const VertexEntry &v0, - const VertexEntry &v1, const VertexEntry &v2, - int synth_vni) { - int v0i, v1i, v2i; - - v0i = add_vertex(converter, v0); - v1i = add_vertex(converter, v1); - - if (synth_vni != 0) { - VertexEntry v2n(v2); - v2n._synth_vni = synth_vni; - v2i = add_vertex(converter, v2n); - } else { - v2i = add_vertex(converter, v2); - } - - _prim->add_vertices(v0i, v1i, v2i); - _prim->close_primitive(); -} - -/** - * Finishes the current geom and stores it as a child in the root. Prepares - * for new geoms. - */ -void ObjToEggConverter::VertexData:: -close_geom(const ObjToEggConverter *converter) { - if (_prim->get_num_vertices() != 0) { - // Create a new format that includes only the columns we actually used. - PT(GeomVertexArrayFormat) aformat = new GeomVertexArrayFormat; - if (_v4_given) { - aformat->add_column(InternalName::get_vertex(), 4, - GeomEnums::NT_stdfloat, GeomEnums::C_point); - } else { - aformat->add_column(InternalName::get_vertex(), 3, - GeomEnums::NT_stdfloat, GeomEnums::C_point); - } - - // We always add normals--if no normals appeared in the file, we - // synthesize them. - aformat->add_column(InternalName::get_normal(), 3, - GeomEnums::NT_stdfloat, GeomEnums::C_vector); - - if (_vt_given) { - if (_vt3_given) { - aformat->add_column(InternalName::get_texcoord(), 3, - GeomEnums::NT_stdfloat, GeomEnums::C_texcoord); - } else { - aformat->add_column(InternalName::get_texcoord(), 2, - GeomEnums::NT_stdfloat, GeomEnums::C_texcoord); - } - } - - if (_rgb_given) { - aformat->add_column(InternalName::get_color(), 4, - GeomEnums::NT_uint8, GeomEnums::C_color); - } - - CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(aformat); - - // Create and populate the vertex data. - PT(GeomVertexData) vdata = new GeomVertexData(_name, format, GeomEnums::UH_static); - GeomVertexWriter vertex_writer(vdata, InternalName::get_vertex()); - GeomVertexWriter normal_writer(vdata, InternalName::get_normal()); - GeomVertexWriter texcoord_writer(vdata, InternalName::get_texcoord()); - GeomVertexWriter color_writer(vdata, InternalName::get_color()); - - for (size_t i = 0; i < _entries.size(); ++i) { - const VertexEntry &entry = _entries[i]; - - if (entry._vi != 0) { - vertex_writer.set_row(i); - vertex_writer.add_data4d(converter->_v_table[entry._vi - 1]); - } - if (entry._vti != 0) { - texcoord_writer.set_row(i); - texcoord_writer.add_data3d(converter->_vt_table[entry._vti - 1]); - } else if (entry._vi - 1 < (int)converter->_xvt_table.size()) { - // We have an xvt texture coordinate. - texcoord_writer.set_row(i); - texcoord_writer.add_data2d(converter->_xvt_table[entry._vi - 1]); - } - if (entry._vni != 0) { - normal_writer.set_row(i); - normal_writer.add_data3d(converter->_vn_table[entry._vni - 1]); - } else if (entry._synth_vni != 0) { - normal_writer.set_row(i); - normal_writer.add_data3d(converter->_synth_vn_table[entry._synth_vni - 1]); - } else { - // In this case, the normal isn't used and doesn't matter; we fill it - // in a unit vector just for neatness. - normal_writer.set_row(i); - normal_writer.add_data3d(0, 0, 1); - } - if (_rgb_given) { - if (entry._vi - 1 < (int)converter->_rgb_table.size()) { - color_writer.set_row(i); - color_writer.add_data3d(converter->_rgb_table[entry._vi - 1]); - } - } - } - - // Transform to zup-right. - vdata->transform_vertices(LMatrix4::convert_mat(CS_zup_right, CS_default)); - - // Now create a Geom with this data. - CPT(RenderState) state = RenderState::make_empty(); - if (_rgb_given) { - state = state->add_attrib(ColorAttrib::make_vertex()); - } else { - state = state->add_attrib(ColorAttrib::make_flat(LColor(1, 1, 1, 1))); - } - if (!_vn_given) { - // We have synthesized these normals; specify the flat-shading attrib. - state = state->add_attrib(ShadeModelAttrib::make(ShadeModelAttrib::M_flat)); - _prim->set_shade_model(GeomEnums::SM_flat_last_vertex); - } - - PT(Geom) geom = new Geom(vdata); - geom->add_primitive(_prim); - - if (_geom_node == nullptr) { - _geom_node = new GeomNode(_name); - _parent->add_child(_geom_node); - } - - _geom_node->add_geom(geom, state); - } - - _prim = new GeomTriangles(GeomEnums::UH_static); - _entries.clear(); - _unique_entries.clear(); -} diff --git a/pandatool/src/objegg/objToEggConverter.h b/pandatool/src/objegg/objToEggConverter.h deleted file mode 100644 index 528dab8e..00000000 --- a/pandatool/src/objegg/objToEggConverter.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file objToEggConverter.h - * @author drose - * @date 2010-12-07 - */ - -#ifndef OBJTOEGGCONVERTER_H -#define OBJTOEGGCONVERTER_H - -#include "pandatoolbase.h" - -#include "somethingToEggConverter.h" -#include "eggVertexPool.h" -#include "eggGroup.h" -#include "geomVertexData.h" -#include "geomVertexWriter.h" -#include "geomPrimitive.h" -#include "geomNode.h" -#include "pandaNode.h" -#include "pvector.h" -#include "epvector.h" - -/** - * Convert an Obj file to egg data. - */ -class ObjToEggConverter : public SomethingToEggConverter { -public: - ObjToEggConverter(); - ObjToEggConverter(const ObjToEggConverter ©); - ~ObjToEggConverter(); - - virtual SomethingToEggConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual bool supports_compressed() const; - virtual bool supports_convert_to_node(const LoaderOptions &options) const; - - virtual bool convert_file(const Filename &filename); - virtual PT(PandaNode) convert_to_node(const LoaderOptions &options, const Filename &filename); - -protected: - bool process(const Filename &filename); - bool process_line(const std::string &line); - bool process_ref_plane_res(const std::string &line); - - bool process_v(vector_string &words); - bool process_vt(vector_string &words); - bool process_xvt(vector_string &words); - bool process_xvc(vector_string &words); - bool process_vn(vector_string &words); - bool process_f(vector_string &words); - bool process_g(vector_string &words); - - EggVertex *get_face_vertex(const std::string &face_reference); - void generate_egg_points(); - - bool process_node(const Filename &filename); - bool process_line_node(const std::string &line); - - bool process_f_node(vector_string &words); - bool process_g_node(vector_string &words); - - void generate_points(); - int add_synth_normal(const LVecBase3d &normal); - - // Read from the obj file. - int _line_number; - typedef epvector Vec4Table; - typedef epvector Vec3Table; - typedef epvector Vec2Table; - typedef pmap UniqueVec3Table; - - Vec4Table _v_table; - Vec3Table _vn_table, _rgb_table; - Vec3Table _vt_table; - Vec2Table _xvt_table; - Vec3Table _synth_vn_table; - UniqueVec3Table _unique_synth_vn_table; - LVecBase2d _ref_plane_res; - bool _v4_given, _vt3_given; - bool _f_given; - - pset _ignored_tags; - - // Structures filled when creating an egg file. - PT(EggVertexPool) _vpool; - PT(EggGroup) _root_group; - EggGroup *_current_group; - - // Structures filled when creating a PandaNode directly. - PT(PandaNode) _root_node; - - class VertexEntry { - public: - VertexEntry(); - VertexEntry(const ObjToEggConverter *converter, const std::string &obj_vertex); - - INLINE bool operator < (const VertexEntry &other) const; - INLINE bool operator == (const VertexEntry &other) const; - INLINE bool matches_except_normal(const VertexEntry &other) const; - - // The 1-based vertex, texcoord, and normal index numbers appearing in the - // obj file for this vertex. 0 if the index number is not given. - int _vi, _vti, _vni; - - // The 1-based index number to the synthesized normal, if needed. - int _synth_vni; - }; - typedef pmap UniqueVertexEntries; - typedef pvector VertexEntries; - - class VertexData { - public: - VertexData(PandaNode *parent, const std::string &name); - - int add_vertex(const ObjToEggConverter *converter, const VertexEntry &entry); - void add_triangle(const ObjToEggConverter *converter, const VertexEntry &v0, - const VertexEntry &v1, const VertexEntry &v2, - int synth_vni); - void close_geom(const ObjToEggConverter *converter); - - PT(PandaNode) _parent; - std::string _name; - PT(GeomNode) _geom_node; - - PT(GeomPrimitive) _prim; - VertexEntries _entries; - UniqueVertexEntries _unique_entries; - - bool _v4_given, _vt3_given; - bool _vt_given, _rgb_given, _vn_given; - }; - - VertexData *_current_vertex_data; - - friend class VertexData; -}; - -#include "objToEggConverter.I" - -#endif diff --git a/pandatool/src/objprogs/CMakeLists.txt b/pandatool/src/objprogs/CMakeLists.txt deleted file mode 100644 index 084f140e..00000000 --- a/pandatool/src/objprogs/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_EGG) - return() -endif() - -add_executable(egg2obj eggToObj.cxx eggToObj.h) -target_link_libraries(egg2obj p3objegg p3eggbase) -install(TARGETS egg2obj EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(obj2egg objToEgg.cxx objToEgg.h) -target_link_libraries(obj2egg p3objegg p3eggbase p3progbase) -install(TARGETS obj2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/objprogs/eggToObj.cxx b/pandatool/src/objprogs/eggToObj.cxx deleted file mode 100644 index aac15220..00000000 --- a/pandatool/src/objprogs/eggToObj.cxx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToObj.cxx - * @author drose - * @date 2012-02-28 - */ - -#include "eggToObj.h" -#include "eggPolygon.h" -#include "eggGroupNode.h" -#include "dcast.h" -#include "string_utils.h" - -/** - * - */ -EggToObj:: -EggToObj() : - EggToSomething("Obj", ".obj", true, false) -{ - set_program_brief("convert .egg files to .obj"); - set_program_description - ("This program converts egg files to obj. It " - "only converts polygon data, with no fancy tricks. " - "Very bare-bones at the moment; not even texture maps are supported."); - - redescribe_option - ("cs", - "Specify the coordinate system of the resulting " + _format_name + - " file. Normally, this is z-up."); - - add_option - ("C", "", 0, - "Clean out higher-order polygons by subdividing into triangles.", - &EggToObj::dispatch_none, &_triangulate_polygons); - - _coordinate_system = CS_zup_right; - _got_coordinate_system = true; -} - -/** - * - */ -void EggToObj:: -run() { - if (_triangulate_polygons) { - nout << "Triangulating polygons.\n"; - int num_produced = _data->triangulate_polygons(~0); - nout << " (" << num_produced << " triangles produced.)\n"; - } - - EggToObjConverter saver; - saver.set_egg_data(_data); - - if (!saver.write_file(get_output_filename())) { - nout << "An error occurred while writing.\n"; - exit(1); - } -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool EggToObj:: -handle_args(ProgramBase::Args &args) { - return EggToSomething::handle_args(args); -} - -int main(int argc, char *argv[]) { - EggToObj prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/objprogs/eggToObj.h b/pandatool/src/objprogs/eggToObj.h deleted file mode 100644 index b3a50215..00000000 --- a/pandatool/src/objprogs/eggToObj.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToObj.h - * @author drose - * @date 2012-02-25 - */ - -#ifndef EGGTOOBJ_H -#define EGGTOOBJ_H - -#include "pandatoolbase.h" -#include "eggToSomething.h" -#include "eggToObjConverter.h" - -/** - * - */ -class EggToObj : public EggToSomething { -public: - EggToObj(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - -private: - bool _triangulate_polygons; -}; - -#endif diff --git a/pandatool/src/objprogs/objToEgg.cxx b/pandatool/src/objprogs/objToEgg.cxx deleted file mode 100644 index 9a46aa71..00000000 --- a/pandatool/src/objprogs/objToEgg.cxx +++ /dev/null @@ -1,74 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file objToEgg.cxx - * @author drose - * @date 2004-05-04 - */ - -#include "objToEgg.h" - -#include "objToEggConverter.h" - -/** - * - */ -ObjToEgg:: -ObjToEgg() : - SomethingToEgg("obj", ".obj") -{ - add_units_options(); - add_points_options(); - add_normals_options(); - add_transform_options(); - - set_program_brief("convert .obj files to .egg"); - set_program_description - ("This program converts obj files to egg. It " - "only converts polygon data, with no fancy tricks. " - "Very bare-bones at the moment; not even texture maps are supported."); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. Normally, this is z-up."); - - _coordinate_system = CS_zup_right; -} - -/** - * - */ -void ObjToEgg:: -run() { - nout << "Reading " << _input_filename << "\n"; - - _data->set_coordinate_system(_coordinate_system); - - ObjToEggConverter converter; - converter.set_egg_data(_data); - converter._allow_errors = _allow_errors; - - apply_parameters(converter); - - if (!converter.convert_file(_input_filename)) { - nout << "Errors in conversion.\n"; - exit(1); - } - - write_egg_file(); - nout << "\n"; -} - - -int main(int argc, char *argv[]) { - ObjToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/objprogs/objToEgg.h b/pandatool/src/objprogs/objToEgg.h deleted file mode 100644 index 310a5d07..00000000 --- a/pandatool/src/objprogs/objToEgg.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file objToEgg.h - * @author drose - * @date 2010-12-07 - */ - -#ifndef OBJTOEGG_H -#define OBJTOEGG_H - -#include "pandatoolbase.h" - -#include "somethingToEgg.h" -#include "objToEggConverter.h" - -/** - * A program to read a Obj file and generate an egg file. - */ -class ObjToEgg : public SomethingToEgg { -public: - ObjToEgg(); - - void run(); -}; - -#endif diff --git a/pandatool/src/palettizer/CMakeLists.txt b/pandatool/src/palettizer/CMakeLists.txt deleted file mode 100644 index f3cb2818..00000000 --- a/pandatool/src/palettizer/CMakeLists.txt +++ /dev/null @@ -1,60 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3PALETTIZER_HEADERS - config_palettizer.h - destTextureImage.h - eggFile.h - filenameUnifier.h - imageFile.h - omitReason.h - paletteGroup.h - paletteGroups.h - paletteImage.h - palettePage.h - palettizer.h - pal_string_utils.h - sourceTextureImage.h - textureImage.h - textureMemoryCounter.h - texturePlacement.h - texturePosition.h - textureProperties.h - textureReference.h - textureRequest.h - txaFile.h - txaLine.h -) - -set(P3PALETTIZER_SOURCES - config_palettizer.cxx - destTextureImage.cxx - eggFile.cxx - filenameUnifier.cxx - imageFile.cxx - omitReason.cxx - paletteGroup.cxx - paletteGroups.cxx - paletteImage.cxx - palettePage.cxx - palettizer.cxx - pal_string_utils.cxx - sourceTextureImage.cxx - textureImage.cxx - textureMemoryCounter.cxx - texturePlacement.cxx - texturePosition.cxx - textureProperties.cxx - textureReference.cxx - textureRequest.cxx - txaFile.cxx - txaLine.cxx -) - -composite_sources(p3palettizer P3PALETTIZER_SOURCES) -add_library(p3palettizer STATIC ${P3PALETTIZER_HEADERS} ${P3PALETTIZER_SOURCES}) -target_link_libraries(p3palettizer p3progbase p3converter) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/palettizer/config_palettizer.cxx b/pandatool/src/palettizer/config_palettizer.cxx deleted file mode 100644 index 160fb922..00000000 --- a/pandatool/src/palettizer/config_palettizer.cxx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_palettizer.cxx - * @author drose - * @date 2003-09-12 - */ - -#include "config_palettizer.h" -#include "palettizer.h" -#include "eggFile.h" -#include "paletteGroup.h" -#include "paletteGroups.h" -#include "textureReference.h" -#include "textureProperties.h" -#include "imageFile.h" -#include "sourceTextureImage.h" -#include "destTextureImage.h" -#include "textureImage.h" -#include "paletteImage.h" -#include "texturePlacement.h" -#include "texturePosition.h" -#include "palettePage.h" - -#include "dconfig.h" - -Configure(config_palettizer); - -ConfigureFn(config_palettizer) { - init_palettizer(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_palettizer() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - Palettizer::init_type(); - EggFile::init_type(); - PaletteGroup::init_type(); - PaletteGroups::init_type(); - TextureReference::init_type(); - TextureProperties::init_type(); - ImageFile::init_type(); - SourceTextureImage::init_type(); - DestTextureImage::init_type(); - TextureImage::init_type(); - PaletteImage::init_type(); - TexturePlacement::init_type(); - TexturePosition::init_type(); - PalettePage::init_type(); - - // Registration of writable object's creation functions with BamReader's - // factory - Palettizer::register_with_read_factory(); - EggFile::register_with_read_factory(); - PaletteGroup::register_with_read_factory(); - PaletteGroups::register_with_read_factory(); - TextureReference::register_with_read_factory(); - TextureProperties::register_with_read_factory(); - SourceTextureImage::register_with_read_factory(); - DestTextureImage::register_with_read_factory(); - TextureImage::register_with_read_factory(); - PaletteImage::register_with_read_factory(); - TexturePlacement::register_with_read_factory(); - TexturePosition::register_with_read_factory(); - PalettePage::register_with_read_factory(); -} diff --git a/pandatool/src/palettizer/config_palettizer.h b/pandatool/src/palettizer/config_palettizer.h deleted file mode 100644 index afb2031d..00000000 --- a/pandatool/src/palettizer/config_palettizer.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_palettizer.h - * @author drose - * @date 2003-09-12 - */ - -#ifndef CONFIG_PALETTIZER_H -#define CONFIG_PALETTIZER_H - -#include "pandatoolbase.h" - -void init_palettizer(); - -#endif /* CONFIG_PALETTIZER_H */ diff --git a/pandatool/src/palettizer/destTextureImage.cxx b/pandatool/src/palettizer/destTextureImage.cxx deleted file mode 100644 index 3c80f3d9..00000000 --- a/pandatool/src/palettizer/destTextureImage.cxx +++ /dev/null @@ -1,161 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file destTextureImage.cxx - * @author drose - * @date 2000-12-05 - */ - -#include "destTextureImage.h" -#include "sourceTextureImage.h" -#include "texturePlacement.h" -#include "textureImage.h" -#include "palettizer.h" - -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" - -TypeHandle DestTextureImage::_type_handle; - - -/** - * The default constructor is only for the convenience of the Bam reader. - */ -DestTextureImage:: -DestTextureImage() { -} - -/** - * - */ -DestTextureImage:: -DestTextureImage(TexturePlacement *placement) { - TextureImage *texture = placement->get_texture(); - _properties = texture->get_properties(); - _size_known = texture->is_size_known(); - if (_size_known) { - _x_size = texture->get_x_size(); - _y_size = texture->get_y_size(); - - if (pal->_force_power_2) { - _x_size = to_power_2(_x_size); - _y_size = to_power_2(_y_size); - } else { - _x_size = std::max(_x_size, 1); - _y_size = std::max(_y_size, 1); - } - } - - set_filename(placement->get_group(), texture->get_name()); -} - -/** - * Unconditionally copies the source texture into the appropriate filename. - */ -void DestTextureImage:: -copy(TextureImage *texture) { - const PNMImage &source_image = texture->read_source_image(); - if (source_image.is_valid()) { - PNMImage dest_image(_x_size, _y_size, texture->get_num_channels(), - source_image.get_maxval()); - dest_image.quick_filter_from(source_image); - write(dest_image); - - } else { - // Couldn't read the texture, so fill it with red. - PNMImage dest_image(_x_size, _y_size, texture->get_num_channels()); - dest_image.fill(1.0, 0.0, 0.0); - if (dest_image.has_alpha()) { - dest_image.alpha_fill(1.0); - } - - write(dest_image); - } - - texture->release_source_image(); -} - -/** - * Copies the source texture into the appropriate filename only if the - * indicated old reference, which represents the way it was last copied, is - * now out-of-date. - */ -void DestTextureImage:: -copy_if_stale(const DestTextureImage *other, TextureImage *texture) { - if (other->get_x_size() != get_x_size() || - other->get_y_size() != get_y_size() || - other->get_num_channels() != get_num_channels()) { - copy(texture); - - } else { - // Also check the timestamps. - SourceTextureImage *source = texture->get_preferred_source(); - - if (source != nullptr && - source->get_filename().compare_timestamps(get_filename()) > 0) { - copy(texture); - } - } -} - -/** - * Returns the largest power of 2 less than or equal to value. - */ -int DestTextureImage:: -to_power_2(int value) { - int x = 1; - while ((x << 1) <= value) { - x = (x << 1); - } - return x; -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void DestTextureImage:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void DestTextureImage:: -write_datagram(BamWriter *writer, Datagram &datagram) { - ImageFile::write_datagram(writer, datagram); -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *DestTextureImage:: -make_from_bam(const FactoryParams ¶ms) { - DestTextureImage *me = new DestTextureImage; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void DestTextureImage:: -fillin(DatagramIterator &scan, BamReader *manager) { - ImageFile::fillin(scan, manager); -} diff --git a/pandatool/src/palettizer/destTextureImage.h b/pandatool/src/palettizer/destTextureImage.h deleted file mode 100644 index 860655b6..00000000 --- a/pandatool/src/palettizer/destTextureImage.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file destTextureImage.h - * @author drose - * @date 2000-12-05 - */ - -#ifndef DESTTEXTUREIMAGE_H -#define DESTTEXTUREIMAGE_H - -#include "pandatoolbase.h" - -#include "imageFile.h" - -class TexturePlacement; -class TextureImage; - -/** - * This represents a texture filename as it has been resized and copied to the - * map directory (e.g. for an unplaced texture). - */ -class DestTextureImage : public ImageFile { -private: - DestTextureImage(); - -public: - DestTextureImage(TexturePlacement *placement); - - void copy(TextureImage *texture); - void copy_if_stale(const DestTextureImage *other, TextureImage *texture); - -private: - static int to_power_2(int value); - - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - ImageFile::init_type(); - register_type(_type_handle, "DestTextureImage", - ImageFile::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -INLINE std::ostream & -operator << (std::ostream &out, const DestTextureImage &dest) { - dest.output_filename(out); - return out; -} - -#endif diff --git a/pandatool/src/palettizer/eggFile.cxx b/pandatool/src/palettizer/eggFile.cxx deleted file mode 100644 index c47eae2f..00000000 --- a/pandatool/src/palettizer/eggFile.cxx +++ /dev/null @@ -1,808 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggFile.cxx - * @author drose - * @date 2000-11-29 - */ - -#include "eggFile.h" -#include "textureImage.h" -#include "paletteGroup.h" -#include "texturePlacement.h" -#include "textureReference.h" -#include "sourceTextureImage.h" -#include "palettizer.h" -#include "filenameUnifier.h" - -#include "eggData.h" -#include "eggGroup.h" -#include "eggTextureCollection.h" -#include "eggComment.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "executionEnvironment.h" -#include "dSearchPath.h" -#include "indirectLess.h" - -#include - -TypeHandle EggFile::_type_handle; - -/** - * - */ -EggFile:: -EggFile() { - _data = nullptr; - _first_txa_match = false; - _default_group = nullptr; - _is_surprise = true; - _is_stale = true; - _had_data = false; -} - -/** - * Accepts the information about the egg file as supplied from the command - * line. Returns true if the egg file is valid, false otherwise. - */ -bool EggFile:: -from_command_line(EggData *data, - const Filename &source_filename, - const Filename &dest_filename, - const std::string &egg_comment) { - _data = data; - _had_data = true; - remove_backstage(_data); - - // We save the current directory at the time the egg file appeared on the - // command line, so that we'll later be able to properly resolve external - // references (like textures) that might be relative to this directory. - _current_directory = ExecutionEnvironment::get_cwd(); - _source_filename = source_filename; - _source_filename.make_absolute(); - _dest_filename = dest_filename; - _dest_filename.make_absolute(); - - // We also save the command line that loaded this egg file, so we can - // continue to write it as a comment to the beginning of the egg file, - // should we need to rewrite it later. - _egg_comment = egg_comment; - - // We save the default PaletteGroup at this point, because the egg file - // inherits the default group that was in effect when it was specified on - // the command line. - _default_group = pal->get_default_group(); - - return true; -} - -/** - * Returns the filename this egg file was read from. - */ -const Filename &EggFile:: -get_source_filename() const { - return _source_filename; -} - - -/** - * Scans the egg file for texture references and updates the _textures list - * appropriately. This assumes the egg file was supplied on the command line - * and thus the _data member is available. - */ -void EggFile:: -scan_textures() { - nassertv(_data != nullptr); - - // Extract the set of textures referenced by this egg file. - EggTextureCollection tc; - tc.find_used_textures(_data); - - // Make sure each tref name is unique within a given file. - tc.uniquify_trefs(); - - // Now build up a list of new TextureReference objects that represent the - // textures actually used and their uv range, etc. - Textures new_textures; - - EggTextureCollection::iterator eti; - for (eti = tc.begin(); eti != tc.end(); ++eti) { - EggTexture *egg_tex = (*eti); - - TextureReference *ref = new TextureReference; - ref->from_egg(this, _data, egg_tex); - - if (!ref->has_uvs()) { - // This texture isn't *really* referenced. (Usually this happens if the - // texture is only referenced by "backstage" geometry, which we don't - // care about.) - delete ref; - - } else { - new_textures.push_back(ref); - } - } - - // Sort the new references into order so we can compare them with the - // original references. - sort(new_textures.begin(), new_textures.end(), - IndirectLess()); - - // Sort the original references too. This should already be sorted from the - // previous run, but we might as well be neurotic about it. - sort(_textures.begin(), _textures.end(), - IndirectLess()); - - // Now go through and merge the lists. - Textures combined_textures; - Textures::const_iterator ai = _textures.begin(); - Textures::const_iterator bi = new_textures.begin(); - - while (ai != _textures.end() && bi != new_textures.end()) { - TextureReference *aref = (*ai); - TextureReference *bref = (*bi); - - if ((*aref) < (*bref)) { - // Here's a texture reference in the original list, but not in the new - // list. Remove it. - delete aref; - ++ai; - - } else if ((*bref) < (*aref)) { - // Here's a texture reference in the new list, but not in the original - // list. Add it. - combined_textures.push_back(bref); - ++bi; - - } else { // (*bref) == (*aref) - // Here's a texture reference that was in both lists. Compare it. - if (aref->is_equivalent(*bref)) { - // It hasn't changed substantially, so keep the original (which still - // has the placement references from a previous pass). - aref->from_egg_quick(*bref); - combined_textures.push_back(aref); - delete bref; - - } else { - // It has changed, so drop the original and keep the new one. - combined_textures.push_back(bref); - delete aref; - } - ++ai; - ++bi; - } - } - - while (bi != new_textures.end()) { - TextureReference *bref = (*bi); - // Here's a texture reference in the new list, but not in the original - // list. Add it. - combined_textures.push_back(bref); - ++bi; - } - - while (ai != _textures.end()) { - TextureReference *aref = (*ai); - // Here's a texture reference in the original list, but not in the new - // list. Remove it. - delete aref; - ++ai; - } - - _textures.swap(combined_textures); -} - -/** - * Fills up the indicated set with the set of textures referenced by this egg - * file. It is the user's responsibility to ensure the set is empty before - * making this call; otherwise, the new textures will be appended to the - * existing set. - */ -void EggFile:: -get_textures(pset &result) const { - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - result.insert((*ti)->get_texture()); - } -} - -/** - * Does some processing prior to scanning the .txa file. - */ -void EggFile:: -pre_txa_file() { - _is_surprise = true; - _first_txa_match = true; -} - -/** - * Adds the indicated set of groups, read from the .txa file, to the set of - * groups to which the egg file is assigned. - */ -void EggFile:: -match_txa_groups(const PaletteGroups &groups) { - if (_first_txa_match) { - // If this is the first line we matched in the .txa file, clear the set of - // groups we'd matched from before. We don't clear until we match a line - // in the .txa file, because if we don't match any lines we still want to - // remember what groups we used to be assigned to. - _explicitly_assigned_groups.clear(); - _first_txa_match = false; - } - - _explicitly_assigned_groups.make_union(_explicitly_assigned_groups, groups); -} - -/** - * Once the egg file has been matched against all of the matching lines the - * .txa file, do whatever adjustment is necessary. - */ -void EggFile:: -post_txa_file() { -} - -/** - * Returns the set of PaletteGroups that the egg file has been explicitly - * assigned to in the .txa file. - */ -const PaletteGroups &EggFile:: -get_explicit_groups() const { - return _explicitly_assigned_groups; -} - -/** - * Returns the PaletteGroup that was specified as the default group on the - * command line at the time the egg file last appeared on the command line. - */ -PaletteGroup *EggFile:: -get_default_group() const { - return _default_group; -} - -/** - * Returns the complete set of PaletteGroups that the egg file is assigned to. - * This is the set of all the groups it is explicitly assigned to, plus all - * the groups that these groups depend on. - */ -const PaletteGroups &EggFile:: -get_complete_groups() const { - return _complete_groups; -} - -/** - * Removes the 'surprise' flag; this file has been successfully matched - * against a line in the .txa file. - */ -void EggFile:: -clear_surprise() { - _is_surprise = false; -} - -/** - * Returns true if this particular egg file is a 'surprise', i.e. it wasn't - * matched by a line in the .txa file that didn't include the keyword 'cont'. - */ -bool EggFile:: -is_surprise() const { - return _is_surprise; -} - -/** - * Marks this particular egg file as stale, meaning that something has - * changed, such as the location of a texture within its palette, which causes - * the egg file to need to be regenerated. - */ -void EggFile:: -mark_stale() { - _is_stale = true; -} - -/** - * Returns true if the egg file needs to be updated, i.e. some palettizations - * have changed affecting it, or false otherwise. - */ -bool EggFile:: -is_stale() const { - return _is_stale; -} - -/** - * Calls TextureImage::note_egg_file() and - * SourceTextureImage::increment_egg_count() for each texture the egg file - * references, and PaletteGroup::increment_egg_count() for each palette group - * it wants. This sets up some of the back references to support determining - * an ideal texture assignment. - */ -void EggFile:: -build_cross_links() { - if (_explicitly_assigned_groups.empty()) { - // If the egg file has been assigned to no groups, we have to assign it to - // something. - _complete_groups.clear(); - _complete_groups.insert(_default_group); - _complete_groups.make_complete(_complete_groups); - - } else { - _complete_groups.make_complete(_explicitly_assigned_groups); - } - - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureReference *reference = (*ti); - TextureImage *texture = reference->get_texture(); - nassertv(texture != nullptr); - texture->note_egg_file(this); - - // Actually, this may count the same egg file multiple times for a - // particular SourceTextureImage, since a given texture may be referenced - // multiples times within an egg file. No harm done, however. - reference->get_source()->increment_egg_count(); - } - - PaletteGroups::const_iterator gi; - for (gi = _complete_groups.begin(); - gi != _complete_groups.end(); - ++gi) { - (*gi)->increment_egg_count(); - } -} - -/** - * Calls apply_properties_to_source() for each texture reference, updating all - * the referenced source textures with the complete set of property - * information from this egg file. - */ -void EggFile:: -apply_properties_to_source() { - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureReference *reference = (*ti); - reference->apply_properties_to_source(); - } -} - -/** - * Once all the textures have been assigned to groups (but before they may - * actually be placed), chooses a suitable TexturePlacement for each texture - * that appears in the egg file. This will be necessary to do at some point - * before writing out the egg file anyway, and doing it before the textures - * are placed allows us to decide what the necessary UV range is for each to- - * be-placed texture. - */ -void EggFile:: -choose_placements() { - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureReference *reference = (*ti); - TextureImage *texture = reference->get_texture(); - - if (reference->get_placement() != nullptr && - texture->get_groups().count(reference->get_placement()->get_group()) != 0) { - // The egg file is already using a TexturePlacement that is suitable. - // Don't bother changing it. - - } else { - // We need to select a new TexturePlacement. - PaletteGroups groups; - groups.make_intersection(get_complete_groups(), texture->get_groups()); - - // Now groups is the set of groups that the egg file requires, which - // also happen to include the texture. - - if (groups.empty()) { - // It might be empty if the egg file was assigned only to the "null" - // group (since this group is not propagated to the textures). In - // this case, choose from the wider set of groups available to the - // texture. - groups = texture->get_groups(); - } - - if (!groups.empty()) { - // It doesn't really matter which group in the set we choose, so we - // arbitrarily choose the first one. - PaletteGroup *group = (*groups.begin()); - - // Now get the TexturePlacement object that corresponds to the - // placement of this texture into this group. - TexturePlacement *placement = texture->get_placement(group); - nassertv(placement != nullptr); - - reference->set_placement(placement); - } - } - } -} - -/** - * Returns true if the EggData for this EggFile has been loaded, and not yet - * released. - */ -bool EggFile:: -has_data() const { - return (_data != nullptr); -} - -/** - * Returns true if the EggData for this EggFile has ever been loaded in this - * session. - */ -bool EggFile:: -had_data() const { - return _had_data; -} - -/** - * Once all textures have been placed appropriately, updates the egg file with - * all the information to reference the new textures. - */ -void EggFile:: -update_egg() { - nassertv(_data != nullptr); - - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureReference *reference = (*ti); - reference->update_egg(); - } -} - -/** - * Removes this egg file from all things that reference it, in preparation for - * removing it from the database. - */ -void EggFile:: -remove_egg() { - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureReference *reference = (*ti); - TexturePlacement *placement = reference->get_placement(); - placement->remove_egg(reference); - } -} - -/** - * Reads in the egg file from its _source_filename. It is only valid to call - * this if it has not already been read in, e.g. from the command line. - * Returns true if successful, false if there is an error. - * - * This may also be called after a previous call to release_egg_data(), in - * order to re-read the same egg file. - */ -bool EggFile:: -read_egg(bool noabs) { - nassertr(_data == nullptr, false); - nassertr(!_source_filename.empty(), false); - - Filename user_source_filename = - FilenameUnifier::make_user_filename(_source_filename); - - if (!_source_filename.exists()) { - nout << user_source_filename << " does not exist.\n"; - return false; - } - - PT(EggData) data = new EggData; - if (!data->read(_source_filename, user_source_filename)) { - // Failure reading. - return false; - } - - if (noabs && data->original_had_absolute_pathnames()) { - nout << _source_filename.get_basename() - << " references textures using absolute pathnames!\n"; - return false; - } - - // Extract the set of textures referenced by this egg file. - EggTextureCollection tc; - tc.find_used_textures(data); - - // Make sure each tref name is unique within a given file. - tc.uniquify_trefs(); - - // Now build up a list of new TextureReference objects that represent the - // textures actually used and their uv range, etc. - Textures new_textures; - - // We want to search for filenames based on the egg directory, and also on - // our current directory from which we originally loaded the egg file. This - // is important because it's possible the egg file referenced some textures - // or something relative to that directory. - DSearchPath dir; - dir.append_directory(_source_filename.get_dirname()); - dir.append_directory(_current_directory); - data->resolve_filenames(dir); - - // If any relative filenames remain, they are relative to the source - // directory, by convention. - data->force_filenames(_current_directory); - - if (!data->load_externals()) { - // Failure reading an external. - return false; - } - - _data = data; - _had_data = true; - remove_backstage(_data); - - // Insert a comment that shows how we first generated the egg file. - PT(EggNode) comment = new EggComment("", _egg_comment); - _data->insert(_data->begin(), comment); - - if (!_textures.empty()) { - // If we already have textures, assume we're re-reading the file. - rescan_textures(); - } - - return true; -} - -/** - * Releases the memory that was loaded by a previous call to read_egg(). - */ -void EggFile:: -release_egg_data() { - if (_data != nullptr) { - _data = nullptr; - } - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureReference *reference = (*ti); - reference->release_egg_data(); - } -} - -/** - * Writes out the egg file to its _dest_filename. Returns true if successful, - * false if there is an error. - */ -bool EggFile:: -write_egg() { - nassertr(_data != nullptr, false); - nassertr(!_dest_filename.empty(), false); - - _dest_filename.make_dir(); - nout << "Writing " << FilenameUnifier::make_user_filename(_dest_filename) - << "\n"; - if (!_data->write_egg(_dest_filename)) { - // Some error while writing. Most unusual. - _is_stale = true; - return false; - } - - _is_stale = false; - return true; -} - -/** - * Writes a one-line description of the egg file and its group assignments to - * the indicated output stream. - */ -void EggFile:: -write_description(std::ostream &out, int indent_level) const { - indent(out, indent_level) << get_name() << ": "; - if (_explicitly_assigned_groups.empty()) { - if (_default_group != nullptr) { - out << _default_group->get_name(); - } - } else { - out << _explicitly_assigned_groups; - } - - if (is_stale()) { - out << " (needs update)"; - } - out << "\n"; -} - -/** - * Writes the list of texture references to the indicated output stream, one - * per line. - */ -void EggFile:: -write_texture_refs(std::ostream &out, int indent_level) const { - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureReference *reference = (*ti); - reference->write(out, indent_level); - } -} - -/** - * Recursively walks the egg hierarchy and removes any "backstage" nodes found - * from the scene graph completely. These aren't part of the egg scene - * anyway, and removing them early helps reduce confusion. - */ -void EggFile:: -remove_backstage(EggGroupNode *node) { - EggGroupNode::iterator ci; - ci = node->begin(); - while (ci != node->end()) { - EggNode *child = (*ci); - bool remove_child = false; - - if (child->is_of_type(EggGroup::get_class_type())) { - EggGroup *egg_group; - DCAST_INTO_V(egg_group, child); - remove_child = egg_group->has_object_type("backstage"); - } - - if (remove_child) { - ci = node->erase(ci); - } else { - if (child->is_of_type(EggGroupNode::get_class_type())) { - // Recurse on children. - remove_backstage(DCAST(EggGroupNode, child)); - } - ++ci; - } - } -} - -/** - * After reloading the egg file for the second time in a given session, - * rematches the texture pointers with the TextureReference objects. - */ -void EggFile:: -rescan_textures() { - nassertv(_data != nullptr); - - // Extract the set of textures referenced by this egg file. - EggTextureCollection tc; - tc.find_used_textures(_data); - - // Make sure each tref name is unique within a given file. - tc.uniquify_trefs(); - - typedef pmap ByTRefName; - ByTRefName by_tref_name; - for (Textures::const_iterator ti = _textures.begin(); - ti != _textures.end(); - ++ti) { - TextureReference *ref = (*ti); - by_tref_name[ref->get_tref_name()] = ref; - } - - EggTextureCollection::iterator eti; - for (eti = tc.begin(); eti != tc.end(); ++eti) { - EggTexture *egg_tex = (*eti); - - ByTRefName::const_iterator tni = by_tref_name.find(egg_tex->get_name()); - if (tni == by_tref_name.end()) { - // We didn't find this TRef name last time around! - nout << _source_filename.get_basename() - << " modified during session--TRef " << egg_tex->get_name() - << " is new!\n"; - - } else { - TextureReference *ref = (*tni).second; - ref->rebind_egg_data(_data, egg_tex); - } - } -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void EggFile:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void EggFile:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - datagram.add_string(get_name()); - - // We don't write out _data; that needs to be reread each session. - - datagram.add_string(FilenameUnifier::make_bam_filename(_current_directory)); - datagram.add_string(FilenameUnifier::make_bam_filename(_source_filename)); - datagram.add_string(FilenameUnifier::make_bam_filename(_dest_filename)); - datagram.add_string(_egg_comment); - - datagram.add_uint32(_textures.size()); - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - writer->write_pointer(datagram, (*ti)); - } - - _explicitly_assigned_groups.write_datagram(writer, datagram); - writer->write_pointer(datagram, _default_group); - - // We don't write out _complete_groups; that is recomputed each session. - - datagram.add_bool(_is_surprise); - datagram.add_bool(_is_stale); -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int EggFile:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = TypedWritable::complete_pointers(p_list, manager); - - int i; - _textures.reserve(_num_textures); - for (i = 0; i < _num_textures; i++) { - TextureReference *texture; - DCAST_INTO_R(texture, p_list[pi], pi); - _textures.push_back(texture); - pi++; - } - - pi += _explicitly_assigned_groups.complete_pointers(p_list + pi, manager); - - if (p_list[pi] != nullptr) { - DCAST_INTO_R(_default_group, p_list[pi], pi); - } - pi++; - - return pi; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *EggFile:: -make_from_bam(const FactoryParams ¶ms) { - EggFile *me = new EggFile(); - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void EggFile:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - set_name(scan.get_string()); - _current_directory = FilenameUnifier::get_bam_filename(scan.get_string()); - _source_filename = FilenameUnifier::get_bam_filename(scan.get_string()); - _dest_filename = FilenameUnifier::get_bam_filename(scan.get_string()); - if (Palettizer::_read_pi_version >= 9) { - _egg_comment = scan.get_string(); - } - - _num_textures = scan.get_uint32(); - manager->read_pointers(scan, _num_textures); - - _explicitly_assigned_groups.fillin(scan, manager); - manager->read_pointer(scan); // _default_group - - _is_surprise = scan.get_bool(); - _is_stale = scan.get_bool(); - - if (Palettizer::_read_pi_version < 11) { - // If this file was written by a version of egg-palettize prior to 11, we - // didn't store the tref names on the texture references. Since we need - // that information now, it follows that every egg file is stale. - _is_stale = true; - } -} diff --git a/pandatool/src/palettizer/eggFile.h b/pandatool/src/palettizer/eggFile.h deleted file mode 100644 index aa8e729e..00000000 --- a/pandatool/src/palettizer/eggFile.h +++ /dev/null @@ -1,137 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggFile.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef EGGFILE_H -#define EGGFILE_H - -#include "pandatoolbase.h" - -#include "paletteGroups.h" -#include "textureReference.h" -#include "eggData.h" -#include "filename.h" -#include "namable.h" -#include "typedWritable.h" -#include "pointerTo.h" -#include "pset.h" - -class TextureImage; - -/** - * This represents a single egg file known to the palettizer. It may - * reference a number of textures, and may also be assigned to a number of - * groups. All of its textures will try to assign themselves to one of its - * groups. - */ -class EggFile : public TypedWritable, public Namable { -public: - EggFile(); - - bool from_command_line(EggData *data, - const Filename &source_filename, - const Filename &dest_filename, - const std::string &egg_comment); - - const Filename &get_source_filename() const; - - void scan_textures(); - void get_textures(pset &result) const; - - void pre_txa_file(); - void match_txa_groups(const PaletteGroups &groups); - void post_txa_file(); - - const PaletteGroups &get_explicit_groups() const; - PaletteGroup *get_default_group() const; - const PaletteGroups &get_complete_groups() const; - void clear_surprise(); - bool is_surprise() const; - - void mark_stale(); - bool is_stale() const; - - void build_cross_links(); - void apply_properties_to_source(); - void choose_placements(); - - bool has_data() const; - bool had_data() const; - - void update_egg(); - void remove_egg(); - bool read_egg(bool noabs); - void release_egg_data(); - bool write_egg(); - - void write_description(std::ostream &out, int indent_level = 0) const; - void write_texture_refs(std::ostream &out, int indent_level = 0) const; - -private: - void remove_backstage(EggGroupNode *node); - void rescan_textures(); - -private: - PT(EggData) _data; - Filename _current_directory; - Filename _source_filename; - Filename _dest_filename; - std::string _egg_comment; - - typedef pvector Textures; - Textures _textures; - - bool _first_txa_match; - PaletteGroups _explicitly_assigned_groups; - PaletteGroup *_default_group; - PaletteGroups _complete_groups; - bool _is_surprise; - bool _is_stale; - bool _had_data; - - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // This value is only filled in while reading from the bam file; don't use - // it otherwise. - int _num_textures; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - Namable::init_type(); - register_type(_type_handle, "EggFile", - TypedWritable::get_class_type(), - Namable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/palettizer/filenameUnifier.cxx b/pandatool/src/palettizer/filenameUnifier.cxx deleted file mode 100644 index f844922b..00000000 --- a/pandatool/src/palettizer/filenameUnifier.cxx +++ /dev/null @@ -1,133 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file filenameUnifier.cxx - * @author drose - * @date 2000-12-05 - */ - -#include "filenameUnifier.h" - -#include "executionEnvironment.h" - -Filename FilenameUnifier::_txa_filename; -Filename FilenameUnifier::_txa_dir; -Filename FilenameUnifier::_rel_dirname; - -FilenameUnifier::CanonicalFilenames FilenameUnifier::_canonical_filenames; - -/** - * Notes the filename the .txa file was found in. This may have come from the - * command line, or it may have been implicitly located. This has other - * implications for the FilenameUnifier, particularly in locating the bam file - * that saves the filenameUnifier state from last session. - */ -void FilenameUnifier:: -set_txa_filename(const Filename &txa_filename) { - _txa_filename = txa_filename; - _txa_dir = txa_filename.get_dirname(); - if (_txa_dir.empty()) { - _txa_dir = "."; - } - make_canonical(_txa_dir); -} - -/** - * Sets the name of the directory that texture filenames will be written - * relative to, when generating egg files. This is not the directory the - * textures are actually written to (see set_map_dirname()), but rather is the - * name of some directory above that, which will be the starting point for the - * pathnames written to the egg files. If this is empty, the full pathnames - * will be written to the egg files. - */ -void FilenameUnifier:: -set_rel_dirname(const Filename &rel_dirname) { - _rel_dirname = rel_dirname; - if (!_rel_dirname.empty()) { - make_canonical(_rel_dirname); - } -} - -/** - * Returns a new filename that's made relative to the bam file itself, - * suitable for writing to the bam file. - */ -Filename FilenameUnifier:: -make_bam_filename(Filename filename) { - make_canonical(filename); - filename.make_relative_to(_txa_dir); - return filename; -} - -/** - * Returns an absolute pathname based on the given relative pathname, - * presumably read from the bam file and relative to the bam file. - */ -Filename FilenameUnifier:: -get_bam_filename(Filename filename) { - if (!filename.empty()) { - filename.make_absolute(_txa_dir); - } - return filename; -} - -/** - * Returns a new filename that's made relative to the rel_directory, suitable - * for writing out within egg files. - */ -Filename FilenameUnifier:: -make_egg_filename(Filename filename) { - if (!filename.empty()) { - make_canonical(filename); - filename.make_relative_to(_rel_dirname); - } - return filename; -} - -/** - * Returns a new filename that's made relative to the current directory, - * suitable for reporting to the user. - */ -Filename FilenameUnifier:: -make_user_filename(Filename filename) { - if (!filename.empty()) { - make_canonical(filename); - filename.make_relative_to(ExecutionEnvironment::get_cwd()); - } - return filename; -} - -/** - * Does the same thing as Filename::make_canonical()--it converts the filename - * to its canonical form--but caches the operation so that repeated calls to - * filenames in the same directory will tend to be faster. - */ -void FilenameUnifier:: -make_canonical(Filename &filename) { - if (filename.empty()) { - return; - } - - Filename orig_dirname = filename.get_dirname(); - - CanonicalFilenames::iterator fi; - fi = _canonical_filenames.find(orig_dirname); - if (fi != _canonical_filenames.end()) { - filename.set_dirname((*fi).second); - return; - } - - Filename new_dirname = orig_dirname; - if (new_dirname.empty()) { - new_dirname = "."; - } - new_dirname.make_canonical(); - filename.set_dirname(new_dirname); - - _canonical_filenames.insert(CanonicalFilenames::value_type(orig_dirname, new_dirname)); -} diff --git a/pandatool/src/palettizer/filenameUnifier.h b/pandatool/src/palettizer/filenameUnifier.h deleted file mode 100644 index 0f701b3c..00000000 --- a/pandatool/src/palettizer/filenameUnifier.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file filenameUnifier.h - * @author drose - * @date 2000-12-05 - */ - -#ifndef FILENAMEUNIFIER_H -#define FILENAMEUNIFIER_H - -#include "pandatoolbase.h" - -#include "filename.h" - -#include "pmap.h" - -/** - * This static class does the job of converting filenames from relative to - * absolute to canonical or whatever is appropriate. Its main purpose is to - * allow us to write relative pathnames to the bam file and turn them back - * into absolute pathnames on read, so that a given bam file does not get tied - * to absolute pathnames. - */ -class FilenameUnifier { -public: - static void set_txa_filename(const Filename &txa_filename); - static void set_rel_dirname(const Filename &rel_dirname); - - static Filename make_bam_filename(Filename filename); - static Filename get_bam_filename(Filename filename); - static Filename make_egg_filename(Filename filename); - static Filename make_user_filename(Filename filename); - static void make_canonical(Filename &filename); - -private: - - static Filename _txa_filename; - static Filename _txa_dir; - static Filename _rel_dirname; - - typedef pmap CanonicalFilenames; - static CanonicalFilenames _canonical_filenames; -}; - -#endif diff --git a/pandatool/src/palettizer/imageFile.cxx b/pandatool/src/palettizer/imageFile.cxx deleted file mode 100644 index 15a5ebc4..00000000 --- a/pandatool/src/palettizer/imageFile.cxx +++ /dev/null @@ -1,480 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageFile.cxx - * @author drose - * @date 2000-11-29 - */ - -#include "imageFile.h" -#include "palettizer.h" -#include "filenameUnifier.h" -#include "paletteGroup.h" - -#include "pnmImage.h" -#include "pnmFileType.h" -#include "eggTexture.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" - -using std::string; - -TypeHandle ImageFile::_type_handle; - -/** - * - */ -ImageFile:: -ImageFile() { - _alpha_file_channel = 0; - _size_known = false; - _x_size = 0; - _y_size = 0; -} - -/** - * Sets up the ImageFile as a "shadow image" of a particular PaletteImage. - * This is a temporary ImageFile that's used to read and write the shadow - * palette image, which is used to keep a working copy of the palette. - * - * Returns true if the filename changes from what it was previously, false - * otherwise. - */ -bool ImageFile:: -make_shadow_image(const string &basename) { - bool any_changed = false; - - if (_properties._color_type != pal->_shadow_color_type || - _properties._alpha_type != pal->_shadow_alpha_type) { - - _properties._color_type = pal->_shadow_color_type; - _properties._alpha_type = pal->_shadow_alpha_type; - any_changed = true; - } - - if (set_filename(pal->_shadow_dirname, basename)) { - any_changed = true; - } - - return any_changed; -} - -/** - * Returns true if the size of the image file is known, false otherwise. - */ -bool ImageFile:: -is_size_known() const { - return _size_known; -} - -/** - * Returns the size of the image file in pixels in the X direction. It is an - * error to call this unless is_size_known() returns true. - */ -int ImageFile:: -get_x_size() const { - nassertr(is_size_known(), 0); - return _x_size; -} - -/** - * Returns the size of the image file in pixels in the Y direction. It is an - * error to call this unless is_size_known() returns true. - */ -int ImageFile:: -get_y_size() const { - nassertr(is_size_known(), 0); - return _y_size; -} - -/** - * Returns true if the number of channels in the image is known, false - * otherwise. - */ -bool ImageFile:: -has_num_channels() const { - return _properties.has_num_channels(); -} - -/** - * Returns the number of channels of the image. It is an error to call this - * unless has_num_channels() returns true. - */ -int ImageFile:: -get_num_channels() const { - return _properties.get_num_channels(); -} - -/** - * Returns the grouping properties of the image. - */ -const TextureProperties &ImageFile:: -get_properties() const { - return _properties; -} - -/** - * Resets the properties to a neutral state, for instance in preparation for - * calling update_properties() with all the known contributing properties. - */ -void ImageFile:: -clear_basic_properties() { - _properties.clear_basic(); -} - -/** - * If the indicate TextureProperties structure is more specific than this one, - * updates this one. - */ -void ImageFile:: -update_properties(const TextureProperties &properties) { - _properties.update_properties(properties); -} - -/** - * Sets the filename, and if applicable, the alpha_filename, from the - * indicated basename. The extension appropriate to the image file type - * specified in _color_type (and _alpha_type) is automatically applied. - * - * Returns true if the filename changes from what it was previously, false - * otherwise. - */ -bool ImageFile:: -set_filename(PaletteGroup *group, const string &basename) { - // Synthesize the directory name based on the map_dirname set to the - // palettizer, and the group's dirname. - string dirname; - string::iterator pi; - pi = pal->_map_dirname.begin(); - while (pi != pal->_map_dirname.end()) { - if (*pi == '%') { - ++pi; - switch (*pi) { - case '%': - dirname += '%'; - break; - - case 'g': - if (group != nullptr) { - dirname += group->get_dirname(); - } - break; - } - } else { - dirname += *pi; - } - ++pi; - } - - return set_filename(dirname, basename); -} - -/** - * Sets the filename, and if applicable, the alpha_filename, from the - * indicated basename. The extension appropriate to the image file type - * specified in _color_type (and _alpha_type) is automatically applied. - * - * Returns true if the filename changes from what it was previously, false - * otherwise. - */ -bool ImageFile:: -set_filename(const string &dirname, const string &basename) { - Filename orig_filename = _filename; - Filename orig_alpha_filename = _alpha_filename; - - _filename = Filename(dirname, basename); - _filename.standardize(); - - // Since we use set_extension() here, if the file already contains a - // filename extension it will be lost. - - // It is particularly important to note that a single embedded dot will - // appear to begin a filename extension, so if the filename does *not* - // contain an extension, but does contain an embedded dot, the filename will - // be truncated at that dot. It is therefore important that the supplied - // basename always contains either an extension or a terminating dot. - - if (_properties._color_type != nullptr) { - _filename.set_extension - (_properties._color_type->get_suggested_extension()); - } - - if (_properties._alpha_type != nullptr) { - _alpha_filename = _filename.get_fullpath_wo_extension() + "_a."; - _alpha_filename.set_extension - (_properties._alpha_type->get_suggested_extension()); - } else { - _alpha_filename = Filename(); - } - - return (_filename != orig_filename || - _alpha_filename != orig_alpha_filename); -} - -/** - * Returns the primary filename of the image file. - */ -const Filename &ImageFile:: -get_filename() const { - return _filename; -} - -/** - * Returns the alpha filename of the image file. This is the name of the file - * that contains the alpha channel, if it is stored in a separate file, or the - * empty string if it is not. - */ -const Filename &ImageFile:: -get_alpha_filename() const { - return _alpha_filename; -} - -/** - * Returns the particular channel number of the alpha image file from which - * the alpha channel should be extracted. This is normally 0 to represent the - * grayscale combination of r, g, and b; or it may be a 1-based channel number - * (for instance, 4 for the alpha channel of a 4-component image). - */ -int ImageFile:: -get_alpha_file_channel() const { - return _alpha_file_channel; -} - - -/** - * Returns true if the file or files named by the image file exist, false - * otherwise. - */ -bool ImageFile:: -exists() const { - if (!_filename.exists()) { - return false; - } - if (_properties._alpha_type != nullptr && - _properties.uses_alpha() && - !_alpha_filename.empty()) { - if (!_alpha_filename.exists()) { - return false; - } - } - - return true; -} - -/** - * Reads in the image (or images, if the alpha_filename is separate) and - * stores it in the indicated PNMImage. Returns true on success, false on - * failure. - */ -bool ImageFile:: -read(PNMImage &image) const { - nassertr(!_filename.empty(), false); - - image.set_type(_properties._color_type); - nout << "Reading " << FilenameUnifier::make_user_filename(_filename) << "\n"; - if (!image.read(_filename)) { - nout << "Unable to read.\n"; - return false; - } - - if (!_alpha_filename.empty() && _alpha_filename.exists()) { - // Read in a separate color image and an alpha channel image. - PNMImage alpha_image; - alpha_image.set_type(_properties._alpha_type); - nout << "Reading " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n"; - if (!alpha_image.read(_alpha_filename)) { - nout << "Unable to read.\n"; - return false; - } - if (image.get_x_size() != alpha_image.get_x_size() || - image.get_y_size() != alpha_image.get_y_size()) { - return false; - } - - image.add_alpha(); - - if (_alpha_file_channel == 4 || - (_alpha_file_channel == 2 && alpha_image.get_num_channels() == 2)) { - // Use the alpha channel. - for (int x = 0; x < image.get_x_size(); x++) { - for (int y = 0; y < image.get_y_size(); y++) { - image.set_alpha(x, y, alpha_image.get_alpha(x, y)); - } - } - - } else if (_alpha_file_channel >= 1 && _alpha_file_channel <= 3 && - alpha_image.get_num_channels() >= 3) { - // Use the appropriate red, green, or blue channel. - for (int x = 0; x < image.get_x_size(); x++) { - for (int y = 0; y < image.get_y_size(); y++) { - image.set_alpha(x, y, alpha_image.get_channel_val(x, y, _alpha_file_channel - 1)); - } - } - - } else { - // Use the grayscale channel. - for (int x = 0; x < image.get_x_size(); x++) { - for (int y = 0; y < image.get_y_size(); y++) { - image.set_alpha(x, y, alpha_image.get_gray(x, y)); - } - } - } - } - - return true; -} - -/** - * Writes out the image in the indicated PNMImage to the _filename and/or - * _alpha_filename. Returns true on success, false on failure. - */ -bool ImageFile:: -write(const PNMImage &image) const { - nassertr(!_filename.empty(), false); - - if (!image.has_alpha() || - _properties._alpha_type == nullptr) { - if (!_alpha_filename.empty() && _alpha_filename.exists()) { - nout << "Deleting " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n"; - _alpha_filename.unlink(); - } - nout << "Writing " << FilenameUnifier::make_user_filename(_filename) << "\n"; - _filename.make_dir(); - if (!image.write(_filename, _properties._color_type)) { - nout << "Unable to write.\n"; - return false; - } - return true; - } - - // Write out a separate color image and an alpha channel image. - PNMImage alpha_image(image.get_x_size(), image.get_y_size(), 1, - image.get_maxval()); - for (int y = 0; y < image.get_y_size(); y++) { - for (int x = 0; x < image.get_x_size(); x++) { - alpha_image.set_gray_val(x, y, image.get_alpha_val(x, y)); - } - } - - PNMImage image_copy(image); - image_copy.remove_alpha(); - nout << "Writing " << FilenameUnifier::make_user_filename(_filename) << "\n"; - _filename.make_dir(); - if (!image_copy.write(_filename, _properties._color_type)) { - nout << "Unable to write.\n"; - return false; - } - - nout << "Writing " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n"; - _alpha_filename.make_dir(); - if (!alpha_image.write(_alpha_filename, _properties._alpha_type)) { - nout << "Unable to write.\n"; - return false; - } - return true; -} - -/** - * Deletes the image file or files. - */ -void ImageFile:: -unlink() { - if (!_filename.empty() && _filename.exists()) { - nout << "Deleting " << FilenameUnifier::make_user_filename(_filename) << "\n"; - _filename.unlink(); - } - if (!_alpha_filename.empty() && _alpha_filename.exists()) { - nout << "Deleting " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n"; - _alpha_filename.unlink(); - } -} - -/** - * Sets the indicated EggTexture to refer to this file. - */ -void ImageFile:: -update_egg_tex(EggTexture *egg_tex) const { - nassertv(egg_tex != nullptr); - - egg_tex->set_filename(FilenameUnifier::make_egg_filename(_filename)); - - if (_properties.uses_alpha() && - !_alpha_filename.empty()) { - egg_tex->set_alpha_filename(FilenameUnifier::make_egg_filename(_alpha_filename)); - egg_tex->set_alpha_file_channel(_alpha_file_channel); - } else { - egg_tex->clear_alpha_filename(); - egg_tex->clear_alpha_file_channel(); - } - - _properties.update_egg_tex(egg_tex); -} - -/** - * Writes the filename (or pair of filenames) to the indicated output stream. - */ -void ImageFile:: -output_filename(std::ostream &out) const { - out << FilenameUnifier::make_user_filename(_filename); - if (_properties.uses_alpha() && !_alpha_filename.empty()) { - out << " " << FilenameUnifier::make_user_filename(_alpha_filename); - } -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void ImageFile:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - _properties.write_datagram(writer, datagram); - datagram.add_string(FilenameUnifier::make_bam_filename(_filename)); - datagram.add_string(FilenameUnifier::make_bam_filename(_alpha_filename)); - datagram.add_uint8(_alpha_file_channel); - datagram.add_bool(_size_known); - datagram.add_int32(_x_size); - datagram.add_int32(_y_size); -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int ImageFile:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = TypedWritable::complete_pointers(p_list, manager); - - pi += _properties.complete_pointers(p_list + pi, manager); - - return pi; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void ImageFile:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - _properties.fillin(scan, manager); - _filename = FilenameUnifier::get_bam_filename(scan.get_string()); - _alpha_filename = FilenameUnifier::get_bam_filename(scan.get_string()); - if (Palettizer::_read_pi_version >= 10) { - _alpha_file_channel = scan.get_uint8(); - } else { - _alpha_file_channel = 0; - } - _size_known = scan.get_bool(); - _x_size = scan.get_int32(); - _y_size = scan.get_int32(); -} diff --git a/pandatool/src/palettizer/imageFile.h b/pandatool/src/palettizer/imageFile.h deleted file mode 100644 index c4d8ed90..00000000 --- a/pandatool/src/palettizer/imageFile.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file imageFile.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef IMAGEFILE_H -#define IMAGEFILE_H - -#include "pandatoolbase.h" - -#include "textureProperties.h" - -#include "filename.h" -#include "typedWritable.h" - -class PNMImage; -class EggTexture; -class PaletteGroup; - -/** - * This is the base class of both TextureImage and PaletteImage. It - * encapsulates all the information specific to an image file that can be - * assigned as a texture image to egg geometry. - */ -class ImageFile : public TypedWritable { -public: - ImageFile(); - - bool make_shadow_image(const std::string &basename); - - bool is_size_known() const; - int get_x_size() const; - int get_y_size() const; - bool has_num_channels() const; - int get_num_channels() const; - - const TextureProperties &get_properties() const; - void clear_basic_properties(); - void update_properties(const TextureProperties &properties); - - bool set_filename(PaletteGroup *group, const std::string &basename); - bool set_filename(const std::string &dirname, const std::string &basename); - const Filename &get_filename() const; - const Filename &get_alpha_filename() const; - int get_alpha_file_channel() const; - bool exists() const; - - bool read(PNMImage &image) const; - bool write(const PNMImage &image) const; - void unlink(); - - void update_egg_tex(EggTexture *egg_tex) const; - - void output_filename(std::ostream &out) const; - -protected: - TextureProperties _properties; - Filename _filename; - Filename _alpha_filename; - int _alpha_file_channel; - - bool _size_known; - int _x_size, _y_size; - - // The TypedWritable interface follows. -public: - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - register_type(_type_handle, "ImageFile", - TypedWritable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; - -}; - -#endif diff --git a/pandatool/src/palettizer/omitReason.cxx b/pandatool/src/palettizer/omitReason.cxx deleted file mode 100644 index 6bc14240..00000000 --- a/pandatool/src/palettizer/omitReason.cxx +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file omitReason.cxx - * @author drose - * @date 2000-12-02 - */ - -#include "omitReason.h" - -std::ostream & -operator << (std::ostream &out, OmitReason omit) { - switch (omit) { - case OR_none: - return out << "none"; - - case OR_working: - return out << "working"; - - case OR_omitted: - return out << "omitted"; - - case OR_size: - return out << "size"; - - case OR_solitary: - return out << "solitary"; - - case OR_coverage: - return out << "coverage"; - - case OR_unknown: - return out << "unknown"; - - case OR_unused: - return out << "unused"; - - case OR_default_omit: - return out << "default_omit"; - } - - return out << "**invalid**(" << (int)omit << ")"; -} diff --git a/pandatool/src/palettizer/omitReason.h b/pandatool/src/palettizer/omitReason.h deleted file mode 100644 index c60a86f3..00000000 --- a/pandatool/src/palettizer/omitReason.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file omitReason.h - * @author drose - * @date 2000-11-30 - */ - -#ifndef OMITREASON_H -#define OMITREASON_H - -#include "pandatoolbase.h" - -/** - * This enumerates the reasons why a texture may not have been placed in a - * palette image. - */ -enum OmitReason { - OR_none, - // Not omitted: the texture appears on a palette image. - - OR_working, - // Still working on placing it. - - OR_omitted, - // Explicitly omitted by the user via "omit" in .txa file. - - OR_size, - // Too big to fit on a single palette image. - - OR_solitary, - // It should be placed, but it's the only one on the palette image so far, - // so there's no point. - - OR_coverage, - // The texture repeats. Specifically, the UV's for the texture exceed the - // maximum rectangle allowed by coverage_threshold. - - OR_unknown, - // The texture file cannot be read, so its size can't be determined. - - OR_unused, - // The texture is no longer used by any of the egg files that formerly - // referenced it. - - OR_default_omit, - // The texture is omitted because _omit_everything is set true. -}; - -std::ostream &operator << (std::ostream &out, OmitReason omit); - -#endif diff --git a/pandatool/src/palettizer/p3palettizer_composite1.cxx b/pandatool/src/palettizer/p3palettizer_composite1.cxx deleted file mode 100644 index d5dc5d0b..00000000 --- a/pandatool/src/palettizer/p3palettizer_composite1.cxx +++ /dev/null @@ -1,24 +0,0 @@ - -#include "config_palettizer.cxx" -#include "destTextureImage.cxx" -#include "eggFile.cxx" -#include "filenameUnifier.cxx" -#include "imageFile.cxx" -#include "omitReason.cxx" -#include "pal_string_utils.cxx" -#include "paletteGroup.cxx" -#include "paletteGroups.cxx" -#include "paletteImage.cxx" -#include "palettePage.cxx" -#include "palettizer.cxx" -#include "sourceTextureImage.cxx" -#include "textureImage.cxx" -#include "textureMemoryCounter.cxx" -#include "texturePlacement.cxx" -#include "texturePosition.cxx" -#include "textureProperties.cxx" -#include "textureReference.cxx" -#include "textureRequest.cxx" -#include "txaFile.cxx" -#include "txaLine.cxx" - diff --git a/pandatool/src/palettizer/pal_string_utils.cxx b/pandatool/src/palettizer/pal_string_utils.cxx deleted file mode 100644 index 279a7aad..00000000 --- a/pandatool/src/palettizer/pal_string_utils.cxx +++ /dev/null @@ -1,86 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pal_string_utils.cxx - * @author drose - * @date 2000-11-30 - */ - -#include "pal_string_utils.h" - -#include "pnmFileType.h" -#include "pnmFileTypeRegistry.h" - -using std::string; - - -// Extracts the first word of the string into param, and the remainder of the -// line into value. -void -extract_param_value(const string &str, string ¶m, string &value) { - size_t i = 0; - - // First, skip all whitespace at the beginning. - while (i < str.length() && isspace(str[i])) { - i++; - } - - size_t start = i; - - // Now skip to the end of the whitespace. - while (i < str.length() && !isspace(str[i])) { - i++; - } - - size_t end = i; - - param = str.substr(start, end - start); - - // Skip a little bit further to the start of the value. - while (i < str.length() && isspace(str[i])) { - i++; - } - value = trim_right(str.substr(i)); -} - - -bool -parse_image_type_request(const string &word, PNMFileType *&color_type, - PNMFileType *&alpha_type) { - PNMFileTypeRegistry *registry = PNMFileTypeRegistry::get_global_ptr(); - color_type = nullptr; - alpha_type = nullptr; - - string color_name = word; - string alpha_name; - size_t comma = word.find(','); - if (comma != string::npos) { - // If we have a comma in the image_type, it's two types: a color type and - // an alpha type. - color_name = word.substr(0, comma); - alpha_name = word.substr(comma + 1); - } - - if (!color_name.empty()) { - color_type = registry->get_type_from_extension(color_name); - if (color_type == nullptr) { - nout << "Image file type '" << color_name << "' is unknown.\n"; - return false; - } - } - - if (!alpha_name.empty()) { - alpha_type = registry->get_type_from_extension(alpha_name); - if (alpha_type == nullptr) { - nout << "Image file type '" << alpha_name << "' is unknown.\n"; - return false; - } - } - - return true; -} diff --git a/pandatool/src/palettizer/pal_string_utils.h b/pandatool/src/palettizer/pal_string_utils.h deleted file mode 100644 index 4f37b330..00000000 --- a/pandatool/src/palettizer/pal_string_utils.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pal_string_utils.h - * @author drose - * @date 2000-11-30 - */ - -#ifndef PAL_STRING_UTILS_H -#define PAL_STRING_UTILS_H - -#include "pandatoolbase.h" -#include "string_utils.h" - -class PNMFileType; - -void extract_param_value(const std::string &str, std::string ¶m, std::string &value); - -bool parse_image_type_request(const std::string &word, PNMFileType *&color_type, - PNMFileType *&alpha_type); - -#endif diff --git a/pandatool/src/palettizer/paletteGroup.cxx b/pandatool/src/palettizer/paletteGroup.cxx deleted file mode 100644 index d7e58325..00000000 --- a/pandatool/src/palettizer/paletteGroup.cxx +++ /dev/null @@ -1,713 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file paletteGroup.cxx - * @author drose - * @date 2000-11-30 - */ - -#include "paletteGroup.h" -#include "palettePage.h" -#include "texturePlacement.h" -#include "textureImage.h" -#include "palettizer.h" -#include "paletteImage.h" -#include "sourceTextureImage.h" - -#include "indent.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "indirectCompareNames.h" -#include "pvector.h" - -using std::string; - -TypeHandle PaletteGroup::_type_handle; - -/** - * - */ -PaletteGroup:: -PaletteGroup() { - _egg_count = 0; - _dependency_level = 0; - _dependency_order = 0; - _dirname_order = 0; - _has_margin_override = false; - _margin_override = 0; -} - -/** - * Sets the directory name associated with the palette group. This is an - * optional feature that can be used to place the maps for the different - * palette groups into different install directories. - */ -void PaletteGroup:: -set_dirname(const string &dirname) { - _dirname = dirname; -} - -/** - * Returns true if the directory name has been explicitly set for this group. - * If it has not, get_dirname() returns an empty string. - */ -bool PaletteGroup:: -has_dirname() const { - return !_dirname.empty(); -} - -/** - * Returns the directory name associated with the palette group. See - * set_dirname(). - */ -const string &PaletteGroup:: -get_dirname() const { - return _dirname; -} - -/** - * Eliminates all the dependency information for this group. - */ -void PaletteGroup:: -clear_depends() { - _dependent.clear(); - _dependency_level = 0; - _dependency_order = 0; - _dirname_order = 0; -} - -/** - * Indicates a dependency of this group on some other group. This means that - * the textures assigned to this group may be considered successfully assigned - * if they are actually placed in the other group. In practice, this means - * that the textures associated with the other palette group will always be - * resident at runtime when textures from this palette group are required. - */ -void PaletteGroup:: -group_with(PaletteGroup *other) { - _dependent.insert(other); -} - -/** - * Returns the set of groups this group depends on. - */ -const PaletteGroups &PaletteGroup:: -get_groups() const { - return _dependent; -} - -/** - * Returns the set of groups this group depends on. - */ -int PaletteGroup:: -get_margin_override() const { - return _margin_override; -} - -/** - * Returns the set of groups this group depends on. - */ -void PaletteGroup:: -set_margin_override(const int override) { - _margin_override = override; - _has_margin_override = true; -} - -/** - * Returns the set of groups this group depends on. - */ -bool PaletteGroup:: -has_margin_override() const { - return _has_margin_override; -} - -/** - * Adds the set of TexturePlacements associated with this group to the - * indicated vector. The vector is not cleared before this operation; if the - * user wants to retrieve the set of placements particular to this group only, - * it is the user's responsibility to clear the vector first. - */ -void PaletteGroup:: -get_placements(pvector &placements) const { - Placements::const_iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - placements.push_back(*pi); - } -} - -/** - * Adds the set of TexturePlacements associated with this group and all - * dependent groups to the indicated vector. See get_placements(). - */ -void PaletteGroup:: -get_complete_placements(pvector &placements) const { - PaletteGroups complete; - complete.make_complete(_dependent); - - PaletteGroups::iterator gi; - for (gi = complete.begin(); gi != complete.end(); ++gi) { - PaletteGroup *group = (*gi); - group->get_placements(placements); - } - - get_placements(placements); -} - -/** - * Unconditionally sets the dependency level and order of this group to zero, - * in preparation for a later call to set_dependency_level(). See - * set_dependency_level(). - */ -void PaletteGroup:: -reset_dependency_level() { - _dependency_level = 0; - _dependency_order = 0; - _dirname_order = 0; -} - -/** - * Sets the dependency level of this group to the indicated level, provided - * that level is not lower than the level that was set previously. Also - * cascades to all dependent groups. See get_dependency_level(). - * - * This call recurses to correctly set the dependency level of all - * PaletteGroups in the hierarchy. - */ -void PaletteGroup:: -set_dependency_level(int level) { - if (level > _dependency_level) { - _dependency_level = level; - PaletteGroups::iterator gi; - for (gi = _dependent.begin(); gi != _dependent.end(); ++gi) { - PaletteGroup *group = (*gi); - group->set_dependency_level(level + 1); - } - } -} - -/** - * Updates the dependency order of this group. This number is the inverse of - * the dependency level, and can be used to rank the groups in order so that - * all the groups that a given group depends on will appear first in the list. - * See get_dependency_order(). - * - * This function returns true if anything was changed, false otherwise. - */ -bool PaletteGroup:: -set_dependency_order() { - bool any_changed = false; - - PaletteGroups::iterator gi; - for (gi = _dependent.begin(); gi != _dependent.end(); ++gi) { - PaletteGroup *group = (*gi); - if (group->set_dependency_order()) { - any_changed = true; - } - - if (_dependency_order <= group->get_dependency_order()) { - _dependency_order = group->get_dependency_order() + 1; - any_changed = true; - } - - if (_dirname == group->get_dirname()) { - // The dirname orders should be equal. - if (_dirname_order < group->get_dirname_order()) { - _dirname_order = group->get_dirname_order(); - any_changed = true; - } - } else { - // The dirname orders should be different. - if (_dirname_order <= group->get_dirname_order()) { - _dirname_order = group->get_dirname_order() + 1; - any_changed = true; - } - } - } - - return any_changed; -} - -/** - * Returns the dependency level of this group. This is a measure of how - * specific the group is; the lower the dependency level, the more specific - * the group. - * - * Groups depend on other groups in a hierarchical relationship. In general, - * if group a depends on group b, then b->get_dependency_level() > - * a->get_dependency_level(). - * - * Thus, groups that lots of other groups depend on have a higher dependency - * level; groups that no one else depends on have a low dependency level. - * This is important when deciding which groups are best suited for assigning - * a texture to; in general, the texture should be assigned to the most - * specific suitable group (i.e. the one with the lowest dependency level). - */ -int PaletteGroup:: -get_dependency_level() const { - return _dependency_level; -} - -/** - * Returns the dependency order of this group. This is similar in principle - * to the dependency level, but it represents the inverse concept: if group a - * depends on group b, then a->get_dependency_order() > - * b->get_dependency_order(). - * - * This is not exactly the same thing as n - get_dependency_level(). In - * particular, this can be used to sort the groups into an ordering such that - * all the groups that group a depends on appear before group a in the list. - */ -int PaletteGroup:: -get_dependency_order() const { - return _dependency_order; -} - -/** - * Returns the dependency order of this group. This is similar in principle - * to the dependency level, but it represents the inverse concept: if group a - * depends on group b, then a->get_dirname_order() > b->get_dirname_order(). - * - * This is not exactly the same thing as n - get_dependency_level(). In - * particular, this can be used to sort the groups into an ordering such that - * all the groups that group a depends on appear before group a in the list. - */ -int PaletteGroup:: -get_dirname_order() const { - return _dirname_order; -} - -/** - * Returns true if this group should be preferred for adding textures over the - * other group, if both are available. In other words, this is a more - * specific group than the other one. - */ -bool PaletteGroup:: -is_preferred_over(const PaletteGroup &other) const { - if (get_dirname_order() != other.get_dirname_order()) { - return (get_dirname_order() > other.get_dirname_order()); - - } else if (get_dependency_order() != other.get_dependency_order()) { - return (get_dependency_order() > other.get_dependency_order()); - - } else { - return (get_egg_count() < other.get_egg_count()); - } -} - -/** - * Increments by one the number of egg files that are known to reference this - * PaletteGroup. This is designed to aid the heuristics in texture placing; - * it's useful to know how many different egg files are sharing a particular - * PaletteGroup. - */ -void PaletteGroup:: -increment_egg_count() { - _egg_count++; -} - -/** - * Returns the number of egg files that share this PaletteGroup. - */ -int PaletteGroup:: -get_egg_count() const { - return _egg_count; -} - -/** - * Returns the page associated with the indicated properties. If no page - * object has yet been created, creates one. - */ -PalettePage *PaletteGroup:: -get_page(const TextureProperties &properties) { - Pages::iterator pi = _pages.find(properties); - if (pi != _pages.end()) { - return (*pi).second; - } - - PalettePage *page = new PalettePage(this, properties); - bool inserted = _pages.insert(Pages::value_type(properties, page)).second; - nassertr(inserted, page); - return page; -} - -/** - * Marks the indicated Texture as ready for placing somewhere within this - * group, and returns a placeholder TexturePlacement object. The texture is - * not placed immediately, but may be placed later when place_all() is called; - * at this time, the TexturePlacement fields will be filled in as appropriate. - */ -TexturePlacement *PaletteGroup:: -prepare(TextureImage *texture) { - TexturePlacement *placement = new TexturePlacement(texture, this); - _placements.insert(placement); - - // [gjeon] update swapTexture information - TextureSwapInfo::iterator tsi = _textureSwapInfo.find(texture->get_name()); - if (tsi != _textureSwapInfo.end()) { - vector_string swapTextures = (*tsi).second; - - vector_string::const_iterator wi; - wi = swapTextures.begin(); - ++wi; - ++wi; - - // [gjeon] since swapped texture usually didn't mapped to any egg file we - // need to create soucreTextureImage by using original texture file's info - const string originalTextureName = (*wi); - TextureImage *originalTexture = pal->get_texture(originalTextureName); - SourceTextureImage *source = originalTexture->get_preferred_source(); - const Filename originalTextureFilename = source->get_filename(); - const Filename originalTextureAlphaFilename = source->get_alpha_filename(); - int originalTextureAlphaFileChannel = source->get_alpha_file_channel(); - - ++wi; - while (wi != swapTextures.end()) { - const string &swapTextureName = (*wi); - TextureImage *swapTextureImage = pal->get_texture(swapTextureName); - Filename swapTextureFilename = Filename(originalTextureFilename.get_dirname(), swapTextureName + "." + originalTextureFilename.get_extension()); - swapTextureImage->get_source(swapTextureFilename, originalTextureAlphaFilename, originalTextureAlphaFileChannel); - placement->_textureSwaps.push_back(swapTextureImage); - ++wi; - } - } - - return placement; -} - -/** - * Removes the texture from its position on a PaletteImage, if it has been so - * placed. - */ -void PaletteGroup:: -unplace(TexturePlacement *placement) { - nassertv(placement->get_group() == this); - - Placements::iterator pi; - pi = _placements.find(placement); - if (pi != _placements.end()) { - _placements.erase(pi); - - if (placement->is_placed()) { - placement->get_page()->unplace(placement); - } - } -} - -/** - * Once all the textures have been assigned to this group, try to place them - * all onto suitable PaletteImages. - */ -void PaletteGroup:: -place_all() { - // First, go through our prepared textures and assign each unplaced one to - // an appropriate page. - Placements::iterator pli; - for (pli = _placements.begin(); pli != _placements.end(); ++pli) { - TexturePlacement *placement = (*pli); - - if (placement->get_omit_reason() == OR_working) { - PalettePage *page = get_page(placement->get_properties()); - page->assign(placement); - } - } - - // Then, go through the pages and actually do the placing. - Pages::iterator pai; - for (pai = _pages.begin(); pai != _pages.end(); ++pai) { - PalettePage *page = (*pai).second; - page->place_all(); - } -} - -/** - * Checks for new information on any textures within the group for which some - * of the saved information is incomplete. This may be necessary before we - * can properly place all of the textures. - */ -void PaletteGroup:: -update_unknown_textures(const TxaFile &txa_file) { - Placements::iterator pli; - for (pli = _placements.begin(); pli != _placements.end(); ++pli) { - TexturePlacement *placement = (*pli); - - if (!placement->is_size_known()) { - // This texture's size isn't known; we have to determine its size. - TextureImage *texture = placement->get_texture(); - if (!texture->got_txa_file()) { - // But first, we need to look up the texture in the .txa file. - texture->pre_txa_file(); - txa_file.match_texture(texture); - texture->post_txa_file(); - } - - placement->determine_size(); - } - } -} - -/** - * Writes a list of the PaletteImages associated with this group, and all of - * their textures, to the indicated output stream. - */ -void PaletteGroup:: -write_image_info(std::ostream &out, int indent_level) const { - Pages::const_iterator pai; - for (pai = _pages.begin(); pai != _pages.end(); ++pai) { - PalettePage *page = (*pai).second; - page->write_image_info(out, indent_level); - } - - // Write out all the unplaced textures, in alphabetical order by name. - pvector placement_vector; - placement_vector.reserve(_placements.size()); - Placements::const_iterator pli; - for (pli = _placements.begin(); pli != _placements.end(); ++pli) { - TexturePlacement *placement = (*pli); - if (placement->get_omit_reason() != OR_none) { - placement_vector.push_back(placement); - } - } - sort(placement_vector.begin(), placement_vector.end(), - IndirectCompareNames()); - - pvector::const_iterator pvi; - for (pvi = placement_vector.begin(); - pvi != placement_vector.end(); - ++pvi) { - TexturePlacement *placement = (*pvi); - - indent(out, indent_level) - << placement->get_texture()->get_name() - << " unplaced because "; - switch (placement->get_omit_reason()) { - case OR_coverage: - out << "coverage (" << placement->get_uv_area() << ")"; - break; - - case OR_size: - out << "size (" << placement->get_x_size() << " " - << placement->get_y_size() << ")"; - break; - - default: - out << placement->get_omit_reason(); - } - out << "\n"; - } -} - -/** - * Attempts to resize each PalettteImage down to its smallest possible size. - */ -void PaletteGroup:: -optimal_resize() { - Pages::iterator pai; - for (pai = _pages.begin(); pai != _pages.end(); ++pai) { - PalettePage *page = (*pai).second; - page->optimal_resize(); - } -} - -/** - * Throws away all of the current PaletteImages, so that new ones may be - * created (and the packing made more optimal). - */ -void PaletteGroup:: -reset_images() { - Pages::iterator pai; - for (pai = _pages.begin(); pai != _pages.end(); ++pai) { - PalettePage *page = (*pai).second; - page->reset_images(); - } -} - -/** - * Ensures that each PaletteImage's _shadow_image has the correct filename and - * image types, based on what was supplied on the command line and in the .txa - * file. - */ -void PaletteGroup:: -setup_shadow_images() { - Pages::iterator pai; - for (pai = _pages.begin(); pai != _pages.end(); ++pai) { - PalettePage *page = (*pai).second; - page->setup_shadow_images(); - } -} - -/** - * Regenerates each PaletteImage on this group that needs it. - */ -void PaletteGroup:: -update_images(bool redo_all) { - Pages::iterator pai; - for (pai = _pages.begin(); pai != _pages.end(); ++pai) { - PalettePage *page = (*pai).second; - page->update_images(redo_all); - } -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void PaletteGroup:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void PaletteGroup:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - datagram.add_string(get_name()); - datagram.add_string(_dirname); - _dependent.write_datagram(writer, datagram); - - datagram.add_int32(_dependency_level); - datagram.add_int32(_dependency_order); - datagram.add_int32(_dirname_order); - - datagram.add_uint32(_placements.size()); - Placements::const_iterator pli; - for (pli = _placements.begin(); pli != _placements.end(); ++pli) { - writer->write_pointer(datagram, (*pli)); - } - - datagram.add_uint32(_pages.size()); - Pages::const_iterator pai; - for (pai = _pages.begin(); pai != _pages.end(); ++pai) { - writer->write_pointer(datagram, (*pai).second); - } - datagram.add_bool(_has_margin_override); - datagram.add_int16(_margin_override); - -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int PaletteGroup:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = TypedWritable::complete_pointers(p_list, manager); - - pi += _dependent.complete_pointers(p_list + pi, manager); - - int i; - for (i = 0; i < _num_placements; i++) { - TexturePlacement *placement; - DCAST_INTO_R(placement, p_list[pi++], pi); - bool inserted = _placements.insert(placement).second; - nassertr(inserted, pi); - } - - // We must store the list of pages in a temporary vector first. We can't - // put them directly into the map because the map requires that all the - // pointers in the page's get_properties() member have been filled in, which - // may not have happened yet. - _load_pages.reserve(_num_pages); - for (i = 0; i < _num_pages; i++) { - PalettePage *page; - DCAST_INTO_R(page, p_list[pi++], pi); - _load_pages.push_back(page); - } - - return pi; -} - -/** - * This method is called by the BamReader after all pointers everywhere in the - * world have been completely read in. It's a hook at which the object can do - * whatever final setup it requires that depends on other pointers being - * valid. - */ -void PaletteGroup:: -finalize(BamReader *) { - // Now we can copy the pages into the actual map. - pvector::const_iterator pi; - for (pi = _load_pages.begin(); pi != _load_pages.end(); ++pi) { - PalettePage *page = (*pi); - bool inserted = _pages. - insert(Pages::value_type(page->get_properties(), page)).second; - nassertv(inserted); - } - - _load_pages.clear(); -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *PaletteGroup:: -make_from_bam(const FactoryParams ¶ms) { - PaletteGroup *me = new PaletteGroup; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - manager->register_finalize(me); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void PaletteGroup:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - set_name(scan.get_string()); - _dirname = scan.get_string(); - _dependent.fillin(scan, manager); - - _dependency_level = scan.get_int32(); - _dependency_order = scan.get_int32(); - _dirname_order = scan.get_int32(); - - _num_placements = scan.get_uint32(); - manager->read_pointers(scan, _num_placements); - - _num_pages = scan.get_uint32(); - manager->read_pointers(scan, _num_pages); - - if(Palettizer::_read_pi_version >= 19) { - _has_margin_override = scan.get_bool(); - _margin_override = scan.get_int16(); - } -} - -/** - * Store textureswap information from textures.txa - */ -void PaletteGroup:: -add_texture_swap_info(const string sourceTextureName, const vector_string &swapTextures) { - TextureSwapInfo::iterator tsi = _textureSwapInfo.find(sourceTextureName); - if (tsi != _textureSwapInfo.end()) { - _textureSwapInfo.erase(tsi); - } - _textureSwapInfo.insert(TextureSwapInfo::value_type(sourceTextureName, swapTextures)); -} - -/** - * Returns textureswap information is set or not, True if it's not set. - */ -bool PaletteGroup:: -is_none_texture_swap() const { - return _textureSwapInfo.empty(); -} diff --git a/pandatool/src/palettizer/paletteGroup.h b/pandatool/src/palettizer/paletteGroup.h deleted file mode 100644 index 5c20e1ca..00000000 --- a/pandatool/src/palettizer/paletteGroup.h +++ /dev/null @@ -1,151 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file paletteGroup.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef PALETTEGROUP_H -#define PALETTEGROUP_H - -#include "pandatoolbase.h" - -#include "paletteGroups.h" -#include "textureProperties.h" - -#include "namable.h" -#include "typedWritable.h" - -#include "pset.h" -#include "pvector.h" -#include "vector_string.h" - -class EggFile; -class TexturePlacement; -class PalettePage; -class TextureImage; -class TxaFile; - -/** - * This is the highest level of grouping for TextureImages. Textures are - * assigned to one or several PaletteGroups based on the information in the - * .txa file; each PaletteGroup is conceptually a collection of textures that - * are to be moved around (into texture memory, downloaded, etc.) in one big - * chunk. It is the set of all textures that may be displayed together at any - * given time. - */ -class PaletteGroup : public TypedWritable, public Namable { -public: - PaletteGroup(); - - void set_dirname(const std::string &dirname); - bool has_dirname() const; - const std::string &get_dirname() const; - - void clear_depends(); - void group_with(PaletteGroup *other); - const PaletteGroups &get_groups() const; - - void get_placements(pvector &placements) const; - void get_complete_placements(pvector &placements) const; - - void reset_dependency_level(); - void set_dependency_level(int level); - bool set_dependency_order(); - int get_dependency_level() const; - int get_dependency_order() const; - int get_dirname_order() const; - - void set_margin_override(const int override); - int get_margin_override() const; - bool has_margin_override() const; - - bool is_preferred_over(const PaletteGroup &other) const; - - void increment_egg_count(); - int get_egg_count() const; - - PalettePage *get_page(const TextureProperties &properties); - - TexturePlacement *prepare(TextureImage *texture); - - void unplace(TexturePlacement *placement); - - void place_all(); - void update_unknown_textures(const TxaFile &txa_file); - - void write_image_info(std::ostream &out, int indent_level = 0) const; - void optimal_resize(); - void reset_images(); - void setup_shadow_images(); - void update_images(bool redo_all); - - void add_texture_swap_info(const std::string sourceTextureName, const vector_string &swapTextures); - bool is_none_texture_swap() const; - -private: - std::string _dirname; - int _egg_count; - PaletteGroups _dependent; - int _dependency_level; - int _dependency_order; - int _dirname_order; - - typedef pset Placements; - Placements _placements; - - typedef pmap Pages; - Pages _pages; - - typedef pmap TextureSwapInfo; - TextureSwapInfo _textureSwapInfo; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - virtual void finalize(BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // These values are only filled in while reading from the bam file; don't - // use them otherwise. - int _num_placements; - int _num_pages; - bool _has_margin_override; - int _margin_override; - pvector _load_pages; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - Namable::init_type(); - register_type(_type_handle, "PaletteGroup", - TypedWritable::get_class_type(), - Namable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; - - friend class PaletteGroups; -}; - -#endif diff --git a/pandatool/src/palettizer/paletteGroups.cxx b/pandatool/src/palettizer/paletteGroups.cxx deleted file mode 100644 index ada0702a..00000000 --- a/pandatool/src/palettizer/paletteGroups.cxx +++ /dev/null @@ -1,343 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file paletteGroups.cxx - * @author drose - * @date 2000-11-30 - */ - -#include "paletteGroups.h" -#include "paletteGroup.h" - -#include "indent.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "indirectCompareNames.h" -#include "pvector.h" - -TypeHandle PaletteGroups::_type_handle; - -/** - * - */ -PaletteGroups:: -PaletteGroups() { -} - -/** - * - */ -PaletteGroups:: -PaletteGroups(const PaletteGroups ©) : - _groups(copy._groups) -{ -} - -/** - * - */ -void PaletteGroups:: -operator = (const PaletteGroups ©) { - _groups = copy._groups; -} - -/** - * Inserts a new group to the set, if it is not already there. - */ -void PaletteGroups:: -insert(PaletteGroup *group) { - _groups.insert(group); -} - -/** - * Returns the number of times the given group appears in the set. This is - * either 1 if it appears at all, or 0 if it does not appear. - */ -PaletteGroups::size_type PaletteGroups:: -count(PaletteGroup *group) const { - return _groups.count(group); -} - -/** - * Completes the set with the transitive closure of all dependencies: for each - * PaletteGroup already in the set a, all of the groups that it depends on are - * added to the set, and so on. The indicated set a may be the same as this - * set. - */ -void PaletteGroups:: -make_complete(const PaletteGroups &a) { - Groups result; - - Groups::const_iterator gi; - for (gi = a._groups.begin(); gi != a._groups.end(); ++gi) { - r_make_complete(result, *gi); - } - - _groups.swap(result); -} - -/** - * Computes the union of PaletteGroups a and b, and stores the result in this - * object. The result may be the same object as either a or b. - */ -void PaletteGroups:: -make_union(const PaletteGroups &a, const PaletteGroups &b) { - Groups u; - - Groups::const_iterator ai, bi; - ai = a._groups.begin(); - bi = b._groups.begin(); - - while (ai != a._groups.end() && bi != b._groups.end()) { - if ((*ai) < (*bi)) { - u.insert(u.end(), *ai); - ++ai; - - } else if ((*bi) < (*ai)) { - u.insert(u.end(), *bi); - ++bi; - - } else { // (*ai) == (*bi) - u.insert(u.end(), *ai); - ++ai; - ++bi; - } - } - - while (ai != a._groups.end()) { - u.insert(u.end(), *ai); - ++ai; - } - - while (bi != b._groups.end()) { - u.insert(u.end(), *bi); - ++bi; - } - - _groups.swap(u); -} - -/** - * Computes the intersection of PaletteGroups a and b, and stores the result - * in this object. The result may be the same object as either a or b. - */ -void PaletteGroups:: -make_intersection(const PaletteGroups &a, const PaletteGroups &b) { - Groups i; - - Groups::const_iterator ai, bi; - ai = a._groups.begin(); - bi = b._groups.begin(); - - while (ai != a._groups.end() && bi != b._groups.end()) { - if ((*ai) < (*bi)) { - ++ai; - - } else if ((*bi) < (*ai)) { - ++bi; - - } else { // (*ai) == (*bi) - i.insert(i.end(), *ai); - ++ai; - ++bi; - } - } - - _groups.swap(i); -} - -/** - * Removes the special "null" group from the set. This is a special group - * that egg files may be assigned to, but which textures never are; it - * indicates that the egg file should not influence the palette assignment. - */ -void PaletteGroups:: -remove_null() { - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - if ((*gi)->get_name() == "null") { - _groups.erase(gi); - return; - } - } -} - -/** - * Empties the set. - */ -void PaletteGroups:: -clear() { - _groups.clear(); -} - -/** - * Returns true if the set is empty, false otherwise. - */ -bool PaletteGroups:: -empty() const { - return _groups.empty(); -} - -/** - * Returns the number of elements in the set. - */ -PaletteGroups::size_type PaletteGroups:: -size() const { - return _groups.size(); -} - -/** - * Returns an iterator suitable for traversing the set. - */ -PaletteGroups::iterator PaletteGroups:: -begin() const { - return _groups.begin(); -} - -/** - * Returns an iterator suitable for traversing the set. - */ -PaletteGroups::iterator PaletteGroups:: -end() const { - return _groups.end(); -} - -/** - * - */ -void PaletteGroups:: -output(std::ostream &out) const { - if (!_groups.empty()) { - // Sort the group names into order by name for output. - pvector group_vector; - group_vector.reserve(_groups.size()); - Groups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - group_vector.push_back(*gi); - } - sort(group_vector.begin(), group_vector.end(), - IndirectCompareNames()); - - pvector::const_iterator gvi = group_vector.begin(); - out << (*gvi)->get_name(); - ++gvi; - while (gvi != group_vector.end()) { - out << " " << (*gvi)->get_name(); - ++gvi; - } - } -} - -/** - * - */ -void PaletteGroups:: -write(std::ostream &out, int indent_level) const { - // Sort the group names into order by name for output. - pvector group_vector; - group_vector.reserve(_groups.size()); - Groups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - group_vector.push_back(*gi); - } - sort(group_vector.begin(), group_vector.end(), - IndirectCompareNames()); - - pvector::const_iterator gvi; - for (gvi = group_vector.begin(); gvi != group_vector.end(); ++gvi) { - indent(out, indent_level) << (*gvi)->get_name() << "\n"; - } -} - -/** - * The recursive implementation of make_complete(), this adds the indicated - * group and all of its dependencies to the set. - */ -void PaletteGroups:: -r_make_complete(PaletteGroups::Groups &result, PaletteGroup *group) { - bool inserted = result.insert(group).second; - - if (inserted) { - Groups::const_iterator gi; - for (gi = group->_dependent._groups.begin(); - gi != group->_dependent._groups.end(); - ++gi) { - r_make_complete(result, *gi); - } - } -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void PaletteGroups:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void PaletteGroups:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - datagram.add_uint32(_groups.size()); - - Groups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - writer->write_pointer(datagram, *gi); - } -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int PaletteGroups:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = TypedWritable::complete_pointers(p_list, manager); - for (int i = 0; i < _num_groups; i++) { - PaletteGroup *group; - DCAST_INTO_R(group, p_list[pi++], i); - _groups.insert(group); - } - return pi; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *PaletteGroups:: -make_from_bam(const FactoryParams ¶ms) { - PaletteGroups *me = new PaletteGroups; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void PaletteGroups:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - _num_groups = scan.get_int32(); - manager->read_pointers(scan, _num_groups); -} diff --git a/pandatool/src/palettizer/paletteGroups.h b/pandatool/src/palettizer/paletteGroups.h deleted file mode 100644 index b9858f82..00000000 --- a/pandatool/src/palettizer/paletteGroups.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file paletteGroups.h - * @author drose - * @date 2000-11-30 - */ - -#ifndef PALETTEGROUPS_H -#define PALETTEGROUPS_H - -#include "pandatoolbase.h" -#include "typedWritable.h" -#include "pset.h" - -class PaletteGroup; -class FactoryParams; - -/** - * A set of PaletteGroups. This presents an interface very like an STL set, - * with a few additional functions. - */ -class PaletteGroups : public TypedWritable { -private: - typedef pset Groups; - -public: -#ifndef _WIN32 - typedef Groups::const_pointer pointer; - typedef Groups::const_pointer const_pointer; -#endif - typedef Groups::const_reference reference; - typedef Groups::const_reference const_reference; - typedef Groups::const_iterator iterator; - typedef Groups::const_iterator const_iterator; - typedef Groups::const_reverse_iterator reverse_iterator; - typedef Groups::const_reverse_iterator const_reverse_iterator; - typedef Groups::size_type size_type; - typedef Groups::difference_type difference_type; - - PaletteGroups(); - PaletteGroups(const PaletteGroups ©); - void operator =(const PaletteGroups ©); - - void insert(PaletteGroup *group); - size_type count(PaletteGroup *group) const; - void make_complete(const PaletteGroups &a); - void make_union(const PaletteGroups &a, const PaletteGroups &b); - void make_intersection(const PaletteGroups &a, const PaletteGroups &b); - void remove_null(); - void clear(); - - bool empty() const; - size_type size() const; - iterator begin() const; - iterator end() const; - - void output(std::ostream &out) const; - void write(std::ostream &out, int indent_level = 0) const; - -private: - void r_make_complete(Groups &result, PaletteGroup *group); - - Groups _groups; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - -public: - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // This value is only filled in while reading from the bam file; don't use - // it otherwise. - int _num_groups; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - register_type(_type_handle, "PaletteGroups", - TypedWritable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -INLINE std::ostream &operator << (std::ostream &out, const PaletteGroups &groups) { - groups.output(out); - return out; -} - -#endif diff --git a/pandatool/src/palettizer/paletteImage.cxx b/pandatool/src/palettizer/paletteImage.cxx deleted file mode 100644 index 3ceedbf5..00000000 --- a/pandatool/src/palettizer/paletteImage.cxx +++ /dev/null @@ -1,1073 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file paletteImage.cxx - * @author drose - * @date 2000-12-01 - */ - -#include "paletteImage.h" -#include "palettePage.h" -#include "paletteGroup.h" -#include "texturePlacement.h" -#include "palettizer.h" -#include "textureImage.h" -#include "sourceTextureImage.h" -#include "filenameUnifier.h" - -#include "indent.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "string_utils.h" - -#include - -TypeHandle PaletteImage::_type_handle; - -/** - * The default constructor is only for the convenience of the bam reader. - */ -PaletteImage::ClearedRegion:: -ClearedRegion() { - _x = 0; - _y = 0; - _x_size = 0; - _y_size = 0; -} - -/** - * - */ -PaletteImage::ClearedRegion:: -ClearedRegion(TexturePlacement *placement) { - _x = placement->get_placed_x(); - _y = placement->get_placed_y(); - _x_size = placement->get_placed_x_size(); - _y_size = placement->get_placed_y_size(); -} - -/** - * - */ -PaletteImage::ClearedRegion:: -ClearedRegion(const PaletteImage::ClearedRegion ©) : - _x(copy._x), - _y(copy._y), - _x_size(copy._x_size), - _y_size(copy._y_size) -{ -} - -/** - * - */ -void PaletteImage::ClearedRegion:: -operator = (const PaletteImage::ClearedRegion ©) { - _x = copy._x; - _y = copy._y; - _x_size = copy._x_size; - _y_size = copy._y_size; -} - -/** - * Sets the appropriate region of the image to black. - */ -void PaletteImage::ClearedRegion:: -clear(PNMImage &image) { - LRGBColorf rgb(pal->_background[0], pal->_background[1], pal->_background[2]); - float alpha = pal->_background[3]; - - for (int y = _y; y < _y + _y_size; y++) { - for (int x = _x; x < _x + _x_size; x++) { - image.set_xel(x, y, rgb); - } - } - if (image.has_alpha()) { - for (int y = _y; y < _y + _y_size; y++) { - for (int x = _x; x < _x + _x_size; x++) { - image.set_alpha(x, y, alpha); - } - } - } -} - -/** - * Writes the contents of the ClearedRegion to the indicated datagram. - */ -void PaletteImage::ClearedRegion:: -write_datagram(Datagram &datagram) const { - datagram.add_int32(_x); - datagram.add_int32(_y); - datagram.add_int32(_x_size); - datagram.add_int32(_y_size); -} - -/** - * Extracts the contents of the ClearedRegion from the indicated datagram. - */ -void PaletteImage::ClearedRegion:: -fillin(DatagramIterator &scan) { - _x = scan.get_int32(); - _y = scan.get_int32(); - _x_size = scan.get_int32(); - _y_size = scan.get_int32(); -} - - - - - - -/** - * The default constructor is only for the convenience of the Bam reader. - */ -PaletteImage:: -PaletteImage() { - _page = nullptr; - _index = 0; - _new_image = false; - _got_image = false; - - _swapped_image = 0; -} - -/** - * - */ -PaletteImage:: -PaletteImage(PalettePage *page, int index) : - _page(page), - _index(index) -{ - _properties = page->get_properties(); - _size_known = true; - _x_size = pal->_pal_x_size; - _y_size = pal->_pal_y_size; - _new_image = true; - _got_image = false; - _swapped_image = 0; - - setup_filename(); -} - -/** - * - */ -PaletteImage:: -PaletteImage(PalettePage *page, int index, unsigned swapIndex) : - _page(page), - _index(index), - _swapped_image(swapIndex) -{ - _properties = page->get_properties(); - _size_known = true; - _x_size = pal->_pal_x_size; - _y_size = pal->_pal_y_size; - _new_image = true; - _got_image = false; - - setup_filename(); -} - - -/** - * Returns the particular PalettePage this image is associated with. - */ -PalettePage *PaletteImage:: -get_page() const { - return _page; -} - -/** - * Returns true if there are no textures, or only one "solitary" texture, - * placed on the image. In either case, the PaletteImage need not be - * generated. - */ -bool PaletteImage:: -is_empty() const { - if (_placements.empty()) { - // The image is genuinely empty. - return true; - - } else if (_placements.size() == 1) { - // If the image has exactly one texture, we consider the image empty only - // if the texture is actually flagged as 'solitary'. - return (_placements[0]->get_omit_reason() == OR_solitary); - - } else { - // The image has more than one texture, so it's definitely not empty. - return false; - } -} - -/** - * Returns the fraction of the PaletteImage that is actually used by any - * textures. This is 1.0 if every pixel in the PaletteImage is used, or 0.0 - * if none are. Normally it will be somewhere in between. - */ -double PaletteImage:: -count_utilization() const { - int used_pixels = 0; - - Placements::const_iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - - int texture_pixels = - placement->get_placed_x_size() * - placement->get_placed_y_size(); - used_pixels += texture_pixels; - } - - int total_pixels = get_x_size() * get_y_size(); - - return (double)used_pixels / (double)total_pixels; -} - -/** - * Returns the a weighted average of the fraction of coverage represented by - * all of the textures placed on the palette. This number represents the - * fraction of wasted pixels in the palette image consumed by copying the same - * pixels multiple times into the palette, or if the number is negative, it - * represents the fraction of pixels saved by not having to copy the entire - * texture into the palette. - */ -double PaletteImage:: -count_coverage() const { - int coverage_pixels = 0; - - Placements::const_iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - TextureImage *texture = placement->get_texture(); - nassertr(texture != nullptr, 0.0); - - int orig_pixels = - texture->get_x_size() * - texture->get_y_size(); - int placed_pixels = - placement->get_placed_x_size() * - placement->get_placed_y_size(); - - coverage_pixels += placed_pixels - orig_pixels; - } - - int total_pixels = get_x_size() * get_y_size(); - - return (double)coverage_pixels / (double)total_pixels; -} - -/** - * Attempts to place the indicated texture on the image. Returns true if - * successful, or false if there was no available space. - */ -bool PaletteImage:: -place(TexturePlacement *placement) { - nassertr(placement->is_size_known(), true); - nassertr(!placement->is_placed(), true); - - int x, y; - if (find_hole(x, y, placement->get_x_size(), placement->get_y_size())) { - placement->place_at(this, x, y); - _placements.push_back(placement); - - // [gjeon] create swappedImages - TexturePlacement::TextureSwaps::iterator tsi; - for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) { - if ((tsi - placement->_textureSwaps.begin()) >= (int)_swappedImages.size()) { - PaletteImage *swappedImage = new PaletteImage(_page, _swappedImages.size(), tsi - placement->_textureSwaps.begin() + 1); - swappedImage->_masterPlacements = &_placements; - _swappedImages.push_back(swappedImage); - } - } - - return true; - } - - return false; -} - -/** - * Removes the texture from the image. - */ -void PaletteImage:: -unplace(TexturePlacement *placement) { - nassertv(placement->is_placed() && placement->get_image() == this); - - Placements::iterator pi; - pi = find(_placements.begin(), _placements.end(), placement); - while (pi != _placements.end()) { - _placements.erase(pi); - pi = find(_placements.begin(), _placements.end(), placement); - } - _cleared_regions.push_back(ClearedRegion(placement)); -} - -/** - * To be called after all textures have been placed on the image, this checks - * to see if there is only one texture on the image. If there is, it is - * flagged as 'solitary' so that the egg files will not needlessly reference - * the palettized image. - * - * However, if pal->_omit_solitary is false, we generally don't change - * textures to solitary state. - */ -void PaletteImage:: -check_solitary() { - if (_placements.size() == 1) { - // How sad, only one. - TexturePlacement *placement = *_placements.begin(); - nassertv(placement->get_omit_reason() == OR_none || - placement->get_omit_reason() == OR_solitary); - - if (pal->_omit_solitary || placement->get_omit_reason() == OR_solitary) { - // We only omit the solitary texture if (a) we have omit_solitary in - // effect, or (b) we don't have omit_solitary in effect now, but we did - // before, and the texture is still flagged as solitary from that - // previous pass. - placement->omit_solitary(); - } - - } else { - // Zero or multiple. - Placements::const_iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - /* - if (!(placement->get_omit_reason() == OR_none || - placement->get_omit_reason() == OR_solitary)) { - nout << "texture " << *placement->get_texture() << " is omitted for " - << placement->get_omit_reason() << "\n"; - } - */ - nassertv(placement->get_omit_reason() == OR_none || - placement->get_omit_reason() == OR_solitary); - placement->not_solitary(); - } - } -} - -/** - * Attempts to resize the palette image to as small as it can go. - */ -void PaletteImage:: -optimal_resize() { - if (is_empty()) { // && (_swapped_image == 0)) { - return; - } - - bool resized_any = false; - bool success; - do { - success = false; - nassertv(_x_size > 0 && _y_size > 0); - - // Try to cut it in half in both dimensions, one at a time. - if (resize_image(_x_size, _y_size / 2)) { - success = true; - resized_any = true; - } - if (resize_image(_x_size / 2, _y_size)) { - success = true; - resized_any = true; - } - - } while (success); - - if (resized_any) { - nout << "Resizing " - << FilenameUnifier::make_user_filename(get_filename()) << " to " - << _x_size << " " << _y_size << "\n"; - - // [gjeon] resize swapped images, also - SwappedImages::iterator si; - for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) { - PaletteImage *swappedImage = (*si); - swappedImage->resize_swapped_image(_x_size, _y_size); - } - } -} - -/** - * Attempts to resize the palette image, and repack all of the textures within - * the new size. Returns true if successful, false otherwise. If this fails, - * it will still result in repacking all the textures in the original size. - */ -bool PaletteImage:: -resize_image(int x_size, int y_size) { - // We already know we're going to be generating a new image from scratch - // after this. - _cleared_regions.clear(); - remove_image(); - - // First, Save the current placement list, while simultaneously clearing it. - Placements saved; - saved.swap(_placements); - - // Also save our current size. - int saved_x_size = _x_size; - int saved_y_size = _y_size; - - // Then, sort the textures to in order from biggest to smallest, as an aid - // to optimal packing. - sort(saved.begin(), saved.end(), SortPlacementBySize()); - - // And while we're at it, we need to officially unplace each of these. - Placements::iterator pi; - for (pi = saved.begin(); pi != saved.end(); ++pi) { - (*pi)->force_replace(); - } - - // Finally, apply the new size and try to fit all the textures. - _x_size = x_size; - _y_size = y_size; - - bool packed = true; - for (pi = saved.begin(); pi != saved.end() && packed; ++pi) { - if (!place(*pi)) { - packed = false; - } - } - - if (!packed) { - // If it didn't work, phooey. Put 'em all back. - _x_size = saved_x_size; - _y_size = saved_y_size; - - Placements remove; - remove.swap(_placements); - for (pi = remove.begin(); pi != remove.end(); ++pi) { - (*pi)->force_replace(); - } - - bool all_packed = true; - for (pi = saved.begin(); pi != saved.end(); ++pi) { - if (!place(*pi)) { - all_packed = false; - } - } - nassertr(all_packed, false); - } - - return packed; -} - -/** - * Attempts to resize the palette image, and repack all of the textures within - * the new size. Returns true if successful, false otherwise. If this fails, - * it will still result in repacking all the textures in the original size. - */ -void PaletteImage:: -resize_swapped_image(int x_size, int y_size) { - // Finally, apply the new size and try to fit all the textures. - _x_size = x_size; - _y_size = y_size; -} - -/** - * Writes a list of the textures that have been placed on this image to the - * indicated output stream, one per line. - */ -void PaletteImage:: -write_placements(std::ostream &out, int indent_level) const { - Placements::const_iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - placement->write_placed(out, indent_level); - } -} - -/** - * Unpacks each texture that has been placed on this image, resetting the - * image to empty. - */ -void PaletteImage:: -reset_image() { - // We need a copy so we can modify this list as we traverse it. - Placements copy_placements = _placements; - Placements::const_iterator pi; - for (pi = copy_placements.begin(); pi != copy_placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - placement->force_replace(); - } - - _placements.clear(); - _cleared_regions.clear(); - remove_image(); -} - -/** - * Ensures the _shadow_image has the correct filename and image types, based - * on what was supplied on the command line and in the .txa file. - */ -void PaletteImage:: -setup_shadow_image() { - _shadow_image.make_shadow_image(_basename); - - // [gjeon] setup shadoe_image of swappedImages - SwappedImages::iterator si; - for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) { - PaletteImage *swappedImage = (*si); - swappedImage->setup_shadow_image(); - } -} - -/** - * If the palette has changed since it was last written out, updates the image - * and writes out a new one. If redo_all is true, regenerates the image from - * scratch and writes it out again, whether it needed it or not. - */ -void PaletteImage:: -update_image(bool redo_all) { - if (is_empty() && pal->_aggressively_clean_mapdir) { - // If the palette image is 'empty', ensure that it doesn't exist. No need - // to clutter up the map directory. - remove_image(); - return; - } - - if (redo_all) { - // If we're redoing everything, throw out the old image anyway. - remove_image(); - } - - // Check the filename too. - update_filename(); - - // Do we need to update? - bool needs_update = - _new_image || !exists() || - !_cleared_regions.empty(); - - Placements::iterator pi; - // We must continue to walk through all of the textures on the palette, even - // after we discover the palette requires an update, so we can determine - // which source images need to be recopied. - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - - if (!placement->is_filled()) { - needs_update = true; - - } else { - TextureImage *texture = placement->get_texture(); - - // Only check the timestamps on textures that are named (indirectly) on - // the command line. - if (texture->is_texture_named()) { - SourceTextureImage *source = texture->get_preferred_source(); - - if (source != nullptr && - source->get_filename().compare_timestamps(get_filename()) > 0) { - // The source image is newer than the palette image; we need to - // regenerate. - placement->mark_unfilled(); - needs_update = true; - } - } - - // [gjeon] to find out all of the swappable textures is up to date - TexturePlacement::TextureSwaps::iterator tsi; - for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) { - TextureImage *swapTexture = (*tsi); - - if (swapTexture->is_texture_named()) { - SourceTextureImage *sourceSwapTexture = swapTexture->get_preferred_source(); - - if (sourceSwapTexture != nullptr && - sourceSwapTexture->get_filename().compare_timestamps(get_filename()) > 0) { - // The source image is newer than the palette image; we need to - // regenerate. - placement->mark_unfilled(); - needs_update = true; - } - } - } - - } - } - - if (!needs_update) { - // No sweat; nothing has changed. - return; - } - - get_image(); - // [gjeon] get swapped images, too - get_swapped_images(); - - // Set to black any parts of the image that we recently unplaced. - ClearedRegions::iterator ci; - for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) { - ClearedRegion ®ion = (*ci); - region.clear(_image); - - // [gjeon] clear swapped images also - SwappedImages::iterator si; - for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) { - PaletteImage *swappedImage = (*si); - region.clear(swappedImage->_image); - } - } - _cleared_regions.clear(); - - // Now add the recent additions to the image. - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - if (!placement->is_filled()) { - placement->fill_image(_image); - - // [gjeon] fill swapped images - SwappedImages::iterator si; - for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) { - PaletteImage *swappedImage = (*si); - swappedImage->update_filename(); - placement->fill_swapped_image(swappedImage->_image, si - _swappedImages.begin()); - } - } - } - - write(_image); - - if (pal->_shadow_color_type != nullptr) { - _shadow_image.write(_image); - } - - release_image(); - - // [gjeon] write and release swapped images - SwappedImages::iterator si; - for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) { - PaletteImage *swappedImage = (*si); - swappedImage->write(swappedImage->_image); - if (pal->_shadow_color_type != nullptr) { - swappedImage->_shadow_image.write(swappedImage->_image); - } - swappedImage->release_image(); - } -} - -/** - * Changes the image filename to match the current naming scheme, assuming - * something has changed since the image was created. Returns true if the - * image filename changes (which means update_image() should be called). - */ -bool PaletteImage:: -update_filename() { - Filename orig_filename = _filename; - Filename orig_alpha_filename = _alpha_filename; - Filename orig_shadow_filename = _shadow_image.get_filename(); - - if (setup_filename()) { - nout << "Renaming " << FilenameUnifier::make_user_filename(orig_filename) - << " to " << FilenameUnifier::make_user_filename(_filename) << "\n"; - - if (!orig_filename.empty() && orig_filename.exists()) { - nout << "Deleting " << FilenameUnifier::make_user_filename(orig_filename) << "\n"; - orig_filename.unlink(); - } - if (!orig_alpha_filename.empty() && orig_alpha_filename.exists()) { - nout << "Deleting " << FilenameUnifier::make_user_filename(orig_alpha_filename) << "\n"; - orig_alpha_filename.unlink(); - } - if (!orig_shadow_filename.empty() && orig_shadow_filename.exists()) { - nout << "Deleting " << FilenameUnifier::make_user_filename(orig_shadow_filename) << "\n"; - orig_shadow_filename.unlink(); - } - _new_image = true; - - // Since the palette filename has changed, we need to mark all of the egg - // files that referenced the old filename as stale. - - // Marking egg files stale at this late point can cause minor problems; - // because we might do this, it's necessary for eggPalettize.cxx to call - // read_stale_eggs() twice. - Placements::iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - placement->mark_eggs_stale(); - } - - return true; - } - - return false; -} - -/** - * Sets up the image's filename (and that of the _shadow_pal) according to the - * specified properties. - * - * Returns true if the filename changes from what it was previously, false - * otherwise. - */ -bool PaletteImage:: -setup_filename() { - // Build up the basename for the palette image, based on the supplied image - // pattern. - _basename = std::string(); - - std::string::iterator si = pal->_generated_image_pattern.begin(); - while (si != pal->_generated_image_pattern.end()) { - if ((*si) == '%') { - // Some keycode. - ++si; - if (si != pal->_generated_image_pattern.end()) { - switch (*si) { - case '%': - _basename += '%'; - break; - - case 'g': - _basename += _page->get_group()->get_name(); - break; - - case 'p': - _basename += _page->get_name(); - break; - - case 'i': - _basename += format_string(_index + 1); - break; - - default: - _basename += '%'; - _basename += (*si); - } - ++si; - } - } else { - // A literal character. - _basename += (*si); - ++si; - } - } - - if (_swapped_image > 0) { - _basename += "_swp_"; - _basename += format_string(_swapped_image); - } - - // We must end the basename with a dot, so that it does not appear to have a - // filename extension. Otherwise, an embedded dot in the group's name would - // make everything following appear to be an extension, which would get lost - // in the set_filename() call. - if (_basename.empty() || _basename[_basename.length() - 1] != '.') { - _basename += '.'; - } - - bool any_changed = false; - - if (set_filename(_page->get_group(), _basename)) { - any_changed = true; - } - - if (_shadow_image.make_shadow_image(_basename)) { - any_changed = true; - } - - return any_changed; -} - -/** - * Searches for a hole of at least x_size by y_size pixels somewhere within - * the PaletteImage. If a suitable hole is found, sets x and y to the top - * left corner and returns true; otherwise, returns false. - */ -bool PaletteImage:: -find_hole(int &x, int &y, int x_size, int y_size) const { - y = 0; - while (y + y_size <= _y_size) { - int next_y = _y_size; - // Scan along the row at 'y'. - x = 0; - while (x + x_size <= _x_size) { - // Consider the spot at x, y. - TexturePlacement *overlap = find_overlap(x, y, x_size, y_size); - - if (overlap == nullptr) { - // Hooray! - return true; - } - - int next_x = overlap->get_placed_x() + overlap->get_placed_x_size(); - next_y = std::min(next_y, overlap->get_placed_y() + overlap->get_placed_y_size()); - nassertr(next_x > x, false); - x = next_x; - } - - nassertr(next_y > y, false); - y = next_y; - } - - // Nope, wouldn't fit anywhere. - return false; -} - -/** - * If the rectangle whose top left corner is x, y and whose size is x_size, - * y_size describes an empty hole that does not overlap any placed images, - * returns NULL; otherwise, returns the first placed texture that the image - * does overlap. It is assumed the rectangle lies completely within the - * boundaries of the image itself. - */ -TexturePlacement *PaletteImage:: -find_overlap(int x, int y, int x_size, int y_size) const { - Placements::const_iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - if (placement->is_placed() && - placement->intersects(x, y, x_size, y_size)) { - return placement; - } - } - - return nullptr; -} - -/** - * Reads or generates the PNMImage that corresponds to the palette as it is - * known so far. - */ -void PaletteImage:: -get_image() { - if (_got_image) { - return; - } - - if (!_new_image) { - if (pal->_shadow_color_type != nullptr) { - if (_shadow_image.get_filename().exists() && _shadow_image.read(_image)) { - _got_image = true; - return; - } - } else { - if (get_filename().exists() && read(_image)) { - _got_image = true; - return; - } - } - } - - nout << "Generating new " - << FilenameUnifier::make_user_filename(get_filename()) << "\n"; - - // We won't be using this any more. - _cleared_regions.clear(); - - _image.clear(get_x_size(), get_y_size(), _properties.get_num_channels()); - _image.fill(pal->_background[0], pal->_background[1], pal->_background[2]); - if (_image.has_alpha()) { - _image.alpha_fill(pal->_background[3]); - } - - _new_image = false; - _got_image = true; - - // Now fill up the image. - Placements::iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - placement->fill_image(_image); - } -} - -/** - * Reads or generates the PNMImage for swapped textures - */ -void PaletteImage:: -get_swapped_image(int index) { - if (_got_image) { - return; - } - - if (!_new_image) { - if (pal->_shadow_color_type != nullptr) { - if (_shadow_image.get_filename().exists() && _shadow_image.read(_image)) { - _got_image = true; - return; - } - } else { - if (get_filename().exists() && read(_image)) { - _got_image = true; - return; - } - } - } - - nout << "Generating new " - << FilenameUnifier::make_user_filename(get_filename()) << "\n"; - - // We won't be using this any more. - _cleared_regions.clear(); - - _image.clear(get_x_size(), get_y_size(), _properties.get_num_channels()); - _image.fill(pal->_background[0], pal->_background[1], pal->_background[2]); - if (_image.has_alpha()) { - _image.alpha_fill(pal->_background[3]); - } - - _new_image = false; - _got_image = true; - - // Now fill up the image. - Placements::iterator pi; - for (pi = _masterPlacements->begin(); pi != _masterPlacements->end(); ++pi) { - TexturePlacement *placement = (*pi); - if ((int)placement->_textureSwaps.size() > index) { - placement->fill_swapped_image(_image, index); - } else { - placement->fill_image(_image); - } - } -} - -/** - * Reads or generates the PNMImage that corresponds to the palette as it is - * known so far. - */ -void PaletteImage:: -get_swapped_images() { - SwappedImages::iterator si; - for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) { - PaletteImage *swappedImage = (*si); - swappedImage->get_swapped_image(si - _swappedImages.begin()); - } -} - -/** - * Deallocates the memory allocated by a previous call to get_image(). - */ -void PaletteImage:: -release_image() { - _image.clear(); - _got_image = false; -} - -/** - * Deletes the image file. - */ -void PaletteImage:: -remove_image() { - unlink(); - if (pal->_shadow_color_type != nullptr) { - _shadow_image.unlink(); - } - _new_image = true; -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void PaletteImage:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void PaletteImage:: -write_datagram(BamWriter *writer, Datagram &datagram) { - ImageFile::write_datagram(writer, datagram); - - datagram.add_uint32(_cleared_regions.size()); - ClearedRegions::const_iterator ci; - for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) { - (*ci).write_datagram(datagram); - } - - datagram.add_uint32(_placements.size()); - Placements::const_iterator pi; - for (pi = _placements.begin(); pi != _placements.end(); ++pi) { - writer->write_pointer(datagram, (*pi)); - } - - writer->write_pointer(datagram, _page); - datagram.add_uint32(_index); - datagram.add_string(_basename); - datagram.add_bool(_new_image); - - // We don't write _got_image or _image. These are loaded per-session. - - // We don't write _shadow_image. This is just a runtime convenience for - // specifying the name of the shadow file, and we redefine this per-session - // (which allows us to pick up a new pal->_shadow_dirname if it changes). -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int PaletteImage:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int index = ImageFile::complete_pointers(p_list, manager); - - int i; - _placements.reserve(_num_placements); - for (i = 0; i < _num_placements; i++) { - TexturePlacement *placement; - DCAST_INTO_R(placement, p_list[index], index); - _placements.push_back(placement); - index++; - } - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_page, p_list[index], index); - } - index++; - - return index; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *PaletteImage:: -make_from_bam(const FactoryParams ¶ms) { - PaletteImage *me = new PaletteImage; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void PaletteImage:: -fillin(DatagramIterator &scan, BamReader *manager) { - ImageFile::fillin(scan, manager); - - int num_cleared_regions = scan.get_uint32(); - _cleared_regions.reserve(num_cleared_regions); - for (int i = 0; i < num_cleared_regions; i++) { - _cleared_regions.push_back(ClearedRegion()); - _cleared_regions.back().fillin(scan); - } - - _num_placements = scan.get_uint32(); - manager->read_pointers(scan, _num_placements); - - manager->read_pointer(scan); // _page - - _index = scan.get_uint32(); - _basename = scan.get_string(); - _new_image = scan.get_bool(); -} diff --git a/pandatool/src/palettizer/paletteImage.h b/pandatool/src/palettizer/paletteImage.h deleted file mode 100644 index cec32aa0..00000000 --- a/pandatool/src/palettizer/paletteImage.h +++ /dev/null @@ -1,145 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file paletteImage.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef PALETTEIMAGE_H -#define PALETTEIMAGE_H - -#include "pandatoolbase.h" - -#include "imageFile.h" - -#include "pnmImage.h" - -class PalettePage; -class TexturePlacement; - -/** - * This is a single palette image, one of several within a PalettePage, which - * is in turn one of several pages within a PaletteGroup. Each palette image - * is a collage of several different textures that were all assigned to the - * same PaletteGroup, and all share the same properties of the PalettePage. - */ -class PaletteImage : public ImageFile { -private: - PaletteImage(); - -public: - PaletteImage(PalettePage *page, int index); - PaletteImage(PalettePage *page, int index, unsigned swapIndex); - - PalettePage *get_page() const; - - bool is_empty() const; - double count_utilization() const; - double count_coverage() const; - - bool place(TexturePlacement *placement); - void unplace(TexturePlacement *placement); - void check_solitary(); - - void optimal_resize(); - bool resize_image(int x_size, int y_size); - void resize_swapped_image(int x_size, int y_size); - - void write_placements(std::ostream &out, int indent_level = 0) const; - void reset_image(); - void setup_shadow_image(); - void update_image(bool redo_all); - - bool update_filename(); - -private: - bool setup_filename(); - bool find_hole(int &x, int &y, int x_size, int y_size) const; - TexturePlacement *find_overlap(int x, int y, int x_size, int y_size) const; - void get_image(); - void release_image(); - void remove_image(); - void get_swapped_image(int index); - void get_swapped_images(); - - // The ClearedRegion object keeps track of TexturePlacements that were - // recently removed and thus need to be set to black. - class ClearedRegion { - public: - ClearedRegion(); - ClearedRegion(TexturePlacement *placement); - ClearedRegion(const ClearedRegion ©); - void operator = (const ClearedRegion ©); - void clear(PNMImage &image); - - void write_datagram(Datagram &datagram) const; - void fillin(DatagramIterator &scan); - - private: - int _x, _y; - int _x_size, _y_size; - }; - - typedef pvector ClearedRegions; - ClearedRegions _cleared_regions; - - typedef pvector Placements; - Placements _placements; - - Placements *_masterPlacements; - - PalettePage *_page; - int _index; - std::string _basename; - - bool _new_image; - bool _got_image; - PNMImage _image; - - unsigned _swapped_image; // 0 for non swapped image - - ImageFile _shadow_image; - - typedef pvector SwappedImages; - SwappedImages _swappedImages; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // This value is only filled in while reading from the bam file; don't use - // it otherwise. - int _num_placements; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - ImageFile::init_type(); - register_type(_type_handle, "PaletteImage", - ImageFile::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/palettizer/palettePage.cxx b/pandatool/src/palettizer/palettePage.cxx deleted file mode 100644 index 98fa9cb2..00000000 --- a/pandatool/src/palettizer/palettePage.cxx +++ /dev/null @@ -1,299 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file palettePage.cxx - * @author drose - * @date 2000-12-01 - */ - -#include "palettePage.h" -#include "texturePlacement.h" -#include "textureImage.h" -#include "paletteImage.h" -#include "paletteGroup.h" - -#include "indent.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" - -#include - -TypeHandle PalettePage::_type_handle; - -/** - * The default constructor is only for the convenience of the Bam reader. - */ -PalettePage:: -PalettePage() { - _group = nullptr; -} - -/** - * - */ -PalettePage:: -PalettePage(PaletteGroup *group, const TextureProperties &properties) : - Namable(properties.get_string()), - _group(group), - _properties(properties) -{ -} - -/** - * Returns the group this particular PalettePage belongs to. - */ -PaletteGroup *PalettePage:: -get_group() const { - return _group; -} - -/** - * Returns the texture grouping properties that all textures in this page - * share. - */ -const TextureProperties &PalettePage:: -get_properties() const { - return _properties; -} - -/** - * Adds the indicated texture to the list of textures to consider placing on - * the page. - */ -void PalettePage:: -assign(TexturePlacement *placement) { - _assigned.push_back(placement); -} - - -/** - * Assigns all the textures to their final home in a PaletteImage somewhere. - */ -void PalettePage:: -place_all() { - // Sort the textures to be placed in order from biggest to smallest, as an - // aid to optimal packing. - sort(_assigned.begin(), _assigned.end(), SortPlacementBySize()); - - Assigned::const_iterator ai; - for (ai = _assigned.begin(); ai != _assigned.end(); ++ai) { - TexturePlacement *placement = (*ai); - place(placement); - } - - _assigned.clear(); - - // Now, look for solitary images; these are left placed, but flagged with - // OR_solitary, so they won't go into egg references. There's no real point - // in referencing these. - Images::iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - PaletteImage *image = (*ii); - image->check_solitary(); - } -} - -/** - * Assigns the particular TexturePlacement to a PaletteImage where it fits. - */ -void PalettePage:: -place(TexturePlacement *placement) { - nassertv(placement->get_omit_reason() == OR_working); - - // First, try to place it in one of our existing PaletteImages. - Images::iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - PaletteImage *image = (*ii); - if (image->place(placement)) { - return; - } - } - - // No good? Then we need to create a new PaletteImage for it. - PaletteImage *image = new PaletteImage(this, _images.size()); - _images.push_back(image); - - bool placed = image->place(placement); - - // This should have stuck. - nassertv(placed); -} - - -/** - * Removes the TexturePlacement from wherever it has been placed. - */ -void PalettePage:: -unplace(TexturePlacement *placement) { - nassertv(placement->is_placed() && placement->get_page() == this); - placement->get_image()->unplace(placement); -} - -/** - * Writes a list of the PaletteImages associated with this page, and all of - * their textures, to the indicated output stream. - */ -void PalettePage:: -write_image_info(std::ostream &out, int indent_level) const { - Images::const_iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - PaletteImage *image = (*ii); - if (!image->is_empty()) { - indent(out, indent_level); - image->output_filename(out); - out << "\n"; - image->write_placements(out, indent_level + 2); - } - } -} - -/** - * Attempts to resize each PalettteImage down to its smallest possible size. - */ -void PalettePage:: -optimal_resize() { - Images::iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - PaletteImage *image = (*ii); - image->optimal_resize(); - } -} - -/** - * Throws away all of the current PaletteImages, so that new ones may be - * created (and the packing made more optimal). - */ -void PalettePage:: -reset_images() { - Images::iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - PaletteImage *image = (*ii); - image->reset_image(); - delete image; - } - - _images.clear(); -} - -/** - * Ensures that each PaletteImage's _shadow_image has the correct filename and - * image types, based on what was supplied on the command line and in the .txa - * file. - */ -void PalettePage:: -setup_shadow_images() { - Images::iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - PaletteImage *image = (*ii); - image->setup_shadow_image(); - } -} - -/** - * Regenerates each PaletteImage on this page that needs it. - */ -void PalettePage:: -update_images(bool redo_all) { - Images::iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - PaletteImage *image = (*ii); - image->update_image(redo_all); - } -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void PalettePage:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void PalettePage:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - datagram.add_string(get_name()); - - writer->write_pointer(datagram, _group); - _properties.write_datagram(writer, datagram); - - // We don't write out _assigned, since that's rebuilt each session. - - datagram.add_uint32(_images.size()); - Images::const_iterator ii; - for (ii = _images.begin(); ii != _images.end(); ++ii) { - writer->write_pointer(datagram, *ii); - } -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int PalettePage:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = TypedWritable::complete_pointers(p_list, manager); - - if (p_list[pi] != nullptr) { - DCAST_INTO_R(_group, p_list[pi], pi); - } - pi++; - - pi += _properties.complete_pointers(p_list + pi, manager); - - int i; - _images.reserve(_num_images); - for (i = 0; i < _num_images; i++) { - PaletteImage *image; - DCAST_INTO_R(image, p_list[pi++], pi); - _images.push_back(image); - } - - return pi; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *PalettePage:: -make_from_bam(const FactoryParams ¶ms) { - PalettePage *me = new PalettePage; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void PalettePage:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - set_name(scan.get_string()); - - manager->read_pointer(scan); // _group - _properties.fillin(scan, manager); - - _num_images = scan.get_uint32(); - manager->read_pointers(scan, _num_images); -} diff --git a/pandatool/src/palettizer/palettePage.h b/pandatool/src/palettizer/palettePage.h deleted file mode 100644 index 8cac0f7a..00000000 --- a/pandatool/src/palettizer/palettePage.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file palettePage.h - * @author drose - * @date 2000-12-01 - */ - -#ifndef PALETTEPAGE_H -#define PALETTEPAGE_H - -#include "pandatoolbase.h" - -#include "textureProperties.h" - -#include "namable.h" -#include "typedWritable.h" - -class PaletteGroup; -class PaletteImage; -class TexturePlacement; - -/** - * This is a particular collection of textures, within a PaletteGroup, that - * all share the same TextureProperties. The textures on the same page may - * therefore all be placed on the same set of PaletteImages together. - */ -class PalettePage : public TypedWritable, public Namable { -private: - PalettePage(); - -public: - PalettePage(PaletteGroup *group, const TextureProperties &properties); - - PaletteGroup *get_group() const; - const TextureProperties &get_properties() const; - - void assign(TexturePlacement *placement); - void place_all(); - void place(TexturePlacement *placement); - void unplace(TexturePlacement *placement); - - void write_image_info(std::ostream &out, int indent_level = 0) const; - void optimal_resize(); - void reset_images(); - void setup_shadow_images(); - void update_images(bool redo_all); - -private: - PaletteGroup *_group; - TextureProperties _properties; - - typedef pvector Assigned; - Assigned _assigned; - - typedef pvector Images; - Images _images; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // This value is only filled in while reading from the bam file; don't use - // it otherwise. - int _num_images; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - Namable::init_type(); - register_type(_type_handle, "PalettePage", - TypedWritable::get_class_type(), - Namable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/palettizer/palettizer.cxx b/pandatool/src/palettizer/palettizer.cxx deleted file mode 100644 index 0860cb38..00000000 --- a/pandatool/src/palettizer/palettizer.cxx +++ /dev/null @@ -1,1175 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file palettizer.cxx - * @author drose - * @date 2000-12-01 - */ - -#include "palettizer.h" -#include "eggFile.h" -#include "textureImage.h" -#include "pal_string_utils.h" -#include "paletteGroup.h" -#include "filenameUnifier.h" -#include "textureMemoryCounter.h" - -#include "pnmImage.h" -#include "pnmFileTypeRegistry.h" -#include "pnmFileType.h" -#include "eggData.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "indent.h" - -using std::cout; -using std::string; - -Palettizer *pal = nullptr; - -// This number is written out as the first number to the pi file, to indicate -// the version of egg-palettize that wrote it out. This allows us to easily -// update egg-palettize to write out additional information to its pi file, -// without having it increment the bam version number for all bam and boo -// files anywhere in the world. -int Palettizer::_pi_version = 21; -/* - * Updated to version 8 on 32003 to remove extensions from texture key names. - * Updated to version 9 on 41303 to add a few properties in various places. - * Updated to version 10 on 41503 to add _alpha_file_channel. Updated to - * version 11 on 43003 to add TextureReference::_tref_name. Updated to - * version 12 on 91103 to add _generated_image_pattern. Updated to version 13 - * on 91303 to add _keep_format and _background. Updated to version 14 on - * 72605 to add _omit_everything. Updated to version 15 on 80105 to make - * TextureImages be case-insensitive. Updated to version 16 on 40306 to add - * Palettizer::_cutout_mode et al. Updated to version 17 on 30207 to add - * TextureImage::_txa_wrap_u etc. Updated to version 18 on 51308 to add - * TextureProperties::_quality_level. Updated to version 19 on 71609 to add - * PaletteGroup::_override_margin Updated to version 20 on 72709 to add - * TexturePlacement::_swapTextures - * Updated to version 21 on 110120 to add sRGB support. - */ - -int Palettizer::_min_pi_version = 8; -// Dropped support for versions 7 and below on 71403. - -int Palettizer::_read_pi_version = 0; - -TypeHandle Palettizer::_type_handle; - -std::ostream &operator << (std::ostream &out, Palettizer::RemapUV remap) { - switch (remap) { - case Palettizer::RU_never: - return out << "never"; - - case Palettizer::RU_group: - return out << "per group"; - - case Palettizer::RU_poly: - return out << "per polygon"; - - case Palettizer::RU_invalid: - return out << "(invalid)"; - } - - return out << "**invalid**(" << (int)remap << ")"; -} - - -// This STL function object is used in report_statistics(), below. -class SortGroupsByDependencyOrder { -public: - bool operator ()(PaletteGroup *a, PaletteGroup *b) { - if (a->get_dependency_order() != b->get_dependency_order()) { - return a->get_dependency_order() < b->get_dependency_order(); - } - return a->get_name() < b->get_name(); - } -}; - -// And this one is used in report_pi(). -class SortGroupsByPreference { -public: - bool operator ()(PaletteGroup *a, PaletteGroup *b) { - return !a->is_preferred_over(*b); - } -}; - -/** - * - */ -Palettizer:: -Palettizer() { - _is_valid = true; - _noabs = false; - - _generated_image_pattern = "%g_palette_%p_%i"; - _map_dirname = "%g"; - _shadow_dirname = "shadow"; - _margin = 2; - _omit_solitary = false; - _omit_everything = false; - _coverage_threshold = 2.5; - _aggressively_clean_mapdir = true; - _force_power_2 = true; - _color_type = PNMFileTypeRegistry::get_global_ptr()->get_type_from_extension("png"); - _alpha_type = nullptr; - _shadow_color_type = nullptr; - _shadow_alpha_type = nullptr; - _pal_x_size = _pal_y_size = 512; - _background.set(0.0, 0.0, 0.0, 0.0); - _cutout_mode = EggRenderMode::AM_dual; - _cutout_ratio = 0.3; - - _round_uvs = true; - _round_unit = 0.1; - _round_fuzz = 0.01; - _remap_uv = RU_poly; - _remap_char_uv = RU_poly; - - get_palette_group("null"); -} - -/** - * Returns the current setting of the noabs flag. See set_noabs(). - */ -bool Palettizer:: -get_noabs() const { - return _noabs; -} - -/** - * Changes the current setting of the noabs flag. - * - * If this flag is true, then it is an error to process an egg file that - * contains absolute pathname references. This flag is intended to help - * detect egg files that are incorrectly built within a model tree (which - * should use entirely relative pathnames). - * - * This flag must be set before any egg files are processed. - */ -void Palettizer:: -set_noabs(bool noabs) { - _noabs = noabs; -} - -/** - * Returns true if the palette information file was read correctly, or false - * if there was some error and the palettization can't continue. - */ -bool Palettizer:: -is_valid() const { - return _is_valid; -} - -/** - * Output a verbose description of all the palettization information to - * standard output, for the user's perusal. - */ -void Palettizer:: -report_pi() const { - // Start out with the cross links and back counts; some of these are nice to - // report. - EggFiles::const_iterator efi; - for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) { - (*efi).second->build_cross_links(); - } - - cout - << "\nparams\n" - << " generated image pattern: " << _generated_image_pattern << "\n" - << " map directory: " << _map_dirname << "\n" - << " shadow directory: " - << FilenameUnifier::make_user_filename(_shadow_dirname) << "\n" - << " egg relative directory: " - << FilenameUnifier::make_user_filename(_rel_dirname) << "\n" - << " palettize size: " << _pal_x_size << " by " << _pal_y_size << "\n" - << " background: " << _background << "\n" - << " margin: " << _margin << "\n" - << " coverage threshold: " << _coverage_threshold << "\n" - << " force textures to power of 2: " << yesno(_force_power_2) << "\n" - << " aggressively clean the map directory: " - << yesno(_aggressively_clean_mapdir) << "\n" - << " omit everything: " << yesno(_omit_everything) << "\n" - << " round UV area: " << yesno(_round_uvs) << "\n"; - if (_round_uvs) { - cout << " round UV area to nearest " << _round_unit << " with fuzz " - << _round_fuzz << "\n"; - } - cout << " remap UV's: " << _remap_uv << "\n" - << " remap UV's for characters: " << _remap_char_uv << "\n"; - cout << " alpha cutouts: " << _cutout_mode << " " << _cutout_ratio << "\n"; - - if (_color_type != nullptr) { - cout << " generate image files of type: " - << _color_type->get_suggested_extension(); - if (_alpha_type != nullptr) { - cout << "," << _alpha_type->get_suggested_extension(); - } - cout << "\n"; - } - - if (_shadow_color_type != nullptr) { - cout << " generate shadow palette files of type: " - << _shadow_color_type->get_suggested_extension(); - if (_shadow_alpha_type != nullptr) { - cout << "," << _shadow_alpha_type->get_suggested_extension(); - } - cout << "\n"; - } - - cout << "\ntexture source pathnames and assignments\n"; - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - if (texture->is_used()) { - cout << " " << texture->get_name() << ":\n"; - texture->write_source_pathnames(cout, 4); - } - } - - cout << "\negg files and textures referenced\n"; - EggFiles::const_iterator ei; - for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { - EggFile *egg_file = (*ei).second; - egg_file->write_description(cout, 2); - egg_file->write_texture_refs(cout, 4); - } - - // Sort the palette groups into order of preference, so that the more - // specific ones appear at the bottom. - pvector sorted_groups; - Groups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - sorted_groups.push_back((*gi).second); - } - sort(sorted_groups.begin(), sorted_groups.end(), - SortGroupsByPreference()); - - cout << "\npalette groups\n"; - pvector::iterator si; - for (si = sorted_groups.begin(); si != sorted_groups.end(); ++si) { - PaletteGroup *group = (*si); - if (si != sorted_groups.begin()) { - cout << "\n"; - } - cout << " " << group->get_name() - // << " (" << group->get_dirname_order() << "," << - // group->get_dependency_order() << ")" - << ": " << group->get_groups() << "\n"; - group->write_image_info(cout, 4); - } - - cout << "\ntextures\n"; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - texture->write_scale_info(cout, 2); - } - - cout << "\nsurprises\n"; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - if (texture->is_surprise()) { - cout << " " << texture->get_name() << "\n"; - } - } - for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { - EggFile *egg_file = (*ei).second; - if (egg_file->is_surprise()) { - cout << " " << egg_file->get_name() << "\n"; - } - } - - cout << "\n"; -} - -/** - * Output a report of the palettization effectiveness, texture memory - * utilization, and so on. - */ -void Palettizer:: -report_statistics() const { - // Sort the groups into order by dependency order, for the user's - // convenience. - pvector sorted_groups; - - Groups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - sorted_groups.push_back((*gi).second); - } - - sort(sorted_groups.begin(), sorted_groups.end(), - SortGroupsByDependencyOrder()); - - Placements overall_placements; - - pvector::const_iterator si; - for (si = sorted_groups.begin(); - si != sorted_groups.end(); - ++si) { - PaletteGroup *group = (*si); - - Placements placements; - group->get_placements(placements); - if (!placements.empty()) { - group->get_placements(overall_placements); - - cout << "\n" << group->get_name() << ", by itself:\n"; - compute_statistics(cout, 2, placements); - - PaletteGroups complete; - complete.make_complete(group->get_groups()); - - if (complete.size() > 1) { - Placements complete_placements; - group->get_complete_placements(complete_placements); - if (complete_placements.size() != placements.size()) { - cout << "\n" << group->get_name() - << ", with dependents (" << complete << "):\n"; - compute_statistics(cout, 2, complete_placements); - } - } - } - } - - cout << "\nOverall:\n"; - compute_statistics(cout, 2, overall_placements); - - cout << "\n"; -} - - -/** - * Reads in the .txa file and keeps it ready for matching textures and egg - * files. - */ -void Palettizer:: -read_txa_file(std::istream &txa_file, const string &txa_filename) { - // Clear out the group dependencies, in preparation for reading them again - // from the .txa file. - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->clear_depends(); - group->set_dirname(""); - } - - // Also reset _shadow_color_type. - _shadow_color_type = nullptr; - _shadow_alpha_type = nullptr; - - if (!_txa_file.read(txa_file, txa_filename)) { - exit(1); - } - - if (_color_type == nullptr) { - nout << "No valid output image file type available; cannot run.\n" - << "Use :imagetype command in .txa file.\n"; - exit(1); - } - - // Compute the correct dependency level and order for each group. This will - // help us when we assign the textures to their groups. - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->reset_dependency_level(); - } - - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->set_dependency_level(1); - } - - bool any_changed; - do { - any_changed = false; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - if (group->set_dependency_order()) { - any_changed = true; - } - } - } while (any_changed); -} - -/** - * Called after all command line parameters have been set up, this is a hook - * to do whatever initialization is necessary. - */ -void Palettizer:: -all_params_set() { - // Make sure the palettes have their shadow images set up properly. - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->setup_shadow_images(); - } -} - -/** - * Processes all the textures named in the _command_line_eggs, placing them on - * the appropriate palettes or whatever needs to be done with them. - * - * If force_texture_read is true, it forces each texture image file to be read - * (and thus legitimately checked for grayscaleness etc.) before placing. - */ -void Palettizer:: -process_command_line_eggs(bool force_texture_read, const Filename &state_filename) { - _command_line_textures.clear(); - - // Start by scanning all the egg files we read up on the command line. - CommandLineEggs::const_iterator ei; - for (ei = _command_line_eggs.begin(); - ei != _command_line_eggs.end(); - ++ei) { - EggFile *egg_file = (*ei); - - egg_file->scan_textures(); - egg_file->get_textures(_command_line_textures); - - egg_file->pre_txa_file(); - _txa_file.match_egg(egg_file); - egg_file->post_txa_file(); - } - - // Now that all of our egg files are read in, build in all the cross links - // and back pointers and stuff. - EggFiles::const_iterator efi; - for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) { - (*efi).second->build_cross_links(); - } - - // Now match each of the textures mentioned in those egg files against a - // line in the .txa file. - CommandLineTextures::iterator ti; - for (ti = _command_line_textures.begin(); - ti != _command_line_textures.end(); - ++ti) { - TextureImage *texture = *ti; - - if (force_texture_read || texture->is_newer_than(state_filename)) { - // If we're forcing a redo, or the texture image has changed, re-read - // the complete image. - texture->read_source_image(); - } else { - // Otherwise, just the header is sufficient. - texture->read_header(); - } - - texture->mark_texture_named(); - texture->pre_txa_file(); - _txa_file.match_texture(texture); - texture->post_txa_file(); - } - - // And now, assign each of the current set of textures to an appropriate - // group or groups. - for (ti = _command_line_textures.begin(); - ti != _command_line_textures.end(); - ++ti) { - TextureImage *texture = *ti; - texture->assign_groups(); - } - - // And then the egg files need to sign up for a particular TexturePlacement, - // so we can determine some more properties about how the textures are - // placed (for instance, how big the UV range is for a particular - // TexturePlacement). - for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) { - (*efi).second->choose_placements(); - } - - // Now that *that's* done, we need to make sure the various - // TexturePlacements require the right size for their textures. - for (ti = _command_line_textures.begin(); - ti != _command_line_textures.end(); - ++ti) { - TextureImage *texture = *ti; - texture->determine_placement_size(); - } - - // Now that each texture has been assigned to a suitable group, make sure - // the textures are placed on specific PaletteImages. - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->update_unknown_textures(_txa_file); - group->place_all(); - } -} - -/** - * Reprocesses all textures known. - * - * If force_texture_read is true, it forces each texture image file to be read - * (and thus legitimately checked for grayscaleness etc.) before placing. - */ -void Palettizer:: -process_all(bool force_texture_read, const Filename &state_filename) { - // First, clear all the basic properties on the source texture images, so we - // can reapply them from the complete set of egg files and thereby ensure - // they are up-to-date. - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - texture->clear_source_basic_properties(); - } - - // If there *were* any egg files on the command line, deal with them. - CommandLineEggs::const_iterator ei; - for (ei = _command_line_eggs.begin(); - ei != _command_line_eggs.end(); - ++ei) { - EggFile *egg_file = (*ei); - - egg_file->scan_textures(); - egg_file->get_textures(_command_line_textures); - } - - // Then match up all the egg files we know about with the .txa file. - EggFiles::const_iterator efi; - for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) { - EggFile *egg_file = (*efi).second; - egg_file->pre_txa_file(); - _txa_file.match_egg(egg_file); - egg_file->post_txa_file(); - } - - // Now that all of our egg files are read in, build in all the cross links - // and back pointers and stuff. - for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) { - (*efi).second->build_cross_links(); - - // Also make sure each egg file's properties are applied to the source - // image (since we reset all the source image properties, above). - (*efi).second->apply_properties_to_source(); - } - - // Now match each of the textures in the world against a line in the .txa - // file. - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - if (force_texture_read || texture->is_newer_than(state_filename)) { - texture->read_source_image(); - } - - texture->mark_texture_named(); - texture->pre_txa_file(); - _txa_file.match_texture(texture); - texture->post_txa_file(); - - // We need to do this to avoid bloating memory. - texture->release_source_image(); - } - - // And now, assign each texture to an appropriate group or groups. - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - texture->assign_groups(); - } - - // And then the egg files need to sign up for a particular TexturePlacement, - // so we can determine some more properties about how the textures are - // placed (for instance, how big the UV range is for a particular - // TexturePlacement). - for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) { - (*efi).second->choose_placements(); - } - - // Now that *that's* done, we need to make sure the various - // TexturePlacements require the right size for their textures. - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - texture->determine_placement_size(); - } - - // Now that each texture has been assigned to a suitable group, make sure - // the textures are placed on specific PaletteImages. - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->update_unknown_textures(_txa_file); - group->place_all(); - } -} - -/** - * Attempts to resize each PalettteImage down to its smallest possible size. - */ -void Palettizer:: -optimal_resize() { - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->optimal_resize(); - } -} - -/** - * Throws away all of the current PaletteImages, so that new ones may be - * created (and the packing made more optimal). - */ -void Palettizer:: -reset_images() { - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->reset_images(); - } -} - -/** - * Actually generates the appropriate palette and unplaced texture images into - * the map directories. If redo_all is true, this forces a regeneration of - * each image file. - */ -void Palettizer:: -generate_images(bool redo_all) { - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - group->update_images(redo_all); - } - - Textures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - TextureImage *texture = (*ti).second; - texture->copy_unplaced(redo_all); - } -} - -/** - * Reads in any egg file that is known to be stale, even if it was not listed - * on the command line, so that it may be updated and written out when - * write_eggs() is called. If redo_all is true, this even reads egg files - * that were not flagged as stale. - * - * Returns true if successful, or false if there was some error. - */ -bool Palettizer:: -read_stale_eggs(bool redo_all) { - bool okflag = true; - - pvector invalid_eggs; - - EggFiles::iterator ei; - for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { - EggFile *egg_file = (*ei).second; - if (!egg_file->had_data() && - (egg_file->is_stale() || redo_all)) { - if (!egg_file->read_egg(_noabs)) { - invalid_eggs.push_back(ei); - - } else { - egg_file->scan_textures(); - egg_file->choose_placements(); - egg_file->release_egg_data(); - } - } - } - - // Now eliminate all the invalid egg files. - pvector::iterator ii; - for (ii = invalid_eggs.begin(); ii != invalid_eggs.end(); ++ii) { - EggFiles::iterator ei = (*ii); - EggFile *egg_file = (*ei).second; - if (egg_file->get_source_filename().exists()) { - // If there is an invalid egg file, remove it; hopefully it will get - // rebuilt properly next time. - nout << "Removing invalid egg file: " - << FilenameUnifier::make_user_filename(egg_file->get_source_filename()) - << "\n"; - - egg_file->get_source_filename().unlink(); - okflag = false; - - } else { - // If the egg file is simply missing, quietly remove any record of it - // from the database. - egg_file->remove_egg(); - _egg_files.erase(ei); - } - } - - if (!okflag) { - nout << "\n" - << "Some errors in egg files encountered.\n" - << "Re-run make install or make opt-pal to try to regenerate these.\n\n"; - } - - return okflag; -} - -/** - * Adjusts the egg files to reference the newly generated textures, and writes - * them out. Returns true if successful, or false if there was some error. - */ -bool Palettizer:: -write_eggs() { - bool okflag = true; - - EggFiles::iterator ei; - for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { - EggFile *egg_file = (*ei).second; - if (egg_file->had_data()) { - if (!egg_file->has_data()) { - // Re-read the egg file. - bool read_ok = egg_file->read_egg(_noabs); - if (!read_ok) { - nout << "Error! Unable to re-read egg file.\n"; - okflag = false; - } - } - - if (egg_file->has_data()) { - egg_file->update_egg(); - if (!egg_file->write_egg()) { - okflag = false; - } - egg_file->release_egg_data(); - } - } - } - - return okflag; -} - -/** - * Returns the EggFile with the given name. If there is no EggFile with the - * indicated name, creates one. This is the key name used to sort the egg - * files, which is typically the basename of the filename. - */ -EggFile *Palettizer:: -get_egg_file(const string &name) { - EggFiles::iterator ei = _egg_files.find(name); - if (ei != _egg_files.end()) { - return (*ei).second; - } - - EggFile *file = new EggFile; - file->set_name(name); - _egg_files.insert(EggFiles::value_type(name, file)); - return file; -} - -/** - * Removes the named egg file from the database, if it exists. Returns true - * if the egg file was found, false if it was not. - */ -bool Palettizer:: -remove_egg_file(const string &name) { - EggFiles::iterator ei = _egg_files.find(name); - if (ei != _egg_files.end()) { - EggFile *file = (*ei).second; - file->remove_egg(); - _egg_files.erase(ei); - return true; - } - - return false; -} - -/** - * Adds the indicated EggFile to the list of eggs that are considered to have - * been read on the command line. These will be processed by - * process_command_line_eggs(). - */ -void Palettizer:: -add_command_line_egg(EggFile *egg_file) { - _command_line_eggs.push_back(egg_file); -} - -/** - * Returns the PaletteGroup with the given name. If there is no PaletteGroup - * with the indicated name, creates one. - */ -PaletteGroup *Palettizer:: -get_palette_group(const string &name) { - Groups::iterator gi = _groups.find(name); - if (gi != _groups.end()) { - return (*gi).second; - } - - PaletteGroup *group = new PaletteGroup; - group->set_name(name); - _groups.insert(Groups::value_type(name, group)); - return group; -} - -/** - * Returns the PaletteGroup with the given name. If there is no PaletteGroup - * with the indicated name, returns NULL. - */ -PaletteGroup *Palettizer:: -test_palette_group(const string &name) const { - Groups::const_iterator gi = _groups.find(name); - if (gi != _groups.end()) { - return (*gi).second; - } - - return nullptr; -} - -/** - * Returns the default group to which an egg file should be assigned if it is - * not mentioned in the .txa file. - */ -PaletteGroup *Palettizer:: -get_default_group() { - PaletteGroup *default_group = get_palette_group(_default_groupname); - if (!_default_groupdir.empty() && !default_group->has_dirname()) { - default_group->set_dirname(_default_groupdir); - } - return default_group; -} - -/** - * Returns the TextureImage with the given name. If there is no TextureImage - * with the indicated name, creates one. This is the key name used to sort - * the textures, which is typically the basename of the primary filename. - */ -TextureImage *Palettizer:: -get_texture(const string &name) { - // Look first in the same-case name, just in case it happens to be there - // (from an older version of egg-palettize that did this). - Textures::iterator ti = _textures.find(name); - if (ti != _textures.end()) { - return (*ti).second; - } - - // Then look in the downcase name, since we nowadays index textures only by - // their downcase names (to implement case insensitivity). - string downcase_name = downcase(name); - ti = _textures.find(downcase_name); - if (ti != _textures.end()) { - return (*ti).second; - } - - TextureImage *image = new TextureImage; - image->set_name(name); - // image->set_filename(name); - _textures.insert(Textures::value_type(downcase_name, image)); - - return image; -} - -/** - * A silly function to return "yes" or "no" based on a bool flag for nicely - * formatted output. - */ -const char *Palettizer:: -yesno(bool flag) { - return flag ? "yes" : "no"; -} - -/** - * Returns the RemapUV code corresponding to the indicated string, or - * RU_invalid if the string is invalid. - */ -Palettizer::RemapUV Palettizer:: -string_remap(const string &str) { - if (str == "never") { - return RU_never; - - } else if (str == "group") { - return RU_group; - - } else if (str == "poly") { - return RU_poly; - - } else { - return RU_invalid; - } -} - -/** - * Determines how much memory, etc. is required by the indicated set of - * texture placements, and reports this to the indicated output stream. - */ -void Palettizer:: -compute_statistics(std::ostream &out, int indent_level, - const Palettizer::Placements &placements) const { - TextureMemoryCounter counter; - - Placements::const_iterator pi; - for (pi = placements.begin(); pi != placements.end(); ++pi) { - TexturePlacement *placement = (*pi); - counter.add_placement(placement); - } - - counter.report(out, indent_level); -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void Palettizer:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void Palettizer:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - - datagram.add_int32(_pi_version); - datagram.add_string(_generated_image_pattern); - datagram.add_string(_map_dirname); - datagram.add_string(FilenameUnifier::make_bam_filename(_shadow_dirname)); - datagram.add_string(FilenameUnifier::make_bam_filename(_rel_dirname)); - datagram.add_int32(_pal_x_size); - datagram.add_int32(_pal_y_size); - datagram.add_float64(_background[0]); - datagram.add_float64(_background[1]); - datagram.add_float64(_background[2]); - datagram.add_float64(_background[3]); - datagram.add_int32(_margin); - datagram.add_bool(_omit_solitary); - datagram.add_bool(_omit_everything); - datagram.add_float64(_coverage_threshold); - datagram.add_bool(_force_power_2); - datagram.add_bool(_aggressively_clean_mapdir); - datagram.add_bool(_round_uvs); - datagram.add_float64(_round_unit); - datagram.add_float64(_round_fuzz); - datagram.add_int32((int)_remap_uv); - datagram.add_int32((int)_remap_char_uv); - datagram.add_uint8((int)_cutout_mode); - datagram.add_float64(_cutout_ratio); - - writer->write_pointer(datagram, _color_type); - writer->write_pointer(datagram, _alpha_type); - writer->write_pointer(datagram, _shadow_color_type); - writer->write_pointer(datagram, _shadow_alpha_type); - - datagram.add_int32(_egg_files.size()); - EggFiles::const_iterator ei; - for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { - writer->write_pointer(datagram, (*ei).second); - } - - // We don't write _command_line_eggs; that's specific to each session. - - datagram.add_int32(_groups.size()); - Groups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - writer->write_pointer(datagram, (*gi).second); - } - - datagram.add_int32(_textures.size()); - Textures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - writer->write_pointer(datagram, (*ti).second); - } -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int Palettizer:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int index = TypedWritable::complete_pointers(p_list, manager); - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_color_type, p_list[index], index); - } - index++; - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_alpha_type, p_list[index], index); - } - index++; - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_shadow_color_type, p_list[index], index); - } - index++; - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_shadow_alpha_type, p_list[index], index); - } - index++; - - int i; - for (i = 0; i < _num_egg_files; i++) { - EggFile *egg_file; - DCAST_INTO_R(egg_file, p_list[index], index); - _egg_files.insert(EggFiles::value_type(egg_file->get_name(), egg_file)); - index++; - } - - for (i = 0; i < _num_groups; i++) { - PaletteGroup *group; - DCAST_INTO_R(group, p_list[index], index); - _groups.insert(Groups::value_type(group->get_name(), group)); - index++; - } - - for (i = 0; i < _num_textures; i++) { - TextureImage *texture; - DCAST_INTO_R(texture, p_list[index], index); - - string name = downcase(texture->get_name()); - std::pair result = _textures.insert(Textures::value_type(name, texture)); - if (!result.second) { - // Two textures mapped to the same slot--probably a case error (since we - // just changed this rule). - _texture_conflicts.push_back(texture); - } - index++; - } - - return index; -} - -/** - * Called by the BamReader to perform any final actions needed for setting up - * the object after all objects have been read and all pointers have been - * completed. - */ -void Palettizer:: -finalize(BamReader *manager) { - // Walk through the list of texture names that were in conflict. These can - // only happen if there were two different names that different only in - // case, which means the textures.boo file was created before we introduced - // the rule that case is insignificant. - TextureConflicts::iterator ci; - for (ci = _texture_conflicts.begin(); - ci != _texture_conflicts.end(); - ++ci) { - TextureImage *texture_b = (*ci); - string downcase_name = downcase(texture_b->get_name()); - - Textures::iterator ti = _textures.find(downcase_name); - nassertv(ti != _textures.end()); - TextureImage *texture_a = (*ti).second; - _textures.erase(ti); - - if (!texture_b->is_used() || !texture_a->is_used()) { - // If either texture is not used, there's not really a conflict--the - // other one wins. - if (texture_a->is_used()) { - bool inserted1 = _textures.insert(Textures::value_type(downcase_name, texture_a)).second; - nassertd(inserted1) { } - - } else if (texture_b->is_used()) { - bool inserted2 = _textures.insert(Textures::value_type(downcase_name, texture_b)).second; - nassertd(inserted2) { } - } - - } else { - // If both textures are used, there *is* a conflict. - nout << "Texture name conflict: \"" << texture_a->get_name() - << "\" vs. \"" << texture_b->get_name() << "\"\n"; - if (texture_a->get_name() != downcase_name && - texture_b->get_name() != downcase_name) { - // Arbitrarily pick texture_a to get the right case. - bool inserted1 = _textures.insert(Textures::value_type(downcase_name, texture_a)).second; - bool inserted2 = _textures.insert(Textures::value_type(texture_b->get_name(), texture_b)).second; - nassertd(inserted1 && inserted2) { } - - } else { - // One of them is already the right case. - bool inserted1 = _textures.insert(Textures::value_type(texture_a->get_name(), texture_a)).second; - bool inserted2 = _textures.insert(Textures::value_type(texture_b->get_name(), texture_b)).second; - nassertd(inserted1 && inserted2) { } - } - } - } -} - - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *Palettizer:: -make_from_bam(const FactoryParams ¶ms) { - Palettizer *me = new Palettizer; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - manager->register_finalize(me); - - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void Palettizer:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - - _read_pi_version = scan.get_int32(); - if (_read_pi_version > _pi_version || _read_pi_version < _min_pi_version) { - // Oops, we don't know how to read this palette information file. - _is_valid = false; - return; - } - if (_read_pi_version >= 12) { - _generated_image_pattern = scan.get_string(); - } - _map_dirname = scan.get_string(); - _shadow_dirname = FilenameUnifier::get_bam_filename(scan.get_string()); - _rel_dirname = FilenameUnifier::get_bam_filename(scan.get_string()); - FilenameUnifier::set_rel_dirname(_rel_dirname); - _pal_x_size = scan.get_int32(); - _pal_y_size = scan.get_int32(); - if (_read_pi_version >= 13) { - _background[0] = scan.get_float64(); - _background[1] = scan.get_float64(); - _background[2] = scan.get_float64(); - _background[3] = scan.get_float64(); - } - _margin = scan.get_int32(); - _omit_solitary = scan.get_bool(); - if (_read_pi_version >= 14) { - _omit_everything = scan.get_bool(); - } - _coverage_threshold = scan.get_float64(); - _force_power_2 = scan.get_bool(); - _aggressively_clean_mapdir = scan.get_bool(); - _round_uvs = scan.get_bool(); - _round_unit = scan.get_float64(); - _round_fuzz = scan.get_float64(); - _remap_uv = (RemapUV)scan.get_int32(); - _remap_char_uv = (RemapUV)scan.get_int32(); - if (_read_pi_version >= 16) { - _cutout_mode = (EggRenderMode::AlphaMode)scan.get_uint8(); - _cutout_ratio = scan.get_float64(); - } - - manager->read_pointer(scan); // _color_type - manager->read_pointer(scan); // _alpha_type - manager->read_pointer(scan); // _shadow_color_type - manager->read_pointer(scan); // _shadow_alpha_type - - _num_egg_files = scan.get_int32(); - manager->read_pointers(scan, _num_egg_files); - - _num_groups = scan.get_int32(); - manager->read_pointers(scan, _num_groups); - - _num_textures = scan.get_int32(); - manager->read_pointers(scan, _num_textures); -} diff --git a/pandatool/src/palettizer/palettizer.h b/pandatool/src/palettizer/palettizer.h deleted file mode 100644 index 93f211bb..00000000 --- a/pandatool/src/palettizer/palettizer.h +++ /dev/null @@ -1,190 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file palettizer.h - * @author drose - * @date 2000-12-01 - */ - -#ifndef PALETTIZER_H -#define PALETTIZER_H - -#include "pandatoolbase.h" - -#include "txaFile.h" - -#include "typedWritable.h" -#include "eggRenderMode.h" -#include "pvector.h" -#include "pset.h" -#include "pmap.h" - -class PNMFileType; -class EggFile; -class PaletteGroup; -class TextureImage; -class TexturePlacement; -class FactoryParams; - -/** - * This is the main engine behind egg-palettize. It contains all of the - * program parameters, from the command line or saved from a previous session, - * and serves as the driving force in the actual palettizing process. - */ -class Palettizer : public TypedWritable { -public: - Palettizer(); - - bool get_noabs() const; - void set_noabs(bool noabs); - - bool is_valid() const; - void report_pi() const; - void report_statistics() const; - - void read_txa_file(std::istream &txa_file, const std::string &txa_filename); - void all_params_set(); - void process_command_line_eggs(bool force_texture_read, const Filename &state_filename); - void process_all(bool force_texture_read, const Filename &state_filename); - void optimal_resize(); - void reset_images(); - void generate_images(bool redo_all); - bool read_stale_eggs(bool redo_all); - bool write_eggs(); - - EggFile *get_egg_file(const std::string &name); - bool remove_egg_file(const std::string &name); - - void add_command_line_egg(EggFile *egg_file); - - PaletteGroup *get_palette_group(const std::string &name); - PaletteGroup *test_palette_group(const std::string &name) const; - PaletteGroup *get_default_group(); - TextureImage *get_texture(const std::string &name); - -private: - static const char *yesno(bool flag); - -public: - static int _pi_version; - static int _min_pi_version; - static int _read_pi_version; - - enum RemapUV { - RU_never, - RU_group, - RU_poly, - RU_invalid - }; - - static RemapUV string_remap(const std::string &str); - - bool _is_valid; - - // These values are not stored in the textures.boo file, but are specific to - // each session. - TxaFile _txa_file; - std::string _default_groupname; - std::string _default_groupdir; - bool _noabs; - - // The following parameter values specifically relate to textures and - // palettes. These values are stored in the textures.boo file for future - // reference. - std::string _generated_image_pattern; - std::string _map_dirname; - Filename _shadow_dirname; - Filename _rel_dirname; - int _pal_x_size, _pal_y_size; - LColord _background; - int _margin; - bool _omit_solitary; - bool _omit_everything; - double _coverage_threshold; - bool _force_power_2; - bool _aggressively_clean_mapdir; - bool _round_uvs; - double _round_unit; - double _round_fuzz; - RemapUV _remap_uv, _remap_char_uv; - PNMFileType *_color_type; - PNMFileType *_alpha_type; - PNMFileType *_shadow_color_type; - PNMFileType *_shadow_alpha_type; - EggRenderMode::AlphaMode _cutout_mode; - double _cutout_ratio; - -private: - typedef pvector Placements; - void compute_statistics(std::ostream &out, int indent_level, - const Placements &placements) const; - - typedef pmap EggFiles; - EggFiles _egg_files; - - typedef pvector CommandLineEggs; - CommandLineEggs _command_line_eggs; - - typedef pset CommandLineTextures; - CommandLineTextures _command_line_textures; - - typedef pmap Groups; - Groups _groups; - - typedef pmap Textures; - Textures _textures; - typedef pvector TextureConflicts; - TextureConflicts _texture_conflicts; - - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - - virtual void finalize(BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // These values are only filled in while reading from the bam file; don't - // use them otherwise. - int _num_egg_files; - int _num_groups; - int _num_textures; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - register_type(_type_handle, "Palettizer", - TypedWritable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; - - friend class TxaLine; -}; - -// This is a global Palettizer pointer that may be filled in when the -// Palettizer is created, for convenience in referencing it from multiple -// places. (Generally, a standalone program will only create one Palettizer -// object in a session.) -extern Palettizer *pal; - -#endif diff --git a/pandatool/src/palettizer/sourceTextureImage.cxx b/pandatool/src/palettizer/sourceTextureImage.cxx deleted file mode 100644 index c3aac422..00000000 --- a/pandatool/src/palettizer/sourceTextureImage.cxx +++ /dev/null @@ -1,209 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file sourceTextureImage.cxx - * @author drose - * @date 2000-11-29 - */ - -#include "sourceTextureImage.h" -#include "textureImage.h" -#include "filenameUnifier.h" - -#include "pnmImageHeader.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" - -TypeHandle SourceTextureImage::_type_handle; - -/** - * The default constructor is only for the convenience of the Bam reader. - */ -SourceTextureImage:: -SourceTextureImage() { - _texture = nullptr; - - _egg_count = 0; - _read_header = false; - _successfully_read_header = false; -} - -/** - * - */ -SourceTextureImage:: -SourceTextureImage(TextureImage *texture, const Filename &filename, - const Filename &alpha_filename, int alpha_file_channel) : - _texture(texture) -{ - _filename = filename; - _alpha_filename = alpha_filename; - _alpha_file_channel = alpha_file_channel; - _egg_count = 0; - _read_header = false; - _successfully_read_header = false; -} - -/** - * Returns the particular texture that this image is one of the sources for. - */ -TextureImage *SourceTextureImage:: -get_texture() const { - return _texture; -} - -/** - * Increments by one the number of egg files that are known to reference this - * SourceTextureImage. - */ -void SourceTextureImage:: -increment_egg_count() { - _egg_count++; -} - -/** - * Returns the number of egg files that share this SourceTextureImage. - */ -int SourceTextureImage:: -get_egg_count() const { - return _egg_count; -} - -/** - * Determines the size of the SourceTextureImage, if it is not already known. - * Returns true if the size was successfully determined (or if was already - * known), or false if the size could not be determined (for instance, because - * the image file is missing). After this call returns true, get_x_size() - * etc. may be safely called to return the size. - */ -bool SourceTextureImage:: -get_size() { - if (!_size_known) { - return read_header(); - } - return true; -} - -/** - * Reads the actual image header to determine the image properties, like its - * size. Returns true if the image header is successfully read (or if has - * previously been successfully read this session), false otherwise. After - * this call returns true, get_x_size() etc. may be safely called to return - * the newly determined size. - */ -bool SourceTextureImage:: -read_header() { - if (_read_header) { - return _successfully_read_header; - } - - _read_header = true; - _successfully_read_header = false; - - PNMImageHeader header; - if (!header.read_header(_filename)) { - nout << "Warning: cannot read texture " - << FilenameUnifier::make_user_filename(_filename) << "\n"; - return false; - } - - set_header(header); - - return true; -} - -/** - * Sets the header information associated with this image, as if it were - * loaded from the disk. - */ -void SourceTextureImage:: -set_header(const PNMImageHeader &header) { - _x_size = header.get_x_size(); - _y_size = header.get_y_size(); - int num_channels = header.get_num_channels(); - - if (!_alpha_filename.empty() && _alpha_filename.exists()) { - // Assume if we have an alpha filename, that we have an additional alpha - // channel. - if (num_channels == 1 || num_channels == 3) { - num_channels++; - } - } - _properties.set_num_channels(num_channels); - - _size_known = true; - _successfully_read_header = true; -} - - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void SourceTextureImage:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void SourceTextureImage:: -write_datagram(BamWriter *writer, Datagram &datagram) { - ImageFile::write_datagram(writer, datagram); - writer->write_pointer(datagram, _texture); - - // We don't store _egg_count; instead, we count these up again each session. - - // We don't store _read_header or _successfully_read_header in the Bam file; - // these are transitory and we need to reread the image header for each - // session (in case the image files change between sessions). -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int SourceTextureImage:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = ImageFile::complete_pointers(p_list, manager); - - DCAST_INTO_R(_texture, p_list[pi++], pi); - return pi; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *SourceTextureImage:: -make_from_bam(const FactoryParams ¶ms) { - SourceTextureImage *me = new SourceTextureImage; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void SourceTextureImage:: -fillin(DatagramIterator &scan, BamReader *manager) { - ImageFile::fillin(scan, manager); - manager->read_pointer(scan); // _texture -} diff --git a/pandatool/src/palettizer/sourceTextureImage.h b/pandatool/src/palettizer/sourceTextureImage.h deleted file mode 100644 index 6c803a73..00000000 --- a/pandatool/src/palettizer/sourceTextureImage.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file sourceTextureImage.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef SOURCETEXTUREIMAGE_H -#define SOURCETEXTUREIMAGE_H - -#include "pandatoolbase.h" - -#include "imageFile.h" - -class TextureImage; -class PNMImageHeader; - -/** - * This is a texture image reference as it appears in an egg file: the source - * image of the texture. - */ -class SourceTextureImage : public ImageFile { -private: - SourceTextureImage(); - -public: - SourceTextureImage(TextureImage *texture, const Filename &filename, - const Filename &alpha_filename, int alpha_file_channel); - - TextureImage *get_texture() const; - - void increment_egg_count(); - int get_egg_count() const; - - bool get_size(); - bool read_header(); - void set_header(const PNMImageHeader &header); - -private: - TextureImage *_texture; - int _egg_count; - bool _read_header; - bool _successfully_read_header; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - ImageFile::init_type(); - register_type(_type_handle, "SourceTextureImage", - ImageFile::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -INLINE std::ostream & -operator << (std::ostream &out, const SourceTextureImage &source) { - source.output_filename(out); - return out; -} - -#endif diff --git a/pandatool/src/palettizer/textureImage.cxx b/pandatool/src/palettizer/textureImage.cxx deleted file mode 100644 index 8eddd6bb..00000000 --- a/pandatool/src/palettizer/textureImage.cxx +++ /dev/null @@ -1,1396 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureImage.cxx - * @author drose - * @date 2000-11-29 - */ - -#include "textureImage.h" -#include "sourceTextureImage.h" -#include "destTextureImage.h" -#include "eggFile.h" -#include "paletteGroup.h" -#include "paletteImage.h" -#include "texturePlacement.h" -#include "filenameUnifier.h" -#include "string_utils.h" -#include "indent.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "pnmFileType.h" -#include "indirectCompareNames.h" -#include "pvector.h" - -#include - -using std::string; - -TypeHandle TextureImage::_type_handle; - -/** - * - */ -TextureImage:: -TextureImage() { - _preferred_source = nullptr; - _read_source_image = false; - _allow_release_source_image = true; - _is_surprise = true; - _ever_read_image = false; - _forced_grayscale = false; - _alpha_bits = 0; - _mid_pixel_ratio = 0.0; - _is_cutout = false; - _alpha_mode = EggRenderMode::AM_unspecified; - _txa_wrap_u = EggTexture::WM_unspecified; - _txa_wrap_v = EggTexture::WM_unspecified; - _texture_named = false; - _got_txa_file = false; -} - -/** - * Records that a particular egg file references this texture. This is - * essential to know when deciding how to assign the TextureImage to the - * various PaletteGroups. - */ -void TextureImage:: -note_egg_file(EggFile *egg_file) { - nassertv(!egg_file->get_complete_groups().empty()); - _egg_files.insert(egg_file); -} - -/** - * Assigns the texture to all of the PaletteGroups the various egg files that - * use it need. Attempts to choose the minimum set of PaletteGroups that - * satisfies all of the egg files. - */ -void TextureImage:: -assign_groups() { - if (_egg_files.empty()) { - // If we're not referenced by any egg files any more, assign us to no - // groups. - PaletteGroups empty; - assign_to_groups(empty); - return; - } - - PaletteGroups definitely_in; - - // First, we need to eliminate from consideration all the egg files that are - // already taken care of by the user's explicit group assignments for this - // texture. - WorkingEggs needed_eggs; - - if (_explicitly_assigned_groups.empty()) { - // If we have no explicit group assignments, we must consider all the egg - // files. - std::copy(_egg_files.begin(), _egg_files.end(), std::back_inserter(needed_eggs)); - - } else { - // Otherwise, we only need to consider the egg files that don't have any - // groups in common with our explicit assignments. - - EggFiles::const_iterator ei; - for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { - PaletteGroups intersect; - intersect.make_intersection(_explicitly_assigned_groups, (*ei)->get_complete_groups()); - if (!intersect.empty()) { - // This egg file is satisfied by one of the texture's explicit - // assignments. - - // We must use at least one of the explicitly-assigned groups that - // satisfied the egg file. We don't need to use all of them, however, - // and we choose the first one arbitrarily. - definitely_in.insert(*intersect.begin()); - - } else { - // This egg file was not satisfied by any of the texture's explicit - // assignments. Therefore, we'll need to choose some additional group - // to assign the texture to, to make the egg file happy. Defer this a - // bit. - needed_eggs.push_back(*ei); - } - } - } - - while (!needed_eggs.empty()) { - // We need to know the complete set of groups that we need to consider - // adding the texture to. This is the union of all the egg files' - // requested groups. - PaletteGroups total; - WorkingEggs::const_iterator ei; - for (ei = needed_eggs.begin(); ei != needed_eggs.end(); ++ei) { - total.make_union(total, (*ei)->get_complete_groups()); - } - - // We don't count the "null" group for texture assignment. - total.remove_null(); - if (total.empty()) { - break; - } - - // Now, find the group that will satisfy the most egg files. If two - // groups satisfy the same number of egg files, choose (a) the most - // specific one, i.e. with the lowest dirname_level, or the lowest - // dependency_level if the dirname_levels are equal, and (b) the one that - // has the fewest egg files sharing it. - PaletteGroups::iterator gi = total.begin(); - PaletteGroup *best = (*gi); - int best_egg_count = compute_egg_count(best, needed_eggs); - ++gi; - while (gi != total.end()) { - PaletteGroup *group = (*gi); - - // Do we prefer this group to our current 'best'? - bool prefer_group = false; - int group_egg_count = compute_egg_count(group, needed_eggs); - if (group_egg_count != best_egg_count) { - prefer_group = (group_egg_count > best_egg_count); - - } else { - prefer_group = group->is_preferred_over(*best); - } - - if (prefer_group) { - best = group; - best_egg_count = group_egg_count; - } - ++gi; - } - - // Okay, now we've picked the best group. Eliminate all the eggs from - // consideration that are satisfied by this group, and repeat. - definitely_in.insert(best); - - WorkingEggs next_needed_eggs; - for (ei = needed_eggs.begin(); ei != needed_eggs.end(); ++ei) { - if ((*ei)->get_complete_groups().count(best) == 0) { - // This one wasn't eliminated. - next_needed_eggs.push_back(*ei); - } - } - needed_eggs.swap(next_needed_eggs); - } - - // Finally, now that we've computed the set of groups we need to assign the - // texture to, we need to reconcile this with the set of groups we've - // assigned the texture to previously. - assign_to_groups(definitely_in); -} - -/** - * Once assign_groups() has been called, this returns the actual set of groups - * the TextureImage has been assigned to. - */ -const PaletteGroups &TextureImage:: -get_groups() const { - return _actual_assigned_groups; -} - -/** - * Gets the TexturePlacement object which represents the assignment of this - * texture to the indicated group. If the texture has not been assigned to - * the indicated group, returns NULL. - */ -TexturePlacement *TextureImage:: -get_placement(PaletteGroup *group) const { - Placement::const_iterator pi; - pi = _placement.find(group); - if (pi == _placement.end()) { - return nullptr; - } - - return (*pi).second; -} - -/** - * Removes the texture from any PaletteImages it is assigned to, but does not - * remove it from the groups. It will be re-placed within each group when - * PaletteGroup::place_all() is called. - */ -void TextureImage:: -force_replace() { - Placement::iterator pi; - for (pi = _placement.begin(); pi != _placement.end(); ++pi) { - (*pi).second->force_replace(); - } -} - -/** - * Marks all the egg files that reference this texture stale. Should be - * called only when the texture properties change in some catastrophic way - * that will require every egg file referencing it to be regenerated, even if - * it is not palettized. - */ -void TextureImage:: -mark_eggs_stale() { - Placement::iterator pi; - for (pi = _placement.begin(); pi != _placement.end(); ++pi) { - (*pi).second->mark_eggs_stale(); - } -} - -/** - * Indicates that this particular texture has been named by the user for - * processing this session, normally by listing an egg file on the command - * line that references it. - */ -void TextureImage:: -mark_texture_named() { - _texture_named = true; -} - -/** - * Returns true if this particular texture has been named by the user for - * procession this session, for instance by listing an egg file on the command - * line that references it. - */ -bool TextureImage:: -is_texture_named() const { - return _texture_named; -} - -/** - * Updates any internal state prior to reading the .txa file. - */ -void TextureImage:: -pre_txa_file() { - // Save our current properties, so we can note if they change. - _pre_txa_properties = _properties; - - // Get our properties from the actual image for this texture. It's possible - // the .txa file will update them further. - SourceTextureImage *source = get_preferred_source(); - if (source != nullptr) { - _properties = source->get_properties(); - } - - _pre_txa_alpha_mode = _alpha_mode; - _alpha_mode = EggRenderMode::AM_unspecified; - - _request.pre_txa_file(); - _is_surprise = true; -} - -/** - * Once the .txa file has been read and the TextureImage matched against it, - * considers applying the requested size change. Updates the TextureImage's - * size with the size the texture ought to be, if this can be determined. - */ -void TextureImage:: -post_txa_file() { - _got_txa_file = true; - - // First, get the actual size of the texture. - SourceTextureImage *source = get_preferred_source(); - if (source != nullptr) { - if (source->get_size()) { - _size_known = true; - _x_size = source->get_x_size(); - _y_size = source->get_y_size(); - _properties.set_num_channels(source->get_num_channels()); - } - } - - // Now update this with a particularly requested size. - if (_request._got_size) { - _size_known = true; - _x_size = _request._x_size; - _y_size = _request._y_size; - } - - if (_txa_wrap_u != _request._wrap_u || - _txa_wrap_v != _request._wrap_v) { - _txa_wrap_u = _request._wrap_u; - _txa_wrap_v = _request._wrap_v; - - // If the explicit wrap mode changes, we may need to regenerate the egg - // files, andor refill the palettes. - mark_eggs_stale(); - - Placement::iterator pi; - for (pi = _placement.begin(); pi != _placement.end(); ++pi) { - TexturePlacement *placement = (*pi).second; - placement->mark_unfilled(); - } - } - - if (_properties.has_num_channels() && !_request._keep_format) { - int num_channels = _properties.get_num_channels(); - // Examine the image to determine if we can downgrade the number of - // channels, for instance from color to grayscale. - if (num_channels == 3 || num_channels == 4) { - consider_grayscale(); - } - - // Also consider the alpha properties, and whether we should downgrade - // from alpha to non-alpha. - if (num_channels == 2 || num_channels == 4) { - consider_alpha(); - } - } - - // However, if we got an explicit request for channels, honor that. - if (_request._got_num_channels) { - _properties.set_num_channels(_request._num_channels); - } - - _properties._generic_format = _request._generic_format; - _properties._keep_format = _request._keep_format; - - if (_request._format != EggTexture::F_unspecified) { - _properties._format = _request._format; - _properties._force_format = _request._force_format; - } - - if (_request._minfilter != EggTexture::FT_unspecified) { - _properties._minfilter = _request._minfilter; - } - if (_request._magfilter != EggTexture::FT_unspecified) { - _properties._magfilter = _request._magfilter; - } - - _properties._anisotropic_degree = _request._anisotropic_degree; - - _properties._srgb = _request._srgb; - - if (_properties._color_type == nullptr) { - _properties._color_type = _request._properties._color_type; - _properties._alpha_type = _request._properties._alpha_type; - } - - // Finally, make sure our properties are fully defined. - _properties.fully_define(); - - // Now, if our properties have changed in all that from our previous - // session, we need to re-place ourself in all palette groups. - if (_properties != _pre_txa_properties) { - force_replace(); - - // The above will mark the egg files stale when the texture is palettized - // (since the UV's will certainly need to be recomputed), but sometimes we - // need to mark the egg files stale even when the texture is not - // palettized (if a critical property has changed). The following - // accomplishes this: - if (!_properties.egg_properties_match(_pre_txa_properties)) { - mark_eggs_stale(); - } - } - - // The alpha mode isn't stored in the properties, because it doesn't affect - // which textures may be associated into a common palette. - if (_request._alpha_mode != EggRenderMode::AM_unspecified) { - _alpha_mode = _request._alpha_mode; - } - - // On the other hand, if we don't have an alpha channel, we shouldn't have - // an alpha mode. - if (_properties.has_num_channels()) { - int num_channels = _properties.get_num_channels(); - if (num_channels == 1 || num_channels == 3) { - _alpha_mode = EggRenderMode::AM_unspecified; - } - } - - // If we've changed the alpha mode, we should also mark the eggs stale. - if (_pre_txa_alpha_mode != _alpha_mode) { - mark_eggs_stale(); - } -} - -/** - * Returns true if this TextureImage has been looked up in the .txa file this - * session, false otherwise. - */ -bool TextureImage:: -got_txa_file() const { - return _got_txa_file; -} - -/** - * Calls determine_size() on each TexturePlacement for the texture, to ensure - * that each TexturePlacement is still requesting the best possible size for - * the texture. - */ -void TextureImage:: -determine_placement_size() { - Placement::iterator pi; - for (pi = _placement.begin(); pi != _placement.end(); ++pi) { - TexturePlacement *placement = (*pi).second; - placement->determine_size(); - } -} - -/** - * Returns true if the user specifically requested to omit this texture via - * the "omit" keyword in the .txa file, or false otherwise. - */ -bool TextureImage:: -get_omit() const { - return _request._omit; -} - -/** - * Returns the appropriate coverage threshold for this texture. This is - * either the Palettizer::_coverage_threshold parameter, given globally via - * -r, or a particular value for this texture as supplied by the "coverage" - * keyword in the .txa file. - */ -double TextureImage:: -get_coverage_threshold() const { - return _request._coverage_threshold; -} - -/** - * Returns the appropriate margin for this texture. This is either the - * Palettizer::_margin parameter, or a particular value for this texture as - * supplied by the "margin" keyword in the .txa file. - */ -int TextureImage:: -get_margin() const { - return _request._margin; -} - -/** - * Returns true if this particular texture is a 'surprise', i.e. it wasn't - * matched by a line in the .txa file that didn't include the keyword 'cont'. - */ -bool TextureImage:: -is_surprise() const { - if (_placement.empty()) { - // A texture that is not actually placed anywhere is not considered a - // surprise. - return false; - } - - return _is_surprise; -} - -/** - * Returns true if this particular texture has been placed somewhere, - * anywhere, or false if it is not used. - */ -bool TextureImage:: -is_used() const { - return !_placement.empty(); -} - -/** - * Returns the alpha mode that should be used to render objects with this - * texture, as specified by the user or as determined from examining the - * texture's alpha channel. - */ -EggRenderMode::AlphaMode TextureImage:: -get_alpha_mode() const { - return _alpha_mode; -} - -/** - * Returns the wrap mode specified in the u direction in the txa file, or - * WM_unspecified. - */ -EggTexture::WrapMode TextureImage:: -get_txa_wrap_u() const { - return _txa_wrap_u; -} - -/** - * Returns the wrap mode specified in the v direction in the txa file, or - * WM_unspecified. - */ -EggTexture::WrapMode TextureImage:: -get_txa_wrap_v() const { - return _txa_wrap_v; -} - - -/** - * Returns the SourceTextureImage corresponding to the given filename(s). If - * the given filename has never been used as a SourceTexture for this - * particular texture, creates a new SourceTextureImage and returns that. - */ -SourceTextureImage *TextureImage:: -get_source(const Filename &filename, const Filename &alpha_filename, - int alpha_file_channel) { - string key = get_source_key(filename, alpha_filename, alpha_file_channel); - - Sources::iterator si; - si = _sources.find(key); - if (si != _sources.end()) { - return (*si).second; - } - - SourceTextureImage *source = - new SourceTextureImage(this, filename, alpha_filename, alpha_file_channel); - _sources.insert(Sources::value_type(key, source)); - - // Clear out the preferred source image to force us to rederive this next - // time someone asks. - _preferred_source = nullptr; - _read_source_image = false; - - return source; -} - -/** - * Determines the preferred source image for examining size and reading - * pixels, etc. This is the largest and most recent of all the available - * source images. - */ -SourceTextureImage *TextureImage:: -get_preferred_source() { - if (_preferred_source != nullptr) { - return _preferred_source; - } - - // Now examine all of the various source images available to us and pick the - // most suitable. We base this on the following criteria: - - // (1) A suitable source image must be referenced by at least one egg file, - // unless no source images are referenced by any egg file. - - // (2) A larger source image is preferable to a smaller one. - - // (3) Given two source images of the same size, the more recent one is - // preferable. - - // Are any source images referenced by an egg file? - - bool any_referenced = false; - Sources::iterator si; - for (si = _sources.begin(); si != _sources.end() && !any_referenced; ++si) { - SourceTextureImage *source = (*si).second; - if (source->get_egg_count() > 0) { - any_referenced = true; - } - } - - SourceTextureImage *best = nullptr; - int best_size = 0; - - for (si = _sources.begin(); si != _sources.end(); ++si) { - SourceTextureImage *source = (*si).second; - - if (source->get_egg_count() > 0 || !any_referenced) { - // Rule (1) passes. - - if (source->exists() && source->get_size()) { - int source_size = source->get_x_size() * source->get_y_size(); - if (best == nullptr) { - best = source; - best_size = source_size; - - } else if (source_size > best_size) { - // Rule (2) passes. - best = source; - best_size = source_size; - - } else if (source_size == best_size && - source->get_filename().compare_timestamps(best->get_filename()) > 0) { - // Rule (3) passes. - best = source; - best_size = source_size; - } - } - } - } - - if (best == nullptr && !_sources.empty()) { - // If we didn't pick any that pass, it must be that all of them are - // unreadable. In this case, it really doesn't matter which one we pick, - // but we should at least pick one that has an egg reference, if any of - // them do. - if (any_referenced) { - for (si = _sources.begin(); - si != _sources.end() && best == nullptr; - ++si) { - SourceTextureImage *source = (*si).second; - if (source->get_egg_count() > 0) { - best = source; - } - } - } else { - best = (*_sources.begin()).second; - } - } - - _preferred_source = best; - return _preferred_source; -} - -/** - * Calls clear_basic_properties() on each source texture image used by this - * texture, to reset the properties in preparation for re-applying them from - * the set of all known egg files. - */ -void TextureImage:: -clear_source_basic_properties() { - Sources::iterator si; - for (si = _sources.begin(); si != _sources.end(); ++si) { - SourceTextureImage *source = (*si).second; - source->clear_basic_properties(); - } -} - -/** - * Copies the texture to whichever destination directories are appropriate for - * the groups in which it has been unplaced. Also removes the old filenames - * for previous sessions where it was unplaced, but is no longer. - * - * If redo_all is true, this recopies the texture whether it needed to or not. - */ -void TextureImage:: -copy_unplaced(bool redo_all) { - // First, we need to build up the set of DestTextureImages that represents - // the files we need to generate. - Dests generate; - - // Go through all the TexturePlacements and note the ones for which we're - // unplaced. We check get_omit_reason() and not is_placed(), because we - // want to consider solitary images to be unplaced in this case. - Placement::iterator pi; - for (pi = _placement.begin(); pi != _placement.end(); ++pi) { - TexturePlacement *placement = (*pi).second; - if (placement->get_omit_reason() != OR_none && - placement->get_omit_reason() != OR_unknown) { - DestTextureImage *dest = new DestTextureImage(placement); - Filename filename = dest->get_filename(); - FilenameUnifier::make_canonical(filename); - - std::pair insert_result = generate.insert - (Dests::value_type(filename, dest)); - if (!insert_result.second) { - // At least two DestTextureImages map to the same filename, no sweat. - delete dest; - dest = (*insert_result.first).second; - } - - placement->set_dest(dest); - - } else { - placement->set_dest(nullptr); - } - } - - if (redo_all) { - // If we're redoing everything, we remove everything first and then recopy - // it again. - Dests empty; - remove_old_dests(empty, _dests); - copy_new_dests(generate, empty); - - } else { - // Otherwise, we only remove and recopy the things that changed between - // this time and last time. - remove_old_dests(generate, _dests); - copy_new_dests(generate, _dests); - } - - // Clean up the old set. - Dests::iterator di; - for (di = _dests.begin(); di != _dests.end(); ++di) { - delete (*di).second; - } - - _dests.swap(generate); -} - -/** - * Reads in the original image, if it has not already been read, and returns - * it. - */ -const PNMImage &TextureImage:: -read_source_image() { - if (!_read_source_image) { - SourceTextureImage *source = get_preferred_source(); - if (source != nullptr) { - source->read(_source_image); - } - _read_source_image = true; - _allow_release_source_image = true; - _ever_read_image = true; - } - - return _source_image; -} - -/** - * Frees the memory that was allocated by a previous call to - * read_source_image(). The next time read_source_image() is called, it will - * have to read the disk again. - */ -void TextureImage:: -release_source_image() { - if (_read_source_image && _allow_release_source_image) { - _source_image.clear(); - _read_source_image = false; - } -} - -/** - * Accepts the indicated source image as if it had been read from disk. This - * image is copied into the structure, and will be returned by future calls to - * read_source_image(). - */ -void TextureImage:: -set_source_image(const PNMImage &image) { - _source_image = image; - _allow_release_source_image = false; - _read_source_image = true; - _ever_read_image = true; -} - -/** - * Causes the header part of the image to be reread, usually to confirm that - * its image properties (size, number of channels, etc.) haven't changed. - */ -void TextureImage:: -read_header() { - if (!_read_source_image) { - SourceTextureImage *source = get_preferred_source(); - if (source != nullptr) { - source->read_header(); - } - } -} - -/** - * Returns true if the source image is newer than the indicated file, false - * otherwise. If the image has already been read, this always returns false. - */ -bool TextureImage:: -is_newer_than(const Filename &reference_filename) { - if (!_read_source_image) { - SourceTextureImage *source = get_preferred_source(); - if (source != nullptr) { - const Filename &source_filename = source->get_filename(); - return source_filename.compare_timestamps(reference_filename) >= 0; - } - } - - return false; -} - -/** - * Writes the list of source pathnames that might contribute to this texture - * to the indicated output stream, one per line. - */ -void TextureImage:: -write_source_pathnames(std::ostream &out, int indent_level) const { - Sources::const_iterator si; - for (si = _sources.begin(); si != _sources.end(); ++si) { - SourceTextureImage *source = (*si).second; - - if (source->get_egg_count() > 0) { - indent(out, indent_level); - source->output_filename(out); - if (!source->is_size_known()) { - out << " (unknown size)"; - - } else { - out << " " << source->get_x_size() << " " - << source->get_y_size(); - - if (source->get_properties().has_num_channels()) { - out << " " << source->get_properties().get_num_channels(); - } - } - out << "\n"; - } - } - - if (_is_cutout) { - indent(out, indent_level) - << "Cutout image (ratio " << (PN_stdfloat)_mid_pixel_ratio << ")\n"; - } - - // Now write out the group assignments. - if (!_egg_files.empty()) { - // Sort the egg files into order by name for output. - pvector egg_vector; - egg_vector.reserve(_egg_files.size()); - EggFiles::const_iterator ei; - for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { - egg_vector.push_back(*ei); - } - sort(egg_vector.begin(), egg_vector.end(), - IndirectCompareNames()); - - indent(out, indent_level) - << "Used by:\n"; - pvector::const_iterator evi; - for (evi = egg_vector.begin(); evi != egg_vector.end(); ++evi) { - EggFile *egg = (*evi); - indent(out, indent_level + 2) - << egg->get_name() << " ("; - if (egg->get_explicit_groups().empty()) { - out << *egg->get_default_group(); - } else { - out << egg->get_explicit_groups(); - } - out << ")\n"; - } - } - if (!_explicitly_assigned_groups.empty()) { - indent(out, indent_level) - << "Explicitly assigned to " << _explicitly_assigned_groups << " in .txa\n"; - } - - if (_placement.empty()) { - indent(out, indent_level) - << "Not used.\n"; - } else { - indent(out, indent_level) - << "Assigned to " << _actual_assigned_groups << "\n"; - } -} - -/** - * Writes the information about the texture's size and placement. - */ -void TextureImage:: -write_scale_info(std::ostream &out, int indent_level) { - SourceTextureImage *source = get_preferred_source(); - indent(out, indent_level) << get_name(); - - // Write the list of groups we're placed in. - if (_placement.empty()) { - out << " (not used)"; - } else { - Placement::const_iterator pi; - pi = _placement.begin(); - out << " (" << (*pi).second->get_group()->get_name(); - ++pi; - while (pi != _placement.end()) { - out << " " << (*pi).second->get_group()->get_name(); - ++pi; - } - out << ")"; - } - - out << " orig "; - - if (source == nullptr || - !source->is_size_known()) { - out << "unknown"; - } else { - out << source->get_x_size() << " " << source->get_y_size() - << " " << source->get_num_channels(); - } - - if (!_placement.empty() && is_size_known()) { - out << " new " << get_x_size() << " " << get_y_size() - << " " << get_num_channels(); - - if (source != nullptr && - source->is_size_known()) { - double scale = - 100.0 * (((double)get_x_size() / (double)source->get_x_size()) + - ((double)get_y_size() / (double)source->get_y_size())) / 2.0; - out << " scale " << scale << "%"; - } - } - out << "\n"; - - // Also cross-reference the placed and unplaced information. - Placement::iterator pi; - for (pi = _placement.begin(); pi != _placement.end(); ++pi) { - TexturePlacement *placement = (*pi).second; - if (placement->get_omit_reason() == OR_none) { - PaletteImage *image = placement->get_image(); - nassertv(image != nullptr); - indent(out, indent_level + 2) - << "placed on " - << FilenameUnifier::make_user_filename(image->get_filename()) - << "\n"; - - } else if (placement->get_omit_reason() == OR_unknown) { - indent(out, indent_level + 2) - << "not placed because unknown.\n"; - - } else { - DestTextureImage *image = placement->get_dest(); - nassertv(image != nullptr); - indent(out, indent_level + 2) - << "copied to " - << FilenameUnifier::make_user_filename(image->get_filename()); - if (image->is_size_known() && is_size_known() && - (image->get_x_size() != get_x_size() || - image->get_y_size() != get_y_size())) { - out << " at size " << image->get_x_size() << " " - << image->get_y_size(); - if (source != nullptr && - source->is_size_known()) { - double scale = - 100.0 * (((double)image->get_x_size() / (double)source->get_x_size()) + - ((double)image->get_y_size() / (double)source->get_y_size())) / 2.0; - out << " scale " << scale << "%"; - } - } - out << "\n"; - } - } -} - -/** - * Counts the number of egg files in the indicated set that will be satisfied - * if a texture is assigned to the indicated group. - */ -int TextureImage:: -compute_egg_count(PaletteGroup *group, - const TextureImage::WorkingEggs &egg_files) { - int count = 0; - - WorkingEggs::const_iterator ei; - for (ei = egg_files.begin(); ei != egg_files.end(); ++ei) { - if ((*ei)->get_complete_groups().count(group) != 0) { - count++; - } - } - - return count; -} - -/** - * Assigns the texture to the indicated set of groups. If the texture was - * previously assigned to any of these groups, keeps the same TexturePlacement - * object for the assignment; at the same time, deletes any TexturePlacement - * objects that represent groups we are no longer assigned to. - */ -void TextureImage:: -assign_to_groups(const PaletteGroups &groups) { - PaletteGroups::const_iterator gi; - Placement::const_iterator pi; - - Placement new_placement; - - gi = groups.begin(); - pi = _placement.begin(); - - while (gi != groups.end() && pi != _placement.end()) { - PaletteGroup *a = (*gi); - PaletteGroup *b = (*pi).first; - - if (a < b) { - // Here's a group we're now assigned to that we weren't assigned to - // previously. - TexturePlacement *place = a->prepare(this); - new_placement.insert - (new_placement.end(), Placement::value_type(a, place)); - ++gi; - - } else if (b < a) { - // Here's a group we're no longer assigned to. - TexturePlacement *place = (*pi).second; - delete place; - ++pi; - - } else { // b == a - // Here's a group we're still assigned to. - TexturePlacement *place = (*pi).second; - new_placement.insert - (new_placement.end(), Placement::value_type(a, place)); - ++gi; - ++pi; - } - } - - while (gi != groups.end()) { - // Here's a group we're now assigned to that we weren't assigned to - // previously. - PaletteGroup *a = (*gi); - TexturePlacement *place = a->prepare(this); - new_placement.insert - (new_placement.end(), Placement::value_type(a, place)); - ++gi; - } - - while (pi != _placement.end()) { - // Here's a group we're no longer assigned to. - TexturePlacement *place = (*pi).second; - delete place; - ++pi; - } - - _placement.swap(new_placement); - _actual_assigned_groups = groups; -} - -/** - * Examines the actual contents of the image to determine if it should maybe - * be considered a grayscale image (even though it has separate rgb - * components). - */ -void TextureImage:: -consider_grayscale() { - // Since this isn't likely to change for a particular texture after its - // creation, we save a bit of time by not performing this check unless this - // is the first time we've ever seen this texture. This will save us from - // having to load the texture images each time we look at them. On the - // other hand, if we've already loaded up the image, then go ahead. - if (!_read_source_image && _ever_read_image) { - if (_forced_grayscale) { - _properties.force_grayscale(); - } - return; - } - - const PNMImage &source = read_source_image(); - if (!source.is_valid()) { - return; - } - - for (int y = 0; y < source.get_y_size(); y++) { - for (int x = 0; x < source.get_x_size(); x++) { - const xel &v = source.get_xel_val(x, y); - if (PPM_GETR(v) != PPM_GETG(v) || PPM_GETR(v) != PPM_GETB(v)) { - // Here's a colored pixel. We can't go grayscale. - _forced_grayscale = false; - return; - } - } - } - - // All pixels in the image were grayscale! - _properties.force_grayscale(); - _forced_grayscale = true; -} - -/** - * Examines the actual contents of the image to determine what alpha - * properties it has. - */ -void TextureImage:: -consider_alpha() { - // As above, we don't bother doing this if we've already done this in a - // previous session. - - // _alpha_bits == -1 indicates we have read an older textures.boo file that - // didn't define these bits. - if (_read_source_image || !_ever_read_image || _alpha_bits == -1) { - _alpha_bits = 0; - int num_mid_pixels = 0; - - const PNMImage &source = read_source_image(); - if (source.is_valid() && source.has_alpha()) { - xelval maxval = source.get_maxval(); - for (int y = 0; y < source.get_y_size(); y++) { - for (int x = 0; x < source.get_x_size(); x++) { - xelval alpha_val = source.get_alpha_val(x, y); - if (alpha_val == 0) { - _alpha_bits |= AB_zero; - } else if (alpha_val == maxval) { - _alpha_bits |= AB_one; - } else { - _alpha_bits |= AB_mid; - ++num_mid_pixels; - } - } - } - } - - int num_pixels = source.get_x_size() * source.get_y_size(); - _mid_pixel_ratio = 0.0; - if (num_pixels != 0) { - _mid_pixel_ratio = (double)num_mid_pixels / (double)num_pixels; - } - } - - _is_cutout = false; - - if (_alpha_bits != 0) { - if (_alpha_bits == AB_one) { - // All alpha pixels are white; drop the alpha channel. - _properties.force_nonalpha(); - - } else if (_alpha_bits == AB_zero) { - // All alpha pixels are invisible; this is probably a mistake. Drop the - // alpha channel and complain. - _properties.force_nonalpha(); - if (_read_source_image) { - nout << *this << " has an all-zero alpha channel; dropping alpha.\n"; - } - - } else if (_alpha_mode == EggRenderMode::AM_unspecified) { - // Consider fiddling with the alpha mode, if the user hasn't specified a - // particular alpha mode in the txa file. - if ((_alpha_bits & AB_mid) == 0) { - // No middle range bits: a binary alpha image. - _alpha_mode = EggRenderMode::AM_binary; - - } else if ((_alpha_bits & AB_one) != 0 && _mid_pixel_ratio < pal->_cutout_ratio) { - // At least some opaque bits, and relatively few middle range bits: a - // cutout image. - _alpha_mode = pal->_cutout_mode; - _is_cutout = true; - - } else { - // No opaque bits; just use regular alpha blending. - _alpha_mode = EggRenderMode::AM_blend; - } - } - } -} - -/** - * Removes all of the filenames named in b that are not also named in a. - */ -void TextureImage:: -remove_old_dests(const TextureImage::Dests &a, const TextureImage::Dests &b) { - Dests::const_iterator ai = a.begin(); - Dests::const_iterator bi = b.begin(); - - while (ai != a.end() && bi != b.end()) { - const string &astr = (*ai).first; - const string &bstr = (*bi).first; - - if (astr < bstr) { - // Here's a filename in a, not in b. - ++ai; - - } else if (bstr < astr) { - // Here's a filename in b, not in a. - (*bi).second->unlink(); - ++bi; - - } else { // bstr == astr - // Here's a filename in both a and b. - ++ai; - ++bi; - } - } - - while (bi != b.end()) { - // Here's a filename in b, not in a. - (*bi).second->unlink(); - ++bi; - } - - while (ai != a.end()) { - ++ai; - } -} - -/** - * Copies a resized texture into each filename named in a that is not also - * listed in b, or whose corresponding listing in b is out of date. - */ -void TextureImage:: -copy_new_dests(const TextureImage::Dests &a, const TextureImage::Dests &b) { - Dests::const_iterator ai = a.begin(); - Dests::const_iterator bi = b.begin(); - - while (ai != a.end() && bi != b.end()) { - const string &astr = (*ai).first; - const string &bstr = (*bi).first; - - if (astr < bstr) { - // Here's a filename in a, not in b. - (*ai).second->copy(this); - ++ai; - - } else if (bstr < astr) { - // Here's a filename in b, not in a. - ++bi; - - } else { // bstr == astr - // Here's a filename in both a and b. - (*ai).second->copy_if_stale((*bi).second, this); - ++ai; - ++bi; - } - } - - while (ai != a.end()) { - // Here's a filename in a, not in b. - (*ai).second->copy(this); - ++ai; - } -} - -/** - * Returns the key that a SourceTextureImage should be stored in, given its - * one or two filenames. - */ -string TextureImage:: -get_source_key(const Filename &filename, const Filename &alpha_filename, - int alpha_file_channel) { - Filename f = FilenameUnifier::make_bam_filename(filename); - Filename a = FilenameUnifier::make_bam_filename(alpha_filename); - - return f.get_fullpath() + ":" + a.get_fullpath() + ":" + - format_string(alpha_file_channel); -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void TextureImage:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void TextureImage:: -write_datagram(BamWriter *writer, Datagram &datagram) { - ImageFile::write_datagram(writer, datagram); - datagram.add_string(get_name()); - - // We don't write out _request; this is re-read from the .txa file each - // time. - - // We don't write out _pre_txa_properties; this is transitional. - - // We don't write out _preferred_source; this is redetermined each session. - - datagram.add_bool(_is_surprise); - datagram.add_bool(_ever_read_image); - datagram.add_bool(_forced_grayscale); - datagram.add_uint8(_alpha_bits); - datagram.add_int16((int)_alpha_mode); - datagram.add_float64(_mid_pixel_ratio); - datagram.add_bool(_is_cutout); - datagram.add_uint8((int)_txa_wrap_u); - datagram.add_uint8((int)_txa_wrap_v); - - // We don't write out _explicitly_assigned_groups; this is re-read from the - // .txa file each time. - - _actual_assigned_groups.write_datagram(writer, datagram); - - // We don't write out _egg_files; this is redetermined each session. - - datagram.add_uint32(_placement.size()); - Placement::const_iterator pi; - for (pi = _placement.begin(); pi != _placement.end(); ++pi) { - writer->write_pointer(datagram, (*pi).first); - writer->write_pointer(datagram, (*pi).second); - } - - datagram.add_uint32(_sources.size()); - Sources::const_iterator si; - for (si = _sources.begin(); si != _sources.end(); ++si) { - writer->write_pointer(datagram, (*si).second); - } - - datagram.add_uint32(_dests.size()); - Dests::const_iterator di; - for (di = _dests.begin(); di != _dests.end(); ++di) { - writer->write_pointer(datagram, (*di).second); - } -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int TextureImage:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = ImageFile::complete_pointers(p_list, manager); - - pi += _actual_assigned_groups.complete_pointers(p_list + pi, manager); - - int i; - for (i = 0; i < _num_placement; i++) { - PaletteGroup *group; - TexturePlacement *placement; - DCAST_INTO_R(group, p_list[pi++], pi); - DCAST_INTO_R(placement, p_list[pi++], pi); - _placement.insert(Placement::value_type(group, placement)); - } - - for (i = 0; i < _num_sources; i++) { - SourceTextureImage *source; - DCAST_INTO_R(source, p_list[pi++], pi); - string key = get_source_key(source->get_filename(), - source->get_alpha_filename(), - source->get_alpha_file_channel()); - - bool inserted = _sources.insert(Sources::value_type(key, source)).second; - if (!inserted) { - nout << "Warning: texture key " << key - << " is nonunique; texture lost.\n"; - } - } - - for (i = 0; i < _num_dests; i++) { - DestTextureImage *dest; - DCAST_INTO_R(dest, p_list[pi++], pi); - bool inserted = _dests.insert(Dests::value_type(dest->get_filename(), dest)).second; - if (!inserted) { - nout << "Warning: dest filename " << dest->get_filename() - << " is nonunique; texture lost.\n"; - } - } - - return pi; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *TextureImage:: -make_from_bam(const FactoryParams ¶ms) { - TextureImage *me = new TextureImage; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void TextureImage:: -fillin(DatagramIterator &scan, BamReader *manager) { - ImageFile::fillin(scan, manager); - set_name(scan.get_string()); - - _is_surprise = scan.get_bool(); - _ever_read_image = scan.get_bool(); - _forced_grayscale = scan.get_bool(); - _alpha_bits = scan.get_uint8(); - _alpha_mode = (EggRenderMode::AlphaMode)scan.get_int16(); - if (pal->_read_pi_version >= 16) { - _mid_pixel_ratio = scan.get_float64(); - _is_cutout = scan.get_bool(); - } else { - // Force a re-read of the image if we are upgrading to pi version 16. - _ever_read_image = false; - _mid_pixel_ratio = 0.0; - _is_cutout = false; - } - if (pal->_read_pi_version >= 17) { - _txa_wrap_u = (EggTexture::WrapMode)scan.get_uint8(); - _txa_wrap_v = (EggTexture::WrapMode)scan.get_uint8(); - } - - _actual_assigned_groups.fillin(scan, manager); - - _num_placement = scan.get_uint32(); - manager->read_pointers(scan, _num_placement * 2); - - _num_sources = scan.get_uint32(); - manager->read_pointers(scan, _num_sources); - _num_dests = scan.get_uint32(); - manager->read_pointers(scan, _num_dests); -} diff --git a/pandatool/src/palettizer/textureImage.h b/pandatool/src/palettizer/textureImage.h deleted file mode 100644 index 3fd041d6..00000000 --- a/pandatool/src/palettizer/textureImage.h +++ /dev/null @@ -1,195 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureImage.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef TEXTUREIMAGE_H -#define TEXTUREIMAGE_H - -#include "pandatoolbase.h" - -#include "imageFile.h" -#include "paletteGroups.h" -#include "textureRequest.h" - -#include "namable.h" -#include "filename.h" -#include "pnmImage.h" -#include "eggRenderMode.h" - -#include "pmap.h" -#include "pset.h" - -class SourceTextureImage; -class DestTextureImage; -class TexturePlacement; -class EggFile; - -/** - * This represents a single source texture that is referenced by one or more - * egg files. It may be assigned to multiple PaletteGroups, and thus placed - * on multiple PaletteImages (up to one per PaletteGroup). - * - * Since a TextureImage may be referenced by multiple egg files that are each - * assigned to a different set of groups, it tries to maximize sharing between - * egg files and minimize the number of different PaletteGroups it is assigned - * to. - */ -class TextureImage : public ImageFile, public Namable { -public: - TextureImage(); - - void note_egg_file(EggFile *egg_file); - void assign_groups(); - - const PaletteGroups &get_groups() const; - TexturePlacement *get_placement(PaletteGroup *group) const; - void force_replace(); - void mark_eggs_stale(); - - void mark_texture_named(); - bool is_texture_named() const; - - void pre_txa_file(); - void post_txa_file(); - bool got_txa_file() const; - void determine_placement_size(); - - bool get_omit() const; - double get_coverage_threshold() const; - int get_margin() const; - bool is_surprise() const; - bool is_used() const; - EggRenderMode::AlphaMode get_alpha_mode() const; - - EggTexture::WrapMode get_txa_wrap_u() const; - EggTexture::WrapMode get_txa_wrap_v() const; - - SourceTextureImage *get_source(const Filename &filename, - const Filename &alpha_filename, - int alpha_file_channel); - - SourceTextureImage *get_preferred_source(); - void clear_source_basic_properties(); - - void copy_unplaced(bool redo_all); - - const PNMImage &read_source_image(); - void release_source_image(); - void set_source_image(const PNMImage &image); - void read_header(); - bool is_newer_than(const Filename &reference_filename); - - void write_source_pathnames(std::ostream &out, int indent_level = 0) const; - void write_scale_info(std::ostream &out, int indent_level = 0); - -private: - typedef pset EggFiles; - typedef pvector WorkingEggs; - typedef pmap Sources; - typedef pmap Dests; - - static int compute_egg_count(PaletteGroup *group, - const WorkingEggs &egg_files); - - void assign_to_groups(const PaletteGroups &groups); - void consider_grayscale(); - void consider_alpha(); - - void remove_old_dests(const Dests &a, const Dests &b); - void copy_new_dests(const Dests &a, const Dests &b); - - std::string get_source_key(const Filename &filename, - const Filename &alpha_filename, - int alpha_file_channel); - -private: - TextureRequest _request; - TextureProperties _pre_txa_properties; - EggRenderMode::AlphaMode _pre_txa_alpha_mode; - SourceTextureImage *_preferred_source; - bool _is_surprise; - - bool _ever_read_image; - bool _forced_grayscale; - - enum AlphaBits { - // consider_alpha() sets alpha_bits to the union of all of these pixel - // values that might be found in the alpha channel. - AB_one = 0x01, - AB_mid = 0x02, - AB_zero = 0x04, - AB_all = 0x07 // == AB_zero | AB_mid | AB_one - }; - int _alpha_bits; - double _mid_pixel_ratio; - bool _is_cutout; - EggRenderMode::AlphaMode _alpha_mode; - EggTexture::WrapMode _txa_wrap_u, _txa_wrap_v; - - PaletteGroups _explicitly_assigned_groups; - PaletteGroups _actual_assigned_groups; - - EggFiles _egg_files; - - typedef pmap Placement; - Placement _placement; - - Sources _sources; - Dests _dests; - - bool _read_source_image; - bool _allow_release_source_image; - PNMImage _source_image; - bool _texture_named; - bool _got_txa_file; - - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // These values are only filled in while reading from the bam file; don't - // use them otherwise. - int _num_placement; - int _num_sources; - int _num_dests; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - ImageFile::init_type(); - Namable::init_type(); - register_type(_type_handle, "TextureImage", - ImageFile::get_class_type(), - Namable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; - - friend class TxaLine; -}; - -#endif diff --git a/pandatool/src/palettizer/textureMemoryCounter.cxx b/pandatool/src/palettizer/textureMemoryCounter.cxx deleted file mode 100644 index 91281670..00000000 --- a/pandatool/src/palettizer/textureMemoryCounter.cxx +++ /dev/null @@ -1,250 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureMemoryCounter.cxx - * @author drose - * @date 2000-12-19 - */ - -#include "textureMemoryCounter.h" -#include "paletteImage.h" -#include "textureImage.h" -#include "destTextureImage.h" -#include "omitReason.h" -#include "texturePlacement.h" - -#include "indent.h" -#include - -/** - * - */ -TextureMemoryCounter:: -TextureMemoryCounter() { - reset(); -} - -/** - * Resets the count to zero. - */ -void TextureMemoryCounter:: -reset() { - _num_textures = 0; - _num_unplaced = 0; - _num_placed = 0; - _num_palettes = 0; - - _bytes = 0; - _unused_bytes = 0; - _duplicate_bytes = 0; - _coverage_bytes = 0; - _textures.clear(); - _palettes.clear(); -} - -/** - * Adds the indicated TexturePlacement to the counter. - */ -void TextureMemoryCounter:: -add_placement(TexturePlacement *placement) { - TextureImage *texture = placement->get_texture(); - nassertv(texture != nullptr); - - if (placement->get_omit_reason() == OR_none) { - PaletteImage *image = placement->get_image(); - nassertv(image != nullptr); - add_palette(image); - - int bytes = count_bytes(image, placement->get_placed_x_size(), - placement->get_placed_y_size()); - add_texture(texture, bytes); - _num_placed++; - - } else { - DestTextureImage *dest = placement->get_dest(); - if (dest != nullptr) { - int bytes = count_bytes(dest); - add_texture(texture, bytes); - - _bytes += bytes; - _num_unplaced++; - } - } -} - -/** - * Reports the measured texture memory usage. - */ -void TextureMemoryCounter:: -report(std::ostream &out, int indent_level) { - indent(out, indent_level) - << _num_placed << " of " << _num_textures << " textures appear on " - << _num_palettes << " palette images with " << _num_unplaced - << " unplaced.\n"; - - indent(out, indent_level) - << (_bytes + 512) / 1024 << "k estimated texture memory required.\n"; - - if (_bytes != 0) { - if (_unused_bytes != 0) { - indent(out, indent_level + 2); - format_memory_fraction(out, _unused_bytes, _bytes) - << " is wasted because of unused palette space.\n"; - } - - if (_coverage_bytes > 0) { - indent(out, indent_level + 2); - format_memory_fraction(out, _coverage_bytes, _bytes) - << " is wasted for repeating textures and margins.\n"; - - } else if (_coverage_bytes < 0) { - indent(out, indent_level + 2); - format_memory_fraction(out, -_coverage_bytes, _bytes) - << " is *saved* for palettizing partial textures.\n"; - } - - if (_duplicate_bytes != 0) { - indent(out, indent_level + 2); - format_memory_fraction(out, _duplicate_bytes, _bytes) - << " is wasted because of a texture appearing in multiple groups.\n"; - } - } -} - -/** - * Writes to the indicated ostream an indication of the fraction of the total - * memory usage that is represented by fraction_bytes. - */ -std::ostream &TextureMemoryCounter:: -format_memory_fraction(std::ostream &out, int fraction_bytes, int palette_bytes) { - out << floor(1000.0 * (double)fraction_bytes / (double)palette_bytes + 0.5) / 10.0 - << "% (" << (fraction_bytes + 512) / 1024 << "k)"; - return out; -} - -/** - * Adds the indicated PaletteImage to the count. If this is called twice for - * a given PaletteImage it does nothing. - */ -void TextureMemoryCounter:: -add_palette(PaletteImage *image) { - bool inserted = _palettes.insert(image).second; - if (!inserted) { - // We've already added this palette image. - return; - } - - int bytes = count_bytes(image); - double unused = 1.0 - image->count_utilization(); - double coverage = image->count_coverage(); - - _bytes += bytes; - _unused_bytes += (int)(unused * bytes); - _coverage_bytes += (int)(coverage * bytes); - - _num_palettes++; -} - -/** - * Adds the given TextureImage to the counter. If the texture image has - * already been added, this counts the smaller of the two as duplicate bytes. - */ -void TextureMemoryCounter:: -add_texture(TextureImage *texture, int bytes) { - std::pair result; - result = _textures.insert(Textures::value_type(texture, bytes)); - if (result.second) { - // If it was inserted, no problem--no duplicates. - _num_textures++; - return; - } - - // If it was not inserted, we have a duplicate. - Textures::iterator ti = result.first; - - _duplicate_bytes += std::min(bytes, (*ti).second); - (*ti).second = std::max(bytes, (*ti).second); -} - -/** - * Attempts to estimate the number of bytes the given image file will use in - * texture memory. - */ -int TextureMemoryCounter:: -count_bytes(ImageFile *image) { - return count_bytes(image, image->get_x_size(), image->get_y_size()); -} - -/** - * Attempts to estimate the number of bytes the given image file will use in - * texture memory. - */ -int TextureMemoryCounter:: -count_bytes(ImageFile *image, int x_size, int y_size) { - int pixels = x_size * y_size; - - // Try to guess the number of bytes per pixel this texture will consume in - // texture memory, based on its requested format. This is only a loose - // guess, because this depends of course on the pecularities of the - // particular rendering engine. - int bpp = 0; - switch (image->get_properties()._format) { - case EggTexture::F_rgba12: - bpp = 6; - break; - - case EggTexture::F_rgba: - case EggTexture::F_rgbm: - case EggTexture::F_rgba8: - bpp = 4; - break; - - case EggTexture::F_rgb: - case EggTexture::F_rgb12: - bpp = 3; - break; - - case EggTexture::F_rgba4: - case EggTexture::F_rgba5: - case EggTexture::F_rgb8: - case EggTexture::F_rgb5: - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - bpp = 2; - break; - - case EggTexture::F_rgb332: - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - case EggTexture::F_luminance: - bpp = 1; - break; - - default: - bpp = image->get_num_channels(); - } - - int bytes = pixels * bpp; - - // If we're mipmapping, it's worth 13 more bytes. - switch (image->get_properties()._minfilter) { - case EggTexture::FT_nearest_mipmap_nearest: - case EggTexture::FT_linear_mipmap_nearest: - case EggTexture::FT_nearest_mipmap_linear: - case EggTexture::FT_linear_mipmap_linear: - bytes = (bytes * 4) / 3; - break; - - default: - break; - } - - return bytes; -} diff --git a/pandatool/src/palettizer/textureMemoryCounter.h b/pandatool/src/palettizer/textureMemoryCounter.h deleted file mode 100644 index 49de4747..00000000 --- a/pandatool/src/palettizer/textureMemoryCounter.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureMemoryCounter.h - * @author drose - * @date 2000-12-19 - */ - -#ifndef TEXTUREMEMORYCOUNTER_H -#define TEXTUREMEMORYCOUNTER_H - -#include "pandatoolbase.h" - -class ImageFile; -class PaletteImage; -class TextureImage; -class DestTextureImage; -class TexturePlacement; - -#include "pmap.h" -#include "pset.h" - -/** - * This class is used to gather statistics on texture memory usage, etc. It - * adds up the total texture memory required by a number of image files, and - * reports it at the end. - */ -class TextureMemoryCounter { -public: - TextureMemoryCounter(); - - void reset(); - void add_placement(TexturePlacement *placement); - - void report(std::ostream &out, int indent_level); - -private: - static std::ostream &format_memory_fraction(std::ostream &out, int fraction_bytes, - int palette_bytes); - void add_palette(PaletteImage *image); - void add_texture(TextureImage *texture, int bytes); - int count_bytes(ImageFile *image); - int count_bytes(ImageFile *image, int x_size, int y_size); - - int _num_textures; - int _num_placed; - int _num_unplaced; - int _num_palettes; - - int _bytes; - int _unused_bytes; - int _duplicate_bytes; - int _coverage_bytes; - - typedef pmap Textures; - Textures _textures; - - typedef pset Palettes; - Palettes _palettes; -}; - -#endif diff --git a/pandatool/src/palettizer/texturePlacement.cxx b/pandatool/src/palettizer/texturePlacement.cxx deleted file mode 100644 index b92583b6..00000000 --- a/pandatool/src/palettizer/texturePlacement.cxx +++ /dev/null @@ -1,1148 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file texturePlacement.cxx - * @author drose - * @date 2000-11-30 - */ - -#include "texturePlacement.h" -#include "textureReference.h" -#include "textureImage.h" -#include "paletteGroup.h" -#include "paletteImage.h" -#include "palettizer.h" -#include "eggFile.h" -#include "destTextureImage.h" - -#include "indent.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "pnmImage.h" - -using std::max; -using std::min; - -TypeHandle TexturePlacement::_type_handle; - -/** - * The default constructor is only for the convenience of the Bam reader. - */ -TexturePlacement:: -TexturePlacement() { - _texture = nullptr; - _group = nullptr; - _image = nullptr; - _dest = nullptr; - _has_uvs = false; - _size_known = false; - _is_filled = true; - _omit_reason = OR_none; -} - -/** - * - */ -TexturePlacement:: -TexturePlacement(TextureImage *texture, PaletteGroup *group) : - _texture(texture), - _group(group) -{ - _omit_reason = OR_working; - - if (!texture->is_size_known()) { - // If we were never able to figure out what size the texture actually is, - // then we can't place the texture on a palette. - _omit_reason = OR_unknown; - } - - _image = nullptr; - _dest = nullptr; - _has_uvs = false; - _size_known = false; - _is_filled = false; -} - -/** - * - */ -TexturePlacement:: -~TexturePlacement() { - // Make sure we tell all our egg references they're not using us any more. - References::iterator ri; - References copy_references = _references; - for (ri = copy_references.begin(); ri != copy_references.end(); ++ri) { - TextureReference *reference = (*ri); - nassertv(reference->get_placement() == this); - reference->clear_placement(); - } - - // And also our group, etc. - _group->unplace(this); -} - -/** - * Returns the name of the texture that this placement represents. - */ -const std::string &TexturePlacement:: -get_name() const { - return _texture->get_name(); -} - -/** - * Returns the texture that this placement represents. - */ -TextureImage *TexturePlacement:: -get_texture() const { - return _texture; -} - -/** - * Returns the grouping properties of the image. - */ -const TextureProperties &TexturePlacement:: -get_properties() const { - return _texture->get_properties(); -} - -/** - * Returns the group that this placement represents. - */ -PaletteGroup *TexturePlacement:: -get_group() const { - return _group; -} - -/** - * Records the fact that a particular egg file is using this particular - * TexturePlacement. - */ -void TexturePlacement:: -add_egg(TextureReference *reference) { - reference->mark_egg_stale(); - - // Turns out that turning these off is a bad idea, because it may make us - // forget the size information halfway through processing. - /* - _has_uvs = false; - _size_known = false; - */ - _references.insert(reference); -} - -/** - * Notes that a particular egg file is no longer using this particular - * TexturePlacement. - */ -void TexturePlacement:: -remove_egg(TextureReference *reference) { - reference->mark_egg_stale(); - /* - _has_uvs = false; - _size_known = false; - */ - _references.erase(reference); -} - -/** - * Marks all the egg files that reference this placement stale. Presumably - * this is called after moving the texture around in the palette or something. - */ -void TexturePlacement:: -mark_eggs_stale() { - References::iterator ri; - for (ri = _references.begin(); ri != _references.end(); ++ri) { - TextureReference *reference = (*ri); - - reference->mark_egg_stale(); - } -} - -/** - * Sets the DestTextureImage that corresponds to this texture as it was copied - * to the install directory. - */ -void TexturePlacement:: -set_dest(DestTextureImage *dest) { - _dest = dest; -} - -/** - * Returns the DestTextureImage that corresponds to this texture as it was - * copied to the install directory. - */ -DestTextureImage *TexturePlacement:: -get_dest() const { - return _dest; -} - -/** - * Attempts to determine the appropriate size of the texture for the given - * placement. This is based on the UV range of the egg files that reference - * the texture. Returns true on success, or false if the texture size cannot - * be determined (e.g. the texture file is unknown). - * - * After this returns true, get_x_size() and get_y_size() may safely be - * called. - */ -bool TexturePlacement:: -determine_size() { - if (!_texture->is_size_known()) { - // Too bad. - force_replace(); - _omit_reason = OR_unknown; - return false; - } - - // This seems to be unnecessary (because of omit_solitary() and - // not_solitary()), and in fact bitches the logic in omit_solitary() and - // not_solitary() so that we call mark_egg_stale() unnecessarily. - /* - if (_omit_reason == OR_solitary) { - // If the texture was previously 'omitted' for being solitary, we give it - // a second chance now. - _omit_reason = OR_none; - } - */ - - // Determine the actual minmax of the UV's in use, as well as whether we - // should wrap or clamp. - _has_uvs = false; - _position._wrap_u = EggTexture::WM_clamp; - _position._wrap_v = EggTexture::WM_clamp; - - LTexCoordd max_uv, min_uv; - - References::iterator ri; - for (ri = _references.begin(); ri != _references.end(); ++ri) { - TextureReference *reference = (*ri); - if (reference->has_uvs()) { - const LTexCoordd &n = reference->get_min_uv(); - const LTexCoordd &x = reference->get_max_uv(); - - if (_has_uvs) { - min_uv.set(min(min_uv[0], n[0]), min(min_uv[1], n[1])); - max_uv.set(max(max_uv[0], x[0]), max(max_uv[1], x[1])); - } else { - min_uv = n; - max_uv = x; - _has_uvs = true; - } - } - - // If any reference repeats the texture, the texture repeats in the - // palette. - if (reference->get_wrap_u() == EggTexture::WM_repeat) { - _position._wrap_u = EggTexture::WM_repeat; - } - if (reference->get_wrap_v() == EggTexture::WM_repeat) { - _position._wrap_v = EggTexture::WM_repeat; - } - } - - // However, if the user specified an explicit wrap mode, allow it to apply. - if (_texture->get_txa_wrap_u() != EggTexture::WM_unspecified) { - _position._wrap_u = _texture->get_txa_wrap_u(); - } - if (_texture->get_txa_wrap_v() != EggTexture::WM_unspecified) { - _position._wrap_v = _texture->get_txa_wrap_v(); - } - - if (!_has_uvs) { - force_replace(); - _omit_reason = OR_unused; - return false; - } - - LTexCoordd rounded_min_uv = min_uv; - LTexCoordd rounded_max_uv = max_uv; - - // cout << get_name() << endl; - - // If so requested, round the minmax out to the next _round_unit. This cuts - // down on unnecessary resizing of textures within the palettes as the egg - // references change in trivial amounts. cout << "rounded_min_uv: " << - // rounded_min_uv << endl; cout << "rounded_max_uv: " << rounded_max_uv << - // endl; - - if (pal->_round_uvs) { - rounded_max_uv[0] = - ceil((rounded_max_uv[0] - pal->_round_fuzz) / pal->_round_unit) * - pal->_round_unit; - rounded_max_uv[1] = - ceil((rounded_max_uv[1] - pal->_round_fuzz) / pal->_round_unit) * - pal->_round_unit; - - rounded_min_uv[0] = - floor((rounded_min_uv[0] + pal->_round_fuzz) / pal->_round_unit) * - pal->_round_unit; - rounded_min_uv[1] = - floor((rounded_min_uv[1] + pal->_round_fuzz) / pal->_round_unit) * - pal->_round_unit; - - // cout << "after rounded_min_uv: " << rounded_min_uv << endl; cout << - // "after rounded_max_uv: " << rounded_max_uv << endl; - } - - // Now determine the size in pixels we require based on the UV's that - // actually reference this texture. - compute_size_from_uvs(rounded_min_uv, rounded_max_uv); - - // Now, can it be placed? - if (_texture->get_omit()) { - // Not if the user says it can't. - force_replace(); - _omit_reason = OR_omitted; - - } else if (get_uv_area() > _texture->get_coverage_threshold()) { - // If the texture repeats too many times, we can't place it. - force_replace(); - _omit_reason = OR_coverage; - - } else if ((_position._x_size > pal->_pal_x_size || - _position._y_size > pal->_pal_y_size) || - (_position._x_size == pal->_pal_x_size && - _position._y_size == pal->_pal_y_size)) { - // If the texture exceeds the size of an empty palette image in either - // dimension, or if it exactly equals the size of an empty palette image - // in both dimensions, we can't place it because it's too big. - force_replace(); - _omit_reason = OR_size; - - } else if (pal->_omit_everything && (_group->is_none_texture_swap())) { - // If we're omitting everything, omit everything. - force_replace(); - _omit_reason = OR_default_omit; - - } else if (_omit_reason == OR_omitted || - _omit_reason == OR_default_omit || - _omit_reason == OR_size || - _omit_reason == OR_coverage || - _omit_reason == OR_unknown) { - // On the other hand, if the texture was previously omitted explicitly, or - // because of its size or coverage, now it seems to fit. - force_replace(); - mark_eggs_stale(); - _omit_reason = OR_working; - - } else if (is_placed()) { - // It *can* be placed. If it was already placed previously, can we leave - // it where it is? - - if (_position._x_size != _placed._x_size || - _position._y_size != _placed._y_size || - _position._min_uv[0] < _placed._min_uv[0] || - _position._min_uv[1] < _placed._min_uv[1] || - _position._max_uv[0] > _placed._max_uv[0] || - _position._max_uv[1] > _placed._max_uv[1]) { - // If the texture was previously placed but is now the wrong size, or if - // the area we need to cover is different, we need to re-place it. - - // However, we make a special exception: if it would have fit without - // rounding up the UV's, then screw rounding it up and just leave it - // alone. - if ((_position._x_size > _placed._x_size || - _position._y_size > _placed._y_size) && - pal->_round_uvs) { - compute_size_from_uvs(min_uv, max_uv); - if (_position._x_size <= _placed._x_size && - _position._y_size <= _placed._y_size && - _position._min_uv[0] >= _placed._min_uv[0] && - _position._min_uv[1] >= _placed._min_uv[1] && - _position._max_uv[0] <= _placed._max_uv[0] && - _position._max_uv[1] <= _placed._max_uv[1]) { - // No problem! It fits here, so leave well enough alone. - } else { - // That's not good enough either, so go back to rounding. - compute_size_from_uvs(rounded_min_uv, rounded_max_uv); - force_replace(); - } - } else { - force_replace(); - } - } - - if (_position._wrap_u != _placed._wrap_u || - _position._wrap_v != _placed._wrap_v) { - // The wrap mode properties have changed slightly. We may or may not - // need to re-place it, but we will need to update it. - _is_filled = false; - _placed._wrap_u = _position._wrap_u; - _placed._wrap_v = _position._wrap_v; - } - } - - return true; -} - -/** - * Returns true if the texture's size is known, false otherwise. Usually this - * can only be false after determine_size() has been called there is something - * wrong with the texture (in which case the placement will automatically omit - * itself from the palette anyway). - */ -bool TexturePlacement:: -is_size_known() const { - return _size_known; -} - -/** - * Returns the reason the texture has been omitted from a palette image, or - * OR_none if it has not. - */ -OmitReason TexturePlacement:: -get_omit_reason() const { - return _omit_reason; -} - -/** - * Returns the size in the X dimension, in pixels, of the texture image as it - * must appear in the palette. This accounts for any growing or shrinking of - * the texture due to the UV coordinate range. - */ -int TexturePlacement:: -get_x_size() const { - nassertr(_size_known, 0); - return _position._x_size; -} - -/** - * Returns the size in the Y dimension, in pixels, of the texture image as it - * must appear in the palette. This accounts for any growing or shrinking of - * the texture due to the UV coordinate range. - */ -int TexturePlacement:: -get_y_size() const { - nassertr(_size_known, 0); - return _position._y_size; -} - -/** - * Returns the total area of the rectangle occupied by the UV minmax box, in - * UV coordinates. 1.0 is the entire texture; values greater than 1 imply the - * texture repeats. - */ -double TexturePlacement:: -get_uv_area() const { - if (!_has_uvs) { - return 0.0; - } - - LTexCoordd range = _position._max_uv - _position._min_uv; - return range[0] * range[1]; -} - -/** - * Returns true if the texture has been placed on a palette image, false - * otherwise. This will generally be true if get_omit_reason() returns - * OR_none or OR_solitary and false otherwise. - */ -bool TexturePlacement:: -is_placed() const { - return _image != nullptr; -} - -/** - * Returns the particular PaletteImage on which the texture has been placed. - */ -PaletteImage *TexturePlacement:: -get_image() const { - nassertr(is_placed(), nullptr); - return _image; -} - -/** - * Returns the particular PalettePage on which the texture has been placed. - */ -PalettePage *TexturePlacement:: -get_page() const { - nassertr(is_placed(), nullptr); - return _image->get_page(); -} - -/** - * Returns the X pixel at which the texture has been placed within its - * PaletteImage. It is an error to call this unless is_placed() returns true. - */ -int TexturePlacement:: -get_placed_x() const { - nassertr(is_placed(), 0); - return _placed._x; -} - -/** - * Returns the Y pixel at which the texture has been placed within its - * PaletteImage. It is an error to call this unless is_placed() returns true. - */ -int TexturePlacement:: -get_placed_y() const { - nassertr(is_placed(), 0); - return _placed._y; -} - -/** - * Returns the size in the X dimension, in pixels, of the texture image as it - * has been placed within the palette. - */ -int TexturePlacement:: -get_placed_x_size() const { - nassertr(is_placed(), 0); - return _placed._x_size; -} - -/** - * Returns the size in the Y dimension, in pixels, of the texture image as it - * has been placed within the palette. - */ -int TexturePlacement:: -get_placed_y_size() const { - nassertr(is_placed(), 0); - return _placed._y_size; -} - -/** - * Returns the total area of the rectangle occupied by the UV minmax box, as - * it has been placed. See also get_uv_area(). - */ -double TexturePlacement:: -get_placed_uv_area() const { - nassertr(is_placed(), 0); - LTexCoordd range = _placed._max_uv - _placed._min_uv; - return range[0] * range[1]; -} - -/** - * Assigns the texture to a particular position within the indicated - * PaletteImage. It is an error to call this if the texture has already been - * placed elsewhere. - */ -void TexturePlacement:: -place_at(PaletteImage *image, int x, int y) { - nassertv(!is_placed()); - nassertv(_size_known); - - _image = image; - _is_filled = false; - _position._x = x; - _position._y = y; - _placed = _position; - _omit_reason = OR_none; -} - -/** - * Removes the texture from its particular PaletteImage, but does not remove - * it from the PaletteGroup. It will be re-placed when the - * PaletteGroup::place_all() is called. - */ -void TexturePlacement:: -force_replace() { - if (_image != nullptr) { - _image->unplace(this); - _image = nullptr; - } - if (_omit_reason == OR_none) { - mark_eggs_stale(); - } - _omit_reason = OR_working; -} - -/** - * Sets the omit reason (returned by get_omit()) to OR_solitary, indicating - * that the palettized version of the texture should not be used because it is - * the only texture on a PaletteImage. However, the texture is still - * considered placed, and is_placed() will return true. - */ -void TexturePlacement:: -omit_solitary() { - nassertv(is_placed()); - if (_omit_reason != OR_solitary) { - mark_eggs_stale(); - _omit_reason = OR_solitary; - } -} - -/** - * Indicates that the texture, formerly indicated as solitary, is now no - * longer. - */ -void TexturePlacement:: -not_solitary() { - nassertv(is_placed()); - if (_omit_reason != OR_none) { - mark_eggs_stale(); - _omit_reason = OR_none; - } -} - -/** - * Returns true if the particular position this texture has been assigned to - * overlaps the rectangle whose top left corner is at x, y and whose size is - * given by x_size, y_size, or false otherwise. - */ -bool TexturePlacement:: -intersects(int x, int y, int x_size, int y_size) { - nassertr(is_placed(), false); - - int hright = x + x_size; - int hbot = y + y_size; - - int mright = _placed._x + _placed._x_size; - int mbot = _placed._y + _placed._y_size; - - return !(x >= mright || hright <= _placed._x || - y >= mbot || hbot <= _placed._y); -} - -/** - * Stores in the indicated matrix the appropriate texture matrix transform for - * the new placement of the texture. - */ -void TexturePlacement:: -compute_tex_matrix(LMatrix3d &transform) { - nassertv(is_placed()); - - LMatrix3d source_uvs = LMatrix3d::ident_mat(); - - LTexCoordd range = _placed._max_uv - _placed._min_uv; - if (range[0] != 0.0 && range[1] != 0.0) { - source_uvs = - LMatrix3d::translate_mat(-_placed._min_uv) * - LMatrix3d::scale_mat(1.0 / range[0], 1.0 / range[1]); - } - - int top = _placed._y + _placed._margin; - int left = _placed._x + _placed._margin; - int x_size = _placed._x_size - _placed._margin * 2; - int y_size = _placed._y_size - _placed._margin * 2; - - int bottom = top + y_size; - int pal_x_size = _image->get_x_size(); - int pal_y_size = _image->get_y_size(); - - LVecBase2d t((double)left / (double)pal_x_size, - (double)(pal_y_size - bottom) / (double)pal_y_size); - LVecBase2d s((double)x_size / (double)pal_x_size, - (double)y_size / (double)pal_y_size); - - LMatrix3d dest_uvs - (s[0], 0.0, 0.0, - 0.0, s[1], 0.0, - t[0], t[1], 1.0); - - transform = source_uvs * dest_uvs; -} - -/** - * Writes the placement position information on a line by itself. - */ -void TexturePlacement:: -write_placed(std::ostream &out, int indent_level) { - indent(out, indent_level) - << get_texture()->get_name(); - - if (is_placed()) { - out << " at " - << get_placed_x() << " " << get_placed_y() << " to " - << get_placed_x() + get_placed_x_size() << " " - << get_placed_y() + get_placed_y_size() << " (coverage " - << get_placed_uv_area() << ")"; - - if (_placed._wrap_u != EggTexture::WM_unspecified || - _placed._wrap_v != EggTexture::WM_unspecified) { - if (_placed._wrap_u != _placed._wrap_v) { - out << " (" << _placed._wrap_u << ", " << _placed._wrap_v << ")"; - } else { - out << " " << _placed._wrap_u; - } - } - out << "\n"; - } else { - out << " not yet placed.\n"; - } -}; - -/** - * Returns true if the texture has been filled (i.e. fill_image() has been - * called) since it was placed. - */ -bool TexturePlacement:: -is_filled() const { - return _is_filled; -} - -/** - * Marks the texture as unfilled, so that it will need to be copied into the - * palette image again. - */ -void TexturePlacement:: -mark_unfilled() { - _is_filled = false; -} - -/** - * Fills in the rectangle of the palette image represented by the texture - * placement with the image pixels. - */ -void TexturePlacement:: -fill_image(PNMImage &image) { - nassertv(is_placed()); - - _is_filled = true; - - // We determine the pixels to place the source image at by transforming the - // unit texture box: the upper-left and lower-right corners. These corners, - // in the final texture coordinate space, represent where on the palette - // image the original texture should be located. - - LMatrix3d transform; - compute_tex_matrix(transform); - LTexCoordd ul = LTexCoordd(0.0, 1.0) * transform; - LTexCoordd lr = LTexCoordd(1.0, 0.0) * transform; - - // Now we convert those texture coordinates back to pixel units. - int pal_x_size = _image->get_x_size(); - int pal_y_size = _image->get_y_size(); - - int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5); - int left = (int)floor(ul[0] * pal_x_size + 0.5); - int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5); - int right = (int)floor(lr[0] * pal_x_size + 0.5); - - // And now we can determine the size to scale the image to based on that. - // This may not be the same as texture->size() because of margins. - int x_size = right - left; - int y_size = bottom - top; - nassertv(x_size >= 0 && y_size >= 0); - - // Now we get a PNMImage that represents the source texture at that size. - const PNMImage &source_full = _texture->read_source_image(); - if (!source_full.is_valid()) { - flag_error_image(image); - return; - } - - PNMImage source(x_size, y_size, source_full.get_num_channels(), - source_full.get_maxval()); - source.quick_filter_from(source_full); - - bool alpha = image.has_alpha(); - bool source_alpha = source.has_alpha(); - - // Now copy the pixels. We do this by walking through the rectangular - // region on the palette image that we have reserved for this texture; for - // each pixel in this region, we determine its appropriate color based on - // its relation to the actual texture image location (determined above), and - // on whether the texture wraps or clamps. - for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) { - int sy = y - top; - - switch (_placed._wrap_v) { - case EggTexture::WM_clamp: - // Clamp at [0, y_size). - sy = max(min(sy, y_size - 1), 0); - break; - - case EggTexture::WM_mirror: - sy = (sy < 0) ? (y_size * 2) - 1 - ((-sy - 1) % (y_size * 2)) : sy % (y_size * 2); - sy = (sy < y_size) ? sy : 2 * y_size - sy - 1; - break; - - case EggTexture::WM_mirror_once: - sy = (sy < y_size) ? sy : 2 * y_size - sy - 1; - // Fall through - - case EggTexture::WM_border_color: - if (sy < 0 || sy >= y_size) { - continue; - } - break; - - default: - // Wrap: sign-independent modulo. - sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size; - break; - } - - for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) { - int sx = x - left; - - switch (_placed._wrap_u) { - case EggTexture::WM_clamp: - // Clamp at [0, x_size). - sx = max(min(sx, x_size - 1), 0); - break; - - case EggTexture::WM_mirror: - sx = (sx < 0) ? (x_size * 2) - 1 - ((-sx - 1) % (x_size * 2)) : sx % (x_size * 2); - sx = (sx < x_size) ? sx : 2 * x_size - sx - 1; - break; - - case EggTexture::WM_mirror_once: - sx = (sx >= 0) ? sx : ~sx; - // Fall through - - case EggTexture::WM_border_color: - if (sx < 0 || sx >= x_size) { - continue; - } - break; - - default: - // Wrap: sign-independent modulo. - sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size; - break; - } - - image.set_xel(x, y, source.get_xel(sx, sy)); - if (alpha) { - if (source_alpha) { - image.set_alpha(x, y, source.get_alpha(sx, sy)); - } else { - image.set_alpha(x, y, 1.0); - } - } - } - } - - _texture->release_source_image(); -} - - -/** - * Fills in the rectangle of the swapped palette image represented by the - * texture placement with the image pixels. - */ -void TexturePlacement:: -fill_swapped_image(PNMImage &image, int index) { - nassertv(is_placed()); - - _is_filled = true; - - // We determine the pixels to place the source image at by transforming the - // unit texture box: the upper-left and lower-right corners. These corners, - // in the final texture coordinate space, represent where on the palette - // image the original texture should be located. - - LMatrix3d transform; - compute_tex_matrix(transform); - LTexCoordd ul = LTexCoordd(0.0, 1.0) * transform; - LTexCoordd lr = LTexCoordd(1.0, 0.0) * transform; - - // Now we convert those texture coordinates back to pixel units. - int pal_x_size = _image->get_x_size(); - int pal_y_size = _image->get_y_size(); - - int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5); - int left = (int)floor(ul[0] * pal_x_size + 0.5); - int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5); - int right = (int)floor(lr[0] * pal_x_size + 0.5); - - // And now we can determine the size to scale the image to based on that. - // This may not be the same as texture->size() because of margins. - int x_size = right - left; - int y_size = bottom - top; - nassertv(x_size >= 0 && y_size >= 0); - - // Now we get a PNMImage that represents the swapped texture at that size. - TextureSwaps::iterator tsi; - tsi = _textureSwaps.begin() + index; - TextureImage *swapTexture = (*tsi); - const PNMImage &source_full = swapTexture->read_source_image(); - if (!source_full.is_valid()) { - flag_error_image(image); - return; - } - - PNMImage source(x_size, y_size, source_full.get_num_channels(), - source_full.get_maxval()); - source.quick_filter_from(source_full); - - bool alpha = image.has_alpha(); - bool source_alpha = source.has_alpha(); - - // Now copy the pixels. We do this by walking through the rectangular - // region on the palette image that we have reserved for this texture; for - // each pixel in this region, we determine its appropriate color based on - // its relation to the actual texture image location (determined above), and - // on whether the texture wraps or clamps. - for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) { - int sy = y - top; - - if (_placed._wrap_v == EggTexture::WM_clamp) { - // Clamp at [0, y_size). - sy = max(min(sy, y_size - 1), 0); - - } else { - // Wrap: sign-independent modulo. - sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size; - } - - for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) { - int sx = x - left; - - if (_placed._wrap_u == EggTexture::WM_clamp) { - // Clamp at [0, x_size). - sx = max(min(sx, x_size - 1), 0); - - } else { - // Wrap: sign-independent modulo. - sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size; - } - - image.set_xel(x, y, source.get_xel(sx, sy)); - if (alpha) { - if (source_alpha) { - image.set_alpha(x, y, source.get_alpha(sx, sy)); - } else { - image.set_alpha(x, y, 1.0); - } - } - } - } - - swapTexture->release_source_image(); -} - -/** - * Sets the rectangle of the palette image represented by the texture - * placement to red, to represent a missing texture. - */ -void TexturePlacement:: -flag_error_image(PNMImage &image) { - nassertv(is_placed()); - for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) { - for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) { - image.set_xel_val(x, y, 1, 0, 0); - } - } - if (image.has_alpha()) { - for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) { - for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) { - image.set_alpha_val(x, y, 1); - } - } - } -} - -/** - * A support function for determine_size(), this computes the appropriate size - * of the texture in pixels based on the UV coverage (as well as on the size - * of the source texture). - */ -void TexturePlacement:: -compute_size_from_uvs(const LTexCoordd &min_uv, const LTexCoordd &max_uv) { - _position._min_uv = min_uv; - _position._max_uv = max_uv; - - LTexCoordd range = _position._max_uv - _position._min_uv; - // cout << "range: " << range << endl; - - // cout << "_x_size texture: " << _texture->get_x_size() << endl; cout << - // "_y_size texture: " << _texture->get_y_size() << endl; - - _position._x_size = (int)floor(_texture->get_x_size() * range[0] + 0.5); - _position._y_size = (int)floor(_texture->get_y_size() * range[1] + 0.5); - - // cout << "_x_size: " << _position._x_size << endl; cout << "_y_size: " << - // _position._y_size << endl; - - // We arbitrarily require at least four pixels in each dimension. Fewer - // than this may be asking for trouble. - _position._x_size = max(_position._x_size, 4); - _position._y_size = max(_position._y_size, 4); - - if(get_group()->has_margin_override()) { - _position._margin = get_group()->get_margin_override(); - } else { - _position._margin = _texture->get_margin(); - } - // cout << "margin: " << _position._margin << endl; - - // Normally, we have interior margins, but if the image size is too small-- - // i.e. the margin size is too great a percentage of the image size--we'll - // make them exterior margins so as not to overly degrade the quality of the - // image. - if ((double)_position._margin / (double)_position._x_size > 0.10) { - _position._x_size += _position._margin * 2; - } - if ((double)_position._margin / (double)_position._y_size > 0.10) { - _position._y_size += _position._margin * 2; - } - - _size_known = true; -} - - - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void TexturePlacement:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void TexturePlacement:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - writer->write_pointer(datagram, _texture); - writer->write_pointer(datagram, _group); - writer->write_pointer(datagram, _image); - writer->write_pointer(datagram, _dest); - - datagram.add_bool(_has_uvs); - datagram.add_bool(_size_known); - _position.write_datagram(writer, datagram); - - datagram.add_bool(_is_filled); - _placed.write_datagram(writer, datagram); - datagram.add_int32((int)_omit_reason); - - datagram.add_int32(_references.size()); - References::const_iterator ri; - for (ri = _references.begin(); ri != _references.end(); ++ri) { - writer->write_pointer(datagram, (*ri)); - } - - datagram.add_int32(_textureSwaps.size()); - TextureSwaps::const_iterator tsi; - for (tsi = _textureSwaps.begin(); tsi != _textureSwaps.end(); ++tsi) { - writer->write_pointer(datagram, (*tsi)); - } - -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int TexturePlacement:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int index = TypedWritable::complete_pointers(p_list, manager); - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_texture, p_list[index], index); - } - index++; - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_group, p_list[index], index); - } - index++; - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_image, p_list[index], index); - } - index++; - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_dest, p_list[index], index); - } - index++; - - int i; - for (i = 0; i < _num_references; i++) { - TextureReference *reference; - DCAST_INTO_R(reference, p_list[index], index); - _references.insert(reference); - index++; - } - - for (i = 0; i < _num_textureSwaps; i++) { - TextureImage *swapTexture; - DCAST_INTO_R(swapTexture, p_list[index], index); - _textureSwaps.push_back(swapTexture); - index++; - } - - return index; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *TexturePlacement:: -make_from_bam(const FactoryParams ¶ms) { - TexturePlacement *me = new TexturePlacement; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void TexturePlacement:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - - manager->read_pointer(scan); // _texture - manager->read_pointer(scan); // _group - manager->read_pointer(scan); // _image - manager->read_pointer(scan); // _dest - - _has_uvs = scan.get_bool(); - _size_known = scan.get_bool(); - _position.fillin(scan, manager); - - _is_filled = scan.get_bool(); - _placed.fillin(scan, manager); - _omit_reason = (OmitReason)scan.get_int32(); - - _num_references = scan.get_int32(); - manager->read_pointers(scan, _num_references); - - if (Palettizer::_read_pi_version >= 20) { - _num_textureSwaps = scan.get_int32(); - } else { - _num_textureSwaps = 0; - } - manager->read_pointers(scan, _num_textureSwaps); -} - - -/** - * Compares two TexturePlacement objects and returns true if the first one is - * bigger than the second one, false otherwise. - */ -bool SortPlacementBySize:: -operator ()(TexturePlacement *a, TexturePlacement *b) const { - if (a->get_y_size() < b->get_y_size()) { - return false; - - } else if (b->get_y_size() < a->get_y_size()) { - return true; - - } else if (a->get_x_size() < b->get_x_size()) { - return false; - - } else if (b->get_x_size() < a->get_x_size()) { - return true; - } else if (a->get_name() < b->get_name()) { - // use this fall through case to let alphabetically smaller textures show - // up first - return true; - } - - return false; -} diff --git a/pandatool/src/palettizer/texturePlacement.h b/pandatool/src/palettizer/texturePlacement.h deleted file mode 100644 index efe90f85..00000000 --- a/pandatool/src/palettizer/texturePlacement.h +++ /dev/null @@ -1,157 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file texturePlacement.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef TEXTUREPLACEMENT_H -#define TEXTUREPLACEMENT_H - -#include "pandatoolbase.h" - -#include "omitReason.h" -#include "texturePosition.h" - -#include "typedWritable.h" -#include "luse.h" - -#include "pset.h" - -class TextureImage; -class DestTextureImage; -class PaletteGroup; -class PaletteImage; -class PalettePage; -class TextureProperties; -class TextureReference; -class PNMImage; - -/** - * This corresponds to a particular assignment of a TextureImage with a - * PaletteGroup, and specifically describes which PaletteImage (if any), and - * where on the PaletteImage, the TextureImage has been assigned to. - */ -class TexturePlacement : public TypedWritable { -private: - TexturePlacement(); - -public: - TexturePlacement(TextureImage *texture, PaletteGroup *group); - ~TexturePlacement(); - - const std::string &get_name() const; - TextureImage *get_texture() const; - const TextureProperties &get_properties() const; - PaletteGroup *get_group() const; - - void add_egg(TextureReference *reference); - void remove_egg(TextureReference *reference); - void mark_eggs_stale(); - - void set_dest(DestTextureImage *dest); - DestTextureImage *get_dest() const; - - bool determine_size(); - bool is_size_known() const; - OmitReason get_omit_reason() const; - int get_x_size() const; - int get_y_size() const; - double get_uv_area() const; - - bool is_placed() const; - PaletteImage *get_image() const; - PalettePage *get_page() const; - int get_placed_x() const; - int get_placed_y() const; - int get_placed_x_size() const; - int get_placed_y_size() const; - double get_placed_uv_area() const; - - void place_at(PaletteImage *image, int x, int y); - void force_replace(); - void omit_solitary(); - void not_solitary(); - bool intersects(int x, int y, int x_size, int y_size); - - void compute_tex_matrix(LMatrix3d &transform); - - void write_placed(std::ostream &out, int indent_level = 0); - - bool is_filled() const; - void mark_unfilled(); - void fill_image(PNMImage &image); - void fill_swapped_image(PNMImage &image, int index); - void flag_error_image(PNMImage &image); - - typedef pvector TextureSwaps; - TextureSwaps _textureSwaps; - -private: - void compute_size_from_uvs(const LTexCoordd &min_uv, const LTexCoordd &max_uv); - - TextureImage *_texture; - PaletteGroup *_group; - PaletteImage *_image; - DestTextureImage *_dest; - - bool _has_uvs; - bool _size_known; - TexturePosition _position; - - bool _is_filled; - TexturePosition _placed; - OmitReason _omit_reason; - - typedef pset References; - References _references; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -private: - // This value is only filled in while reading from the bam file; don't use - // it otherwise. - int _num_references; - int _num_textureSwaps; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - register_type(_type_handle, "TexturePlacement", - TypedWritable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - - -// This is an STL object to sort an array of TexturePlacement pointers in -// order from biggest to smallest. -class SortPlacementBySize { -public: - bool operator ()(TexturePlacement *a, TexturePlacement *b) const; -}; - -#endif diff --git a/pandatool/src/palettizer/texturePosition.cxx b/pandatool/src/palettizer/texturePosition.cxx deleted file mode 100644 index ea4f61ac..00000000 --- a/pandatool/src/palettizer/texturePosition.cxx +++ /dev/null @@ -1,135 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file texturePosition.cxx - * @author drose - * @date 2000-12-04 - */ - -#include "texturePosition.h" - -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" - -TypeHandle TexturePosition::_type_handle; - -/** - * - */ -TexturePosition:: -TexturePosition() { - _margin = 0; - _x = 0; - _y = 0; - _x_size = 0; - _y_size = 0; - _min_uv.set(0.0, 0.0); - _max_uv.set(0.0, 0.0); - _wrap_u = EggTexture::WM_unspecified; - _wrap_v = EggTexture::WM_unspecified; -} - -/** - * - */ -TexturePosition:: -TexturePosition(const TexturePosition ©) : - _margin(copy._margin), - _x(copy._x), - _y(copy._y), - _x_size(copy._x_size), - _y_size(copy._y_size), - _min_uv(copy._min_uv), - _max_uv(copy._max_uv), - _wrap_u(copy._wrap_u), - _wrap_v(copy._wrap_v) -{ -} - -/** - * - */ -void TexturePosition:: -operator = (const TexturePosition ©) { - _margin = copy._margin; - _x = copy._x; - _y = copy._y; - _x_size = copy._x_size; - _y_size = copy._y_size; - _min_uv = copy._min_uv; - _max_uv = copy._max_uv; - _wrap_u = copy._wrap_u; - _wrap_v = copy._wrap_v; -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void TexturePosition:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void TexturePosition:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - datagram.add_int32(_margin); - datagram.add_int32(_x); - datagram.add_int32(_y); - datagram.add_int32(_x_size); - datagram.add_int32(_y_size); - datagram.add_float64(_min_uv[0]); - datagram.add_float64(_min_uv[1]); - datagram.add_float64(_max_uv[0]); - datagram.add_float64(_max_uv[1]); - datagram.add_int32((int)_wrap_u); - datagram.add_int32((int)_wrap_v); -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *TexturePosition:: -make_from_bam(const FactoryParams ¶ms) { - TexturePosition *me = new TexturePosition; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void TexturePosition:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - _margin = scan.get_int32(); - _x = scan.get_int32(); - _y = scan.get_int32(); - _x_size = scan.get_int32(); - _y_size = scan.get_int32(); - _min_uv[0] = scan.get_float64(); - _min_uv[1] = scan.get_float64(); - _max_uv[0] = scan.get_float64(); - _max_uv[1] = scan.get_float64(); - _wrap_u = (EggTexture::WrapMode)scan.get_int32(); - _wrap_v = (EggTexture::WrapMode)scan.get_int32(); -} diff --git a/pandatool/src/palettizer/texturePosition.h b/pandatool/src/palettizer/texturePosition.h deleted file mode 100644 index c1edd40e..00000000 --- a/pandatool/src/palettizer/texturePosition.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file texturePosition.h - * @author drose - * @date 2000-12-04 - */ - -#ifndef TEXTUREPOSITION_H -#define TEXTUREPOSITION_H - -#include "pandatoolbase.h" - -#include "typedWritable.h" -#include "luse.h" -#include "eggTexture.h" - -class FactoryParams; - -/** - * This represents a particular position of a texture within a PaletteImage. - * There is only one of these per TexturePlacement, but it exists as a - * separate structure so the TexturePlacement can easily consider - * repositioning the texture. - */ -class TexturePosition : public TypedWritable { -public: - TexturePosition(); - TexturePosition(const TexturePosition ©); - void operator = (const TexturePosition ©); - - int _margin; - int _x, _y; - int _x_size, _y_size; - - LTexCoordd _min_uv; - LTexCoordd _max_uv; - - EggTexture::WrapMode _wrap_u; - EggTexture::WrapMode _wrap_v; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - -public: - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - register_type(_type_handle, "TexturePosition", - TypedWritable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/palettizer/textureProperties.cxx b/pandatool/src/palettizer/textureProperties.cxx deleted file mode 100644 index c5635409..00000000 --- a/pandatool/src/palettizer/textureProperties.cxx +++ /dev/null @@ -1,938 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureProperties.cxx - * @author drose - * @date 2000-11-29 - */ - -#include "textureProperties.h" -#include "palettizer.h" -#include "pnmFileType.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "string_utils.h" - -using std::string; - -TypeHandle TextureProperties::_type_handle; - -/** - * - */ -TextureProperties:: -TextureProperties() { - _got_num_channels = false; - _num_channels = 0; - _effective_num_channels = 0; - _format = EggTexture::F_unspecified; - _force_format = false; - _generic_format = false; - _keep_format = false; - _minfilter = EggTexture::FT_unspecified; - _magfilter = EggTexture::FT_unspecified; - _quality_level = EggTexture::QL_unspecified; - _anisotropic_degree = 0; - _color_type = nullptr; - _alpha_type = nullptr; - _srgb = false; -} - -/** - * - */ -TextureProperties:: -TextureProperties(const TextureProperties ©) : - _format(copy._format), - _force_format(copy._force_format), - _generic_format(copy._generic_format), - _keep_format(copy._keep_format), - _minfilter(copy._minfilter), - _magfilter(copy._magfilter), - _quality_level(copy._quality_level), - _anisotropic_degree(copy._anisotropic_degree), - _color_type(copy._color_type), - _alpha_type(copy._alpha_type), - _srgb(copy._srgb), - _got_num_channels(copy._got_num_channels), - _num_channels(copy._num_channels), - _effective_num_channels(copy._effective_num_channels) -{ -} - -/** - * - */ -void TextureProperties:: -operator = (const TextureProperties ©) { - _force_format = copy._force_format; - _generic_format = copy._generic_format; - _keep_format = copy._keep_format; - _minfilter = copy._minfilter; - _magfilter = copy._magfilter; - _quality_level = copy._quality_level; - _anisotropic_degree = copy._anisotropic_degree; - _color_type = copy._color_type; - _alpha_type = copy._alpha_type; - _got_num_channels = copy._got_num_channels; - _num_channels = copy._num_channels; - _effective_num_channels = copy._effective_num_channels; - _format = copy._format; - _srgb = copy._srgb; -} - -/** - * Resets only the properties that might be changed by update_properties() to - * a neutral state. - */ -void TextureProperties:: -clear_basic() { - if (!_force_format) { - _format = EggTexture::F_unspecified; - } - - _minfilter = EggTexture::FT_unspecified; - _magfilter = EggTexture::FT_unspecified; - _quality_level = EggTexture::QL_unspecified; - _anisotropic_degree = 0; -} - -/** - * Returns true if the number of channels is known. - */ -bool TextureProperties:: -has_num_channels() const { - return _got_num_channels; -} - -/** - * Returns the number of channels (1 through 4) associated with the image. It - * is an error to call this unless has_num_channels() returns true. - */ -int TextureProperties:: -get_num_channels() const { - nassertr(_got_num_channels, 0); - return _effective_num_channels; -} - -/** - * Sets the number of channels (1 through 4) associated with the image, - * presumably after reading this information from the image header. - */ -void TextureProperties:: -set_num_channels(int num_channels) { - _num_channels = num_channels; - _effective_num_channels = num_channels; - _got_num_channels = true; -} - -/** - * Sets the actual number of channels to indicate a grayscale image, - * presumably after discovering that the image contains no colored pixels. - */ -void TextureProperties:: -force_grayscale() { - nassertv(_got_num_channels && _num_channels >= 3); - _num_channels -= 2; - _effective_num_channels = _num_channels; -} - -/** - * Sets the actual number of channels to indicate an image with no alpha - * channel, presumably after discovering that the alpha channel contains no - * meaningful pixels. - */ -void TextureProperties:: -force_nonalpha() { - nassertv(_got_num_channels && (_num_channels == 2 || _num_channels == 4)); - _num_channels--; - _effective_num_channels = _num_channels; -} - -/** - * Returns true if the texture uses an alpha channel, false otherwise. - */ -bool TextureProperties:: -uses_alpha() const { - switch (_format) { - case EggTexture::F_rgba: - case EggTexture::F_rgbm: - case EggTexture::F_rgba12: - case EggTexture::F_rgba8: - case EggTexture::F_rgba4: - case EggTexture::F_rgba5: - case EggTexture::F_alpha: - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - case EggTexture::F_srgb_alpha: - case EggTexture::F_sluminance_alpha: - return true; - - default: - return false; - } -} - -/** - * Returns a string corresponding to the TextureProperties object. Each - * unique set of TextureProperties will generate a unique string. This is - * used to generate unique palette image filenames. - */ -string TextureProperties:: -get_string() const { - string result; - - if (_got_num_channels) { - std::ostringstream num; - num << _effective_num_channels; - result += num.str(); - } - - result += get_format_string(_format); - result += get_filter_string(_minfilter); - result += get_filter_string(_magfilter); - result += get_anisotropic_degree_string(_anisotropic_degree); - result += get_type_string(_color_type, _alpha_type); - result += get_quality_level_string(_quality_level); - return result; -} - -/** - * If the indicate TextureProperties structure is more specific than this one, - * updates this one. - */ -void TextureProperties:: -update_properties(const TextureProperties &other) { - if (!_got_num_channels) { - _got_num_channels = other._got_num_channels; - _num_channels = other._num_channels; - _effective_num_channels = _num_channels; - } - - _srgb = other._srgb; - - if (_force_format) { - // If we've forced our own format, it doesn't change. - } else if (other._force_format) { - _format = other._format; - } else { - _format = union_format(_format, other._format); - } - - _minfilter = union_filter(_minfilter, other._minfilter); - _magfilter = union_filter(_magfilter, other._magfilter); - _quality_level = union_quality_level(_quality_level, other._quality_level); - - _anisotropic_degree = other._anisotropic_degree; - - if (_color_type == nullptr) { - _color_type = other._color_type; - _alpha_type = other._alpha_type; - } -} - -/** - * If any properties remain unspecified, specify them now. Also reconcile - * conflicting information. - */ -void TextureProperties:: -fully_define() { - if (!_got_num_channels || _force_format) { - switch (_format) { - case EggTexture::F_rgba: - case EggTexture::F_rgbm: - case EggTexture::F_rgba12: - case EggTexture::F_rgba8: - case EggTexture::F_rgba4: - case EggTexture::F_rgba5: - case EggTexture::F_srgb_alpha: - _num_channels = 4; - break; - - case EggTexture::F_unspecified: - case EggTexture::F_rgb: - case EggTexture::F_rgb12: - case EggTexture::F_rgb8: - case EggTexture::F_rgb5: - case EggTexture::F_rgb332: - case EggTexture::F_srgb: - _num_channels = 3; - break; - - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - case EggTexture::F_sluminance_alpha: - _num_channels = 2; - break; - - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - case EggTexture::F_luminance: - case EggTexture::F_sluminance: - _num_channels = 1; - break; - } - _got_num_channels = true; - } - - _effective_num_channels = _num_channels; - - // Respect the _generic_format flag. If this is set, it means the user has - // indicated that we should strip off any bitcount-specific formats and - // replace them with the more generic equivalents. - if (_generic_format) { - switch (_format) { - case EggTexture::F_unspecified: - case EggTexture::F_rgba: - case EggTexture::F_rgbm: - case EggTexture::F_rgb: - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - case EggTexture::F_luminance: - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - case EggTexture::F_srgb: - case EggTexture::F_srgb_alpha: - case EggTexture::F_sluminance: - case EggTexture::F_sluminance_alpha: - break; - - case EggTexture::F_rgba12: - case EggTexture::F_rgba8: - case EggTexture::F_rgba4: - case EggTexture::F_rgba5: - _format = EggTexture::F_rgba; - break; - - case EggTexture::F_rgb12: - case EggTexture::F_rgb8: - case EggTexture::F_rgb5: - case EggTexture::F_rgb332: - _format = EggTexture::F_rgb; - break; - } - } - - // Make sure the format reflects the number of channels, although we accept - // a format that ignores an alpha channel. - if (!_force_format && !_keep_format) { - switch (_num_channels) { - case 1: - switch (_format) { - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - case EggTexture::F_luminance: - case EggTexture::F_sluminance: - break; - - // These formats suggest an alpha channel; they are quietly replaced - // with non-alpha equivalents. - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - _format = EggTexture::F_luminance; - break; - - case EggTexture::F_sluminance_alpha: - _format = EggTexture::F_sluminance; - break; - - default: - if (_srgb) { - _format = EggTexture::F_sluminance; - } else { - _format = EggTexture::F_luminance; - } - } - break; - - case 2: - switch (_format) { - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - case EggTexture::F_sluminance_alpha: - break; - - // These formats implicitly reduce the number of channels to 1. - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - case EggTexture::F_luminance: - case EggTexture::F_sluminance: - break; - - default: - if (_srgb) { - _format = EggTexture::F_sluminance_alpha; - } else { - _format = EggTexture::F_luminance_alpha; - } - } - break; - - case 3: - switch (_format) { - case EggTexture::F_rgb: - case EggTexture::F_rgb12: - case EggTexture::F_rgb8: - case EggTexture::F_rgb5: - case EggTexture::F_rgb332: - case EggTexture::F_srgb: - break; - - // These formats suggest an alpha channel; they are quietly replaced - // with non-alpha equivalents. - case EggTexture::F_rgba8: - _format = EggTexture::F_rgb8; - break; - - case EggTexture::F_rgba5: - case EggTexture::F_rgba4: - _format = EggTexture::F_rgb5; - break; - - // These formats implicitly reduce the number of channels to 1. - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - case EggTexture::F_luminance: - case EggTexture::F_sluminance: - break; - - default: - if (_srgb) { - _format = EggTexture::F_srgb; - } else { - _format = EggTexture::F_rgb; - } - } - break; - - case 4: - switch (_format) { - case EggTexture::F_rgba: - case EggTexture::F_rgbm: - case EggTexture::F_rgba12: - case EggTexture::F_rgba8: - case EggTexture::F_rgba4: - case EggTexture::F_rgba5: - case EggTexture::F_srgb_alpha: - break; - - // These formats implicitly reduce the number of channels to 3. - case EggTexture::F_rgb: - case EggTexture::F_rgb12: - case EggTexture::F_rgb8: - case EggTexture::F_rgb5: - case EggTexture::F_rgb332: - case EggTexture::F_srgb: - _effective_num_channels = 3; - break; - - // These formats implicitly reduce the number of channels to 2. - case EggTexture::F_luminance_alpha: - case EggTexture::F_luminance_alphamask: - case EggTexture::F_sluminance_alpha: - _effective_num_channels = 2; - break; - - // These formats implicitly reduce the number of channels to 1. - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - case EggTexture::F_luminance: - case EggTexture::F_sluminance: - _effective_num_channels = 1; - break; - - default: - if (_srgb) { - _format = EggTexture::F_srgb_alpha; - } else { - _format = EggTexture::F_rgba; - } - } - } - } - - // Respect the _srgb flag. If this is set, it means the texture is in sRGB - // color space and the format should be changed to reflect that. - if (_srgb) { - switch (_num_channels) { - case 1: - // Don't respect sRGB for textures using the F_alpha format, which - // indicates that the image represents an alpha channel, not a color - // channel. - if (_format != EggTexture::F_alpha) { - _format = EggTexture::F_sluminance; - } - break; - case 2: - _format = EggTexture::F_sluminance_alpha; - break; - case 3: - _format = EggTexture::F_srgb; - break; - case 4: - default: - _format = EggTexture::F_srgb_alpha; - break; - } - } - - switch (_minfilter) { - case EggTexture::FT_unspecified: - _minfilter = EggTexture::FT_linear; - break; - - default: - break; - } - - switch (_magfilter) { - case EggTexture::FT_unspecified: - case EggTexture::FT_nearest_mipmap_nearest: - case EggTexture::FT_linear_mipmap_nearest: - case EggTexture::FT_nearest_mipmap_linear: - case EggTexture::FT_linear_mipmap_linear: - _magfilter = EggTexture::FT_linear; - break; - - default: - break; - } - - if (_color_type == nullptr) { - _color_type = pal->_color_type; - _alpha_type = pal->_alpha_type; - } -} - -/** - * Adjusts the texture properties of the indicated egg reference to match - * these properties. - */ -void TextureProperties:: -update_egg_tex(EggTexture *egg_tex) const { - egg_tex->set_format(_format); - egg_tex->set_minfilter(_minfilter); - egg_tex->set_magfilter(_minfilter); - egg_tex->set_quality_level(_quality_level); - egg_tex->set_anisotropic_degree(_anisotropic_degree); -} - -/** - * Returns true if all of the properties that are reflected directly in an egg - * file match between this TextureProperties object and the other, or false if - * any of them differ. - */ -bool TextureProperties:: -egg_properties_match(const TextureProperties &other) const { - return (_format == other._format && - _minfilter == other._minfilter && - _magfilter == other._magfilter && - _quality_level == other._quality_level && - _anisotropic_degree == other._anisotropic_degree); -} - -/** - * - */ -bool TextureProperties:: -operator < (const TextureProperties &other) const { - if (_format != other._format) { - return (int)_format < (int)other._format; - } - if (_minfilter != other._minfilter) { - return (int)_minfilter < (int)other._minfilter; - } - if (_magfilter != other._magfilter) { - return (int)_magfilter < (int)other._magfilter; - } - if (_quality_level != other._quality_level) { - return (int)_quality_level < (int)other._quality_level; - } - if (_anisotropic_degree != other._anisotropic_degree) { - return _anisotropic_degree < other._anisotropic_degree; - } - if (_srgb != other._srgb) { - return _srgb < other._srgb; - } - if (_color_type != other._color_type) { - return _color_type < other._color_type; - } - if (_color_type != nullptr) { - if (_alpha_type != other._alpha_type) { - return _alpha_type < other._alpha_type; - } - } - return false; -} - -/** - * - */ -bool TextureProperties:: -operator == (const TextureProperties &other) const { - return (_format == other._format && - _minfilter == other._minfilter && - _magfilter == other._magfilter && - _quality_level == other._quality_level && - _anisotropic_degree == other._anisotropic_degree && - _srgb == other._srgb && - _color_type == other._color_type && - (_color_type == nullptr || - _alpha_type == other._alpha_type)); -} - -/** - * - */ -bool TextureProperties:: -operator != (const TextureProperties &other) const { - return !operator == (other); -} - -/** - * Returns a short string representing the given EggTexture format. - */ -string TextureProperties:: -get_format_string(EggTexture::Format format) { - switch (format) { - case EggTexture::F_unspecified: - return "u"; - - case EggTexture::F_rgba: - return "a"; - - case EggTexture::F_rgbm: - return "m"; - - case EggTexture::F_rgba12: - return "a12"; - - case EggTexture::F_rgba8: - return "a8"; - - case EggTexture::F_rgba4: - return "a4"; - - case EggTexture::F_rgba5: - return "a5"; - - case EggTexture::F_rgb: - return "c"; - - case EggTexture::F_rgb12: - return "c12"; - - case EggTexture::F_rgb8: - return "c8"; - - case EggTexture::F_rgb5: - return "c5"; - - case EggTexture::F_rgb332: - return "c3"; - - case EggTexture::F_luminance_alpha: - return "t"; // t for two-channel - - case EggTexture::F_luminance_alphamask: - return "t1"; - - case EggTexture::F_red: - return "r"; - - case EggTexture::F_green: - return "g"; - - case EggTexture::F_blue: - return "b"; - - case EggTexture::F_alpha: - return "a"; - - case EggTexture::F_luminance: - return "l"; - - case EggTexture::F_srgb: - return "sc"; - - case EggTexture::F_srgb_alpha: - return "sa"; - - case EggTexture::F_sluminance: - return "sl"; - - case EggTexture::F_sluminance_alpha: - return "st"; - } - - return "x"; -} - -/** - * Returns a short string representing the given EggTexture filter type. - */ -string TextureProperties:: -get_filter_string(EggTexture::FilterType filter_type) { - switch (filter_type) { - case EggTexture::FT_unspecified: - return "u"; - - case EggTexture::FT_nearest: - return "n"; - - case EggTexture::FT_linear: - return "l"; - - case EggTexture::FT_nearest_mipmap_nearest: - return "m1"; - - case EggTexture::FT_linear_mipmap_nearest: - return "m2"; - - case EggTexture::FT_nearest_mipmap_linear: - return "m3"; - - case EggTexture::FT_linear_mipmap_linear: - return "m"; - } - - return "x"; -} - -/** - * Returns a short string describing the anisotropic degree. - */ -string TextureProperties:: -get_anisotropic_degree_string(int aniso_degree) { - if (aniso_degree <= 1) { - return ""; - } else { - return string("an") + format_string(aniso_degree); - } -} - -/** - * Returns a short string describing the quality level. - */ -string TextureProperties:: -get_quality_level_string(EggTexture::QualityLevel quality_level) { - switch (quality_level) { - case EggTexture::QL_unspecified: - case EggTexture::QL_default: - return ""; - - case EggTexture::QL_fastest: - return "f"; - - case EggTexture::QL_normal: - return "n"; - - case EggTexture::QL_best: - return "b"; - } - return ""; -} - -/** - * Returns a short string representing whether the color and/or alpha type has - * been specified or not. - */ -string TextureProperties:: -get_type_string(PNMFileType *color_type, PNMFileType *alpha_type) { - if (color_type == nullptr) { - return ""; - } - if (alpha_type == nullptr) { - return "c"; - } - return "a"; -} - -/** - * Returns the EggTexture format which is the more specific of the two. - */ -EggTexture::Format TextureProperties:: -union_format(EggTexture::Format a, EggTexture::Format b) { - switch (a) { - case EggTexture::F_unspecified: - return b; - - case EggTexture::F_rgba: - switch (b) { - case EggTexture::F_rgbm: - case EggTexture::F_rgba12: - case EggTexture::F_rgba8: - case EggTexture::F_rgba4: - case EggTexture::F_rgba5: - case EggTexture::F_red: - case EggTexture::F_green: - case EggTexture::F_blue: - case EggTexture::F_alpha: - return b; - - default: - return a; - }; - - case EggTexture::F_rgb: - if (b != EggTexture::F_unspecified) { - return b; - } - return a; - - default: - return a; - } -} - -/** - * Returns the EggTexture filter type which is the more specific of the two. - */ -EggTexture::FilterType TextureProperties:: -union_filter(EggTexture::FilterType a, EggTexture::FilterType b) { - if ((int)a < (int)b) { - return b; - } else { - return a; - } -} - -/** - * Returns the EggTexture quality level which is the more specific of the two. - */ -EggTexture::QualityLevel TextureProperties:: -union_quality_level(EggTexture::QualityLevel a, EggTexture::QualityLevel b) { - if ((int)a < (int)b) { - return b; - } else { - return a; - } -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void TextureProperties:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void TextureProperties:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - datagram.add_bool(_got_num_channels); - datagram.add_int32(_num_channels); - datagram.add_int32(_effective_num_channels); - datagram.add_int32((int)_format); - datagram.add_bool(_force_format); - datagram.add_bool(_generic_format); - datagram.add_bool(_keep_format); - datagram.add_int32((int)_minfilter); - datagram.add_int32((int)_magfilter); - datagram.add_int32((int)_quality_level); - datagram.add_int32(_anisotropic_degree); - datagram.add_bool(_srgb); - writer->write_pointer(datagram, _color_type); - writer->write_pointer(datagram, _alpha_type); -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int TextureProperties:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int index = TypedWritable::complete_pointers(p_list, manager); - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_color_type, p_list[index], index); - } - index++; - - if (p_list[index] != nullptr) { - DCAST_INTO_R(_alpha_type, p_list[index], index); - } - index++; - - return index; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *TextureProperties:: -make_from_bam(const FactoryParams ¶ms) { - TextureProperties *me = new TextureProperties; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void TextureProperties:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - _got_num_channels = scan.get_bool(); - _num_channels = scan.get_int32(); - _effective_num_channels = _num_channels; - if (Palettizer::_read_pi_version >= 9) { - _effective_num_channels = scan.get_int32(); - } - _format = (EggTexture::Format)scan.get_int32(); - _force_format = scan.get_bool(); - _generic_format = false; - if (Palettizer::_read_pi_version >= 9) { - _generic_format = scan.get_bool(); - } - _keep_format = false; - if (Palettizer::_read_pi_version >= 13) { - _keep_format = scan.get_bool(); - } - _minfilter = (EggTexture::FilterType)scan.get_int32(); - _magfilter = (EggTexture::FilterType)scan.get_int32(); - if (Palettizer::_read_pi_version >= 18) { - _quality_level = (EggTexture::QualityLevel)scan.get_int32(); - } - _anisotropic_degree = scan.get_int32(); - - if (Palettizer::_read_pi_version >= 21) { - _srgb = scan.get_bool(); - } - - manager->read_pointer(scan); // _color_type - manager->read_pointer(scan); // _alpha_type -} diff --git a/pandatool/src/palettizer/textureProperties.h b/pandatool/src/palettizer/textureProperties.h deleted file mode 100644 index f143bdcb..00000000 --- a/pandatool/src/palettizer/textureProperties.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureProperties.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef TEXTUREPROPERTIES_H -#define TEXTUREPROPERTIES_H - -#include "pandatoolbase.h" - -#include "eggTexture.h" -#include "typedWritable.h" - -class PNMFileType; -class FactoryParams; - -/** - * This is the set of characteristics of a texture that, if different from - * another texture, prevent the two textures from sharing a PaletteImage. It - * includes properties such as mipmapping, number of channels, etc. - */ -class TextureProperties : public TypedWritable { -public: - TextureProperties(); - TextureProperties(const TextureProperties ©); - void operator = (const TextureProperties ©); - - void clear_basic(); - - bool has_num_channels() const; - int get_num_channels() const; - void set_num_channels(int num_channels); - void force_grayscale(); - void force_nonalpha(); - bool uses_alpha() const; - - std::string get_string() const; - void update_properties(const TextureProperties &other); - void fully_define(); - - void update_egg_tex(EggTexture *egg_tex) const; - bool egg_properties_match(const TextureProperties &other) const; - - bool operator < (const TextureProperties &other) const; - bool operator == (const TextureProperties &other) const; - bool operator != (const TextureProperties &other) const; - - EggTexture::Format _format; - bool _force_format; // true when format has been explicitly specified - bool _generic_format; // true if 'generic' keyword, meaning rgba8 -> rgba. - bool _keep_format; // true if 'keep-format' keyword. - EggTexture::FilterType _minfilter, _magfilter; - EggTexture::QualityLevel _quality_level; - int _anisotropic_degree; - PNMFileType *_color_type; - PNMFileType *_alpha_type; - bool _srgb; - -private: - static std::string get_format_string(EggTexture::Format format); - static std::string get_filter_string(EggTexture::FilterType filter_type); - static std::string get_anisotropic_degree_string(int aniso_degree); - static std::string get_quality_level_string(EggTexture::QualityLevel quality_level); - static std::string get_type_string(PNMFileType *color_type, - PNMFileType *alpha_type); - - static EggTexture::Format union_format(EggTexture::Format a, - EggTexture::Format b); - - static EggTexture::FilterType union_filter(EggTexture::FilterType a, - EggTexture::FilterType b); - static EggTexture::QualityLevel union_quality_level(EggTexture::QualityLevel a, - EggTexture::QualityLevel b); - - bool _got_num_channels; - int _num_channels; - int _effective_num_channels; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - -public: - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - register_type(_type_handle, "TextureProperties", - TypedWritable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/palettizer/textureReference.cxx b/pandatool/src/palettizer/textureReference.cxx deleted file mode 100644 index 3b6c2696..00000000 --- a/pandatool/src/palettizer/textureReference.cxx +++ /dev/null @@ -1,901 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureReference.cxx - * @author drose - * @date 2000-11-29 - */ - -#include "textureReference.h" -#include "textureImage.h" -#include "paletteImage.h" -#include "sourceTextureImage.h" -#include "destTextureImage.h" -#include "texturePlacement.h" -#include "palettizer.h" -#include "eggFile.h" - -#include "indent.h" -#include "eggTexture.h" -#include "eggData.h" -#include "eggGroupNode.h" -#include "eggGroup.h" -#include "eggNurbsSurface.h" -#include "eggVertexPool.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "string_utils.h" - -#include - -using std::max; -using std::min; -using std::string; - -TypeHandle TextureReference::_type_handle; - -/** - * - */ -TextureReference:: -TextureReference() { - _egg_file = nullptr; - _egg_tex = nullptr; - _tex_mat = LMatrix3d::ident_mat(); - _inv_tex_mat = LMatrix3d::ident_mat(); - _source_texture = nullptr; - _placement = nullptr; - _uses_alpha = false; - _any_uvs = false; - _min_uv.set(0.0, 0.0); - _max_uv.set(0.0, 0.0); - _wrap_u = EggTexture::WM_unspecified; - _wrap_v = EggTexture::WM_unspecified; -} - -/** - * - */ -TextureReference:: -~TextureReference() { - clear_placement(); -} - -/** - * Sets up the TextureReference using information extracted from an egg file. - */ -void TextureReference:: -from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex) { - _egg_file = egg_file; - _egg_tex = egg_tex; - _egg_data = data; - _tref_name = egg_tex->get_name(); - - if (_egg_tex->has_transform2d()) { - _tex_mat = _egg_tex->get_transform2d(); - if (!_inv_tex_mat.invert_from(_tex_mat)) { - _inv_tex_mat = LMatrix3d::ident_mat(); - } - } else { - _tex_mat = LMatrix3d::ident_mat(); - _inv_tex_mat = LMatrix3d::ident_mat(); - } - - Filename filename = _egg_tex->get_filename(); - Filename alpha_filename; - if (_egg_tex->has_alpha_filename()) { - alpha_filename = _egg_tex->get_alpha_filename(); - } - int alpha_file_channel = _egg_tex->get_alpha_file_channel(); - - _properties._format = _egg_tex->get_format(); - _properties._minfilter = _egg_tex->get_minfilter(); - _properties._magfilter = _egg_tex->get_magfilter(); - _properties._quality_level = _egg_tex->get_quality_level(); - _properties._anisotropic_degree = _egg_tex->get_anisotropic_degree(); - - string name = filename.get_basename_wo_extension(); - TextureImage *texture = pal->get_texture(name); - if (texture->get_name() != name) { - nout << "Texture name conflict: \"" << name - << "\" conflicts with existing texture named \"" - << texture->get_name() << "\".\n"; - - // Make this a hard error; refuse to do anything else until the user fixes - // it. Case conflicts can be very bad, especially if CVS is involved on a - // Windows machine. - exit(1); - } - _source_texture = texture->get_source(filename, alpha_filename, - alpha_file_channel); - _source_texture->update_properties(_properties); - - _uses_alpha = false; - EggRenderMode::AlphaMode alpha_mode = _egg_tex->get_alpha_mode(); - if (alpha_mode == EggRenderMode::AM_unspecified) { - if (_source_texture->get_size()) { - _uses_alpha = - _egg_tex->has_alpha_channel(_source_texture->get_num_channels()); - } - - } else if (alpha_mode == EggRenderMode::AM_off) { - _uses_alpha = false; - - } else { - _uses_alpha = true; - } - - get_uv_range(_egg_data, pal->_remap_uv); - - _wrap_u = _egg_tex->determine_wrap_u(); - _wrap_v = _egg_tex->determine_wrap_v(); -} - -/** - * Sets up the pointers within the TextureReference to the same egg file - * pointers indicated by the other TextureReference object, without changing - * any of the other internal data stored here regarding the egg structures. - * This is intended for use when we have already shown that the two - * TextureReferences describe equivalent data. - */ -void TextureReference:: -from_egg_quick(const TextureReference &other) { - nassertv(_tref_name == other._tref_name); - _egg_file = other._egg_file; - _egg_tex = other._egg_tex; - _egg_data = other._egg_data; -} - -/** - * Called to indicate that the EggData previously passed to from_egg() is - * about to be deallocated, and all of its pointers should be cleared. - */ -void TextureReference:: -release_egg_data() { - _egg_tex = nullptr; - _egg_data = nullptr; -} - -/** - * After an EggData has previously been released via release_egg_data(), this - * can be called to indicate that the egg file has been reloaded and we should - * assign the indicated pointers. - */ -void TextureReference:: -rebind_egg_data(EggData *data, EggTexture *egg_tex) { - nassertv(_tref_name == egg_tex->get_name()); - _egg_data = data; - _egg_tex = egg_tex; -} - -/** - * Returns the EggFile that references this texture. - */ -EggFile *TextureReference:: -get_egg_file() const { - return _egg_file; -} - -/** - * Returns the SourceTextureImage that this object refers to. - */ -SourceTextureImage *TextureReference:: -get_source() const { - return _source_texture; -} - -/** - * Returns the TextureImage that this object refers to. - */ -TextureImage *TextureReference:: -get_texture() const { - nassertr(_source_texture != nullptr, nullptr); - return _source_texture->get_texture(); -} - -/** - * Returns the name of the EggTexture entry that references this texture. - */ -const string &TextureReference:: -get_tref_name() const { - return _tref_name; -} - -/** - * Defines an ordering of TextureReference pointers in alphabetical order by - * their tref name. - */ -bool TextureReference:: -operator < (const TextureReference &other) const { - return _tref_name < other._tref_name; -} - -/** - * Returns true if this TextureReference actually uses the texture on - * geometry, with UV's and everything, or false otherwise. Strictly speaking, - * this should always return true. - */ -bool TextureReference:: -has_uvs() const { - return _any_uvs; -} - -/** - * Returns the minimum UV coordinate in use for the texture by this reference. - */ -const LTexCoordd &TextureReference:: -get_min_uv() const { - nassertr(_any_uvs, _min_uv); - return _min_uv; -} - -/** - * Returns the maximum UV coordinate in use for the texture by this reference. - */ -const LTexCoordd &TextureReference:: -get_max_uv() const { - nassertr(_any_uvs, _max_uv); - return _max_uv; -} - -/** - * Returns the specification for the wrapping in the U direction. - */ -EggTexture::WrapMode TextureReference:: -get_wrap_u() const { - return _wrap_u; -} - -/** - * Returns the specification for the wrapping in the V direction. - */ -EggTexture::WrapMode TextureReference:: -get_wrap_v() const { - return _wrap_v; -} - -/** - * Returns true if all essential properties of this TextureReference are the - * same as that of the other, or false if any of them differ. This is useful - * when reading a new egg file and comparing its references to its previously- - * defined references. - */ -bool TextureReference:: -is_equivalent(const TextureReference &other) const { - if (_source_texture != other._source_texture) { - return false; - } - if (!_properties.egg_properties_match(other._properties)) { - return false; - } - if (_uses_alpha != other._uses_alpha) { - return false; - } - if (_any_uvs != other._any_uvs) { - return false; - } - if (_wrap_u != other._wrap_u || - _wrap_v != other._wrap_v) { - return false; - } - if (_any_uvs) { - if (!_min_uv.almost_equal(other._min_uv, 0.00001)) { - return false; - } - if (!_max_uv.almost_equal(other._max_uv, 0.00001)) { - return false; - } - } - if (!_tex_mat.almost_equal(other._tex_mat, 0.00001)) { - return false; - } - - return true; -} - -/** - * Sets the particular TexturePlacement that is appropriate for this egg file. - * This is called by EggFile::choose_placements(). - */ -void TextureReference:: -set_placement(TexturePlacement *placement) { - if (_placement != placement) { - if (_placement != nullptr) { - // Remove our reference from the old placement object. - _placement->remove_egg(this); - } - _placement = placement; - if (_placement != nullptr) { - // Add our reference to the new placement object. - _placement->add_egg(this); - } - } -} - -/** - * Removes any reference to a TexturePlacement. - */ -void TextureReference:: -clear_placement() { - set_placement(nullptr); -} - -/** - * Returns the particular TexturePlacement that is appropriate for this egg - * file. This will not be filled in until EggFile::choose_placements() has - * been called. - */ -TexturePlacement *TextureReference:: -get_placement() const { - return _placement; -} - -/** - * Marks the egg file that shares this reference as stale. - */ -void TextureReference:: -mark_egg_stale() { - if (_egg_file != nullptr) { - _egg_file->mark_stale(); - } -} - -/** - * Updates the egg file with all the relevant information to reference the - * texture in its new home, wherever that might be. - */ -void TextureReference:: -update_egg() { - if (_egg_tex == nullptr) { - // Not much we can do if we don't have an actual egg file to reference. - return; - } - - if (_placement == nullptr) { - // Nor if we don't have an actual placement yet. This is possible if the - // egg was assigned to the "null" group, and the texture hasn't been re- - // assigned yet. - return; - } - - TextureImage *texture = get_texture(); - if (texture != nullptr) { - // Make sure the alpha mode is set according to what the texture image - // wants. - if (texture->has_num_channels() && - !_egg_tex->has_alpha_channel(texture->get_num_channels())) { - // The egg file doesn't want to use the alpha on the texture; leave it - // unspecified so the egg loader can figure out whether to enable alpha - // or not based on the object color. - _egg_tex->set_alpha_mode(EggRenderMode::AM_unspecified); - - } else { - // The egg file does want alpha, so get the alpha mode from the texture. - EggRenderMode::AlphaMode am = texture->get_alpha_mode(); - if (am != EggRenderMode::AM_unspecified) { - _egg_tex->set_alpha_mode(am); - } - } - - // Also make sure the wrap mode is set properly. - if (texture->get_txa_wrap_u() != EggTexture::WM_unspecified) { - _egg_tex->set_wrap_u(texture->get_txa_wrap_u()); - } - if (texture->get_txa_wrap_v() != EggTexture::WM_unspecified) { - _egg_tex->set_wrap_v(texture->get_txa_wrap_v()); - } - } - - // We check for an OmitReason of OR_none, rather than asking is_placed(), - // because in this case we don't want to consider an OR_solitary texture as - // having been placed. - if (_placement->get_omit_reason() == OR_unknown) { - // The texture doesn't even exist. We can't update the egg to point to - // any meaningful path; just leave it pointing to the source texture's - // basename. Maybe it will be found along the texture path later. - Filename orig_filename = _egg_tex->get_filename(); - texture->update_egg_tex(_egg_tex); - _egg_tex->set_filename(orig_filename.get_basename()); - return; - } - if (_placement->get_omit_reason() != OR_none) { - // The texture exists but is not on a palette. This is the easy case; we - // simply have to update the texture reference to the new texture - // location. - DestTextureImage *dest = _placement->get_dest(); - nassertv(dest != nullptr); - dest->update_egg_tex(_egg_tex); - return; - } - - // The texture *does* appear on a palette. This means we need to not only - // update the texture reference, but also adjust the UV's. In most cases, - // we can do this by simply applying a texture matrix to the reference. - PaletteImage *image = _placement->get_image(); - nassertv(image != nullptr); - - image->update_egg_tex(_egg_tex); - - // Palette images never wrap, so the wrap mode doesn't matter. We let this - // default to unspecified, which means the images will wrap by default, - // which is the fastest mode for tinydisplay anyway. - _egg_tex->set_wrap_mode(EggTexture::WM_unspecified); - _egg_tex->set_wrap_u(EggTexture::WM_unspecified); - _egg_tex->set_wrap_v(EggTexture::WM_unspecified); - - LMatrix3d new_tex_mat; - _placement->compute_tex_matrix(new_tex_mat); - - // Compose the new texture matrix with whatever matrix was already there, if - // any. - _egg_tex->set_transform2d(_tex_mat * new_tex_mat); - - // Finally, go back and actually adjust the UV's to match what we claimed - // they could be. - if (_egg_tex->get_tex_gen() == EggTexture::TG_unspecified) { - update_uv_range(_egg_data, pal->_remap_uv); - } -} - -/** - * Applies the texture properties as read from the egg file to the source - * image's properties. This updates the source image with the now-known - * properties indicated with in the tref block of the egg file. - */ -void TextureReference:: -apply_properties_to_source() { - nassertv(_source_texture != nullptr); - _source_texture->update_properties(_properties); -} - -/** - * - */ -void TextureReference:: -output(std::ostream &out) const { - out << *_source_texture; -} - -/** - * - */ -void TextureReference:: -write(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << get_texture()->get_name(); - - if (_uses_alpha) { - out << " (uses alpha)"; - } - - if (_any_uvs) { - // Compute the fraction of the image that is covered by the UV's minmax - // rectangle. - LTexCoordd box = _max_uv - _min_uv; - double area = box[0] * box[1]; - - out << " coverage " << area; - } - - if (_wrap_u != EggTexture::WM_unspecified || - _wrap_v != EggTexture::WM_unspecified) { - if (_wrap_u != _wrap_v) { - out << " (" << _wrap_u << ", " << _wrap_v << ")"; - } else { - out << " " << _wrap_u; - } - } - - if (_properties._format != EggTexture::F_unspecified) { - out << " " << _properties._format; - } - - switch (_properties._minfilter) { - case EggTexture::FT_nearest_mipmap_nearest: - case EggTexture::FT_linear_mipmap_nearest: - case EggTexture::FT_nearest_mipmap_linear: - case EggTexture::FT_linear_mipmap_linear: - out << " mipmap"; - break; - - default: - break; - } - - if(_properties._anisotropic_degree>1) { - out << " aniso " << _properties._anisotropic_degree; - } - - out << "\n"; -} - - -/** - * Checks the geometry in the egg file to see what range of UV's are requested - * for this particular texture reference. - * - * If pal->_remap_uv is not RU_never, this will also attempt to remap the UV's - * found so that the midpoint lies in the unit square (0,0) - (1,1), in the - * hopes of maximizing overlap of UV coordinates between different polygons. - * However, the hypothetical translations are not actually applied to the egg - * file at this point (because we might decide not to place the texture in a - * palette); they will actually be applied when update_uv_range(), below, is - * called later. - * - * The return value is true if the search should continue, or false if it - * should abort prematurely. - */ -bool TextureReference:: -get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { - if (group->is_of_type(EggGroup::get_class_type())) { - EggGroup *egg_group; - DCAST_INTO_R(egg_group, group, false); - - if (egg_group->get_dart_type() != EggGroup::DT_none) { - // If it's a character, we might change the kind of remapping we do. - remap = pal->_remap_char_uv; - } - } - - bool group_any_uvs = false; - LTexCoordd group_min_uv, group_max_uv; - - EggGroupNode::iterator ci; - for (ci = group->begin(); ci != group->end(); ci++) { - EggNode *child = (*ci); - if (child->is_of_type(EggNurbsSurface::get_class_type())) { - EggNurbsSurface *nurbs = DCAST(EggNurbsSurface, child); - if (nurbs->has_texture(_egg_tex)) { - // Here's a NURBS surface that references the texture. Unlike other - // kinds of geometries, NURBS don't store UV's; they're implicit in - // the surface. NURBS UV's will always run in the range (0, 0) - (1, - // 1). However, we do need to apply the texture matrix. - - // We also don't count the NURBS surfaces in with the group's UV's, - // because we can't adjust the UV's on a NURBS, so counting them up - // would be misleading (the reason we count up the group UV's is so we - // can consider adjusting them later). Instead, we just accumulate - // the NURBS UV's directly into our total. - collect_nominal_uv_range(); - } - - } else if (child->is_of_type(EggPrimitive::get_class_type())) { - EggPrimitive *geom = DCAST(EggPrimitive, child); - if (geom->has_texture(_egg_tex)) { - // Here's a piece of geometry that references this texture. Walk - // through its vertices and get its UV's. - - if (_egg_tex->get_tex_gen() != EggTexture::TG_unspecified) { - // If the texture has a TexGen mode, we don't check the UV range on - // the model, since that doesn't matter. Instead, we assume the - // texture is used in the range (0, 0) - (1, 1), which will be true - // for a sphere map, although the effective range is a little less - // clear for the TG_world_position and similar modes. - collect_nominal_uv_range(); - - // In fact, now we can return, having found at least one model that - // references the texture; there's no need to search further. - return false; - - } else { - LTexCoordd geom_min_uv, geom_max_uv; - - if (get_geom_uvs(geom, geom_min_uv, geom_max_uv)) { - if (remap == Palettizer::RU_poly) { - LVector2d trans = translate_uv(geom_min_uv, geom_max_uv); - geom_min_uv += trans; - geom_max_uv += trans; - } - collect_uv(group_any_uvs, group_min_uv, group_max_uv, - geom_min_uv, geom_max_uv); - } - } - } - - } else if (child->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *cg = DCAST(EggGroupNode, child); - if (!get_uv_range(cg, remap)) { - return false; - } - } - } - - if (group_any_uvs) { - if (remap == Palettizer::RU_group) { - LVector2d trans = translate_uv(group_min_uv, group_max_uv); - group_min_uv += trans; - group_max_uv += trans; - } - collect_uv(_any_uvs, _min_uv, _max_uv, group_min_uv, group_max_uv); - } - - return true; -} - -/** - * Actually applies the UV translates that were assumed in the previous call - * to get_uv_range(). - */ -void TextureReference:: -update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap) { - if (group->is_of_type(EggGroup::get_class_type())) { - EggGroup *egg_group; - DCAST_INTO_V(egg_group, group); - - if (egg_group->get_dart_type() != EggGroup::DT_none) { - // If it's a character, we might change the kind of remapping we do. - remap = pal->_remap_char_uv; - } - } - - bool group_any_uvs = false; - LTexCoordd group_min_uv, group_max_uv; - - EggGroupNode::iterator ci; - for (ci = group->begin(); ci != group->end(); ci++) { - EggNode *child = (*ci); - if (child->is_of_type(EggNurbsSurface::get_class_type())) { - // We do nothing at this point for a Nurbs. Nothing we can do about - // these things. - - } else if (child->is_of_type(EggPrimitive::get_class_type())) { - if (remap != Palettizer::RU_never) { - EggPrimitive *geom = DCAST(EggPrimitive, child); - if (geom->has_texture(_egg_tex)) { - LTexCoordd geom_min_uv, geom_max_uv; - - if (get_geom_uvs(geom, geom_min_uv, geom_max_uv)) { - if (remap == Palettizer::RU_poly) { - LVector2d trans = translate_uv(geom_min_uv, geom_max_uv); - trans = trans * _inv_tex_mat; - if (!trans.almost_equal(LVector2d::zero())) { - translate_geom_uvs(geom, trans); - } - } else { - collect_uv(group_any_uvs, group_min_uv, group_max_uv, - geom_min_uv, geom_max_uv); - } - } - } - } - - } else if (child->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *cg = DCAST(EggGroupNode, child); - update_uv_range(cg, remap); - } - } - - if (group_any_uvs && remap == Palettizer::RU_group) { - LVector2d trans = translate_uv(group_min_uv, group_max_uv); - trans = trans * _inv_tex_mat; - if (!trans.almost_equal(LVector2d::zero())) { - for (ci = group->begin(); ci != group->end(); ci++) { - EggNode *child = (*ci); - if (child->is_of_type(EggPrimitive::get_class_type())) { - EggPrimitive *geom = DCAST(EggPrimitive, child); - if (geom->has_texture(_egg_tex)) { - translate_geom_uvs(geom, trans); - } - } - } - } - } -} - -/** - * Determines the minimum and maximum UV range for a particular primitive. - * Returns true if it has any UV's, false otherwise. - */ -bool TextureReference:: -get_geom_uvs(EggPrimitive *geom, - LTexCoordd &geom_min_uv, LTexCoordd &geom_max_uv) { - string uv_name = _egg_tex->get_uv_name(); - bool geom_any_uvs = false; - - EggPrimitive::iterator pi; - for (pi = geom->begin(); pi != geom->end(); ++pi) { - EggVertex *vtx = (*pi); - if (vtx->has_uv(uv_name)) { - LTexCoordd uv = vtx->get_uv(uv_name) * _tex_mat; - collect_uv(geom_any_uvs, geom_min_uv, geom_max_uv, uv, uv); - } - } - - return geom_any_uvs; -} - -/** - * Applies the indicated translation to each UV in the primitive. - */ -void TextureReference:: -translate_geom_uvs(EggPrimitive *geom, const LTexCoordd &trans) const { - string uv_name = _egg_tex->get_uv_name(); - - EggPrimitive::iterator pi; - for (pi = geom->begin(); pi != geom->end(); ++pi) { - EggVertex *vtx = (*pi); - if (vtx->has_uv(uv_name)) { - EggVertex vtx_copy(*vtx); - vtx_copy.set_uv(uv_name, vtx_copy.get_uv(uv_name) + trans); - EggVertex *new_vtx = vtx->get_pool()->create_unique_vertex(vtx_copy); - - if (new_vtx->gref_size() != vtx->gref_size()) { - new_vtx->copy_grefs_from(*vtx); - } - - geom->replace(pi, new_vtx); - } - } -} - -/** - * Updates _any_uvs, _min_uv, and _max_uv with the range (0, 0) - (1, 1), - * adjusted by the texture matrix. - */ -void TextureReference:: -collect_nominal_uv_range() { - static const int num_nurbs_uvs = 4; - static LTexCoordd nurbs_uvs[num_nurbs_uvs] = { - LTexCoordd(0.0, 0.0), - LTexCoordd(0.0, 1.0), - LTexCoordd(1.0, 1.0), - LTexCoordd(1.0, 0.0) - }; - - for (int i = 0; i < num_nurbs_uvs; i++) { - LTexCoordd uv = nurbs_uvs[i] * _tex_mat; - collect_uv(_any_uvs, _min_uv, _max_uv, uv, uv); - } -} - -/** - * Updates any_uvs, min_uv, and max_uv with the indicated min and max UV's - * already determined. - */ -void TextureReference:: -collect_uv(bool &any_uvs, LTexCoordd &min_uv, LTexCoordd &max_uv, - const LTexCoordd &got_min_uv, const LTexCoordd &got_max_uv) { - if (any_uvs) { - min_uv.set(min(min_uv[0], got_min_uv[0]), - min(min_uv[1], got_min_uv[1])); - max_uv.set(max(max_uv[0], got_max_uv[0]), - max(max_uv[1], got_max_uv[1])); - } else { - // The first UV. - min_uv = got_min_uv; - max_uv = got_max_uv; - any_uvs = true; - } -} - -/** - * Returns the needed adjustment to translate the given bounding box so that - * its center lies in the unit square (0,0) - (1,1). - */ -LVector2d TextureReference:: -translate_uv(const LTexCoordd &min_uv, const LTexCoordd &max_uv) { - LTexCoordd center = (min_uv + max_uv) / 2; - return LVector2d(-floor(center[0]), -floor(center[1])); -} - -/** - * Registers the current object as something that can be read from a Bam file. - */ -void TextureReference:: -register_with_read_factory() { - BamReader::get_factory()-> - register_factory(get_class_type(), make_from_bam); -} - -/** - * Fills the indicated datagram up with a binary representation of the current - * object, in preparation for writing to a Bam file. - */ -void TextureReference:: -write_datagram(BamWriter *writer, Datagram &datagram) { - TypedWritable::write_datagram(writer, datagram); - writer->write_pointer(datagram, _egg_file); - - // We don't write _egg_tex or _egg_data; that's specific to the session. - - datagram.add_string(_tref_name); - - _tex_mat.write_datagram(datagram); - _inv_tex_mat.write_datagram(datagram); - - writer->write_pointer(datagram, _source_texture); - writer->write_pointer(datagram, _placement); - - datagram.add_bool(_uses_alpha); - datagram.add_bool(_any_uvs); - datagram.add_float64(_min_uv[0]); - datagram.add_float64(_min_uv[1]); - datagram.add_float64(_max_uv[0]); - datagram.add_float64(_max_uv[1]); - datagram.add_int32((int)_wrap_u); - datagram.add_int32((int)_wrap_v); - _properties.write_datagram(writer, datagram); -} - -/** - * Called after the object is otherwise completely read from a Bam file, this - * function's job is to store the pointers that were retrieved from the Bam - * file for each pointer object written. The return value is the number of - * pointers processed from the list. - */ -int TextureReference:: -complete_pointers(TypedWritable **p_list, BamReader *manager) { - int pi = TypedWritable::complete_pointers(p_list, manager); - - if (p_list[pi] != nullptr) { - DCAST_INTO_R(_egg_file, p_list[pi], pi); - } - pi++; - - if (p_list[pi] != nullptr) { - DCAST_INTO_R(_source_texture, p_list[pi], pi); - } - pi++; - - if (p_list[pi] != nullptr) { - DCAST_INTO_R(_placement, p_list[pi], pi); - } - pi++; - - pi += _properties.complete_pointers(p_list + pi, manager); - - return pi; -} - -/** - * This method is called by the BamReader when an object of this type is - * encountered in a Bam file; it should allocate and return a new object with - * all the data read. - */ -TypedWritable *TextureReference:: -make_from_bam(const FactoryParams ¶ms) { - TextureReference *me = new TextureReference; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - me->fillin(scan, manager); - return me; -} - -/** - * Reads the binary data from the given datagram iterator, which was written - * by a previous call to write_datagram(). - */ -void TextureReference:: -fillin(DatagramIterator &scan, BamReader *manager) { - TypedWritable::fillin(scan, manager); - manager->read_pointer(scan); // _egg_file - - if (Palettizer::_read_pi_version >= 11) { - _tref_name = scan.get_string(); - } - - _tex_mat.read_datagram(scan); - _inv_tex_mat.read_datagram(scan); - - manager->read_pointer(scan); // _source_texture - manager->read_pointer(scan); // _placement - - _uses_alpha = scan.get_bool(); - _any_uvs = scan.get_bool(); - _min_uv[0] = scan.get_float64(); - _min_uv[1] = scan.get_float64(); - _max_uv[0] = scan.get_float64(); - _max_uv[1] = scan.get_float64(); - _wrap_u = (EggTexture::WrapMode)scan.get_int32(); - _wrap_v = (EggTexture::WrapMode)scan.get_int32(); - _properties.fillin(scan, manager); -} diff --git a/pandatool/src/palettizer/textureReference.h b/pandatool/src/palettizer/textureReference.h deleted file mode 100644 index 720994c9..00000000 --- a/pandatool/src/palettizer/textureReference.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureReference.h - * @author drose - * @date 2000-11-28 - */ - -#ifndef TEXTUREREFERENCE_H -#define TEXTUREREFERENCE_H - -#include "pandatoolbase.h" - -#include "textureProperties.h" -#include "palettizer.h" - -#include "luse.h" -#include "typedWritable.h" - -class TextureImage; -class SourceTextureImage; -class Filename; -class EggFile; -class EggData; -class EggTexture; -class EggGroupNode; -class EggPrimitive; -class TexturePlacement; - -/** - * This is the particular reference of a texture filename by an egg file. It - * also includes information about the way in which the egg file uses the - * texture; e.g. does it repeat. - */ -class TextureReference : public TypedWritable { -public: - TextureReference(); - ~TextureReference(); - - void from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex); - void from_egg_quick(const TextureReference &other); - void release_egg_data(); - void rebind_egg_data(EggData *data, EggTexture *egg_tex); - - EggFile *get_egg_file() const; - SourceTextureImage *get_source() const; - TextureImage *get_texture() const; - const std::string &get_tref_name() const; - - bool operator < (const TextureReference &other) const; - - bool has_uvs() const; - const LTexCoordd &get_min_uv() const; - const LTexCoordd &get_max_uv() const; - - EggTexture::WrapMode get_wrap_u() const; - EggTexture::WrapMode get_wrap_v() const; - - bool is_equivalent(const TextureReference &other) const; - - void set_placement(TexturePlacement *placement); - void clear_placement(); - TexturePlacement *get_placement() const; - - void mark_egg_stale(); - void update_egg(); - void apply_properties_to_source(); - - void output(std::ostream &out) const; - void write(std::ostream &out, int indent_level = 0) const; - - -private: - bool get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap); - void update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap); - - bool get_geom_uvs(EggPrimitive *geom, - LTexCoordd &geom_min_uv, LTexCoordd &geom_max_uv); - void translate_geom_uvs(EggPrimitive *geom, const LTexCoordd &trans) const; - void collect_nominal_uv_range(); - static void collect_uv(bool &any_uvs, LTexCoordd &min_uv, LTexCoordd &max_uv, - const LTexCoordd &got_min_uv, - const LTexCoordd &got_max_uv); - static LVector2d translate_uv(const LTexCoordd &min_uv, - const LTexCoordd &max_uv); - - EggFile *_egg_file; - EggTexture *_egg_tex; - EggData *_egg_data; - - std::string _tref_name; - LMatrix3d _tex_mat, _inv_tex_mat; - SourceTextureImage *_source_texture; - TexturePlacement *_placement; - - bool _uses_alpha; - - bool _any_uvs; - LTexCoordd _min_uv, _max_uv; - EggTexture::WrapMode _wrap_u, _wrap_v; - - TextureProperties _properties; - - // The TypedWritable interface follows. -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *writer, Datagram &datagram); - virtual int complete_pointers(TypedWritable **p_list, - BamReader *manager); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWritable::init_type(); - register_type(_type_handle, "TextureReference", - TypedWritable::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - -private: - static TypeHandle _type_handle; -}; - -INLINE std::ostream & -operator << (std::ostream &out, const TextureReference &ref) { - ref.output(out); - return out; -} - -#endif diff --git a/pandatool/src/palettizer/textureRequest.cxx b/pandatool/src/palettizer/textureRequest.cxx deleted file mode 100644 index 775c5bb5..00000000 --- a/pandatool/src/palettizer/textureRequest.cxx +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureRequest.cxx - * @author drose - * @date 2000-11-30 - */ - -#include "textureRequest.h" -#include "palettizer.h" - -/** - * - */ -TextureRequest:: -TextureRequest() { - _got_size = false; - _got_num_channels = false; - _srgb = false; - _x_size = 0; - _y_size = 0; - _num_channels = 0; - _format = EggTexture::F_unspecified; - _force_format = false; - _generic_format = false; - _keep_format = false; - _minfilter = EggTexture::FT_unspecified; - _magfilter = EggTexture::FT_unspecified; - _anisotropic_degree = 0; - _alpha_mode = EggRenderMode::AM_unspecified; - _wrap_u = EggTexture::WM_unspecified; - _wrap_v = EggTexture::WM_unspecified; - _omit = false; - _margin = 0; - _coverage_threshold = 0.0; -} - -/** - * Sets some state up that must be set prior to reading the .txa file. - */ -void TextureRequest:: -pre_txa_file() { - _margin = pal->_margin; - _coverage_threshold = pal->_coverage_threshold; -} diff --git a/pandatool/src/palettizer/textureRequest.h b/pandatool/src/palettizer/textureRequest.h deleted file mode 100644 index 54162283..00000000 --- a/pandatool/src/palettizer/textureRequest.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textureRequest.h - * @author drose - * @date 2000-11-29 - */ - -#ifndef TEXTUREREQUEST_H -#define TEXTUREREQUEST_H - -#include "pandatoolbase.h" - -#include "textureProperties.h" - -#include "eggTexture.h" -#include "eggRenderMode.h" - -/** - * These are the things that a user might explicitly request to adjust on a - * texture via a line in the .txa file. - */ -class TextureRequest { -public: - TextureRequest(); - void pre_txa_file(); - - TextureProperties _properties; - - bool _got_size; - bool _got_num_channels; - int _x_size; - int _y_size; - int _num_channels; - EggTexture::Format _format; - bool _force_format; - bool _generic_format; - bool _keep_format; - bool _srgb; - EggTexture::FilterType _minfilter; - EggTexture::FilterType _magfilter; - int _anisotropic_degree; - EggRenderMode::AlphaMode _alpha_mode; - EggTexture::WrapMode _wrap_u, _wrap_v; - bool _omit; - int _margin; - double _coverage_threshold; -}; - -#endif diff --git a/pandatool/src/palettizer/txaFile.cxx b/pandatool/src/palettizer/txaFile.cxx deleted file mode 100644 index cb4cb533..00000000 --- a/pandatool/src/palettizer/txaFile.cxx +++ /dev/null @@ -1,598 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file txaFile.cxx - * @author drose - * @date 2000-11-30 - */ - -#include "txaFile.h" -#include "pal_string_utils.h" -#include "palettizer.h" -#include "paletteGroup.h" -#include "textureImage.h" - -#include "pnotify.h" -#include "pnmFileTypeRegistry.h" - -using std::string; - -/** - * - */ -TxaFile:: -TxaFile() { -} - -/** - * Reads the indicated stream, and returns true if successful, or false if - * there is an error. - */ -bool TxaFile:: -read(std::istream &in, const string &filename) { - string line; - int line_number = 1; - - int ch = get_line_or_semicolon(in, line); - while (ch != EOF || !line.empty()) { - bool okflag = true; - - // Strip off the comment. - size_t hash = line.find('#'); - if (hash != string::npos) { - line = line.substr(0, hash); - } - line = trim_left(line); - if (line.empty()) { - // Empty lines are ignored. - - } else if (line[0] == ':') { - // This is a keyword line. - vector_string words; - extract_words(line, words); - if (words[0] == ":group") { - okflag = parse_group_line(words); - - } else if (words[0] == ":palette") { - okflag = parse_palette_line(words); - - } else if (words[0] == ":margin") { - okflag = parse_margin_line(words); - - } else if (words[0] == ":background") { - okflag = parse_background_line(words); - - } else if (words[0] == ":coverage") { - okflag = parse_coverage_line(words); - - } else if (words[0] == ":powertwo") { - okflag = parse_powertwo_line(words); - - } else if (words[0] == ":imagetype") { - okflag = parse_imagetype_line(words); - - } else if (words[0] == ":shadowtype") { - okflag = parse_shadowtype_line(words); - - } else if (words[0] == ":round") { - okflag = parse_round_line(words); - - } else if (words[0] == ":remap") { - okflag = parse_remap_line(words); - - } else if (words[0] == ":cutout") { - okflag = parse_cutout_line(words); - - } else if (words[0] == ":textureswap") { - okflag = parse_textureswap_line(words); - - } else { - nout << "Invalid keyword " << words[0] << "\n"; - okflag = false; - } - - } else { - _lines.push_back(TxaLine()); - TxaLine &txa_line = _lines.back(); - - okflag = txa_line.parse(line); - } - - if (!okflag) { - nout << "Error on line " << line_number << " of " << filename << "\n"; - return false; - } - if (ch == '\n') { - line_number++; - } - ch = get_line_or_semicolon(in, line); - } - - if (!in.eof()) { - nout << "I/O error reading " << filename << "\n"; - return false; - } - - return true; -} - -/** - * Searches for a matching line in the .txa file for the given egg file and - * applies its specifications. If a match is found, returns true; otherwise, - * returns false. Also returns false if all the matching lines for the egg - * file include the keyword "cont". - */ -bool TxaFile:: -match_egg(EggFile *egg_file) const { - Lines::const_iterator li; - for (li = _lines.begin(); li != _lines.end(); ++li) { - if ((*li).match_egg(egg_file)) { - return true; - } - } - - return false; -} - -/** - * Searches for a matching line in the .txa file for the given texture and - * applies its specifications. If a match is found, returns true; otherwise, - * returns false. Also returns false if all the matching lines for the - * texture include the keyword "cont". - */ -bool TxaFile:: -match_texture(TextureImage *texture) const { - Lines::const_iterator li; - for (li = _lines.begin(); li != _lines.end(); ++li) { - if ((*li).match_texture(texture)) { - return true; - } - } - - return false; -} - -/** - * Outputs a representation of the lines that were read in to the indicated - * output stream. This is primarily useful for debugging. - */ -void TxaFile:: -write(std::ostream &out) const { - Lines::const_iterator li; - for (li = _lines.begin(); li != _lines.end(); ++li) { - out << (*li) << "\n"; - } -} - -/** - * Reads the next line, or the next semicolon-delimited phrase, from the - * indicated input stream. Returns the character that marks the end of the - * line, or EOF if the end of file has been reached. - */ -int TxaFile:: -get_line_or_semicolon(std::istream &in, string &line) { - line = string(); - int ch = in.get(); - char semicolon = ';'; - - while (ch != EOF && ch != '\n' && ch != semicolon) { - if (ch == '#') { - // We don't consider a semicolon within a comment to be a line break. - semicolon = EOF; - } - line += ch; - ch = in.get(); - } - - return ch; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":group" and - * indicates the relationships between one or more groups. - */ -bool TxaFile:: -parse_group_line(const vector_string &words) { - vector_string::const_iterator wi; - wi = words.begin(); - assert (wi != words.end()); - ++wi; - - const string &group_name = (*wi); - PaletteGroup *group = pal->get_palette_group(group_name); - ++wi; - - enum State { - S_none, - S_on, - S_includes, - S_dir, - S_margin, - }; - State state = S_none; - - bool first_on = true; - - while (wi != words.end()) { - const string &word = (*wi); - if (word == "with") { - // Deprecated keyword: "with" means the same thing as "on". - state = S_on; - - } else if (word == "on") { - state = S_on; - - } else if (word == "includes") { - state = S_includes; - - } else if (word == "dir") { - state = S_dir; - - } else if (word == "margin") { - state = S_margin; - - } else { - switch (state) { - case S_none: - nout << "Invalid keyword: " << word << "\n"; - return false; - - case S_on: - { - PaletteGroup *on_group = pal->get_palette_group(word); - if (first_on) { - if (!group->has_dirname() && on_group->has_dirname()) { - group->set_dirname(on_group->get_dirname()); - } - first_on = false; - } - group->group_with(on_group); - } - break; - - case S_includes: - pal->get_palette_group(word)->group_with(group); - break; - - case S_dir: - group->set_dirname(word); - state = S_none; - break; - - case S_margin: - int margin_override; - if (string_to_int(word, margin_override)) { - group->set_margin_override(margin_override); - } - state = S_none; - break; - } - - } - - ++wi; - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":palette" and - * indicates the appropriate size for the palette images. - */ -bool TxaFile:: -parse_palette_line(const vector_string &words) { - if (words.size() != 3) { - nout << "Exactly two parameters required for :palette, the x and y " - << "size of the palette images to generate.\n"; - return false; - } - - if (!string_to_int(words[1], pal->_pal_x_size) || - !string_to_int(words[2], pal->_pal_y_size)) { - nout << "Invalid palette size: " << words[1] << " " << words[2] << "\n"; - return false; - } - - if (pal->_pal_x_size <= 0 || pal->_pal_y_size <= 0) { - nout << "Invalid palette size: " << pal->_pal_x_size - << " " << pal->_pal_y_size << "\n"; - return false; - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":margin" and - * indicates the default margin size. - */ -bool TxaFile:: -parse_margin_line(const vector_string &words) { - if (words.size() != 2) { - nout << "Exactly one parameter required for :margin, the " - << "size of the default margin to apply.\n"; - return false; - } - - if (!string_to_int(words[1], pal->_margin)) { - nout << "Invalid margin: " << words[1] << "\n"; - return false; - } - - if (pal->_margin < 0) { - nout << "Invalid margin: " << pal->_margin << "\n"; - return false; - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":background" - * and indicates the palette background color. - */ -bool TxaFile:: -parse_background_line(const vector_string &words) { - if (words.size() != 5) { - nout << "Exactly four parameter required for :background: the " - << "four [r g b a] components of the background color.\n"; - return false; - } - - if (!string_to_double(words[1], pal->_background[0]) || - !string_to_double(words[2], pal->_background[1]) || - !string_to_double(words[3], pal->_background[2]) || - !string_to_double(words[4], pal->_background[3])) { - nout << "Invalid color: " - << words[1] << " " << words[2] << " " - << words[3] << " " << words[4] << " " << "\n"; - return false; - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":coverage" - * and indicates the default coverage threshold. - */ -bool TxaFile:: -parse_coverage_line(const vector_string &words) { - if (words.size() != 2) { - nout << "Exactly one parameter required for :coverage, the " - << "value for the default coverage threshold.\n"; - return false; - } - - - if (!string_to_double(words[1], pal->_coverage_threshold)) { - nout << "Invalid coverage threshold: " << words[1] << "\n"; - return false; - } - - if (pal->_coverage_threshold <= 0.0) { - nout << "Invalid coverage threshold: " << pal->_coverage_threshold << "\n"; - return false; - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":powertwo" - * and indicates whether textures should by default be forced to a power of - * two. - */ -bool TxaFile:: -parse_powertwo_line(const vector_string &words) { - if (words.size() != 2) { - nout << "Exactly one parameter required for :powertwo, either a 0 " - << "or a 1.\n"; - return false; - } - - int flag; - if (!string_to_int(words[1], flag)) { - nout << "Invalid powertwo flag: " << words[1] << "\n"; - return false; - } - - if (flag != 0 && flag != 1) { - nout << "Invalid powertwo flag: " << flag << "\n"; - return false; - } - - pal->_force_power_2 = (flag != 0); - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":imagetype" - * and indicates the default image file type to convert palettes and textures - * to. - */ -bool TxaFile:: -parse_imagetype_line(const vector_string &words) { - if (words.size() != 2) { - nout << "Exactly one parameter required for :imagetype.\n"; - return false; - } - const string &imagetype = words[1]; - if (!parse_image_type_request(imagetype, pal->_color_type, pal->_alpha_type)) { - nout << "\nKnown image types are:\n"; - PNMFileTypeRegistry::get_global_ptr()->write(nout, 2); - nout << "\n"; - return false; - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":shadowtype" - * and indicates the image file type to convert working copies of the palette - * images to. - */ -bool TxaFile:: -parse_shadowtype_line(const vector_string &words) { - if (words.size() != 2) { - nout << "Exactly one parameter required for :shadowtype.\n"; - return false; - } - const string &shadowtype = words[1]; - if (!parse_image_type_request(shadowtype, pal->_shadow_color_type, - pal->_shadow_alpha_type)) { - nout << "\nKnown image types are:\n"; - PNMFileTypeRegistry::get_global_ptr()->write(nout, 2); - nout << "\n"; - return false; - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":round" and - * indicates how or whether to round up UV minmax boxes. - */ -bool TxaFile:: -parse_round_line(const vector_string &words) { - if (words.size() == 2) { - if (words[1] == "no") { - pal->_round_uvs = false; - return true; - } else { - nout << "Invalid round keyword: " << words[1] << ".\n" - << "Expected 'no', or a round fraction and fuzz factor.\n"; - return false; - } - } - - if (words.size() != 3) { - nout << "Exactly two parameters required for :round, the fraction " - << "to round to, and the fuzz factor.\n"; - return false; - } - - if (!string_to_double(words[1], pal->_round_unit) || - !string_to_double(words[2], pal->_round_fuzz)) { - nout << "Invalid rounding: " << words[1] << " " << words[2] << "\n"; - return false; - } - - if (pal->_round_unit <= 0.0 || pal->_round_fuzz < 0.0) { - nout << "Invalid rounding: " << pal->_round_unit - << " " << pal->_round_fuzz << "\n"; - return false; - } - - pal->_round_uvs = true; - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":remap" and - * indicates how or whether to remap UV coordinates in egg files to the unit - * box. - */ -bool TxaFile:: -parse_remap_line(const vector_string &words) { - int i = 1; - while (i < (int)words.size()) { - const string &keyword = words[i]; - if (keyword == "char") { - // Defining how to remap UV's for characters. - i++; - if (i == (int)words.size()) { - nout << "Keyword expected following 'char'\n"; - return false; - } - pal->_remap_char_uv = Palettizer::string_remap(words[i]); - if (pal->_remap_char_uv == Palettizer::RU_invalid) { - nout << "Invalid remap keyword: " << words[i] << "\n"; - return false; - } - - } else { - // Defining how to remap UV's in general. - pal->_remap_uv = Palettizer::string_remap(words[i]); - if (pal->_remap_uv == Palettizer::RU_invalid) { - nout << "Invalid remap keyword: " << words[i] << "\n"; - return false; - } - - pal->_remap_char_uv = pal->_remap_uv; - } - - i++; - } - - return true; -} - - -/** - * Handles the line in a .txa file that begins with the keyword ":cutout" and - * indicates how to handle alpha-cutout textures: those textures that appear - * to be mostly solid parts and invisible parts, with a thin border of - * antialiased alpha along the boundary. - */ -bool TxaFile:: -parse_cutout_line(const vector_string &words) { - if (words.size() < 2 || words.size() > 3) { - nout << ":cutout alpha-mode [ratio]\n"; - return false; - } - - EggRenderMode::AlphaMode am = EggRenderMode::string_alpha_mode(words[1]); - if (am == EggRenderMode::AM_unspecified) { - nout << "Invalid cutout keyword: " << words[1] << "\n"; - return false; - } - pal->_cutout_mode = am; - - if (words.size() >= 3) { - if (!string_to_double(words[2], pal->_cutout_ratio)) { - nout << "Invalid cutout ratio: " << words[2] << "\n"; - } - } - - return true; -} - -/** - * Handles the line in a .txa file that begins with the keyword ":textureswap" - * and indicates the relationships between textures to be swapped. - */ -bool TxaFile:: -parse_textureswap_line(const vector_string &words) { - vector_string::const_iterator wi; - wi = words.begin(); - assert (wi != words.end()); - ++wi; - - const string &group_name = (*wi); - PaletteGroup *group = pal->get_palette_group(group_name); - ++wi; - - string sourceTextureName = (*wi); - ++wi; - - // vector_string swapTextures; copy(words.begin(), words.end(), - // swapTextures); group->add_texture_swap_info(sourceTextureName, - // swapTextures); - size_t dot = sourceTextureName.rfind('.'); - if (dot != string::npos) { - sourceTextureName = sourceTextureName.substr(0, dot); - } - group->add_texture_swap_info(sourceTextureName, words); - - return true; -} diff --git a/pandatool/src/palettizer/txaFile.h b/pandatool/src/palettizer/txaFile.h deleted file mode 100644 index 05d0a32a..00000000 --- a/pandatool/src/palettizer/txaFile.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file txaFile.h - * @author drose - * @date 2000-11-30 - */ - -#ifndef TXAFILE_H -#define TXAFILE_H - -#include "pandatoolbase.h" - -#include "txaLine.h" - -#include "filename.h" -#include "vector_string.h" - -#include "pvector.h" - -/** - * This represents the .txa file (usually textures.txa) that contains the user - * instructions for resizing, grouping, etc. the various textures. - */ -class TxaFile { -public: - TxaFile(); - - bool read(std::istream &in, const std::string &filename); - - bool match_egg(EggFile *egg_file) const; - bool match_texture(TextureImage *texture) const; - - void write(std::ostream &out) const; - -private: - static int get_line_or_semicolon(std::istream &in, std::string &line); - - bool parse_group_line(const vector_string &words); - bool parse_palette_line(const vector_string &words); - bool parse_margin_line(const vector_string &words); - bool parse_background_line(const vector_string &words); - bool parse_coverage_line(const vector_string &words); - bool parse_powertwo_line(const vector_string &words); - bool parse_imagetype_line(const vector_string &words); - bool parse_shadowtype_line(const vector_string &words); - bool parse_round_line(const vector_string &words); - bool parse_remap_line(const vector_string &words); - bool parse_cutout_line(const vector_string &words); - bool parse_textureswap_line(const vector_string &words); - - typedef pvector Lines; - Lines _lines; -}; - -#endif diff --git a/pandatool/src/palettizer/txaLine.cxx b/pandatool/src/palettizer/txaLine.cxx deleted file mode 100644 index bf3b645c..00000000 --- a/pandatool/src/palettizer/txaLine.cxx +++ /dev/null @@ -1,621 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file txaLine.cxx - * @author drose - * @date 2000-11-30 - */ - -#include "txaLine.h" -#include "pal_string_utils.h" -#include "eggFile.h" -#include "palettizer.h" -#include "textureImage.h" -#include "sourceTextureImage.h" -#include "paletteGroup.h" - -#include "pnotify.h" -#include "pnmFileType.h" - -using std::string; - -/** - * - */ -TxaLine:: -TxaLine() { - _size_type = ST_none; - _scale = 0.0; - _x_size = 0; - _y_size = 0; - _aniso_degree = 0; - _num_channels = 0; - _format = EggTexture::F_unspecified; - _force_format = false; - _generic_format = false; - _keep_format = false; - _alpha_mode = EggRenderMode::AM_unspecified; - _wrap_u = EggTexture::WM_unspecified; - _wrap_v = EggTexture::WM_unspecified; - _quality_level = EggTexture::QL_unspecified; - _got_margin = false; - _margin = 0; - _got_coverage_threshold = false; - _coverage_threshold = 0.0; - _color_type = nullptr; - _alpha_type = nullptr; -} - -/** - * Accepts a string that defines a line of the .txa file and parses it into - * its constinuent parts. Returns true if successful, false on error. - */ -bool TxaLine:: -parse(const string &line) { - size_t colon = line.find(':'); - if (colon == string::npos) { - nout << "Colon required.\n"; - return false; - } - - // Chop up the first part of the string (preceding the colon) into its - // individual words. These are patterns to match. - vector_string words; - extract_words(line.substr(0, colon), words); - - vector_string::iterator wi; - for (wi = words.begin(); wi != words.end(); ++wi) { - string word = (*wi); - - // If the pattern ends in the string ".egg", and only if it ends in this - // string, it is deemed an egg pattern and will only be tested against egg - // files. If it ends in anything else, it is deemed a texture pattern and - // will only be tested against textures. - if (word.length() > 4 && word.substr(word.length() - 4) == ".egg") { - GlobPattern pattern(word); - pattern.set_case_sensitive(false); - _egg_patterns.push_back(pattern); - - } else { - // However, the filename extension, if any, is stripped off because the - // texture key names nowadays don't include them. - size_t dot = word.rfind('.'); - if (dot != string::npos) { - word = word.substr(0, dot); - } - GlobPattern pattern(word); - pattern.set_case_sensitive(false); - _texture_patterns.push_back(pattern); - } - } - - if (_egg_patterns.empty() && _texture_patterns.empty()) { - nout << "No texture or egg filenames given.\n"; - return false; - } - - // Now chop up the rest of the string (following the colon) into its - // individual words. These are keywords and size indications. - words.clear(); - extract_words(line.substr(colon + 1), words); - - wi = words.begin(); - while (wi != words.end()) { - const string &word = *wi; - nassertr(!word.empty(), false); - - if (isdigit(word[0])) { - // This is either a new size or a scale percentage. - if (_size_type != ST_none) { - nout << "Invalid repeated size request: " << word << "\n"; - return false; - } - if (word[word.length() - 1] == '%') { - // It's a scale percentage! - _size_type = ST_scale; - - string tail; - _scale = string_to_double(word, tail); - if (!(tail == "%")) { - // This is an invalid number. - return false; - } - ++wi; - - } else { - // Collect a number of consecutive numeric fields. - pvector numbers; - while (wi != words.end() && isdigit((*wi)[0])) { - const string &word = *wi; - int num; - if (!string_to_int(word, num)) { - nout << "Invalid size: " << word << "\n"; - return false; - } - numbers.push_back(num); - ++wi; - } - if (numbers.size() < 2) { - nout << "At least two size numbers must be given, or a percent sign used to indicate scaling.\n"; - return false; - - } else if (numbers.size() == 2) { - _size_type = ST_explicit_2; - _x_size = numbers[0]; - _y_size = numbers[1]; - - } else if (numbers.size() == 3) { - _size_type = ST_explicit_3; - _x_size = numbers[0]; - _y_size = numbers[1]; - _num_channels = numbers[2]; - - } else { - nout << "Too many size numbers given.\n"; - return false; - } - } - - } else { - // The word does not begin with a digit; therefore it's either a keyword - // or an image file type request. - if (word == "omit") { - _keywords.push_back(KW_omit); - - } else if (word == "nearest") { - _keywords.push_back(KW_nearest); - - } else if (word == "linear") { - _keywords.push_back(KW_linear); - - } else if (word == "mipmap") { - _keywords.push_back(KW_mipmap); - - } else if (word == "cont") { - _keywords.push_back(KW_cont); - - } else if (word == "srgb") { - _keywords.push_back(KW_srgb); - - } else if (word == "margin") { - ++wi; - if (wi == words.end()) { - nout << "Argument required for 'margin'.\n"; - return false; - } - - const string &arg = (*wi); - if (!string_to_int(arg, _margin)) { - nout << "Not an integer: " << arg << "\n"; - return false; - } - if (_margin < 0) { - nout << "Invalid margin: " << _margin << "\n"; - return false; - } - _got_margin = true; - - } else if (word == "aniso") { - ++wi; - if (wi == words.end()) { - nout << "Integer argument required for 'aniso'.\n"; - return false; - } - - const string &arg = (*wi); - if (!string_to_int(arg, _aniso_degree)) { - nout << "Not an integer: " << arg << "\n"; - return false; - } - if ((_aniso_degree < 2) || (_aniso_degree > 16)) { - // make it an error to specific degree 0 or 1, which means no - // anisotropy so it's probably an input mistake - nout << "Invalid anistropic degree (range is 2-16): " << _aniso_degree << "\n"; - return false; - } - - _keywords.push_back(KW_anisotropic); - - } else if (word == "coverage") { - ++wi; - if (wi == words.end()) { - nout << "Argument required for 'coverage'.\n"; - return false; - } - - const string &arg = (*wi); - if (!string_to_double(arg, _coverage_threshold)) { - nout << "Not a number: " << arg << "\n"; - return false; - } - if (_coverage_threshold <= 0.0) { - nout << "Invalid coverage threshold: " << _coverage_threshold << "\n"; - return false; - } - _got_coverage_threshold = true; - - } else if (word.substr(0, 6) == "force-") { - // Force a particular format, despite the number of channels in the - // image. - string format_name = word.substr(6); - EggTexture::Format format = EggTexture::string_format(format_name); - if (format != EggTexture::F_unspecified) { - _format = format; - _force_format = true; - } else { - nout << "Unknown image format: " << format_name << "\n"; - return false; - } - - } else if (word == "generic") { - // Genericize the image format by replacing bitcount-specific formats - // with their generic equivalents, e.g. rgba8 becomes rgba. - _generic_format = true; - - } else if (word == "keep-format") { - // Keep whatever image format was specified. - _keep_format = true; - - } else { - // Maybe it's a group name. - PaletteGroup *group = pal->test_palette_group(word); - if (group != nullptr) { - _palette_groups.insert(group); - - } else { - // Maybe it's a format name. This suggests an image format, but may - // be overridden to reflect the number of channels in the image. - EggTexture::Format format = EggTexture::string_format(word); - if (format != EggTexture::F_unspecified) { - if (!_force_format) { - _format = format; - } - } else { - // Maybe it's an alpha mode. - EggRenderMode::AlphaMode am = EggRenderMode::string_alpha_mode(word); - if (am != EggRenderMode::AM_unspecified) { - _alpha_mode = am; - - } else { - // Maybe it's a quality level. - EggTexture::QualityLevel ql = EggTexture::string_quality_level(word); - if (ql != EggTexture::QL_unspecified) { - _quality_level = ql; - - } else if (word.length() > 2 && word[word.length() - 2] == '_' && - strchr("uv", word[word.length() - 1]) != nullptr) { - // It must be a wrap mode for u or v. - string prefix = word.substr(0, word.length() - 2); - EggTexture::WrapMode wm = EggTexture::string_wrap_mode(prefix); - if (wm == EggTexture::WM_unspecified) { - return false; - } - switch (word[word.length() - 1]) { - case 'u': - _wrap_u = wm; - break; - - case 'v': - _wrap_v = wm; - break; - } - - } else { - // Maybe it's an image file request. - if (!parse_image_type_request(word, _color_type, _alpha_type)) { - return false; - } - } - } - } - } - } - ++wi; - } - } - - return true; -} - -/** - * Compares the patterns on the line to the indicated EggFile. If they match, - * updates the egg with the appropriate information. Returns true if a match - * is detected and the search for another line should stop, or false if a - * match is not detected (or if the keyword "cont" is present, which means the - * search should continue regardless). - */ -bool TxaLine:: -match_egg(EggFile *egg_file) const { - string name = egg_file->get_name(); - - bool matched_any = false; - Patterns::const_iterator pi; - for (pi = _egg_patterns.begin(); - pi != _egg_patterns.end() && !matched_any; - ++pi) { - matched_any = (*pi).matches(name); - } - - if (!matched_any) { - // No match this line; continue. - return false; - } - - bool got_cont = false; - Keywords::const_iterator ki; - for (ki = _keywords.begin(); ki != _keywords.end(); ++ki) { - switch (*ki) { - case KW_omit: - break; - - case KW_nearest: - case KW_linear: - case KW_mipmap: - case KW_anisotropic: - case KW_srgb: - // These mean nothing to an egg file. - break; - - case KW_cont: - got_cont = true; - break; - } - } - - egg_file->match_txa_groups(_palette_groups); - - if (got_cont) { - // If we have the "cont" keyword, we should keep scanning for another - // line, even though we matched this one. - return false; - } - - // Otherwise, in the normal case, a match ends the search for matches. - egg_file->clear_surprise(); - - return true; -} - -/** - * Compares the patterns on the line to the indicated TextureImage. If they - * match, updates the texture with the appropriate information. Returns true - * if a match is detected and the search for another line should stop, or - * false if a match is not detected (or if the keyword "cont" is present, - * which means the search should continue regardless). - */ -bool TxaLine:: -match_texture(TextureImage *texture) const { - string name = texture->get_name(); - - bool matched_any = false; - Patterns::const_iterator pi; - for (pi = _texture_patterns.begin(); - pi != _texture_patterns.end() && !matched_any; - ++pi) { - matched_any = (*pi).matches(name); - } - - if (!matched_any) { - // No match this line; continue. - return false; - } - - SourceTextureImage *source = texture->get_preferred_source(); - TextureRequest &request = texture->_request; - - if (!request._got_size) { - switch (_size_type) { - case ST_none: - break; - - case ST_scale: - if (source != nullptr && source->get_size()) { - request._got_size = true; - request._x_size = std::max(1, (int)(source->get_x_size() * _scale / 100.0)); - request._y_size = std::max(1, (int)(source->get_y_size() * _scale / 100.0)); - } - break; - - case ST_explicit_3: - request._got_num_channels = true; - request._num_channels = _num_channels; - // fall through - - case ST_explicit_2: - request._got_size = true; - request._x_size = _x_size; - request._y_size = _y_size; - break; - } - } - - if (_got_margin) { - request._margin = _margin; - } - - if (_got_coverage_threshold) { - request._coverage_threshold = _coverage_threshold; - } - - if (_color_type != nullptr) { - request._properties._color_type = _color_type; - request._properties._alpha_type = _alpha_type; - } - - if (_quality_level != EggTexture::QL_unspecified) { - request._properties._quality_level = _quality_level; - } - - if (_format != EggTexture::F_unspecified) { - request._format = _format; - request._force_format = _force_format; - request._generic_format = false; - } - - if (_generic_format) { - request._generic_format = true; - } - - if (_keep_format) { - request._keep_format = true; - } - - if (_alpha_mode != EggRenderMode::AM_unspecified) { - request._alpha_mode = _alpha_mode; - } - - if (_wrap_u != EggTexture::WM_unspecified) { - request._wrap_u = _wrap_u; - } - if (_wrap_v != EggTexture::WM_unspecified) { - request._wrap_v = _wrap_v; - } - - bool got_cont = false; - Keywords::const_iterator ki; - for (ki = _keywords.begin(); ki != _keywords.end(); ++ki) { - switch (*ki) { - case KW_omit: - request._omit = true; - break; - - case KW_nearest: - request._minfilter = EggTexture::FT_nearest; - request._magfilter = EggTexture::FT_nearest; - break; - - case KW_linear: - request._minfilter = EggTexture::FT_linear; - request._magfilter = EggTexture::FT_linear; - break; - - case KW_mipmap: - request._minfilter = EggTexture::FT_linear_mipmap_linear; - request._magfilter = EggTexture::FT_linear; - break; - - case KW_anisotropic: - request._anisotropic_degree = _aniso_degree; - break; - - case KW_cont: - got_cont = true; - break; - - case KW_srgb: - request._srgb = true; - } - } - - texture->_explicitly_assigned_groups.make_union - (texture->_explicitly_assigned_groups, _palette_groups); - texture->_explicitly_assigned_groups.remove_null(); - - if (got_cont) { - // If we have the "cont" keyword, we should keep scanning for another - // line, even though we matched this one. - return false; - } - - // Otherwise, in the normal case, a match ends the search for matches. - texture->_is_surprise = false; - - return true; -} - -/** - * - */ -void TxaLine:: -output(std::ostream &out) const { - Patterns::const_iterator pi; - for (pi = _texture_patterns.begin(); pi != _texture_patterns.end(); ++pi) { - out << (*pi) << " "; - } - for (pi = _egg_patterns.begin(); pi != _egg_patterns.end(); ++pi) { - out << (*pi) << " "; - } - out << ":"; - - switch (_size_type) { - case ST_none: - break; - - case ST_scale: - out << " " << _scale << "%"; - break; - - case ST_explicit_2: - out << " " << _x_size << " " << _y_size; - break; - - case ST_explicit_3: - out << " " << _x_size << " " << _y_size << " " << _num_channels; - break; - } - - if (_got_margin) { - out << " margin " << _margin; - } - - if (_got_coverage_threshold) { - out << " coverage " << _coverage_threshold; - } - - Keywords::const_iterator ki; - for (ki = _keywords.begin(); ki != _keywords.end(); ++ki) { - switch (*ki) { - case KW_omit: - out << " omit"; - break; - - case KW_nearest: - out << " nearest"; - break; - - case KW_linear: - out << " linear"; - break; - - case KW_mipmap: - out << " mipmap"; - break; - - case KW_cont: - out << " cont"; - break; - - case KW_anisotropic: - out << " aniso " << _aniso_degree; - break; - - case KW_srgb: - out << " srgb"; - break; - } - } - - PaletteGroups::const_iterator gi; - for (gi = _palette_groups.begin(); gi != _palette_groups.end(); ++gi) { - out << " " << (*gi)->get_name(); - } - - if (_format != EggTexture::F_unspecified) { - out << " " << _format; - if (_force_format) { - out << " (forced)"; - } - } - - if (_color_type != nullptr) { - out << " " << _color_type->get_suggested_extension(); - if (_alpha_type != nullptr) { - out << "," << _alpha_type->get_suggested_extension(); - } - } -} diff --git a/pandatool/src/palettizer/txaLine.h b/pandatool/src/palettizer/txaLine.h deleted file mode 100644 index 8a93c45a..00000000 --- a/pandatool/src/palettizer/txaLine.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file txaLine.h - * @author drose - * @date 2000-11-30 - */ - -#ifndef TXALINE_H -#define TXALINE_H - -#include "pandatoolbase.h" - -#include "paletteGroups.h" - -#include "globPattern.h" -#include "eggTexture.h" -#include "eggRenderMode.h" - -#include "pvector.h" - -class PNMFileType; -class EggFile; -class TextureImage; - -/** - * This is a single matching line in the .txa file. It consists of a list of - * names (texture names or egg file names), followed by a colon and an - * optional size and a set of keywords. - */ -class TxaLine { -public: - TxaLine(); - - bool parse(const std::string &line); - - bool match_egg(EggFile *egg_file) const; - bool match_texture(TextureImage *texture) const; - - void output(std::ostream &out) const; - -private: - typedef pvector Patterns; - Patterns _texture_patterns; - Patterns _egg_patterns; - - enum SizeType { - ST_none, - ST_scale, - ST_explicit_2, - ST_explicit_3 - }; - - SizeType _size_type; - PN_stdfloat _scale; - int _x_size; - int _y_size; - int _num_channels; - EggTexture::Format _format; - bool _force_format; - bool _generic_format; - bool _keep_format; - EggRenderMode::AlphaMode _alpha_mode; - EggTexture::WrapMode _wrap_u, _wrap_v; - EggTexture::QualityLevel _quality_level; - - int _aniso_degree; - bool _got_margin; - int _margin; - bool _got_coverage_threshold; - double _coverage_threshold; - - enum Keyword { - KW_omit, - KW_nearest, - KW_linear, - KW_mipmap, - KW_cont, - KW_anisotropic, - KW_srgb, - }; - - typedef pvector Keywords; - Keywords _keywords; - - PaletteGroups _palette_groups; - - PNMFileType *_color_type; - PNMFileType *_alpha_type; -}; - -INLINE std::ostream &operator << (std::ostream &out, const TxaLine &line) { - line.output(out); - return out; -} - -#endif diff --git a/pandatool/src/pandatoolbase/CMakeLists.txt b/pandatool/src/pandatoolbase/CMakeLists.txt deleted file mode 100644 index 6c8165d5..00000000 --- a/pandatool/src/pandatoolbase/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -set(P3PANDATOOLBASE_HEADERS - animationConvert.h - config_pandatoolbase.h - distanceUnit.h - pandatoolbase.h pandatoolsymbols.h - pathReplace.h pathReplace.I - pathStore.h -) - -set(P3PANDATOOLBASE_SOURCES - animationConvert.cxx - config_pandatoolbase.cxx - distanceUnit.cxx - pandatoolbase.cxx - pathReplace.cxx - pathStore.cxx -) - -composite_sources(p3pandatoolbase P3PANDATOOLBASE_SOURCES) -add_library(p3pandatoolbase STATIC ${P3PANDATOOLBASE_HEADERS} ${P3PANDATOOLBASE_SOURCES}) -target_link_libraries(p3pandatoolbase panda) - -# ptloader - a module - may need to link in libraries in this package, so: -if(MODULE_TYPE STREQUAL "MODULE") - set_target_properties(p3pandatoolbase PROPERTIES - POSITION_INDEPENDENT_CODE ON - INTERFACE_POSITION_INDEPENDENT_CODE ON) -endif() - -install(TARGETS p3pandatoolbase - EXPORT ToolsDevel COMPONENT ToolsDevel - DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d - ARCHIVE COMPONENT ToolsDevel) -install(FILES ${P3PANDATOOLBASE_HEADERS} COMPONENT ToolsDevel DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d) diff --git a/pandatool/src/pandatoolbase/animationConvert.cxx b/pandatool/src/pandatoolbase/animationConvert.cxx deleted file mode 100644 index d09ce0f1..00000000 --- a/pandatool/src/pandatoolbase/animationConvert.cxx +++ /dev/null @@ -1,91 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file animationConvert.cxx - * @author drose - * @date 2003-01-21 - */ - -#include "animationConvert.h" - -#include "string_utils.h" -#include "pnotify.h" - -/** - * Returns the string corresponding to this method. - */ -std::string -format_animation_convert(AnimationConvert convert) { - switch (convert) { - case AC_invalid: - return "invalid"; - - case AC_none: - return "none"; - - case AC_pose: - return "pose"; - - case AC_flip: - return "flip"; - - case AC_strobe: - return "strobe"; - - case AC_model: - return "model"; - - case AC_chan: - return "chan"; - - case AC_both: - return "both"; - } - nout << "**unexpected AnimationConvert value: (" << (int)convert << ")**"; - return "**"; -} - -/** - * - */ -std::ostream & -operator << (std::ostream &out, AnimationConvert convert) { - return out << format_animation_convert(convert); -} - -/** - * Converts from a string, as might be input by the user, to one of the known - * AnimationConvert types. Returns AC_invalid if the string is unknown. - */ -AnimationConvert -string_animation_convert(const std::string &str) { - if (cmp_nocase(str, "none") == 0) { - return AC_none; - - } else if (cmp_nocase(str, "pose") == 0) { - return AC_pose; - - } else if (cmp_nocase(str, "flip") == 0) { - return AC_flip; - - } else if (cmp_nocase(str, "strobe") == 0) { - return AC_strobe; - - } else if (cmp_nocase(str, "model") == 0) { - return AC_model; - - } else if (cmp_nocase(str, "chan") == 0) { - return AC_chan; - - } else if (cmp_nocase(str, "both") == 0) { - return AC_both; - - } else { - return AC_invalid; - } -} diff --git a/pandatool/src/pandatoolbase/animationConvert.h b/pandatool/src/pandatoolbase/animationConvert.h deleted file mode 100644 index 2365cfff..00000000 --- a/pandatool/src/pandatoolbase/animationConvert.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file animationConvert.h - * @author drose - * @date 2003-01-21 - */ - -#ifndef ANIMATIONCONVERT_H -#define ANIMATIONCONVERT_H - -#include "pandatoolbase.h" - -/** - * This enumerated type lists the methods by which animation from an animation - * package might be represented in egg format. - */ -enum AnimationConvert { - AC_invalid, // Never use this. - AC_none, // No animation: static geometry only. - AC_pose, // Pose to one frame, then get static geometry. - AC_flip, // A flip (sequence) of static geometry models. - AC_strobe, // All frames of a flip visible at the same time. - AC_model, // A character model, with joints. - AC_chan, // Animation tables for the above model. - AC_both, // A character model and tables in the same file. -}; - -std::string format_animation_convert(AnimationConvert unit); - -std::ostream &operator << (std::ostream &out, AnimationConvert unit); -AnimationConvert string_animation_convert(const std::string &str); - -#endif diff --git a/pandatool/src/pandatoolbase/config_pandatoolbase.cxx b/pandatool/src/pandatoolbase/config_pandatoolbase.cxx deleted file mode 100644 index 65f02228..00000000 --- a/pandatool/src/pandatoolbase/config_pandatoolbase.cxx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_pandatoolbase.cxx - * @author drose - * @date 2004-11-29 - */ - -#include "config_pandatoolbase.h" - -NotifyCategoryDef(pandatoolbase, ""); - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libpandatoolbase() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; -} diff --git a/pandatool/src/pandatoolbase/config_pandatoolbase.h b/pandatool/src/pandatoolbase/config_pandatoolbase.h deleted file mode 100644 index 2bfe9c9f..00000000 --- a/pandatool/src/pandatoolbase/config_pandatoolbase.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_pandatoolbase.h - * @author drose - * @date 2004-11-29 - */ - -#ifndef CONFIG_PANDATOOLBASE_H -#define CONFIG_PANDATOOLBASE_H - -#include "pandatoolbase.h" - -#include "notifyCategoryProxy.h" - -NotifyCategoryDeclNoExport(pandatoolbase); - -extern void init_libpandatoolbase(); - -#endif diff --git a/pandatool/src/pandatoolbase/distanceUnit.cxx b/pandatool/src/pandatoolbase/distanceUnit.cxx deleted file mode 100644 index 8ee495be..00000000 --- a/pandatool/src/pandatoolbase/distanceUnit.cxx +++ /dev/null @@ -1,215 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file distanceUnit.cxx - * @author drose - * @date 2001-04-17 - */ - -#include "distanceUnit.h" -#include "config_pandatoolbase.h" -#include "string_utils.h" -#include "pnotify.h" - -using std::istream; -using std::ostream; -using std::string; - -/** - * Returns the string representing the common abbreviation for the given unit. - */ -string -format_abbrev_unit(DistanceUnit unit) { - switch (unit) { - case DU_millimeters: - return "mm"; - - case DU_centimeters: - return "cm"; - - case DU_meters: - return "m"; - - case DU_kilometers: - return "km"; - - case DU_yards: - return "yd"; - - case DU_feet: - return "ft"; - - case DU_inches: - return "in"; - - case DU_nautical_miles: - return "nmi"; - - case DU_statute_miles: - return "mi"; - - case DU_invalid: - return "invalid"; - } - nout << "**unexpected DistanceUnit value: (" << (int)unit << ")**"; - return "**"; -} - -/** - * Returns the string representing the full name (plural) for the given unit. - */ -string -format_long_unit(DistanceUnit unit) { - switch (unit) { - case DU_millimeters: - return "millimeters"; - - case DU_centimeters: - return "centimeters"; - - case DU_meters: - return "meters"; - - case DU_kilometers: - return "kilometers"; - - case DU_yards: - return "yards"; - - case DU_feet: - return "feet"; - - case DU_inches: - return "inches"; - - case DU_nautical_miles: - return "nautical miles"; - - case DU_statute_miles: - return "miles"; - - case DU_invalid: - return "invalid"; - } - nout << "**unexpected DistanceUnit value: (" << (int)unit << ")**"; - return "**"; -} - -/** - * - */ -ostream & -operator << (ostream &out, DistanceUnit unit) { - return out << format_abbrev_unit(unit); -} - -/** - * - */ -istream & -operator >> (istream &in, DistanceUnit &unit) { - string word; - in >> word; - unit = string_distance_unit(word); - if (unit == DU_invalid) { - pandatoolbase_cat->error() - << "Invalid distance unit: " << word << "\n"; - } - return in; -} - -/** - * Converts from a string, as might be input by the user, to one of the known - * DistanceUnit types. Returns DU_invalid if the string is unknown. - */ -DistanceUnit -string_distance_unit(const string &str) { - if (cmp_nocase(str, "mm") == 0 || cmp_nocase(str, "millimeters") == 0) { - return DU_millimeters; - - } else if (cmp_nocase(str, "cm") == 0 || cmp_nocase(str, "centimeters") == 0) { - return DU_centimeters; - - } else if (cmp_nocase(str, "m") == 0 || cmp_nocase(str, "meters") == 0) { - return DU_meters; - - } else if (cmp_nocase(str, "km") == 0 || cmp_nocase(str, "kilometers") == 0) { - return DU_kilometers; - - } else if (cmp_nocase(str, "yd") == 0 || cmp_nocase(str, "yards") == 0) { - return DU_yards; - - } else if (cmp_nocase(str, "ft") == 0 || cmp_nocase(str, "feet") == 0) { - return DU_feet; - - } else if (cmp_nocase(str, "in") == 0 || cmp_nocase(str, "inches") == 0) { - return DU_inches; - - } else if (cmp_nocase(str, "nmi") == 0 || - cmp_nocase(str, "nm") == 0 || - cmp_nocase_uh(str, "nautical_miles") == 0) { - return DU_nautical_miles; - - } else if (cmp_nocase(str, "mi") == 0 || - cmp_nocase(str, "miles") == 0 || - cmp_nocase_uh(str, "statute_miles") == 0) { - return DU_statute_miles; - - } else { - return DU_invalid; - } -} - -/** - * Returns the number of the indicated unit per each centimeter. This - * internal function is used to implement convert_units(), below. - */ -static double unit_scale(DistanceUnit unit) { - switch (unit) { - case DU_millimeters: - return 0.1; - - case DU_centimeters: - return 1.0; - - case DU_meters: - return 100.0; - - case DU_kilometers: - return 100000.0; - - case DU_yards: - return 3.0 * 12.0 * 2.54; - - case DU_feet: - return 12.0 * 2.54; - - case DU_inches: - return 2.54; - - case DU_nautical_miles: - // This is the U.S. definition. - return 185200.0; - - case DU_statute_miles: - return 5280.0 * 12.0 * 2.54; - - case DU_invalid: - return 1.0; - } - - return 1.0; -} - -/** - * Returns the scaling factor that must be applied to convert from units of - * "from" to "to". - */ -double convert_units(DistanceUnit from, DistanceUnit to) { - return unit_scale(from) / unit_scale(to); -} diff --git a/pandatool/src/pandatoolbase/distanceUnit.h b/pandatool/src/pandatoolbase/distanceUnit.h deleted file mode 100644 index 2030ae09..00000000 --- a/pandatool/src/pandatoolbase/distanceUnit.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file distanceUnit.h - * @author drose - * @date 2001-04-17 - */ - -#ifndef DISTANCEUNIT_H -#define DISTANCEUNIT_H - -#include "pandatoolbase.h" - -/** - * This enumerated type lists all the kinds of units we're likely to come - * across in model conversion programs. - */ -enum DistanceUnit { - DU_millimeters, - DU_centimeters, - DU_meters, - DU_kilometers, - DU_yards, - DU_feet, - DU_inches, - DU_nautical_miles, - DU_statute_miles, - DU_invalid -}; - -std::string format_abbrev_unit(DistanceUnit unit); -std::string format_long_unit(DistanceUnit unit); - -std::ostream &operator << (std::ostream &out, DistanceUnit unit); -std::istream &operator >> (std::istream &in, DistanceUnit &unit); -DistanceUnit string_distance_unit(const std::string &str); - -double convert_units(DistanceUnit from, DistanceUnit to); - -#endif diff --git a/pandatool/src/pandatoolbase/p3pandatoolbase_composite1.cxx b/pandatool/src/pandatoolbase/p3pandatoolbase_composite1.cxx deleted file mode 100644 index 56ce2f5e..00000000 --- a/pandatool/src/pandatoolbase/p3pandatoolbase_composite1.cxx +++ /dev/null @@ -1,6 +0,0 @@ -#include "config_pandatoolbase.cxx" -#include "pathStore.cxx" -#include "pathReplace.cxx" -#include "animationConvert.cxx" -#include "distanceUnit.cxx" -#include "pandatoolbase.cxx" diff --git a/pandatool/src/pandatoolbase/pandatoolbase.cxx b/pandatool/src/pandatoolbase/pandatoolbase.cxx deleted file mode 100644 index 834ec05b..00000000 --- a/pandatool/src/pandatoolbase/pandatoolbase.cxx +++ /dev/null @@ -1,14 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandatoolbase.cxx - * @author drose - * @date 2000-09-15 - */ - -#include "pandatoolbase.h" diff --git a/pandatool/src/pandatoolbase/pandatoolbase.h b/pandatool/src/pandatoolbase/pandatoolbase.h deleted file mode 100644 index 2d87f29b..00000000 --- a/pandatool/src/pandatoolbase/pandatoolbase.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandatoolbase.h - * @author drose - * @date 2000-09-12 - */ - -/* This file is included at the beginning of every header file and/or - C or C++ file. It must be compilable for C as well as C++ files, - so no C++-specific code or syntax can be put here. */ - -#ifndef PANDATOOLBASE_H -#define PANDATOOLBASE_H - -#include "pandabase.h" -#include "pandatoolsymbols.h" - -#endif diff --git a/pandatool/src/pandatoolbase/pandatoolsymbols.h b/pandatool/src/pandatoolbase/pandatoolsymbols.h deleted file mode 100644 index e2e16b8b..00000000 --- a/pandatool/src/pandatoolbase/pandatoolsymbols.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pandatoolsymbols.h - * @author drose - * @date 2001-04-26 - */ - -#ifndef PANDATOOLSYMBOLS_H -#define PANDATOOLSYMBOLS_H - -/* See dtoolsymbols.h for a rant on the purpose of this file. */ - -#ifdef BUILDING_ASSIMP - #define EXPCL_ASSIMP EXPORT_CLASS - #define EXPTP_ASSIMP EXPORT_TEMPL -#else - #define EXPCL_ASSIMP IMPORT_CLASS - #define EXPTP_ASSIMP IMPORT_TEMPL -#endif - -#ifdef BUILDING_PTLOADER - #define EXPCL_PTLOADER EXPORT_CLASS - #define EXPTP_PTLOADER EXPORT_TEMPL -#else - #define EXPCL_PTLOADER IMPORT_CLASS - #define EXPTP_PTLOADER IMPORT_TEMPL -#endif - -#endif diff --git a/pandatool/src/pandatoolbase/pathReplace.I b/pandatool/src/pandatoolbase/pathReplace.I deleted file mode 100644 index 282c37d3..00000000 --- a/pandatool/src/pandatoolbase/pathReplace.I +++ /dev/null @@ -1,147 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pathReplace.I - * @author drose - * @date 2003-02-07 - */ - -/** - * Resets the error flag to the no-error state. had_error() will return false - * until a new error is generated. - */ -INLINE void PathReplace:: -clear_error() { - _error_flag = false; -} - -/** - * Returns true if an error was detected since the last call to clear_error(), - * false otherwise. - */ -INLINE bool PathReplace:: -had_error() const { - return _error_flag; -} - -/** - * Removes all the patterns from the specification. - */ -INLINE void PathReplace:: -clear() { - clear_error(); - _entries.clear(); -} - -/** - * Adds the indicated original/replace pattern to the specification. If a - * filename is encountered whose initial prefix matches the indicated - * orig_prefix, that prefix will be replaced with replacement_prefix. - */ -INLINE void PathReplace:: -add_pattern(const std::string &orig_prefix, const std::string &replacement_prefix) { - _entries.push_back(Entry(orig_prefix, replacement_prefix)); -} - -/** - * Returns the number of original/replace patterns that have been added. - */ -INLINE int PathReplace:: -get_num_patterns() const { - return _entries.size(); -} - -/** - * Returns the original prefix associated with the nth pattern. - */ -INLINE const std::string &PathReplace:: -get_orig_prefix(int n) const { - nassertr(n >= 0 && n < (int)_entries.size(), _entries[0]._orig_prefix); - return _entries[n]._orig_prefix; -} - -/** - * Returns the replacement prefix associated with the nth pattern. - */ -INLINE const std::string &PathReplace:: -get_replacement_prefix(int n) const { - nassertr(n >= 0 && n < (int)_entries.size(), _entries[0]._replacement_prefix); - return _entries[n]._replacement_prefix; -} - -/** - * Returns true if the PathReplace object specifies no action, or false if - * convert_path() may do something. - */ -INLINE bool PathReplace:: -is_empty() const { - return (_entries.empty() && _path.is_empty() && _path_store == PS_keep); -} - -/** - * Calls match_path() followed by store_path(), to replace the initial prefix - * and then convert the file for storing, as the user indicated. - */ -INLINE Filename PathReplace:: -convert_path(const Filename &orig_filename, const DSearchPath &additional_path) { - Filename fullpath, outpath; - full_convert_path(orig_filename, additional_path, fullpath, outpath); - return outpath; -} - -/** - * - */ -INLINE PathReplace::Component:: -Component(const std::string &component) : - _orig_prefix(component), - _double_star(component == "**") -{ -} - -/** - * - */ -INLINE PathReplace::Component:: -Component(const PathReplace::Component ©) : - _orig_prefix(copy._orig_prefix), - _double_star(copy._double_star) -{ -} - -/** - * - */ -INLINE void PathReplace::Component:: -operator = (const PathReplace::Component ©) { - _orig_prefix = copy._orig_prefix; - _double_star = copy._double_star; -} - -/** - * - */ -INLINE PathReplace::Entry:: -Entry(const PathReplace::Entry ©) : - _orig_prefix(copy._orig_prefix), - _orig_components(copy._orig_components), - _is_local(copy._is_local), - _replacement_prefix(copy._replacement_prefix) -{ -} - -/** - * - */ -INLINE void PathReplace::Entry:: -operator = (const PathReplace::Entry ©) { - _orig_prefix = copy._orig_prefix; - _orig_components = copy._orig_components; - _is_local = copy._is_local; - _replacement_prefix = copy._replacement_prefix; -} diff --git a/pandatool/src/pandatoolbase/pathReplace.cxx b/pandatool/src/pandatoolbase/pathReplace.cxx deleted file mode 100644 index b3b6bcb4..00000000 --- a/pandatool/src/pandatoolbase/pathReplace.cxx +++ /dev/null @@ -1,554 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pathReplace.cxx - * @author drose - * @date 2003-02-07 - */ - -#include "pathReplace.h" -#include "config_putil.h" -#include "config_pandatoolbase.h" -#include "indent.h" -#include "virtualFileSystem.h" - -/** - * - */ -PathReplace:: -PathReplace() { - _path_store = PS_keep; - _copy_files = false; - _noabs = false; - _exists = false; - _error_flag = false; -} - -/** - * - */ -PathReplace:: -~PathReplace() { -} - -/** - * Looks for a match for the given filename among all the replacement - * patterns, and returns the first match found. If additional_path is - * nonempty, it is an additional search path on which to look for the file. - * The model_path is always implicitly searched. - */ -Filename PathReplace:: -match_path(const Filename &orig_filename, - const DSearchPath &additional_path) { - Filename match; - bool got_match = false; - - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - - Entries::const_iterator ei; - for (ei = _entries.begin(); ei != _entries.end(); ++ei) { - const Entry &entry = (*ei); - Filename new_filename; - if (entry.try_match(orig_filename, new_filename)) { - // The prefix matches. Save the resulting filename for posterity. - got_match = true; - match = new_filename; - - if (new_filename.is_fully_qualified()) { - // If the resulting filename is fully qualified, it's a match if and - // only if it exists. - if (vfs->exists(new_filename)) { - return new_filename; - } - - } else { - // Otherwise, if it's a relative filename, attempt to look it up on - // the search path. - if (vfs->resolve_filename(new_filename, _path) || - vfs->resolve_filename(new_filename, additional_path) || - vfs->resolve_filename(new_filename, get_model_path())) { - // Found it! - if (_path_store == PS_keep) { - // If we asked to "keep" the pathname, we return the matched path, - // but not the found path. - return match; - } else { - // Otherwise, we return the actual, found path. - return new_filename; - } - } - } - - // The prefix matched, but it didn't exist. Keep looking. - } - } - - // The file couldn't be found anywhere. Did we at least get any prefix - // match? - if (got_match) { - if (_exists) { - _error_flag = true; - pandatoolbase_cat.error() - << "File does not exist: " << match << "\n"; - } else if (pandatoolbase_cat.is_debug()) { - pandatoolbase_cat.debug() - << "File does not exist: " << match << "\n"; - } - - return match; - } - - if (!orig_filename.is_local()) { - // Ok, we didn't match any specified prefixes. If the file is an absolute - // pathname and we have _noabs set, that's an error. - if (_noabs) { - _error_flag = true; - pandatoolbase_cat.error() - << "Absolute pathname: " << orig_filename << "\n"; - } else if (pandatoolbase_cat.is_debug()) { - pandatoolbase_cat.debug() - << "Absolute pathname: " << orig_filename << "\n"; - } - } - - // Well, we still haven't found it; look it up on the search path as is. - if (_path_store != PS_keep) { - Filename new_filename = orig_filename; - if (vfs->resolve_filename(new_filename, _path) || - vfs->resolve_filename(new_filename, additional_path) || - vfs->resolve_filename(new_filename, get_model_path())) { - // Found it! - return new_filename; - } - } - - // Nope, couldn't find anything. This is an error, but just return the - // original filename. - if (_exists) { - _error_flag = true; - pandatoolbase_cat.error() - << "File does not exist: " << orig_filename << "\n"; - } else if (pandatoolbase_cat.is_debug()) { - pandatoolbase_cat.debug() - << "File does not exist: " << orig_filename << "\n"; - } - return orig_filename; -} - -/** - * Given a path to an existing filename, converts it as specified in the - * _path_store and or _path_directory properties to a form suitable for - * storing in an output file. - */ -Filename PathReplace:: -store_path(const Filename &orig_filename) { - if (orig_filename.empty()) { - return orig_filename; - } - - if (_path_directory.is_local()) { - _path_directory.make_absolute(); - } - Filename filename = orig_filename; - - if (_copy_files) { - copy_this_file(filename); - } - - switch (_path_store) { - case PS_relative: - filename.make_absolute(); - filename.make_relative_to(_path_directory); - break; - - case PS_absolute: - filename.make_absolute(); - break; - - case PS_rel_abs: - filename.make_absolute(); - filename.make_relative_to(_path_directory, false); - break; - - case PS_strip: - filename = filename.get_basename(); - break; - - case PS_keep: - break; - - case PS_invalid: - break; - } - - return filename; -} - -/** - * Converts the input path into two different forms: A resolved path, and an - * output path. The resolved path is an absolute path if at all possible. - * The output path is in the form specified by the -ps path store option. - */ -void PathReplace:: -full_convert_path(const Filename &orig_filename, - const DSearchPath &additional_path, - Filename &resolved_path, - Filename &output_path) { - if (_path_directory.is_local()) { - _path_directory.make_absolute(); - } - - Filename match; - bool got_match = false; - - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - - Entries::const_iterator ei; - for (ei = _entries.begin(); ei != _entries.end(); ++ei) { - const Entry &entry = (*ei); - Filename new_filename; - if (entry.try_match(orig_filename, new_filename)) { - // The prefix matches. Save the resulting filename for posterity. - got_match = true; - match = new_filename; - - if (new_filename.is_fully_qualified()) { - // If the resulting filename is fully qualified, it's a match if and - // only if it exists. - if (vfs->exists(new_filename)) { - resolved_path = new_filename; - goto calculate_output_path; - } - - } else { - // Otherwise, if it's a relative filename, attempt to look it up on - // the search path. - if (vfs->resolve_filename(new_filename, _path) || - vfs->resolve_filename(new_filename, additional_path) || - vfs->resolve_filename(new_filename, get_model_path())) { - // Found it! - resolved_path = new_filename; - goto calculate_output_path; - } - } - - // The prefix matched, but it didn't exist. Keep looking. - } - } - - // The file couldn't be found anywhere. Did we at least get any prefix - // match? - if (got_match) { - if (_exists) { - _error_flag = true; - pandatoolbase_cat.error() - << "File does not exist: " << match << "\n"; - } else if (pandatoolbase_cat.is_debug()) { - pandatoolbase_cat.debug() - << "File does not exist: " << match << "\n"; - } - - resolved_path = match; - goto calculate_output_path; - } - - if (!orig_filename.is_local()) { - // Ok, we didn't match any specified prefixes. If the file is an absolute - // pathname and we have _noabs set, that's an error. - if (_noabs) { - _error_flag = true; - pandatoolbase_cat.error() - << "Absolute pathname: " << orig_filename << "\n"; - } else if (pandatoolbase_cat.is_debug()) { - pandatoolbase_cat.debug() - << "Absolute pathname: " << orig_filename << "\n"; - } - } - - // Well, we still haven't found it; look it up on the search path as is. - { - Filename new_filename = orig_filename; - if (vfs->resolve_filename(new_filename, _path) || - vfs->resolve_filename(new_filename, additional_path) || - vfs->resolve_filename(new_filename, get_model_path())) { - // Found it! - match = orig_filename; - resolved_path = new_filename; - goto calculate_output_path; - } - } - - // Nope, couldn't find anything. This is an error, but just return the - // original filename. - if (_exists) { - _error_flag = true; - pandatoolbase_cat.error() - << "File does not exist: " << orig_filename << "\n"; - } else if (pandatoolbase_cat.is_debug()) { - pandatoolbase_cat.debug() - << "File does not exist: " << orig_filename << "\n"; - } - match = orig_filename; - resolved_path = orig_filename; - - // To calculate the output path, we need two inputs: the match, and the - // resolved path. Which one is used depends upon the path-store mode. - calculate_output_path: - - if (_copy_files) { - if (copy_this_file(resolved_path)) { - match = resolved_path; - } - } - - switch (_path_store) { - case PS_relative: - if (resolved_path.empty()) - output_path = resolved_path; - else { - output_path = resolved_path; - output_path.make_absolute(); - output_path.make_relative_to(_path_directory); - } - break; - - case PS_absolute: - if (resolved_path.empty()) - output_path = resolved_path; - else { - output_path = resolved_path; - output_path.make_absolute(); - } - break; - - case PS_rel_abs: - if (resolved_path.empty()) - output_path = resolved_path; - else { - output_path = resolved_path; - output_path.make_absolute(); - output_path.make_relative_to(_path_directory, false); - } - break; - - case PS_strip: - output_path = match.get_basename(); - break; - - case PS_keep: - output_path = match; - break; - - case PS_invalid: - output_path = ""; - break; - } -} - -/** - * - */ -void PathReplace:: -write(std::ostream &out, int indent_level) const { - Entries::const_iterator ei; - for (ei = _entries.begin(); ei != _entries.end(); ++ei) { - indent(out, indent_level) - << "-pr " << (*ei)._orig_prefix << "=" - << (*ei)._replacement_prefix << "\n"; - } - int num_directories = _path.get_num_directories(); - for (int i = 0; i < num_directories; i++) { - indent(out, indent_level) - << "-pp " << _path.get_directory(i) << "\n"; - } - indent(out, indent_level) - << "-ps " << _path_store << "\n"; - - // The path directory is only relevant if _path_store is rel or rel_abs. - switch (_path_store) { - case PS_relative: - case PS_rel_abs: - indent(out, indent_level) - << "-pd " << _path_directory << "\n"; - - default: - break; - } - - if (_copy_files) { - indent(out, indent_level) - << "-pc " << _copy_into_directory << "\n"; - } - - if (_noabs) { - indent(out, indent_level) - << "-noabs\n"; - } -} - -/** - * Copies the indicated file into the copy_into_directory, and adjusts - * filename to reference the new location. Returns true if the copy is made - * and the filename is changed, false otherwise. - */ -bool PathReplace:: -copy_this_file(Filename &filename) { - if (_copy_into_directory.is_local()) { - _copy_into_directory = Filename(_path_directory, _copy_into_directory); - } - - Copied::iterator ci = _orig_to_target.find(filename); - if (ci != _orig_to_target.end()) { - // This file has already been successfully copied, so we can quietly - // return its new target filename. - if (filename != (*ci).second) { - filename = (*ci).second; - return true; - } - return false; - } - - Filename target_filename(_copy_into_directory, filename.get_basename()); - ci = _target_to_orig.find(target_filename); - if (ci != _target_to_orig.end()) { - if ((*ci).second != filename) { - _error_flag = true; - pandatoolbase_cat.error() - << "Filename conflict! Both " << (*ci).second << " and " - << filename << " map to " << target_filename << "\n"; - } - - // Don't copy this one. - _orig_to_target[filename] = filename; - return false; - } - - _orig_to_target[filename] = target_filename; - _target_to_orig[target_filename] = filename; - - // Make the copy. - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - vfs->make_directory_full(_copy_into_directory); - if (!vfs->copy_file(filename, target_filename)) { - _error_flag = true; - pandatoolbase_cat.error() - << "Cannot copy file from " << filename << " to " << target_filename - << "\n"; - _orig_to_target[filename] = filename; - return false; - } - - filename = target_filename; - return true; -} - -/** - * - */ -PathReplace::Entry:: -Entry(const std::string &orig_prefix, const std::string &replacement_prefix) : - _orig_prefix(orig_prefix), - _replacement_prefix(replacement_prefix) -{ - // Eliminate trailing slashes; they're implicit. - if (_orig_prefix.length() > 1 && - _orig_prefix[_orig_prefix.length() - 1] == '/') { - _orig_prefix = _orig_prefix.substr(0, _orig_prefix.length() - 1); - } - if (_replacement_prefix.length() > 1 && - _replacement_prefix[_replacement_prefix.length() - 1] == '/') { - _replacement_prefix = _replacement_prefix.substr(0, _replacement_prefix.length() - 1); - } - - Filename filename(_orig_prefix); - _is_local = filename.is_local(); - - vector_string components; - filename.extract_components(components); - vector_string::const_iterator ci; - for (ci = components.begin(); ci != components.end(); ++ci) { - _orig_components.push_back(Component(*ci)); - } -} - -/** - * Considers whether the indicated filename matches this entry's prefix. If - * so, switches the prefix and stores the result in new_filename, and returns - * true; otherwise, returns false. - */ -bool PathReplace::Entry:: -try_match(const Filename &filename, Filename &new_filename) const { - if (_is_local != filename.is_local()) { - return false; - } - vector_string components; - filename.extract_components(components); - size_t mi = r_try_match(components, 0, 0); - if (mi == 0) { - // Sorry, no match. - return false; - } - - // We found a match. Construct the replacement string. - std::string result = _replacement_prefix; - while (mi < components.size()) { - if (!result.empty()) { - result += '/'; - } - result += components[mi]; - ++mi; - } - new_filename = result; - return true; -} - -/** - * The recursive implementation of try_match(). Actually, this is doubly- - * recursive, to implement the "**" feature. - * - * The return value is the number of the "components" vector that successfully - * matched against all of the orig_components. (It's a variable number - * because there might be one or more "**" entries.) - */ -size_t PathReplace::Entry:: -r_try_match(const vector_string &components, size_t oi, size_t ci) const { - if (oi >= _orig_components.size()) { - // If we ran out of user-supplied components, we're done. - return ci; - } - if (ci >= components.size()) { - // If we reached the end of the string, but we still have user-supplied - // components, we failed. (Arguably there should be a special case here - // for a user-supplied string that ends in "**", but I don't think the - // user ever wants to match the complete string.) - return 0; - } - - const Component &orig_component = _orig_components[oi]; - if (orig_component._double_star) { - // If we have a double star, first consider the match if it were expanded - // as far as possible. - size_t mi = r_try_match(components, oi, ci + 1); - if (mi != 0) { - return mi; - } - - // Then try the match as if it there were no double star entry. - return r_try_match(components, oi + 1, ci); - } - - // We don't have a double star, it's just a one-for-one component entry. - // Does it match? - if (orig_component._orig_prefix.matches(components[ci])) { - // It does! Keep going. - return r_try_match(components, oi + 1, ci + 1); - } - - // It doesn't match, sorry. - return 0; -} diff --git a/pandatool/src/pandatoolbase/pathReplace.h b/pandatool/src/pandatoolbase/pathReplace.h deleted file mode 100644 index edc69abc..00000000 --- a/pandatool/src/pandatoolbase/pathReplace.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pathReplace.h - * @author drose - * @date 2003-02-07 - */ - -#ifndef PATHREPLACE_H -#define PATHREPLACE_H - -#include "pandatoolbase.h" -#include "pathStore.h" -#include "referenceCount.h" -#include "globPattern.h" -#include "filename.h" -#include "dSearchPath.h" -#include "pvector.h" -#include "pmap.h" - -/** - * This encapsulates the user's command-line request to replace existing, - * incorrect pathnames to models and textures from a file with correct - * pathnames. It corresponds to a sequence of -pr command-line options, as - * well as the -pp option. - * - * This can also go the next step, which is to convert a known file into a - * suitable form for storing in a model file. In this capacity, it - * corresponds to the -ps and -pd options. - */ -class PathReplace : public ReferenceCount { -public: - PathReplace(); - ~PathReplace(); - - INLINE void clear_error(); - INLINE bool had_error() const; - - INLINE void clear(); - INLINE void add_pattern(const std::string &orig_prefix, const std::string &replacement_prefix); - - INLINE int get_num_patterns() const; - INLINE const std::string &get_orig_prefix(int n) const; - INLINE const std::string &get_replacement_prefix(int n) const; - - INLINE bool is_empty() const; - - Filename match_path(const Filename &orig_filename, - const DSearchPath &additional_path = DSearchPath()); - Filename store_path(const Filename &orig_filename); - - INLINE Filename convert_path(const Filename &orig_filename, - const DSearchPath &additional_path = DSearchPath()); - - void full_convert_path(const Filename &orig_filename, - const DSearchPath &additional_path, - Filename &resolved_path, - Filename &output_path); - - void write(std::ostream &out, int indent_level = 0) const; - -public: - // This is used (along with _entries) to support match_path(). - DSearchPath _path; - - // These are used to support store_path(). - PathStore _path_store; - Filename _path_directory; - bool _copy_files; - Filename _copy_into_directory; - - // If this is this true, then the error flag is set (see had_error() and - // clear_error()) if any Filename passed to match_path() or convert_path(), - // and unmatched by one of the prefixes, happens to be an absolute pathname. - bool _noabs; - - // If this is true, then the error flag is set if any Filename passed to - // match_path() or convert_path() cannot be found. - bool _exists; - -private: - bool copy_this_file(Filename &filename); - - class Component { - public: - INLINE Component(const std::string &component); - INLINE Component(const Component ©); - INLINE void operator = (const Component ©); - - GlobPattern _orig_prefix; - bool _double_star; - }; - typedef pvector Components; - - class Entry { - public: - Entry(const std::string &orig_prefix, const std::string &replacement_prefix); - INLINE Entry(const Entry ©); - INLINE void operator = (const Entry ©); - - bool try_match(const Filename &filename, Filename &new_filename) const; - size_t r_try_match(const vector_string &components, size_t oi, size_t ci) const; - - std::string _orig_prefix; - Components _orig_components; - bool _is_local; - std::string _replacement_prefix; - }; - - typedef pvector Entries; - Entries _entries; - - bool _error_flag; - - typedef pmap Copied; - Copied _orig_to_target; - Copied _target_to_orig; -}; - -#include "pathReplace.I" - -#endif diff --git a/pandatool/src/pandatoolbase/pathStore.cxx b/pandatool/src/pandatoolbase/pathStore.cxx deleted file mode 100644 index dffacfe6..00000000 --- a/pandatool/src/pandatoolbase/pathStore.cxx +++ /dev/null @@ -1,81 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pathStore.cxx - * @author drose - * @date 2003-02-10 - */ - -#include "pathStore.h" - -#include "string_utils.h" -#include "pnotify.h" - -/** - * Returns the string corresponding to this method. - */ -std::string -format_path_store(PathStore store) { - switch (store) { - case PS_invalid: - return "invalid"; - - case PS_relative: - return "relative"; - - case PS_absolute: - return "absolute"; - - case PS_rel_abs: - return "rel_abs"; - - case PS_strip: - return "strip"; - - case PS_keep: - return "keep"; - } - nout << "**unexpected PathStore value: (" << (int)store << ")**"; - return "**"; -} - -/** - * - */ -std::ostream & -operator << (std::ostream &out, PathStore store) { - return out << format_path_store(store); -} - -/** - * Stores from a string, as might be input by the user, to one of the known - * PathStore types. Returns PS_invalid if the string is unknown. - */ -PathStore -string_path_store(const std::string &str) { - if (cmp_nocase(str, "relative") == 0 || - cmp_nocase(str, "rel") == 0) { - return PS_relative; - - } else if (cmp_nocase(str, "absolute") == 0 || - cmp_nocase(str, "abs") == 0) { - return PS_absolute; - - } else if (cmp_nocase_uh(str, "rel_abs") == 0) { - return PS_rel_abs; - - } else if (cmp_nocase(str, "strip") == 0) { - return PS_strip; - - } else if (cmp_nocase(str, "keep") == 0) { - return PS_keep; - - } else { - return PS_invalid; - } -} diff --git a/pandatool/src/pandatoolbase/pathStore.h b/pandatool/src/pandatoolbase/pathStore.h deleted file mode 100644 index 30440b70..00000000 --- a/pandatool/src/pandatoolbase/pathStore.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pathStore.h - * @author drose - * @date 2003-02-10 - */ - -#ifndef PATHSTORE_H -#define PATHSTORE_H - -#include "pandatoolbase.h" - -/** - * This enumerated type lists the methods by which a filename path might be - * mangled before storing in a destination file. - */ -enum PathStore { - PS_invalid, // Never use this. - PS_relative, // Make relative to a user-specified directory. - PS_absolute, // Make absolute. - PS_rel_abs, // Make relative if within the directory, otherwise absolute. - PS_strip, // Strip prefix and just store the basename. - PS_keep, // Don't change the filename at all. -}; - -std::string format_path_store(PathStore unit); - -std::ostream &operator << (std::ostream &out, PathStore unit); -PathStore string_path_store(const std::string &str); - -#endif diff --git a/pandatool/src/pfmprogs/CMakeLists.txt b/pandatool/src/pfmprogs/CMakeLists.txt deleted file mode 100644 index 4176ad2c..00000000 --- a/pandatool/src/pfmprogs/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(pfm-bba - config_pfmprogs.cxx config_pfmprogs.h - pfmBba.cxx pfmBba.h) -target_link_libraries(pfm-bba p3progbase) -install(TARGETS pfm-bba EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -add_executable(pfm-trans pfmTrans.cxx pfmTrans.h) -target_link_libraries(pfm-trans p3progbase) -install(TARGETS pfm-trans EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/pfmprogs/config_pfmprogs.cxx b/pandatool/src/pfmprogs/config_pfmprogs.cxx deleted file mode 100644 index afa49ef9..00000000 --- a/pandatool/src/pfmprogs/config_pfmprogs.cxx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_pfmprogs.cxx - * @author drose - * @date 2010-12-23 - */ - -#include "config_pfmprogs.h" - -#include "dconfig.h" - -Configure(config_pfmprogs); -NotifyCategoryDef(pfm, ""); - -ConfigVariableDouble pfm_bba_dist -("pfm-bba-dist", "0.2 0.05", - PRC_DESC("Specifies the point_dist and sample_radius, in UV space, for " - "compute bba files with pfm_trans.")); - -ConfigureFn(config_pfmprogs) { - init_libpfm(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libpfm() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; -} diff --git a/pandatool/src/pfmprogs/config_pfmprogs.h b/pandatool/src/pfmprogs/config_pfmprogs.h deleted file mode 100644 index 98777496..00000000 --- a/pandatool/src/pfmprogs/config_pfmprogs.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_pfmprogs.h - * @author drose - * @date 2010-12-23 - */ - -#ifndef CONFIG_PFM_H -#define CONFIG_PFM_H - -#include "pandatoolbase.h" - -#include "notifyCategoryProxy.h" -#include "configVariableBool.h" -#include "configVariableDouble.h" - -NotifyCategoryDeclNoExport(pfm); - -extern ConfigVariableDouble pfm_bba_dist; - -extern void init_libpfm(); - -#endif diff --git a/pandatool/src/pfmprogs/pfmBba.cxx b/pandatool/src/pfmprogs/pfmBba.cxx deleted file mode 100644 index ce0851a4..00000000 --- a/pandatool/src/pfmprogs/pfmBba.cxx +++ /dev/null @@ -1,142 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pfmBba.cxx - * @author drose - * @date 2011-03-02 - */ - -#include "pfmBba.h" -#include "config_pfmprogs.h" -#include "pfmFile.h" - -/** - * - */ -PfmBba:: -PfmBba() { - set_program_brief("generate .bba files from .pfm files"); - set_program_description - ("pfm-bba generates a .bba file from a .pfm file that lists the " - "planar bounding volume of the pfm's internal data."); - - add_option - ("z", "", 0, - "Treats (0,0,0) in the pfm file as a special don't-touch value.", - &PfmBba::dispatch_none, &_got_zero_special); - - add_option - ("o", "filename", 50, - "Specify the filename to which the resulting bba file will be written.", - &PfmBba::dispatch_filename, &_got_output_filename, &_output_filename); -} - - -/** - * - */ -void PfmBba:: -run() { - Filenames::const_iterator fi; - for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) { - PfmFile file; - if (!file.read(*fi)) { - nout << "Cannot read " << *fi << "\n"; - exit(1); - } - if (!process_pfm(*fi, file)) { - exit(1); - } - } -} - -/** - * Handles a single pfm file. - */ -bool PfmBba:: -process_pfm(const Filename &input_filename, PfmFile &file) { - file.set_zero_special(_got_zero_special); - - Filename bba_filename; - if (_got_output_filename) { - bba_filename = _output_filename; - } else { - bba_filename = input_filename; - bba_filename.set_extension("bba"); - } - - if (!bba_filename.empty()) { - bba_filename.set_text(); - PT(BoundingHexahedron) bounds = file.compute_planar_bounds(LPoint2f(0.5, 0.5), pfm_bba_dist[0], pfm_bba_dist[1], false); - nassertr(bounds != nullptr, false); - - pofstream out; - if (!bba_filename.open_write(out)) { - std::cerr << "Unable to open " << bba_filename << "\n"; - return false; - } - - LPoint3 points[8]; - for (int i = 0; i < 8; ++i) { - points[i] = bounds->get_point(i); - } - - // Experiment with expanding the back wall backwards. - /* - LPlane plane(points[0], points[1], points[2]); - LVector3 normal = plane.get_normal(); - - static const PN_stdfloat scale = 20.0f; - normal *= scale; - points[0] += normal; - points[1] += normal; - points[2] += normal; - points[3] += normal; - */ - - for (int i = 0; i < 8; ++i) { - const LPoint3 &p = points[i]; - out << p[0] << "," << p[1] << "," << p[2] << "\n"; - } - } - - return true; -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool PfmBba:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the pfm file(s) to read on the command line.\n"; - return false; - } - - if (args.size() > 1 && _got_output_filename) { - nout << "Cannot use -o when multiple pfm files are specified.\n"; - return false; - } - - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - _input_filenames.push_back(Filename::from_os_specific(*ai)); - } - - return true; -} - - -int main(int argc, char *argv[]) { - PfmBba prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/pfmprogs/pfmBba.h b/pandatool/src/pfmprogs/pfmBba.h deleted file mode 100644 index 4d01ca64..00000000 --- a/pandatool/src/pfmprogs/pfmBba.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pfmBba.h - * @author drose - * @date 2011-03-02 - */ - -#ifndef PFMBBA_H -#define PFMBBA_H - -#include "pandatoolbase.h" -#include "programBase.h" -#include "filename.h" -#include "pvector.h" -#include "nodePath.h" -#include "luse.h" - -class PfmFile; - -/** - * Generates a bounding-box description of a pfm file. - */ -class PfmBba : public ProgramBase { -public: - PfmBba(); - - void run(); - bool process_pfm(const Filename &input_filename, PfmFile &file); - -protected: - virtual bool handle_args(Args &args); - -private: - typedef pvector Filenames; - Filenames _input_filenames; - - bool _got_zero_special; - bool _got_output_filename; - Filename _output_filename; -}; - -#endif diff --git a/pandatool/src/pfmprogs/pfmTrans.cxx b/pandatool/src/pfmprogs/pfmTrans.cxx deleted file mode 100644 index ffb99b24..00000000 --- a/pandatool/src/pfmprogs/pfmTrans.cxx +++ /dev/null @@ -1,512 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pfmTrans.cxx - * @author drose - * @date 2010-12-23 - */ - -#include "pfmTrans.h" -#include "config_pfmprogs.h" -#include "pfmFile.h" -#include "pfmVizzer.h" -#include "texture.h" -#include "texturePool.h" -#include "pointerTo.h" -#include "string_utils.h" -#include "pandaFileStream.h" - -using std::string; - -/** - * - */ -PfmTrans:: -PfmTrans() { - _no_data_nan_num_channels = 0; - _got_transform = false; - _transform = LMatrix4::ident_mat(); - _rotate = 0; - - add_transform_options(); - - set_program_brief("transform .pfm files"); - set_program_description - ("pfm-trans reads an pfm file and transforms it, filters it, " - "operates on it, writing the output to another pfm file. A pfm " - "file contains a 2-d table of floating-point values."); - - add_option - ("z", "", 0, - "Treats (0,0,0) in the pfm file as a special don't-touch value.", - &PfmTrans::dispatch_none, &_got_zero_special); - - add_option - ("nan", "num_channels", 0, - "Treats a NaN in any of the first num_channels channels as a special don't-touch value.", - &PfmTrans::dispatch_int, &_got_no_data_nan, &_no_data_nan_num_channels); - - add_option - ("resize", "width,height", 0, - "Resamples the pfm file to scale it to the indicated grid size. " - "A simple box filter is applied during the scale. Don't confuse this " - "with -TS, which scales the individual point values, but doesn't " - "change the number of points.", - &PfmTrans::dispatch_int_pair, &_got_resize, &_resize); - - add_option - ("crop", "xbegin,xend,ybegin,yend", 0, - "Crops the pfm file to the indicated subregion.", - &PfmTrans::dispatch_int_quad, &_got_crop, &_crop); - - add_option - ("autocrop", "", 0, - "Automatically crops to the smallest possible rectangle that includes " - "all points. Requires -z or -nan.", - &PfmTrans::dispatch_none, &_got_autocrop); - - add_option - ("rotate", "degrees", 0, - "Rotates the pfm file the specified number of degrees counterclockwise, " - "which must be a multiple of 90.", - &PfmTrans::dispatch_int, nullptr, &_rotate); - - add_option - ("mirror_x", "", 0, - "Flips the pfm file about the x axis.", - &PfmTrans::dispatch_none, &_got_mirror_x); - - add_option - ("mirror_y", "", 0, - "Flips the pfm file about the y axis.", - &PfmTrans::dispatch_none, &_got_mirror_y); - - add_option - ("o", "filename", 50, - "Specify the filename to which the resulting pfm file will be written. " - "This is only valid when there is only one input pfm file on the command " - "line. If you want to process multiple files simultaneously, you must " - "use -d.", - &PfmTrans::dispatch_filename, &_got_output_filename, &_output_filename); - - add_option - ("d", "dirname", 50, - "Specify the name of the directory in which to write the processed pfm " - "files. If you are processing only one pfm file, this may be omitted " - "in lieu of the -o option.", - &PfmTrans::dispatch_filename, &_got_output_dirname, &_output_dirname); - - add_option - ("vis", "filename.bam", 60, - "Generates a bam file that represents a visualization of the pfm file " - "as a 3-D geometric mesh. If -vistex is specified, the mesh is " - "textured.", - &PfmTrans::dispatch_filename, &_got_vis_filename, &_vis_filename); - - add_option - ("visinv", "", 60, - "Inverts the visualization, generating a uniform 2-d mesh with the " - "3-d depth values encoded in the texture coordinates.", - &PfmTrans::dispatch_none, &_got_vis_inverse); - - add_option - ("vis2d", "", 60, - "Respect only the first two components of each depth value, ignoring z.", - &PfmTrans::dispatch_none, &_got_vis_2d); - - add_option - ("vistex", "texture.jpg", 60, - "Specifies the name of the texture to apply to the visualization.", - &PfmTrans::dispatch_filename, &_got_vistex_filename, &_vistex_filename); - - add_option - ("ls", "filename.txt", 60, - "Lists the points in the file to the indicated text file.", - &PfmTrans::dispatch_filename, &_got_ls_filename, &_ls_filename); -} - - -/** - * - */ -void PfmTrans:: -run() { - if ((int)(_rotate / 90) * 90 != _rotate) { - nout << "-rotate can only accept a multiple of 90 degrees.\n"; - exit(1); - } - - if (_got_vis_filename) { - _mesh_root = NodePath("mesh_root"); - } - - Filenames::const_iterator fi; - for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) { - PfmFile file; - if (!file.read(*fi)) { - nout << "Cannot read " << *fi << "\n"; - exit(1); - } - if (!process_pfm(*fi, file)) { - exit(1); - } - } - - if (_got_vis_filename) { - _mesh_root.write_bam_file(_vis_filename); - } -} - -/** - * Handles a single pfm file. - */ -bool PfmTrans:: -process_pfm(const Filename &input_filename, PfmFile &file) { - PfmVizzer vizzer(file); - if (_got_no_data_nan) { - file.set_no_data_nan(_no_data_nan_num_channels); - } else if (_got_zero_special) { - file.set_zero_special(true); - } - vizzer.set_vis_inverse(_got_vis_inverse); - vizzer.set_vis_2d(_got_vis_2d); - - if (_got_autocrop) { - _got_crop = file.calc_autocrop(_crop[0], _crop[1], _crop[2], _crop[3]); - } - - if (_got_crop) { - file.apply_crop(_crop[0], _crop[1], _crop[2], _crop[3]); - } - - if (_got_resize) { - file.resize(_resize[0], _resize[1]); - } - - if (_rotate != 0) { - int r = (_rotate / 90) % 4; - if (r < 0) { - r += 4; - } - switch (r) { - case 0: - break; - case 1: - // Rotate 90 degrees ccw. - file.flip(true, false, true); - break; - case 2: - // Rotate 180 degrees. - - // Not sure right now why we can't flip both axes at once. But it works - // if we do one at a time. file.flip(true, true, false); - file.flip(true, false, false); - file.flip(false, true, false); - break; - case 3: - // Rotate 90 degrees cw. - file.flip(false, true, true); - break; - default: - nassertr(false, false); - } - } - - if (_got_mirror_x) { - file.flip(true, false, false); - } - - if (_got_mirror_y) { - file.flip(false, true, false); - } - - if (_got_transform) { - file.xform(LCAST(PN_float32, _transform)); - } - - if (_got_vis_filename) { - NodePath mesh = vizzer.generate_vis_mesh(PfmVizzer::MF_both); - if (_got_vistex_filename) { - PT(Texture) tex = TexturePool::load_texture(_vistex_filename); - if (tex == nullptr) { - nout << "Couldn't find " << _vistex_filename << "\n"; - } else { - tex->set_minfilter(SamplerState::FT_linear_mipmap_linear); - mesh.set_texture(tex); - if (tex->has_alpha(tex->get_format())) { - mesh.set_transparency(TransparencyAttrib::M_dual); - } - } - } - mesh.set_name(input_filename.get_basename_wo_extension()); - mesh.reparent_to(_mesh_root); - } - - if (_got_ls_filename) { - pofstream out; - _ls_filename.set_text(); - if (_ls_filename.open_write(out, true)) { - for (int yi = 0; yi < file.get_y_size(); ++yi) { - for (int xi = 0; xi < file.get_x_size(); ++xi) { - if (file.has_point(xi, yi)) { - out << "(" << xi << ", " << yi << "):"; - for (int ci = 0; ci < file.get_num_channels(); ++ci) { - out << " " << file.get_channel(xi, yi, ci); - } - out << "\n"; - } - } - } - } - } - - Filename output_filename; - if (_got_output_filename) { - output_filename = _output_filename; - } else if (_got_output_dirname) { - output_filename = Filename(_output_dirname, input_filename.get_basename()); - } - - if (!output_filename.empty()) { - return file.write(output_filename); - } - - return true; -} - -/** - * Adds -TS, -TT, etc. as valid options for this program. If the user - * specifies one of the options on the command line, the data will be - * transformed when the egg file is written out. - */ -void PfmTrans:: -add_transform_options() { - add_option - ("TS", "sx[,sy,sz]", 49, - "Scale the model uniformly by the given factor (if only one number " - "is given) or in each axis by sx, sy, sz (if three numbers are given).", - &PfmTrans::dispatch_scale, &_got_transform, &_transform); - - add_option - ("TR", "x,y,z", 49, - "Rotate the model x degrees about the x axis, then y degrees about the " - "y axis, and then z degrees about the z axis.", - &PfmTrans::dispatch_rotate_xyz, &_got_transform, &_transform); - - add_option - ("TA", "angle,x,y,z", 49, - "Rotate the model angle degrees counterclockwise about the given " - "axis.", - &PfmTrans::dispatch_rotate_axis, &_got_transform, &_transform); - - add_option - ("TT", "x,y,z", 49, - "Translate the model by the indicated amount.\n\n" - "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are " - "applied in the order they are encountered on the command line.", - &PfmTrans::dispatch_translate, &_got_transform, &_transform); -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool PfmTrans:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - nout << "You must specify the pfm file(s) to read on the command line.\n"; - return false; - } - - if (_got_output_filename && args.size() == 1) { - if (_got_output_dirname) { - nout << "Cannot specify both -o and -d.\n"; - return false; - } - - } else { - if (_got_output_filename) { - nout << "Cannot use -o when multiple pfm files are specified.\n"; - return false; - } - } - - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - _input_filenames.push_back(Filename::from_os_specific(*ai)); - } - - return true; -} - -/** - * Handles -TS, which specifies a scale transform. Var is an LMatrix4. - */ -bool PfmTrans:: -dispatch_scale(const string &opt, const string &arg, void *var) { - LMatrix4 *transform = (LMatrix4 *)var; - - vector_string words; - tokenize(arg, words, ","); - - PN_stdfloat sx, sy, sz; - - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_stdfloat(words[0], sx) && - string_to_stdfloat(words[1], sy) && - string_to_stdfloat(words[2], sz); - - } else if (words.size() == 1) { - okflag = - string_to_stdfloat(words[0], sx); - sy = sz = sx; - } - - if (!okflag) { - nout << "-" << opt - << " requires one or three numbers separated by commas.\n"; - return false; - } - - *transform = (*transform) * LMatrix4::scale_mat(sx, sy, sz); - - return true; -} - -/** - * Handles -TR, which specifies a rotate transform about the three cardinal - * axes. Var is an LMatrix4. - */ -bool PfmTrans:: -dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) { - PfmTrans *base = (PfmTrans *)self; - return base->ns_dispatch_rotate_xyz(opt, arg, var); -} - -/** - * Handles -TR, which specifies a rotate transform about the three cardinal - * axes. Var is an LMatrix4. - */ -bool PfmTrans:: -ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) { - LMatrix4 *transform = (LMatrix4 *)var; - - vector_string words; - tokenize(arg, words, ","); - - LVecBase3 xyz; - - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_stdfloat(words[0], xyz[0]) && - string_to_stdfloat(words[1], xyz[1]) && - string_to_stdfloat(words[2], xyz[2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires three numbers separated by commas.\n"; - return false; - } - - LMatrix4 mat = - LMatrix4::rotate_mat(xyz[0], LVector3(1.0, 0.0, 0.0)) * - LMatrix4::rotate_mat(xyz[1], LVector3(0.0, 1.0, 0.0)) * - LMatrix4::rotate_mat(xyz[2], LVector3(0.0, 0.0, 1.0)); - - *transform = (*transform) * mat; - - return true; -} - -/** - * Handles -TA, which specifies a rotate transform about an arbitrary axis. - * Var is an LMatrix4. - */ -bool PfmTrans:: -dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) { - PfmTrans *base = (PfmTrans *)self; - return base->ns_dispatch_rotate_axis(opt, arg, var); -} - -/** - * Handles -TA, which specifies a rotate transform about an arbitrary axis. - * Var is an LMatrix4. - */ -bool PfmTrans:: -ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) { - LMatrix4 *transform = (LMatrix4 *)var; - - vector_string words; - tokenize(arg, words, ","); - - PN_stdfloat angle; - LVecBase3 axis; - - bool okflag = false; - if (words.size() == 4) { - okflag = - string_to_stdfloat(words[0], angle) && - string_to_stdfloat(words[1], axis[0]) && - string_to_stdfloat(words[2], axis[1]) && - string_to_stdfloat(words[3], axis[2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires four numbers separated by commas.\n"; - return false; - } - - *transform = (*transform) * LMatrix4::rotate_mat(angle, axis); - - return true; -} - -/** - * Handles -TT, which specifies a translate transform. Var is an LMatrix4. - */ -bool PfmTrans:: -dispatch_translate(const string &opt, const string &arg, void *var) { - LMatrix4 *transform = (LMatrix4 *)var; - - vector_string words; - tokenize(arg, words, ","); - - LVector3 trans; - - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_stdfloat(words[0], trans[0]) && - string_to_stdfloat(words[1], trans[1]) && - string_to_stdfloat(words[2], trans[2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires three numbers separated by commas.\n"; - return false; - } - - *transform = (*transform) * LMatrix4::translate_mat(trans); - - return true; -} - - -int main(int argc, char *argv[]) { - PfmTrans prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/pfmprogs/pfmTrans.h b/pandatool/src/pfmprogs/pfmTrans.h deleted file mode 100644 index 7d791277..00000000 --- a/pandatool/src/pfmprogs/pfmTrans.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pfmTrans.h - * @author drose - * @date 2010-12-23 - */ - -#ifndef PFMTRANS_H -#define PFMTRANS_H - -#include "pandatoolbase.h" -#include "programBase.h" -#include "filename.h" -#include "pvector.h" -#include "nodePath.h" -#include "luse.h" - -class PfmFile; - -/** - * Operates on a pfm file. - */ -class PfmTrans : public ProgramBase { -public: - PfmTrans(); - - void run(); - bool process_pfm(const Filename &input_filename, PfmFile &file); - - void add_transform_options(); - -protected: - virtual bool handle_args(Args &args); - - static bool dispatch_scale(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_rotate_xyz(ProgramBase *self, const std::string &opt, const std::string &arg, void *var); - bool ns_dispatch_rotate_xyz(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_rotate_axis(ProgramBase *self, const std::string &opt, const std::string &arg, void *var); - bool ns_dispatch_rotate_axis(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_translate(const std::string &opt, const std::string &arg, void *var); - -private: - typedef pvector Filenames; - Filenames _input_filenames; - - bool _got_zero_special; - bool _got_no_data_nan; - int _no_data_nan_num_channels; - bool _got_vis_inverse; - bool _got_vis_2d; - bool _got_resize; - int _resize[2]; - bool _got_crop; - int _crop[4]; - bool _got_autocrop; - int _rotate; - bool _got_mirror_x; - bool _got_mirror_y; - - bool _got_output_filename; - Filename _output_filename; - bool _got_output_dirname; - Filename _output_dirname; - bool _got_vis_filename; - Filename _vis_filename; - bool _got_vistex_filename; - Filename _vistex_filename; - bool _got_ls_filename; - Filename _ls_filename; - - bool _got_transform; - LMatrix4 _transform; - - NodePath _mesh_root; -}; - -#endif diff --git a/pandatool/src/progbase/CMakeLists.txt b/pandatool/src/progbase/CMakeLists.txt deleted file mode 100644 index b607968b..00000000 --- a/pandatool/src/progbase/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -set(P3PROGBASE_HEADERS - programBase.h programBase.I - withOutputFile.h withOutputFile.I - wordWrapStream.h wordWrapStreamBuf.I - wordWrapStreamBuf.h -) - -set(P3PROGBASE_SOURCES - programBase.cxx withOutputFile.cxx wordWrapStream.cxx - wordWrapStreamBuf.cxx -) - -composite_sources(p3progbase P3PROGBASE_SOURCES) -add_library(p3progbase STATIC ${P3PROGBASE_HEADERS} ${P3PROGBASE_SOURCES}) -target_link_libraries(p3progbase p3pandatoolbase panda PKG::ZLIB) - -if(IOCTL_TERMINAL_WIDTH) - target_compile_definitions(p3progbase PRIVATE IOCTL_TERMINAL_WIDTH) -endif() - -install(TARGETS p3progbase - EXPORT ToolsDevel COMPONENT ToolsDevel - DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d - ARCHIVE COMPONENT ToolsDevel) -install(FILES ${P3PROGBASE_HEADERS} COMPONENT ToolsDevel DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/panda3d) diff --git a/pandatool/src/progbase/p3progbase_composite1.cxx b/pandatool/src/progbase/p3progbase_composite1.cxx deleted file mode 100644 index c5960019..00000000 --- a/pandatool/src/progbase/p3progbase_composite1.cxx +++ /dev/null @@ -1,7 +0,0 @@ - -#include "programBase.cxx" -#include "withOutputFile.cxx" -#include "wordWrapStream.cxx" -#include "wordWrapStreamBuf.cxx" - - diff --git a/pandatool/src/progbase/programBase.I b/pandatool/src/progbase/programBase.I deleted file mode 100644 index 960bad09..00000000 --- a/pandatool/src/progbase/programBase.I +++ /dev/null @@ -1,20 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file programBase.I - * @author drose - * @date 2000-06-28 - */ - -/** - * Formats the indicated text to stderr with the known _terminal_width. - */ -INLINE void ProgramBase:: -show_text(const std::string &text) { - show_text("", 0, text); -} diff --git a/pandatool/src/progbase/programBase.cxx b/pandatool/src/progbase/programBase.cxx deleted file mode 100644 index 7486c4a9..00000000 --- a/pandatool/src/progbase/programBase.cxx +++ /dev/null @@ -1,1493 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file programBase.cxx - * @author drose - * @date 2000-02-13 - */ - -#include "programBase.h" -#include "wordWrapStream.h" - -#include "pnmFileTypeRegistry.h" -#include "indent.h" -#include "dSearchPath.h" -#include "coordinateSystem.h" -#include "dconfig.h" -#include "string_utils.h" -#include "vector_string.h" -#include "configVariableInt.h" -#include "configVariableBool.h" -#include "panda_getopt_long.h" -#include "preprocess_argv.h" -#include "pandaSystem.h" - -#include -#include -#include - -// This manifest is defined if we are running on a system (e.g. most any -// Unix) that allows us to determine the width of the terminal screen via an -// ioctl() call. It's just handy to know for formatting output nicely for the -// user. -#ifdef IOCTL_TERMINAL_WIDTH - #include - #ifndef TIOCGWINSZ - #include - #elif __APPLE__ - #include - #endif // TIOCGWINSZ -#endif // IOCTL_TERMINAL_WIDTH - -using std::cerr; -using std::cout; -using std::max; -using std::min; -using std::string; - -bool ProgramBase::SortOptionsByIndex:: -operator () (const Option *a, const Option *b) const { - if (a->_index_group != b->_index_group) { - return a->_index_group < b->_index_group; - } - return a->_sequence < b->_sequence; -} - -// This should be called at program termination just to make sure Notify gets -// properly flushed before we exit, if someone calls exit(). It's probably -// not necessary, but why not be phobic about it? -static void flush_nout() { - nout << std::flush; -} - -static ConfigVariableInt default_terminal_width -("default-terminal-width", 72, - PRC_DESC("Specify the column at which to wrap output lines " - "from pandatool-based programs, if it cannot be determined " - "automatically.")); - -static ConfigVariableBool use_terminal_width -("use-terminal-width", true, - PRC_DESC("True to try to determine the terminal width automatically from " - "the operating system, if supported; false to use the width " - "specified by default-terminal-width even if the operating system " - "appears to report a valid width.")); - -/** - * - */ -ProgramBase:: -ProgramBase(const string &name) : _name(name) { - // Set up Notify to write output to our own formatted stream. - Notify::ptr()->set_ostream_ptr(new WordWrapStream(this), true); - - // And we'll want to be sure to flush that in all normal exit cases. - atexit(&flush_nout); - - _path_replace = new PathReplace; - - // If a program never adds the path store options, the default path store is - // PS_absolute. This is the most robust solution for programs that read - // files but do not need to write them. - _path_replace->_path_store = PS_absolute; - _got_path_store = false; - _got_path_directory = false; - - _next_sequence = 0; - _sorted_options = false; - _last_newline = false; - _got_terminal_width = false; - _got_option_indent = false; - - add_option("h", "", 100, - "Display this help page.", - &ProgramBase::handle_help_option, nullptr, (void *)this); - - // It's nice to start with a blank line. - nout << "\r"; -} - -/** - * - */ -ProgramBase:: -~ProgramBase() { - // Reset Notify in case any messages get sent after our destruction--our - // stream is no longer valid. - Notify::ptr()->set_ostream_ptr(nullptr, false); -} - -/** - * Writes the program description to stderr. - */ -void ProgramBase:: -show_description() { - nout << _description << "\n"; -} - -/** - * Writes the usage line(s) to stderr. - */ -void ProgramBase:: -show_usage() { - nout << "\rUsage:\n"; - Runlines::const_iterator ri; - string prog = " " + _program_name.get_basename_wo_extension(); - - for (ri = _runlines.begin(); ri != _runlines.end(); ++ri) { - show_text(prog, prog.length() + 1, *ri); - } - nout << "\r"; -} - -/** - * Describes each of the available options to stderr. - */ -void ProgramBase:: -show_options() { - sort_options(); - if (!_got_option_indent) { - get_terminal_width(); - _option_indent = min(15, (int)(_terminal_width * 0.25)); - _got_option_indent = true; - } - - nout << "Options:\n"; - OptionsByIndex::const_iterator oi; - for (oi = _options_by_index.begin(); oi != _options_by_index.end(); ++oi) { - const Option &opt = *(*oi); - string prefix = " -" + opt._option + " " + opt._parm_name; - show_text(prefix, _option_indent, opt._description + "\r"); - } -} - -/** - * Formats the indicated text and its prefix for output to stderr with the - * known _terminal_width. - */ -void ProgramBase:: -show_text(const string &prefix, int indent_width, string text) { - get_terminal_width(); - - // This is correct! It goes go to cerr, not to nout. Sending it to nout - // would be cyclic, since nout is redefined to map back through this - // function. - format_text(cerr, _last_newline, - prefix, indent_width, text, _terminal_width); -} - -/** - * Generates a man page in nroff syntax based on the description and options. - * This is useful when creating a man page for this utility. - */ -void ProgramBase:: -write_man_page(std::ostream &out) { - string prog = _program_name.get_basename_wo_extension(); - out << ".\\\" Automatically generated by " << prog << " -write-man\n"; - - // Format the man page title as the uppercase version of the program name, - // as per the UNIX manual conventions. - out << ".TH "; - string::const_iterator si; - for (si = _name.begin(); si != _name.end(); ++si) { - out << (char)toupper(*si); - } - - // Generate a date string for inclusion into the footer. - char date_str[256]; - date_str[0] = 0; - time_t current_time; - tm *today = nullptr; - - // This variable overrides the time we write to the footer. - const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); - if (source_date_epoch == nullptr || source_date_epoch[0] == 0 || - (current_time = (time_t)strtoll(source_date_epoch, nullptr, 10)) <= 0) { - current_time = time(nullptr); - if (current_time != (time_t)-1) { - today = localtime(¤t_time); - } - } - else { - // Format as UTC to avoid inconsistency being introduced due to timezones. - today = gmtime(¤t_time); - } - - if (today == nullptr || 0 == strftime(date_str, 256, "%d %B %Y", today)) { - date_str[0] = 0; - } - - out << " 1 \"" << date_str << "\" \"" - << PandaSystem::get_version_string() << "\" Panda3D\n"; - - out << ".SH NAME\n"; - if (_brief.empty()) { - out << _name << "\n"; - } else { - out << _name << " \\- " << _brief << "\n"; - } - - out << ".SH SYNOPSIS\n"; - Runlines::const_iterator ri = _runlines.begin(); - if (ri != _runlines.end()) { - out << "\\fB" << prog << "\\fR " << *ri << "\n"; - ++ri; - } - - for (; ri != _runlines.end(); ++ri) { - out << ".br\n"; - out << "\\fB" << prog << "\\fR " << *ri << "\n"; - } - - out << ".SH DESCRIPTION\n"; - string::const_iterator di; - char prev = 0; - for (di = _description.begin(); di != _description.end(); ++di) { - if ((*di) == '-') { - // We have to escape hyphens. - out << "\\-"; - } else if (prev == '\n' && (*di) == '\n') { - // Indicate the start of a new paragraph. - out << ".PP\n"; - } else { - out << (char)(*di); - } - prev = (*di); - } - out << "\n"; - - out << ".SH OPTIONS\n"; - sort_options(); - OptionsByIndex::const_iterator oi; - for (oi = _options_by_index.begin(); oi != _options_by_index.end(); ++oi) { - const Option &opt = *(*oi); - out << ".TP\n"; - - if (opt._parm_name.empty()) { - out << ".B \\-" << opt._option << "\n"; - } else { - out << ".BI \"\\-" << opt._option << " \" \"" << opt._parm_name << "\"\n"; - } - out << opt._description << "\n"; - } -} - -/** - * Dispatches on each of the options on the command line, and passes the - * remaining parameters to handle_args(). If an error on the command line is - * detected, will automatically call show_usage() and exit(1). If exit_on_complete - * is not set, will return the program's exit code instead of exiting. - */ -ProgramBase::ExitCode ProgramBase:: -parse_command_line(int argc, char **argv, bool exit_on_complete) { - if (!exit_on_complete) { - // The help option should not be available in programmatic environments. - remove_option("h"); - } - - preprocess_argv(argc, argv); - - // Setting this variable to zero reinitializes the options parser This is - // only necessary for processing multiple command lines in the same program - // (mainly the MaxToEgg converter plugin) - extern int optind; - optind = 0; - -#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_LONG_ONLY) - // We're using a Panda implementation of getopt. Let's reset that as well. - pgetopt_reset(); -#endif - - _program_name = Filename::from_os_specific(argv[0]); - int i; - for (i = 1; i < argc; i++) { - _program_args.push_back(argv[i]); - } - - if (_name.empty()) { - _name = _program_name.get_basename_wo_extension(); - } - - // Catch a special hidden option: -write-man, which causes the tool to - // generate a manual page. - if (argc > 1 && strcmp(argv[1], "-write-man") == 0) { - if (argc == 2) { - write_man_page(cout); - - } else if (argc == 3) { - if (strlen(argv[2]) == 1 && argv[2][0] == '-') { - write_man_page(cout); - - } else { - pofstream man_out(argv[2], std::ios::out | std::ios::trunc); - if (!man_out) { - cerr << "Failed to open output file " << argv[2] << "!\n"; - } - write_man_page(man_out); - man_out.close(); - } - } else { - cerr << "Invalid number of options for -write-man!\n"; - if (exit_on_complete) { - exit(1); - } - return ExitCode::EC_failure; - } - - if (exit_on_complete) { - exit(0); - } - return ExitCode::EC_clean_exit; - } - - // Build up the long options list and the short options string for - // getopt_long_only(). - pvector long_options; - string short_options; - - // We also need to build a temporary map of int index numbers to Option - // pointers. We'll pass these index numbers to GNU's getopt_long() so we - // can tell one option from another. - typedef pmap Options; - Options options; - - OptionsByName::const_iterator oi; - int next_index = 256; - - // Let's prefix the option string with "-" to tell getopt that we want it to - // tell us the post-option arguments, instead of trying to meddle with ARGC - // and ARGV (which we aren't using directly). - short_options = "-"; - - for (oi = _options_by_name.begin(); oi != _options_by_name.end(); ++oi) { - const Option &opt = (*oi).second; - - int index; - if (opt._option.length() == 1) { - // This is a "short" option; its option string consists of only one - // letter. Its index is the letter itself. - index = (int)opt._option[0]; - - short_options += opt._option; - if (!opt._parm_name.empty()) { - // This option takes an argument. - short_options += ':'; - } - } else { - // This is a "long" option; we'll assign it the next available index. - index = ++next_index; - } - - // Now add it to the GNU data structures. - struct option gopt; - gopt.name = (char *)opt._option.c_str(); - gopt.has_arg = (opt._parm_name.empty()) ? - no_argument : required_argument; - gopt.flag = nullptr; - - // Return an index into the _options_by_index array, offset by 256 so we - // don't confuse it with '?'. - gopt.val = index; - - long_options.push_back(gopt); - - options[index] = &opt; - } - - // Finally, add one more structure, all zeroes, to indicate the end of the - // options. - struct option gopt; - memset(&gopt, 0, sizeof(gopt)); - long_options.push_back(gopt); - - // We'll use this vector to save the non-option arguments. Generally, these - // will all be at the end, but with the GNU extensions, they need not be. - Args remaining_args; - - // Now call getopt_long() to actually parse the arguments. - extern char *optarg; - const struct option *long_opts = &long_options[0]; - - int flag = - getopt_long_only(argc, argv, short_options.c_str(), long_opts, nullptr); - while (flag != EOF) { - string arg; - if (optarg != nullptr) { - arg = optarg; - } - - switch (flag) { - case '?': - // Invalid option or parameter. - show_usage(); - if (exit_on_complete) { - exit(1); - } - return ExitCode::EC_failure; - - case '\x1': - // A special return value from getopt() indicating a non-option - // argument. - remaining_args.push_back(arg); - break; - - default: - { - // A normal option. Figure out which one it is. - Options::const_iterator ii; - ii = options.find(flag); - if (ii == options.end()) { - nout << "Internal error! Invalid option index returned.\n"; - abort(); - } - - const Option &opt = *(*ii).second; - bool okflag = true; - if (opt._option_function != (OptionDispatchFunction)nullptr) { - okflag = (*opt._option_function)(opt._option, arg, opt._option_data); - } - if (opt._option_method != (OptionDispatchMethod)nullptr) { - okflag = (*opt._option_method)(this, opt._option, arg, opt._option_data); - } - if (opt._bool_var != nullptr) { - (*opt._bool_var) = true; - } - - if (!okflag) { - show_usage(); - if (exit_on_complete) { - exit(1); - } - return ExitCode::EC_failure; - } - } - } - - flag = - getopt_long_only(argc, argv, short_options.c_str(), long_opts, nullptr); - } - - if (!handle_args(remaining_args)) { - show_usage(); - if (exit_on_complete) { - exit(1); - } - return ExitCode::EC_failure; - } - - if (!post_command_line()) { - show_usage(); - if (exit_on_complete) { - exit(1); - } - return ExitCode::EC_failure; - } - - return ExitCode::EC_not_exited; -} - -/** - * Returns the command that invoked this program, as a shell-friendly string, - * suitable for pasting into the comments of output files. - */ -string ProgramBase:: -get_exec_command() const { - string command; - - command = _program_name.get_basename_wo_extension(); - Args::const_iterator ai; - for (ai = _program_args.begin(); ai != _program_args.end(); ++ai) { - const string &arg = (*ai); - - // First, check to see if the string is shell-acceptable. - bool legal = true; - string::const_iterator si; - for (si = arg.begin(); legal && si != arg.end(); ++si) { - switch (*si) { - case ' ': - case '\n': - case '\t': - case '*': - case '?': - case '\\': - case '(': - case ')': - case '|': - case '&': - case '<': - case '>': - case '"': - case ';': - case '$': - legal = false; - } - } - - if (legal) { - command += " " + arg; - } else { - command += " '" + arg + "'"; - } - } - - return command; -} - - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool ProgramBase:: -handle_args(ProgramBase::Args &args) { - if (!args.empty()) { - nout << "Unexpected arguments on command line:\n"; - Args::const_iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - nout << (*ai) << " "; - } - nout << "\r"; - return false; - } - - return true; -} - -/** - * This is called after the command line has been completely processed, and it - * gives the program a chance to do some last-minute processing and validation - * of the options and arguments. It should return true if everything is fine, - * false if there is an error. - */ -bool ProgramBase:: -post_command_line() { - return true; -} - -/** - * Sets a brief synopsis of the program's function. This is currently only - * used for generating the synopsis of the program's man page. - * - * This should be of the format: "perform operation foo on bar files" - */ -void ProgramBase:: -set_program_brief(const string &brief) { - _brief = brief; -} - -/** - * Sets the description of the program that will be reported by show_usage(). - * The description should be one long string of text. Embedded newline - * characters are interpreted as paragraph breaks and printed as blank lines. - */ -void ProgramBase:: -set_program_description(const string &description) { - _description = description; -} - -/** - * Removes all of the runlines that were previously added, presumably before - * adding some new ones. - */ -void ProgramBase:: -clear_runlines() { - _runlines.clear(); -} - -/** - * Adds an additional line to the list of lines that will be displayed to - * describe briefly how the program is to be run. Each line should be - * something like "[opts] arg1 arg2", that is, it does *not* include the name - * of the program, but it includes everything that should be printed after the - * name of the program. - * - * Normally there is only one runline for a given program, but it is possible - * to define more than one. - */ -void ProgramBase:: -add_runline(const string &runline) { - _runlines.push_back(runline); -} - -/** - * Removes all of the options that were previously added, presumably before - * adding some new ones. Normally you wouldn't want to do this unless you - * want to completely replace all of the options defined by base classes. - */ -void ProgramBase:: -clear_options() { - _options_by_name.clear(); -} - -/** - * Adds (or redefines) a command line option. When parse_command_line() is - * executed it will look for these options (followed by a hyphen) on the - * command line; when a particular option is found it will call the indicated - * option_function, supplying the provided option_data. This allows the user - * to define a function that does some special behavior for any given option, - * or to use any of a number of generic pre-defined functions to fill in data - * for each option. - * - * Each option may or may not take a parameter. If parm_name is nonempty, it - * is assumed that the option does take a parameter (and parm_name contains - * the name that will be printed by show_options()). This parameter will be - * supplied as the second parameter to the dispatch function. If parm_name is - * empty, it is assumed that the option does not take a parameter. There is - * no provision for optional parameters. - * - * The options are listed first in order by their index_group number, and then - * in the order that add_option() was called. This provides a mechanism for - * listing the options defined in derived classes before those of the base - * classes. - */ -void ProgramBase:: -add_option(const string &option, const string &parm_name, - int index_group, const string &description, - OptionDispatchFunction option_function, - bool *bool_var, void *option_data) { - Option opt; - opt._option = option; - opt._parm_name = parm_name; - opt._index_group = index_group; - opt._sequence = ++_next_sequence; - opt._description = description; - opt._option_function = option_function; - opt._option_method = (OptionDispatchMethod)nullptr; - opt._bool_var = bool_var; - opt._option_data = option_data; - - _options_by_name[option] = opt; - _sorted_options = false; - - if (bool_var != nullptr) { - (*bool_var) = false; - } -} - -/** - * This is another variant on add_option(), above, except that it receives a - * pointer to a "method", which is really just another static (or global) - * function, whose first parameter is a ProgramBase *. - * - * We can't easily add a variant that accepts a real method, because the C++ - * syntax for methods requires us to know exactly what class object the method - * is defined for, and we want to support adding pointers for methods that are - * defined in other classes. So we have this hacky thing, which requires the - * "method" to be declared static, and receive its this pointer explicitly, as - * the first argument. - */ -void ProgramBase:: -add_option(const string &option, const string &parm_name, - int index_group, const string &description, - OptionDispatchMethod option_method, - bool *bool_var, void *option_data) { - Option opt; - opt._option = option; - opt._parm_name = parm_name; - opt._index_group = index_group; - opt._sequence = ++_next_sequence; - opt._description = description; - opt._option_function = (OptionDispatchFunction)nullptr; - opt._option_method = option_method; - opt._bool_var = bool_var; - opt._option_data = option_data; - - _options_by_name[option] = opt; - _sorted_options = false; - - if (bool_var != nullptr) { - (*bool_var) = false; - } -} - -/** - * Changes the description associated with a previously-defined option. - * Returns true if the option was changed, false if it hadn't been defined. - */ -bool ProgramBase:: -redescribe_option(const string &option, const string &description) { - OptionsByName::iterator oi = _options_by_name.find(option); - if (oi == _options_by_name.end()) { - return false; - } - (*oi).second._description = description; - return true; -} - -/** - * Removes a previously-defined option. Returns true if the option was - * removed, false if it hadn't existed. - */ -bool ProgramBase:: -remove_option(const string &option) { - OptionsByName::iterator oi = _options_by_name.find(option); - if (oi == _options_by_name.end()) { - return false; - } - _options_by_name.erase(oi); - _sorted_options = false; - return true; -} - -/** - * Adds -pr etc. as valid options for this program. These are appropriate - * for a model converter or model reader type program, and specify how to - * locate possibly-invalid pathnames in the source model file. - */ -void ProgramBase:: -add_path_replace_options() { - add_option - ("pr", "path_replace", 40, - "Sometimes references to other files (textures, external references) " - "are stored with a full path that is appropriate for some other system, " - "but does not exist here. This option may be used to specify how " - "those invalid paths map to correct paths. Generally, this is of " - "the form 'orig_prefix=replacement_prefix', which indicates a " - "particular initial sequence of characters that should be replaced " - "with a new sequence; e.g. '/c/home/models=/beta/fish'. " - "If the replacement prefix does not begin with a slash, the file " - "will then be searched for along the search path specified by -pp. " - "You may use standard filename matching characters ('*', '?', etc.) in " - "the original prefix, and '**' as a component by itself stands for " - "any number of components.\n\n" - - "This option may be repeated as necessary; each file will be tried " - "against each specified method, in the order in which they appear in " - "the command line, until the file is found. If the file is not found, " - "the last matching prefix is used anyway.", - &ProgramBase::dispatch_path_replace, nullptr, _path_replace.p()); - - add_option - ("pp", "dirname", 40, - "Adds the indicated directory name to the list of directories to " - "search for filenames referenced by the source file. This is used " - "only for relative paths, or for paths that are made relative by a " - "-pr replacement string that doesn't begin with a leading slash. " - "The model-path is always implicitly searched anyway.", - &ProgramBase::dispatch_search_path, nullptr, &(_path_replace->_path)); -} - -/** - * Adds -ps etc. as valid options for this program. These are appropriate - * for a model converter type program, and specify how to represent filenames - * in the output file. - */ -void ProgramBase:: -add_path_store_options() { - // If a program has path store options at all, the default path store is - // relative. - _path_replace->_path_store = PS_relative; - - add_option - ("ps", "path_store", 40, - "Specifies the way an externally referenced file is to be " - "represented in the resulting output file. This " - "assumes the named filename actually exists; " - "see -pr to indicate how to deal with external " - "references that have bad pathnames. " - "This option will not help you to find a missing file, but simply " - "controls how filenames are represented in the output.\n\n" - - "The option may be one of: rel, abs, rel_abs, strip, or keep. If " - "either rel or rel_abs is specified, the files are made relative to " - "the directory specified by -pd. The default is rel.", - &ProgramBase::dispatch_path_store, &_got_path_store, - &(_path_replace->_path_store)); - - add_option - ("pd", "path_directory", 40, - "Specifies the name of a directory to make paths relative to, if " - "'-ps rel' or '-ps rel_abs' is specified. If this is omitted, the " - "directory name is taken from the name of the output file.", - &ProgramBase::dispatch_filename, &_got_path_directory, - &(_path_replace->_path_directory)); - - add_option - ("pc", "target_directory", 40, - "Copies textures and other dependent files into the indicated " - "directory. If a relative pathname is specified, it is relative " - "to the directory specified with -pd, above.", - &ProgramBase::dispatch_filename, &(_path_replace->_copy_files), - &(_path_replace->_copy_into_directory)); -} - -/** - * Standard dispatch function for an option that takes no parameters, and does - * nothing special. Typically this would be used for a boolean flag, whose - * presence means something and whose absence means something else. Use the - * bool_var parameter to add_option() to determine whether the option appears - * on the command line or not. - */ -bool ProgramBase:: -dispatch_none(const string &, const string &, void *) { - return true; -} - -/** - * Standard dispatch function for an option that takes no parameters, and when - * it is present sets a bool variable to the 'true' value. This is another - * way to handle a boolean flag. See also dispatch_none() and - * dispatch_false(). - * - * The data pointer is to a bool variable. - */ -bool ProgramBase:: -dispatch_true(const string &, const string &, void *var) { - bool *bp = (bool *)var; - (*bp) = true; - return true; -} - -/** - * Standard dispatch function for an option that takes no parameters, and when - * it is present sets a bool variable to the 'false' value. This is another - * way to handle a boolean flag. See also dispatch_none() and - * dispatch_true(). - * - * The data pointer is to a bool variable. - */ -bool ProgramBase:: -dispatch_false(const string &, const string &, void *var) { - bool *bp = (bool *)var; - (*bp) = false; - return true; -} - -/** - * Standard dispatch function for an option that takes no parameters, but - * whose presence on the command line increments an integer counter for each - * time it appears. -v is often an option that works this way. The data - * pointer is to an int counter variable. - */ -bool ProgramBase:: -dispatch_count(const string &, const string &, void *var) { - int *ip = (int *)var; - (*ip)++; - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as an integer. The data pointer is to an int variable. - */ -bool ProgramBase:: -dispatch_int(const string &opt, const string &arg, void *var) { - int *ip = (int *)var; - - if (!string_to_int(arg, *ip)) { - nout << "Invalid integer parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes a pair of integer - * parameters. The data pointer is to an array of two integers. - */ -bool ProgramBase:: -dispatch_int_pair(const string &opt, const string &arg, void *var) { - int *ip = (int *)var; - - vector_string words; - tokenize(arg, words, ","); - - bool okflag = false; - if (words.size() == 2) { - okflag = - string_to_int(words[0], ip[0]) && - string_to_int(words[1], ip[1]); - } - - if (!okflag) { - nout << "-" << opt - << " requires a pair of integers separated by a comma.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes a quad of integer - * parameters. The data pointer is to an array of four integers. - */ -bool ProgramBase:: -dispatch_int_quad(const string &opt, const string &arg, void *var) { - int *ip = (int *)var; - - vector_string words; - tokenize(arg, words, ","); - - bool okflag = false; - if (words.size() == 4) { - okflag = - string_to_int(words[0], ip[0]) && - string_to_int(words[1], ip[1]) && - string_to_int(words[1], ip[2]) && - string_to_int(words[1], ip[3]); - } - - if (!okflag) { - nout << "-" << opt - << " requires a quad of integers separated by a comma.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a double. The data pointer is to an double variable. - */ -bool ProgramBase:: -dispatch_double(const string &opt, const string &arg, void *var) { - double *ip = (double *)var; - - if (!string_to_double(arg, *ip)) { - nout << "Invalid numeric parameter for -" << opt << ": " - << arg << "\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes a pair of double - * parameters. The data pointer is to an array of two doubles. - */ -bool ProgramBase:: -dispatch_double_pair(const string &opt, const string &arg, void *var) { - double *ip = (double *)var; - - vector_string words; - tokenize(arg, words, ","); - - bool okflag = false; - if (words.size() == 2) { - okflag = - string_to_double(words[0], ip[0]) && - string_to_double(words[1], ip[1]); - } - - if (!okflag) { - nout << "-" << opt - << " requires a pair of numbers separated by a comma.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes a triple of double - * parameters. The data pointer is to an array of three doubles. - */ -bool ProgramBase:: -dispatch_double_triple(const string &opt, const string &arg, void *var) { - double *ip = (double *)var; - - vector_string words; - tokenize(arg, words, ","); - - bool okflag = false; - if (words.size() == 3) { - okflag = - string_to_double(words[0], ip[0]) && - string_to_double(words[1], ip[1]) && - string_to_double(words[2], ip[2]); - } - - if (!okflag) { - nout << "-" << opt - << " requires three numbers separated by commas.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes a quad of double - * parameters. The data pointer is to an array of four doubles. - */ -bool ProgramBase:: -dispatch_double_quad(const string &opt, const string &arg, void *var) { - double *ip = (double *)var; - - vector_string words; - tokenize(arg, words, ","); - - bool okflag = false; - if (words.size() == 4) { - okflag = - string_to_double(words[0], ip[0]) && - string_to_double(words[1], ip[1]) && - string_to_double(words[2], ip[2]) && - string_to_double(words[3], ip[3]); - } - - if (!okflag) { - nout << "-" << opt - << " requires four numbers separated by commas.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes a color, as l or l,a or - * r,g,b or r,g,b,a. The data pointer is to an array of four floats, e.g. a - * LColor. - */ -bool ProgramBase:: -dispatch_color(const string &opt, const string &arg, void *var) { - PN_stdfloat *ip = (PN_stdfloat *)var; - - vector_string words; - tokenize(arg, words, ","); - - bool okflag = false; - switch (words.size()) { - case 4: - okflag = - string_to_stdfloat(words[0], ip[0]) && - string_to_stdfloat(words[1], ip[1]) && - string_to_stdfloat(words[2], ip[2]) && - string_to_stdfloat(words[3], ip[3]); - break; - - case 3: - okflag = - string_to_stdfloat(words[0], ip[0]) && - string_to_stdfloat(words[1], ip[1]) && - string_to_stdfloat(words[2], ip[2]); - ip[3] = 1.0; - break; - - case 2: - okflag = - string_to_stdfloat(words[0], ip[0]) && - string_to_stdfloat(words[1], ip[3]); - ip[1] = ip[0]; - ip[2] = ip[0]; - break; - - case 1: - okflag = - string_to_stdfloat(words[0], ip[0]); - ip[1] = ip[0]; - ip[2] = ip[0]; - ip[3] = 1.0; - break; - } - - if (!okflag) { - nout << "-" << opt - << " requires one through four numbers separated by commas.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a string. The data pointer is to a string variable. - */ -bool ProgramBase:: -dispatch_string(const string &, const string &arg, void *var) { - string *ip = (string *)var; - (*ip) = arg; - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a string. This is different from dispatch_string in - * that the parameter may be repeated multiple times, and each time the string - * value is appended to a vector. - * - * The data pointer is to a vector_string variable. - */ -bool ProgramBase:: -dispatch_vector_string(const string &, const string &arg, void *var) { - vector_string *ip = (vector_string *)var; - (*ip).push_back(arg); - - return true; -} - -/** - * Similar to dispatch_vector_string, but a comma is allowed to separate - * multiple tokens in one argument, without having to repeat the argument for - * each token. - * - * The data pointer is to a vector_string variable. - */ -bool ProgramBase:: -dispatch_vector_string_comma(const string &, const string &arg, void *var) { - vector_string *ip = (vector_string *)var; - - vector_string words; - tokenize(arg, words, ","); - - vector_string::const_iterator wi; - for (wi = words.begin(); wi != words.end(); ++wi) { - (*ip).push_back(*wi); - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a filename. The data pointer is to a Filename - * variable. - */ -bool ProgramBase:: -dispatch_filename(const string &opt, const string &arg, void *var) { - if (arg.empty()) { - nout << "-" << opt << " requires a filename parameter.\n"; - return false; - } - - Filename *ip = (Filename *)var; - (*ip) = Filename::from_os_specific(arg); - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a single directory name to add to a search path. The - * data pointer is to a DSearchPath variable. This kind of option may appear - * multiple times on the command line; each time, the new directory is - * appended. - */ -bool ProgramBase:: -dispatch_search_path(const string &opt, const string &arg, void *var) { - if (arg.empty()) { - nout << "-" << opt << " requires a search path parameter.\n"; - return false; - } - - DSearchPath *ip = (DSearchPath *)var; - ip->append_directory(Filename::from_os_specific(arg)); - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a coordinate system string. The data pointer is to a - * CoordinateSystem variable. - */ -bool ProgramBase:: -dispatch_coordinate_system(const string &opt, const string &arg, void *var) { - CoordinateSystem *ip = (CoordinateSystem *)var; - (*ip) = parse_coordinate_system_string(arg); - - if ((*ip) == CS_invalid) { - nout << "Invalid coordinate system for -" << opt << ": " << arg << "\n" - << "Valid coordinate system strings are any of 'y-up', 'z-up', " - "'y-up-left', or 'z-up-left'.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a unit of distance measurement. The data pointer is - * to a DistanceUnit variable. - */ -bool ProgramBase:: -dispatch_units(const string &opt, const string &arg, void *var) { - DistanceUnit *ip = (DistanceUnit *)var; - (*ip) = string_distance_unit(arg); - - if ((*ip) == DU_invalid) { - nout << "Invalid units for -" << opt << ": " << arg << "\n" - << "Valid units are mm, cm, m, km, yd, ft, in, nmi, and mi.\n"; - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to indicate an image file type, like rgb, bmp, jpg, etc. The data pointer - * is to a PNMFileType pointer. - */ -bool ProgramBase:: -dispatch_image_type(const string &opt, const string &arg, void *var) { - PNMFileType **ip = (PNMFileType **)var; - - PNMFileTypeRegistry *reg = PNMFileTypeRegistry::get_global_ptr(); - - (*ip) = reg->get_type_from_extension(arg); - - if ((*ip) == nullptr) { - nout << "Invalid image type for -" << opt << ": " << arg << "\n" - << "The following image types are known:\n"; - reg->write(nout, 2); - return false; - } - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a single component of a path replace request. The - * data pointer is to a PathReplace variable. - */ -bool ProgramBase:: -dispatch_path_replace(const string &opt, const string &arg, void *var) { - PathReplace *ip = (PathReplace *)var; - size_t equals = arg.find('='); - if (equals == string::npos) { - nout << "Invalid path replacement string for -" << opt << ": " << arg << "\n" - << "String should be of the form 'old-prefix=new-prefix'.\n"; - return false; - } - ip->add_pattern(arg.substr(0, equals), arg.substr(equals + 1)); - - return true; -} - -/** - * Standard dispatch function for an option that takes one parameter, which is - * to be interpreted as a path store string. The data pointer is to a - * PathStore variable. - */ -bool ProgramBase:: -dispatch_path_store(const string &opt, const string &arg, void *var) { - PathStore *ip = (PathStore *)var; - (*ip) = string_path_store(arg); - - if ((*ip) == PS_invalid) { - nout << "Invalid path store for -" << opt << ": " << arg << "\n" - << "Valid path store strings are any of 'rel', 'abs', " - << "'rel_abs', 'strip', or 'keep'.\n"; - return false; - } - - return true; -} - -/** - * Called when the user enters '-h', this describes how to use the program and - * then exits. - */ -bool ProgramBase:: -handle_help_option(const string &, const string &, void *data) { - ProgramBase *me = (ProgramBase *)data; - me->show_description(); - me->show_usage(); - me->show_options(); - exit(0); - - return false; -} - - -/** - * Word-wraps the indicated text to the indicated output stream. The first - * line is prefixed with the indicated prefix, then tabbed over to - * indent_width where the text actually begins. A newline is inserted at or - * before column line_width. Each subsequent line begins with indent_width - * spaces. - * - * An embedded newline character ('\n') forces a line break, while an embedded - * carriage-return character ('\r'), or two or more consecutive newlines, - * marks a paragraph break, which is usually printed as a blank line. - * Redundant newline and carriage-return characters are generally ignored. - * - * The flag last_newline should be initialized to false for the first call to - * format_text, and then preserved for future calls; it tracks the state of - * trailing newline characters between calls so we can correctly identify - * doubled newlines. - */ -void ProgramBase:: -format_text(std::ostream &out, bool &last_newline, - const string &prefix, int indent_width, - const string &text, int line_width) { - indent_width = min(indent_width, line_width - 20); - int indent_amount = indent_width; - bool initial_break = false; - - if (!prefix.empty()) { - out << prefix; - indent_amount = indent_width - prefix.length(); - if ((int)prefix.length() + 1 > indent_width) { - out << "\n"; - initial_break = true; - indent_amount = indent_width; - } - } - - size_t p = 0; - - // Skip any initial whitespace and newlines. - while (p < text.length() && isspace(text[p])) { - if (text[p] == '\r' || - (p > 0 && text[p] == '\n' && text[p - 1] == '\n') || - (p == 0 && text[p] == '\n' && last_newline)) { - if (!initial_break) { - // Here's an initial paragraph break, however. - out << "\n"; - initial_break = true; - } - indent_amount = indent_width; - - } else if (text[p] == '\n') { - // Largely ignore an initial newline. - indent_amount = indent_width; - - } else if (text[p] == ' ') { - // Do count up leading spaces. - indent_amount++; - } - p++; - } - - last_newline = (!text.empty() && text[text.length() - 1] == '\n'); - - while (p < text.length()) { - // Look for the paragraph or line break--the next newline character, if - // any. - size_t par = text.find_first_of("\n\r", p); - bool is_paragraph_break = false; - if (par == string::npos) { - par = text.length(); - /* - This shouldn't be necessary. - } else { - is_paragraph_break = (text[par] == '\r'); - */ - } - - indent(out, indent_amount); - - size_t eol = p + (line_width - indent_width); - if (eol >= par) { - // The rest of the paragraph fits completely on the line. - eol = par; - - } else { - // The paragraph doesn't fit completely on the line. Determine the best - // place to break the line. Look for the last space before the ideal - // eol. - size_t min_eol = max((int)p, (int)eol - 25); - size_t q = eol; - while (q > min_eol && !isspace(text[q])) { - q--; - } - // Now roll back to the last non-space before this one. - while (q > min_eol && isspace(text[q])) { - q--; - } - - if (q != min_eol) { - // Here's a good place to stop! - eol = q + 1; - - } else { - // The line cannot be broken cleanly. Just let it keep going; don't - // try to wrap it. - eol = par; - } - } - out << text.substr(p, eol - p) << "\n"; - p = eol; - - // Skip additional whitespace between the lines. - while (p < text.length() && isspace(text[p])) { - if (text[p] == '\r' || - (p > 0 && text[p] == '\n' && text[p - 1] == '\n')) { - is_paragraph_break = true; - } - p++; - } - - if (eol == par && is_paragraph_break) { - // Print the paragraph break as a blank line. - out << "\n"; - if (p >= text.length()) { - // If we end on a paragraph break, don't try to insert a new one in - // the next pass. - last_newline = false; - } - } - - indent_amount = indent_width; - } -} - - -/** - * Puts all the options in order by index number (e.g. in the order they were - * added, within index_groups), for output by show_options(). - */ -void ProgramBase:: -sort_options() { - if (!_sorted_options) { - _options_by_index.clear(); - - OptionsByName::const_iterator oi; - for (oi = _options_by_name.begin(); oi != _options_by_name.end(); ++oi) { - _options_by_index.push_back(&(*oi).second); - } - - sort(_options_by_index.begin(), _options_by_index.end(), - SortOptionsByIndex()); - _sorted_options = true; - } -} - -/** - * Attempts to determine the ideal terminal width for formatting output. - */ -void ProgramBase:: -get_terminal_width() { - if (!_got_terminal_width) { - _got_terminal_width = true; - _got_option_indent = false; - -#ifdef IOCTL_TERMINAL_WIDTH - if (use_terminal_width) { - struct winsize size; - int result = ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&size); - if (result < 0 || size.ws_col < 10) { - // Couldn't determine the width for some reason. Instead of - // complaining, just punt. - _terminal_width = default_terminal_width; - } else { - - // Subtract 10% for the comfort margin at the edge. - _terminal_width = size.ws_col - min(8, (int)(size.ws_col * 0.1)); - } - return; - } -#endif // IOCTL_TERMINAL_WIDTH - - _terminal_width = default_terminal_width; - } -} diff --git a/pandatool/src/progbase/programBase.h b/pandatool/src/progbase/programBase.h deleted file mode 100644 index a245e999..00000000 --- a/pandatool/src/progbase/programBase.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file programBase.h - * @author drose - * @date 2000-02-13 - */ - -#ifndef PROGRAMBASE_H -#define PROGRAMBASE_H - -#include "pandatoolbase.h" - -#include "distanceUnit.h" -#include "pathReplace.h" -#include "pathStore.h" -#include "filename.h" -#include "pointerTo.h" -#include "vector_string.h" -#include "pvector.h" -#include "pdeque.h" -#include "pmap.h" - -/** - * This is intended to be the base class for most general-purpose utility - * programs in the PANDATOOL tree. It automatically handles things like - * command-line arguments in a portable way. - */ -class ProgramBase { -public: - enum ExitCode { - EC_not_exited = -1, - EC_clean_exit = 0, - EC_failure = 1 - }; - - ProgramBase(const std::string &name = std::string()); - virtual ~ProgramBase(); - - void show_description(); - void show_usage(); - void show_options(); - - INLINE void show_text(const std::string &text); - void show_text(const std::string &prefix, int indent_width, std::string text); - - void write_man_page(std::ostream &out); - - virtual ExitCode parse_command_line(int argc, char **argv, bool exit_on_complete = true); - - std::string get_exec_command() const; - - typedef pdeque Args; - Filename _program_name; - Args _program_args; - -protected: - typedef bool (*OptionDispatchFunction)(const std::string &opt, const std::string &parm, void *data); - typedef bool (*OptionDispatchMethod)(ProgramBase *self, const std::string &opt, const std::string &parm, void *data); - - virtual bool handle_args(Args &args); - virtual bool post_command_line(); - - void set_program_brief(const std::string &brief); - void set_program_description(const std::string &description); - void clear_runlines(); - void add_runline(const std::string &runline); - void clear_options(); - void add_option(const std::string &option, const std::string &parm_name, - int index_group, const std::string &description, - OptionDispatchFunction option_function, - bool *bool_var = nullptr, - void *option_data = nullptr); - void add_option(const std::string &option, const std::string &parm_name, - int index_group, const std::string &description, - OptionDispatchMethod option_method, - bool *bool_var = nullptr, - void *option_data = nullptr); - bool redescribe_option(const std::string &option, const std::string &description); - bool remove_option(const std::string &option); - - void add_path_replace_options(); - void add_path_store_options(); - - static bool dispatch_none(const std::string &opt, const std::string &arg, void *); - static bool dispatch_true(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_false(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_count(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_int(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_int_pair(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_int_quad(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_double(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_double_pair(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_double_triple(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_double_quad(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_color(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_string(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_vector_string(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_vector_string_comma(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_filename(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_search_path(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_coordinate_system(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_units(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_image_type(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_path_replace(const std::string &opt, const std::string &arg, void *var); - static bool dispatch_path_store(const std::string &opt, const std::string &arg, void *var); - - static bool handle_help_option(const std::string &opt, const std::string &arg, void *); - - static void format_text(std::ostream &out, bool &last_newline, - const std::string &prefix, int indent_width, - const std::string &text, int line_width); - - PT(PathReplace) _path_replace; - bool _got_path_store; - bool _got_path_directory; - - -private: - void sort_options(); - void get_terminal_width(); - - class Option { - public: - std::string _option; - std::string _parm_name; - int _index_group; - int _sequence; - std::string _description; - OptionDispatchFunction _option_function; - OptionDispatchMethod _option_method; - bool *_bool_var; - void *_option_data; - }; - - class SortOptionsByIndex { - public: - bool operator () (const Option *a, const Option *b) const; - }; - - std::string _name; - std::string _brief; - std::string _description; - typedef vector_string Runlines; - Runlines _runlines; - - typedef pmap OptionsByName; - typedef pvector OptionsByIndex; - OptionsByName _options_by_name; - OptionsByIndex _options_by_index; - int _next_sequence; - bool _sorted_options; - - typedef pmap GotOptions; - GotOptions _got_options; - - bool _last_newline; - int _terminal_width; - bool _got_terminal_width; - int _option_indent; - bool _got_option_indent; -}; - -#include "programBase.I" - -#endif diff --git a/pandatool/src/progbase/test_prog.cxx b/pandatool/src/progbase/test_prog.cxx deleted file mode 100644 index 289b68c8..00000000 --- a/pandatool/src/progbase/test_prog.cxx +++ /dev/null @@ -1,69 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file test_prog.cxx - * @author drose - * @date 2000-02-14 - */ - -#include "programBase.h" - -#include "pnotify.h" - -class TestProgram : public ProgramBase { -public: - TestProgram(); - - bool _bool_a; - int _count_b; - int _int_c; -}; - -TestProgram:: -TestProgram() { - set_program_brief("test program for ProgramBase class"); - set_program_description - ("This is a simple test program to verify the effectiveness of the " - "ProgramBase base class as a base class for simple programs. It " - "includes some simple options and some description strings that are " - "long enough to require word-wrapping.\r" - "Don't expect anything fancy, though."); - add_runline("[opts]"); - - add_option - ("bog", "", 90, - "This is test option 'bog'. It is a simple boolean toggle; if it appears " - "at all, it sets a boolean flag to indicate that. If it does not " - "appear, it leaves the boolean flag alone.\r" - "There's not a whole lot of point to this option, when you come down " - "to it.", - &TestProgram::dispatch_none, &_bool_a); - - add_option - ("b", "", 90, "Test option b", - &TestProgram::dispatch_count, nullptr, &_count_b); - _count_b = 0; - - add_option - ("c", "integer_parameter", 90, - "This is test option 'c'. It takes an integer parameter.", - &TestProgram::dispatch_int, nullptr, &_int_c); - _int_c = 0; -} - - -int main(int argc, char *argv[]) { - TestProgram t; - t.parse_command_line(argc, argv); - - nout << "Executed successfully.\n" - << " _bool_a = " << t._bool_a << "\n" - << " _count_b = " << t._count_b << "\n" - << " _int_c = " << t._int_c << "\n"; - return 0; -} diff --git a/pandatool/src/progbase/withOutputFile.I b/pandatool/src/progbase/withOutputFile.I deleted file mode 100644 index 1daa8487..00000000 --- a/pandatool/src/progbase/withOutputFile.I +++ /dev/null @@ -1,21 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file withOutputFile.I - * @author drose - * @date 2003-10-01 - */ - -/** - * Changes the flag specifying whether the output file is to be opened in - * binary mode or not. - */ -INLINE void WithOutputFile:: -set_binary_output(bool binary_output) { - _binary_output = binary_output; -} diff --git a/pandatool/src/progbase/withOutputFile.cxx b/pandatool/src/progbase/withOutputFile.cxx deleted file mode 100644 index 04e5005f..00000000 --- a/pandatool/src/progbase/withOutputFile.cxx +++ /dev/null @@ -1,200 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file withOutputFile.cxx - * @author drose - * @date 2001-04-11 - */ - -#include "withOutputFile.h" -#include "executionEnvironment.h" -#include "zStream.h" - -#include "pnotify.h" - -/** - * - */ -WithOutputFile:: -WithOutputFile(bool allow_last_param, bool allow_stdout, - bool binary_output) { - _allow_last_param = allow_last_param; - _allow_stdout = allow_stdout; - _binary_output = binary_output; - _got_output_filename = false; - _output_ptr = nullptr; - _owns_output_ptr = false; -} - -/** - * - */ -WithOutputFile:: -~WithOutputFile() { - if (_owns_output_ptr) { - delete _output_ptr; - _owns_output_ptr = false; - } -} - -/** - * Returns an output stream that corresponds to the user's intended egg file - * output--either stdout, or the named output file. - */ -std::ostream &WithOutputFile:: -get_output() { - if (_output_ptr == nullptr) { - if (!_got_output_filename) { - // No filename given; use standard output. - if (!_allow_stdout) { - nout << "No output filename specified.\n"; - exit(1); - } - _output_ptr = &std::cout; - _owns_output_ptr = false; - - } else { - // Attempt to open the named file. - unlink(_output_filename.c_str()); - _output_filename.make_dir(); - - bool pz_file = false; -#ifdef HAVE_ZLIB - if (_output_filename.get_extension() == "pz") { - // The filename ends in .pz, which means to automatically compress the - // file that we write. - pz_file = true; - } -#endif // HAVE_ZLIB - - if (_binary_output || pz_file) { - _output_filename.set_binary(); - } else { - _output_filename.set_text(); - } - - _output_stream.clear(); - if (!_output_filename.open_write(_output_stream)) { - nout << "Unable to write to " << _output_filename << "\n"; - exit(1); - } - nout << "Writing " << _output_filename << "\n"; - _output_ptr = &_output_stream; - _owns_output_ptr = false; - -#ifdef HAVE_ZLIB - if (pz_file) { - _output_ptr = new OCompressStream(_output_ptr, _owns_output_ptr); - _owns_output_ptr = true; - } -#endif // HAVE_ZLIB - } - } - return *_output_ptr; -} - -/** - * Closes the output stream previously opened by get_output(). A subsequent - * call to get_output() will open a new stream. - */ -void WithOutputFile:: -close_output() { - if (_owns_output_ptr) { - delete _output_ptr; - _owns_output_ptr = false; - } - _output_ptr = nullptr; - _output_stream.close(); -} - - - -/** - * Returns true if the user specified an output filename, false otherwise - * (e.g. the output file is implicitly stdout). - */ -bool WithOutputFile:: -has_output_filename() const { - return _got_output_filename; -} - -/** - * If has_output_filename() returns true, this is the filename that the user - * specified. Otherwise, it returns the empty string. - */ -Filename WithOutputFile:: -get_output_filename() const { - if (_got_output_filename) { - return _output_filename; - } - return Filename(); -} - -/** - * Checks if the last filename on the argument list is a file with the - * expected extension (if _allow_last_param was set true), and removes it from - * the argument list if it is. Returns true if the arguments are good, false - * if something is invalid. - * - * minimum_args is the number of arguments we know must be input parameters - * and therefore cannot be interpreted as output filenames. - */ -bool WithOutputFile:: -check_last_arg(ProgramBase::Args &args, int minimum_args) { - if (_allow_last_param && !_got_output_filename && - (int)args.size() > minimum_args) { - Filename filename = Filename::from_os_specific(args.back()); - - if (!_preferred_extension.empty() && - ("." + filename.get_extension()) != _preferred_extension) { - // This argument must not be an output filename. - if (!_allow_stdout) { - nout << "Output filename " << filename - << " does not end in " << _preferred_extension - << ". If this is really what you intended, " - "use the -o output_file syntax.\n"; - return false; - } - - } else { - // This argument appears to be an output filename. - _got_output_filename = true; - _output_filename = filename; - args.pop_back(); - - if (!verify_output_file_safe()) { - return false; - } - } - } - - return true; -} - -/** - * This is called when the output file is given as the last parameter on the - * command line. Since this is a fairly dangerous way to specify the output - * file (it's easy to accidentally overwrite an input file this way), the - * convention is to disallow this syntax if the output file already exists. - * - * This function will test if the output file exists, and issue a warning - * message if it does, returning false. If all is well, it will return true. - */ -bool WithOutputFile:: -verify_output_file_safe() const { - nassertr(_got_output_filename, false); - - if (_output_filename.exists()) { - nout << "The output filename " << _output_filename << " already exists. " - "If you wish to overwrite it, you must use the -o option to specify " - "the output filename, instead of simply specifying it as the last " - "parameter.\n"; - return false; - } - return true; -} diff --git a/pandatool/src/progbase/withOutputFile.h b/pandatool/src/progbase/withOutputFile.h deleted file mode 100644 index 385114c0..00000000 --- a/pandatool/src/progbase/withOutputFile.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file withOutputFile.h - * @author drose - * @date 2001-04-11 - */ - -#ifndef WITHOUTPUTFILE_H -#define WITHOUTPUTFILE_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "filename.h" - -/** - * This is the bare functionality (intended to be inherited from along with - * ProgramBase or some derivative) for a program that might generate an output - * file. - * - * This provides the has_output_filename() and get_output_filename() methods. - */ -class WithOutputFile { -public: - WithOutputFile(bool allow_last_param, bool allow_stdout, - bool binary_output); - virtual ~WithOutputFile(); - - std::ostream &get_output(); - void close_output(); - bool has_output_filename() const; - Filename get_output_filename() const; - -protected: - INLINE void set_binary_output(bool binary_output); - - bool check_last_arg(ProgramBase::Args &args, int minimum_args); - bool verify_output_file_safe() const; - -protected: - bool _allow_last_param; - bool _allow_stdout; - bool _binary_output; - std::string _preferred_extension; - bool _got_output_filename; - Filename _output_filename; - -private: - std::ofstream _output_stream; - std::ostream *_output_ptr; - bool _owns_output_ptr; -}; - -#include "withOutputFile.I" - -#endif diff --git a/pandatool/src/progbase/wordWrapStream.cxx b/pandatool/src/progbase/wordWrapStream.cxx deleted file mode 100644 index cd069d1e..00000000 --- a/pandatool/src/progbase/wordWrapStream.cxx +++ /dev/null @@ -1,25 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file wordWrapStream.cxx - * @author drose - * @date 2000-06-28 - */ - -#include "wordWrapStream.h" - - -/** - * - */ -WordWrapStream:: -WordWrapStream(ProgramBase *program) : - std::ostream(&_lsb), - _lsb(this, program) -{ -} diff --git a/pandatool/src/progbase/wordWrapStream.h b/pandatool/src/progbase/wordWrapStream.h deleted file mode 100644 index cfa7969d..00000000 --- a/pandatool/src/progbase/wordWrapStream.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file wordWrapStream.h - * @author drose - * @date 2000-06-28 - */ - -#ifndef WORDWRAPSTREAM_H -#define WORDWRAPSTREAM_H - -#include "pandatoolbase.h" - -#include "wordWrapStreamBuf.h" - -/** - * A special ostream that formats all of its output through - * ProgramBase::show_text(). This allows the program to easily word-wrap its - * output messages to fit the terminal width. - * - * By convention (inherited from show_text), a newline written to the - * WordWrapStream indicates a paragraph break, and is generally printed as a - * blank line. To force a line break without a paragraph break, use '\r'. - */ -class WordWrapStream : public std::ostream { -public: - WordWrapStream(ProgramBase *program); - -private: - WordWrapStreamBuf _lsb; -}; - -#endif diff --git a/pandatool/src/progbase/wordWrapStreamBuf.I b/pandatool/src/progbase/wordWrapStreamBuf.I deleted file mode 100644 index 67a0f688..00000000 --- a/pandatool/src/progbase/wordWrapStreamBuf.I +++ /dev/null @@ -1,26 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file wordWrapStreamBuf.I - * @author drose - * @date 2000-07-01 - */ - -/** - * An internal function called to update the internal state according to the - * current value of the Notify::literal flag, which might or might not be set - * of the ostream at any time. When the literal flag is true, we should not - * word-wrap, so toggling this flag means we need to flush the current buffer. - */ -INLINE void WordWrapStreamBuf:: -set_literal_mode(bool mode) { - if (mode != _literal_mode) { - flush_data(); - _literal_mode = mode; - } -} diff --git a/pandatool/src/progbase/wordWrapStreamBuf.cxx b/pandatool/src/progbase/wordWrapStreamBuf.cxx deleted file mode 100644 index 0e0c4abb..00000000 --- a/pandatool/src/progbase/wordWrapStreamBuf.cxx +++ /dev/null @@ -1,114 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file wordWrapStreamBuf.cxx - * @author drose - * @date 2000-06-28 - */ - -#include "wordWrapStreamBuf.h" -#include "wordWrapStream.h" -#include "programBase.h" - -#include "pnotify.h" - -/** - * - */ -WordWrapStreamBuf:: -WordWrapStreamBuf(WordWrapStream *owner, ProgramBase *program) : - _owner(owner), - _program(program) -{ - _literal_mode = false; -} - -/** - * - */ -WordWrapStreamBuf:: -~WordWrapStreamBuf() { - sync(); -} - -/** - * Called by the system ostream implementation when the buffer should be - * flushed to output (for instance, on destruction). - */ -int WordWrapStreamBuf:: -sync() { - std::streamsize n = pptr() - pbase(); - write_chars(pbase(), n); - - // Send all the data out now. - flush_data(); - - return 0; // EOF to indicate write full. -} - -/** - * Called by the system ostream implementation when its internal buffer is - * filled, plus one character. - */ -int WordWrapStreamBuf:: -overflow(int ch) { - std::streamsize n = pptr() - pbase(); - - if (n != 0 && sync() != 0) { - return EOF; - } - - if (ch != EOF) { - // Write one more character. - char c = ch; - write_chars(&c, 1); - } - - pbump(-n); // Reset pptr(). - return 0; -} - -/** - * An internal function called by sync() and overflow() to store one or more - * characters written to the stream into the memory buffer. - */ -void WordWrapStreamBuf:: -write_chars(const char *start, int length) { - if (length > 0) { - set_literal_mode((_owner->flags() & Notify::get_literal_flag()) != 0); - std::string new_data(start, length); - size_t newline = new_data.find_first_of("\n\r"); - size_t p = 0; - while (newline != std::string::npos) { - // The new data contains a newline; flush our data to that point. - _data += new_data.substr(p, newline - p + 1); - flush_data(); - p = newline + 1; - newline = new_data.find_first_of("\n\r", p); - } - - // Save the rest for the next write. - _data += new_data.substr(p); - } -} - -/** - * Writes the contents of _data to the actual output stream, either word- - * wrapped or not as appropriate, and empties the contents of _data. - */ -void WordWrapStreamBuf:: -flush_data() { - if (!_data.empty()) { - if (_literal_mode) { - std::cerr << _data; - } else { - _program->show_text(_data); - } - _data = ""; - } -} diff --git a/pandatool/src/progbase/wordWrapStreamBuf.h b/pandatool/src/progbase/wordWrapStreamBuf.h deleted file mode 100644 index f1c54abf..00000000 --- a/pandatool/src/progbase/wordWrapStreamBuf.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file wordWrapStreamBuf.h - * @author drose - * @date 2000-06-28 - */ - -#ifndef WORDWRAPSTREAMBUF_H -#define WORDWRAPSTREAMBUF_H - -#include "pandatoolbase.h" - -#include - -class ProgramBase; -class WordWrapStream; - -/** - * Used by WordWrapStream to implement an ostream that flushes its output to - * ProgramBase::show_text(). - */ -class WordWrapStreamBuf final : public std::streambuf { -public: - WordWrapStreamBuf(WordWrapStream *owner, ProgramBase *program); - virtual ~WordWrapStreamBuf(); - -protected: - virtual int overflow(int c); - virtual int sync(); - -private: - void write_chars(const char *start, int length); - INLINE void set_literal_mode(bool mode); - void flush_data(); - - std::string _data; - WordWrapStream *_owner; - ProgramBase *_program; - bool _literal_mode; -}; - -#include "wordWrapStreamBuf.I" - -#endif diff --git a/pandatool/src/pstatserver/CMakeLists.txt b/pandatool/src/pstatserver/CMakeLists.txt deleted file mode 100644 index 8587806e..00000000 --- a/pandatool/src/pstatserver/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_NET) - return() -endif() - -set(P3PSTATSERVER_HEADERS - pStatClientData.h - pStatFlameGraph.h pStatFlameGraph.I - pStatGraph.h pStatGraph.I - pStatListener.h - pStatMonitor.h pStatMonitor.I - pStatPianoRoll.h pStatPianoRoll.I - pStatReader.h - pStatServer.h - pStatStripChart.h pStatStripChart.I - pStatThreadData.h pStatThreadData.I - pStatTimeline.h pStatTimeline.I - pStatView.h pStatView.I - pStatViewLevel.h pStatViewLevel.I -) - -set(P3PSTATSERVER_SOURCES - pStatClientData.cxx - pStatFlameGraph.cxx - pStatGraph.cxx - pStatListener.cxx - pStatMonitor.cxx - pStatPianoRoll.cxx - pStatReader.cxx - pStatServer.cxx - pStatStripChart.cxx - pStatThreadData.cxx - pStatTimeline.cxx - pStatView.cxx - pStatViewLevel.cxx -) - -composite_sources(p3pstatserver P3PSTATSERVER_SOURCES) -add_library(p3pstatserver STATIC ${P3PSTATSERVER_HEADERS} ${P3PSTATSERVER_SOURCES}) -target_link_libraries(p3pstatserver p3pandatoolbase panda) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/pstatserver/p3pstatserver_composite1.cxx b/pandatool/src/pstatserver/p3pstatserver_composite1.cxx deleted file mode 100644 index a3f7c09d..00000000 --- a/pandatool/src/pstatserver/p3pstatserver_composite1.cxx +++ /dev/null @@ -1,13 +0,0 @@ -#include "pStatClientData.cxx" -#include "pStatFlameGraph.cxx" -#include "pStatGraph.cxx" -#include "pStatListener.cxx" -#include "pStatMonitor.cxx" -#include "pStatPianoRoll.cxx" -#include "pStatReader.cxx" -#include "pStatServer.cxx" -#include "pStatStripChart.cxx" -#include "pStatThreadData.cxx" -#include "pStatTimeline.cxx" -#include "pStatView.cxx" -#include "pStatViewLevel.cxx" diff --git a/pandatool/src/pstatserver/pStatClientData.cxx b/pandatool/src/pstatserver/pStatClientData.cxx deleted file mode 100644 index a3dc317d..00000000 --- a/pandatool/src/pstatserver/pStatClientData.cxx +++ /dev/null @@ -1,560 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatClientData.cxx - * @author drose - * @date 2000-07-11 - */ - -#include "pStatClientData.h" -#include "pStatFrameData.h" -#include "pStatReader.h" - -#include "pStatCollectorDef.h" - -using std::string; - -PStatCollectorDef PStatClientData::_null_collector(-1, "Unknown"); - -/** - * - */ -PStatClientData:: -PStatClientData(PStatReader *reader) : - _is_alive(true), - _is_dirty(false), - _reader(reader) -{ -} - -/** - * - */ -PStatClientData:: -~PStatClientData() { - for (Collector &collector : _collectors) { - delete collector._def; - } -} - -/** - * Clears the is_dirty() flag. - */ -void PStatClientData:: -clear_dirty() const { - _is_dirty = false; -} - -/** - * Returns true if the data was modified since the last time clear_dirty() was - * called. - */ -bool PStatClientData:: -is_dirty() const { - return _is_dirty; -} - -/** - * Returns true if the data is actively getting filled by a connected client, - * or false if the client has terminated. - */ -bool PStatClientData:: -is_alive() const { - return _is_alive; -} - -/** - * Closes the client connection if it is open. - */ -void PStatClientData:: -close() { - if (_is_alive && _reader != nullptr) { - _reader->close(); - _reader = nullptr; - _is_alive = false; - } -} - -/** - * Returns the timestamp (in seconds elapsed since connection) of the latest - * available frame. - */ -double PStatClientData:: -get_latest_time() const { - double time = 0.0; - for (const Thread &thread : _threads) { - if (thread._data != nullptr && !thread._data->is_empty()) { - time = std::max(time, thread._data->get_latest_time()); - } - } - - return time; -} - -/** - * Returns the total number of collectors the Data knows about. - */ -int PStatClientData:: -get_num_collectors() const { - return _collectors.size(); -} - -/** - * Returns true if the indicated collector has been defined by the client - * already, false otherwise. It is possible for the client to start streaming - * data before all of the collectors have been defined. - */ -bool PStatClientData:: -has_collector(int index) const { - return (index >= 0 && index < (int)_collectors.size() && - _collectors[index]._def != nullptr); -} - -/** - * Returns the index of the collector with the given full name, or -1 if no - * such collector has been defined by the client. - */ -int PStatClientData:: -find_collector(const std::string &fullname) const { - // Take the last bit, we can compare it more cheaply, only check the full - // name if the basename matches. - const char *colon = strrchr(fullname.c_str(), ':'); - std::string name(colon != nullptr ? colon + 1 : fullname.c_str()); - - for (int index = 0; index < get_num_collectors(); ++index) { - const PStatCollectorDef *def = _collectors[index]._def; - if (def != nullptr && def->_name == name && - get_collector_fullname(index) == fullname) { - return index; - } - } - - return -1; -} - -/** - * Returns the nth collector definition. - */ -const PStatCollectorDef &PStatClientData:: -get_collector_def(int index) const { - if (!has_collector(index)) { - return _null_collector; - } - return *_collectors[index]._def; -} - -/** - * Returns the name of the indicated collector. - */ -string PStatClientData:: -get_collector_name(int index) const { - if (!has_collector(index)) { - return "Unknown"; - } - const PStatCollectorDef *def = _collectors[index]._def; - return def->_name; -} - -/** - * Returns the "full name" of the indicated collector. This will be the - * concatenation of all of the collector's parents' names (except Frame) and - * the collector's own name. - */ -string PStatClientData:: -get_collector_fullname(int index) const { - if (!has_collector(index)) { - return "Unknown"; - } - - const PStatCollectorDef *def = _collectors[index]._def; - if (def->_parent_index == 0) { - return def->_name; - } else { - return get_collector_fullname(def->_parent_index) + ":" + def->_name; - } -} - -/** - * Indicates whether the given collector has level data (and consequently, - * whether it should appear on the Levels menu). - * - * The return value is true if anything changed, false otherwise. - */ -bool PStatClientData:: -set_collector_has_level(int index, int thread_index, bool flag) { - bool any_changed = false; - slot_collector(index); - nassertr(index >= 0 && index < (int)_collectors.size(), false); - - if (_collectors[index]._is_level.get_bit(thread_index) != flag) { - any_changed = true; - _collectors[index]._is_level.set_bit_to(thread_index, flag); - } - - // Turning this on for a given collector also implicitly turns all of its - // ancestors. - if (flag) { - PStatCollectorDef *def = _collectors[index]._def; - if (def != nullptr && def->_parent_index != 0) { - if (set_collector_has_level(def->_parent_index, thread_index, flag)) { - any_changed = true; - } - } - } - - if (any_changed) { - _is_dirty = true; - } - - return any_changed; -} - - -/** - * Returns whether the given collector has level data (and consequently, - * whether it should appear on the Levels menu). - */ -bool PStatClientData:: -get_collector_has_level(int index, int thread_index) const { - return (index >= 0 && index < (int)_collectors.size() && - _collectors[index]._is_level.get_bit(thread_index)); -} - -/** - * Returns the total number of collectors that are toplevel collectors. These - * are the collectors that are the children of "Frame", which is collector 0. - */ -int PStatClientData:: -get_num_toplevel_collectors() const { - return _toplevel_collectors.size(); -} - -/** - * Returns the collector index of the nth toplevel collector. Use this - * function to iterate through the n toplevel collectors indicated by - * get_num_toplevel_collectors(). - */ -int PStatClientData:: -get_toplevel_collector(int n) const { - nassertr(n >= 0 && n < (int)_toplevel_collectors.size(), 0); - return _toplevel_collectors[n]; -} - -/** - * Returns the total number of threads the Data knows about. - */ -int PStatClientData:: -get_num_threads() const { - return _threads.size(); -} - -/** - * Returns true if the indicated thread has been defined by the client - * already, false otherwise. It is possible for the client to start streaming - * data before all of the threads have been defined. - */ -bool PStatClientData:: -has_thread(int index) const { - return (index >= 0 && (size_t)index < _threads.size() && - !_threads[index]._name.empty()); -} - -/** - * Returns the index of the thread with the given name, or -1 if no such thread - * has yet been defined. - */ -int PStatClientData:: -find_thread(const std::string &name) const { - for (int index = 0; index < get_num_threads(); ++index) { - if (_threads[index]._name == name) { - return index; - } - } - - return -1; -} - -/** - * Returns the name of the indicated thread. - */ -string PStatClientData:: -get_thread_name(int index) const { - if (!has_thread(index)) { - return "Unknown"; - } - return _threads[index]._name; -} - -/** - * Returns the data associated with the indicated thread. This will create a - * thread definition if it does not already exist. - */ -const PStatThreadData *PStatClientData:: -get_thread_data(int index) const { - ((PStatClientData *)this)->define_thread(index); - nassertr(index >= 0 && (size_t)index < _threads.size(), nullptr); - return _threads[index]._data; -} - -/** - * Returns true if the given thread is still alive. - */ -bool PStatClientData:: -is_thread_alive(int index) const { - return (index >= 0 && (size_t)index < _threads.size() && _threads[index]._is_alive); -} - -/** - * Returns the number of Collectors between the indicated parent and the child - * Collector in the relationship graph. If child is the same as parent, - * returns zero. If child is an immediate child of parent, returns 1. If - * child is a grandchild of parent, returns 2, and so on. If child is not a - * descendant of parent at all, returns -1. - */ -int PStatClientData:: -get_child_distance(int parent, int child) const { - if (parent == child) { - return 0; - } - if (!has_collector(child) || child == 0) { - return -1; - } - int dist = get_child_distance(parent, get_collector_def(child)._parent_index); - if (dist == -1) { - return -1; - } else { - return dist + 1; - } -} - -/** - * Adds a new collector definition to the dataset. Presumably this is - * information just arrived from the client. - * - * The pointer will become owned by the PStatClientData object and will be - * freed on destruction. - */ -void PStatClientData:: -add_collector(PStatCollectorDef *def) { - slot_collector(def->_index); - nassertv(def->_index >= 0 && def->_index < (int)_collectors.size()); - - if (_collectors[def->_index]._def != nullptr) { - // Free the old definition, if any. - delete _collectors[def->_index]._def; - } - - _collectors[def->_index]._def = def; - update_toplevel_collectors(); - - // If we already had the _is_level flag set, it should be immediately - // applied to all ancestors. - const BitArray &is_level = _collectors[def->_index]._is_level; - int max_threads = is_level.get_num_bits(); - for (int thread_index = 0; thread_index < max_threads; ++thread_index) { - if (is_level.get_bit(thread_index)) { - set_collector_has_level(def->_parent_index, thread_index, true); - } - } - - _is_dirty = true; -} - -/** - * Adds a new thread definition to the dataset. Presumably this is - * information just arrived from the client. - */ -void PStatClientData:: -define_thread(int thread_index, const string &name, bool mark_alive) { - // A sanity check on the index number. - nassertv(thread_index < 1000); - - // Make sure we have enough slots allocated. - while ((int)_threads.size() <= thread_index) { - _threads.push_back(Thread()); - } - - if (mark_alive) { - _threads[thread_index]._is_alive = true; - } - - if (!name.empty()) { - _threads[thread_index]._name = name; - } - - if (_threads[thread_index]._data.is_null()) { - _threads[thread_index]._data = new PStatThreadData(this); - } - - _is_dirty = true; -} - -/** - * Indicates that the given thread has expired. Presumably this is information - * just arrived from the client. - */ -void PStatClientData:: -expire_thread(int thread_index) { - if (thread_index >= 0 && (size_t)thread_index < _threads.size()) { - _threads[thread_index]._is_alive = false; - } -} - -/** - * Removes the given thread data entirely. - */ -void PStatClientData:: -remove_thread(int thread_index) { - if (thread_index >= 0 && (size_t)thread_index < _threads.size()) { - _threads[thread_index]._name.clear(); - _threads[thread_index]._data.clear(); - _threads[thread_index]._is_alive = false; - } -} - -/** - * Makes room for and stores a new frame's worth of data associated with some - * particular thread (which may or may not have already been defined). - * - * The pointer will become owned by the PStatThreadData object and will be - * freed on destruction. - */ -void PStatClientData:: -record_new_frame(int thread_index, int frame_number, - PStatFrameData *frame_data) { - define_thread(thread_index); - nassertv(thread_index >= 0 && thread_index < (int)_threads.size()); - _threads[thread_index]._data->record_new_frame(frame_number, frame_data); - _is_dirty = true; -} - -/** - * Writes the client data in the form of a JSON output that can be loaded into - * Chrome's event tracer. - */ -void PStatClientData:: -write_json(std::ostream &out, int pid) const { - out << "[\n"; - - for (int thread_index = 0; thread_index < get_num_threads(); ++thread_index) { - const Thread &thread = _threads[thread_index]; - - if (thread_index == 0) { - out << "{\"name\":\"thread_name\",\"ph\":\"M\",\"pid\":" << pid - << ",\"tid\":0,\"args\":{\"name\":\"Main\"}}"; - } - else if (!thread._name.empty()) { - out - << ",\n{\"name\":\"thread_name\",\"ph\":\"M\",\"pid\":" << pid - << ",\"tid\":" << thread_index << ",\"args\":{\"name\":\"" - << thread._name << "\"}}"; - } - if (thread._data == nullptr || thread._data->is_empty()) { - continue; - } - - int first_frame = thread._data->get_oldest_frame_number(); - int last_frame = thread._data->get_latest_frame_number(); - for (int frame_number = first_frame; frame_number <= last_frame; ++frame_number) { - const PStatFrameData &frame_data = thread._data->get_frame(frame_number); - size_t num_events = frame_data.get_num_events(); - for (size_t i = 0; i < num_events; ++i) { - int collector_index = frame_data.get_time_collector(i); - out - << ",\n{\"name\":\"" << get_collector_fullname(collector_index) - << "\",\"ts\":" << (uint64_t)(frame_data.get_time(i) * 1000000) - << ",\"ph\":\"" << (frame_data.is_start(i) ? 'B' : 'E') << "\"" - << ",\"pid\":" << pid << ",\"tid\":" << thread_index << "}"; - } - } - } - - out << "\n]\n"; - out.flush(); -} - -/** - * Writes the client data to a datagram. - */ -void PStatClientData:: -write_datagram(Datagram &dg) const { - for (const Collector &collector : _collectors) { - PStatCollectorDef *def = collector._def; - if (def != nullptr && def->_index != -1) { - def->write_datagram(dg); - collector._is_level.write_datagram(nullptr, dg); - } - } - dg.add_int16(-1); - - int thread_index = 0; - for (const Thread &thread : _threads) { - if (thread._data != nullptr) { - dg.add_int16(thread_index); - dg.add_string(thread._name); - thread._data->write_datagram(dg); - } - ++thread_index; - } - dg.add_int16(-1); -} - -/** - * Restores the client data from a datagram. - */ -void PStatClientData:: -read_datagram(DatagramIterator &scan) { - while (scan.peek_int16() != -1) { - PStatCollectorDef *def = new PStatCollectorDef; - def->read_datagram(scan); - add_collector(def); - _collectors[def->_index]._is_level.read_datagram(scan, nullptr); - } - scan.skip_bytes(2); - - int thread_index; - while ((thread_index = scan.get_int16()) != -1) { - std::string name = scan.get_string(); - define_thread(thread_index, name, true); - - _threads[thread_index]._data->read_datagram(scan, this); - } - - update_toplevel_collectors(); -} - -/** - * Makes sure there is an entry in the array for a collector with the given - * index number. - */ -void PStatClientData:: -slot_collector(int collector_index) { - // A sanity check on the index number. - nassertv(collector_index < 100000); - - while ((int)_collectors.size() <= collector_index) { - Collector collector; - collector._def = nullptr; - _collectors.push_back(collector); - } -} - -/** - * Rebuilds the list of toplevel collectors. - */ -void PStatClientData:: -update_toplevel_collectors() { - _toplevel_collectors.clear(); - - for (Collector &collector : _collectors) { - PStatCollectorDef *def = collector._def; - if (def != nullptr && def->_parent_index == 0) { - _toplevel_collectors.push_back(def->_index); - } - } -} diff --git a/pandatool/src/pstatserver/pStatClientData.h b/pandatool/src/pstatserver/pStatClientData.h deleted file mode 100644 index bd2bb1d6..00000000 --- a/pandatool/src/pstatserver/pStatClientData.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatClientData.h - * @author drose - * @date 2000-07-11 - */ - -#ifndef PSTATCLIENTDATA_H -#define PSTATCLIENTDATA_H - -#include "pandatoolbase.h" - -#include "pStatThreadData.h" - -#include "pStatClientVersion.h" -#include "referenceCount.h" -#include "pointerTo.h" -#include "bitArray.h" - -#include "pvector.h" -#include "vector_int.h" - -class PStatReader; - -/** - * The data associated with a particular client, but not with any one - * particular frame or thread: the list of collectors and threads, for - * instance. - */ -class PStatClientData : public PStatClientVersion { -public: - PStatClientData() = default; - PStatClientData(PStatReader *reader); - ~PStatClientData(); - - void clear_dirty() const; - bool is_dirty() const; - - bool is_alive() const; - void close(); - - double get_latest_time() const; - - int get_num_collectors() const; - bool has_collector(int index) const; - int find_collector(const std::string &fullname) const; - const PStatCollectorDef &get_collector_def(int index) const; - std::string get_collector_name(int index) const; - std::string get_collector_fullname(int index) const; - bool set_collector_has_level(int index, int thread_index, bool flag); - bool get_collector_has_level(int index, int thread_index) const; - - int get_num_toplevel_collectors() const; - int get_toplevel_collector(int index) const; - - int get_num_threads() const; - bool has_thread(int index) const; - int find_thread(const std::string &name) const; - std::string get_thread_name(int index) const; - const PStatThreadData *get_thread_data(int index) const; - bool is_thread_alive(int index) const; - - int get_child_distance(int parent, int child) const; - - - void add_collector(PStatCollectorDef *def); - void define_thread(int thread_index, const std::string &name = std::string(), - bool mark_alive = false); - void expire_thread(int thread_index); - void remove_thread(int thread_index); - - void record_new_frame(int thread_index, int frame_number, - PStatFrameData *frame_data); - - void write_json(std::ostream &out, int pid = 0) const; - void write_datagram(Datagram &dg) const; - void read_datagram(DatagramIterator &scan); - -private: - void slot_collector(int collector_index); - void update_toplevel_collectors(); - -private: - bool _is_alive = false; - mutable bool _is_dirty = false; - PStatReader *_reader = nullptr; - - class Collector { - public: - PStatCollectorDef *_def; - BitArray _is_level; - }; - - typedef pvector Collectors; - Collectors _collectors; - - typedef vector_int ToplevelCollectors; - ToplevelCollectors _toplevel_collectors; - - class Thread { - public: - std::string _name; - PT(PStatThreadData) _data; - bool _is_alive = false; - }; - typedef pvector Threads; - Threads _threads; - - static PStatCollectorDef _null_collector; - friend class PStatReader; -}; - -#endif diff --git a/pandatool/src/pstatserver/pStatFlameGraph.I b/pandatool/src/pstatserver/pStatFlameGraph.I deleted file mode 100644 index e99afd04..00000000 --- a/pandatool/src/pstatserver/pStatFlameGraph.I +++ /dev/null @@ -1,137 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatFlameGraph.I - * @author rdb - * @date 2022-01-28 - */ - -/** - * Returns the particular thread whose data this flame graph reflects. - */ -INLINE int PStatFlameGraph:: -get_thread_index() const { - return _thread_index; -} - -/** - * Returns the particular collector whose data this flame graph reflects. - */ -INLINE int PStatFlameGraph:: -get_collector_index() const { - return _collector_index; -} - -/** - * Clears the history stack. - */ -INLINE void PStatFlameGraph:: -clear_history() { - _history.clear(); -} - -/** - * Returns the depth of the history stack. - */ -INLINE size_t PStatFlameGraph:: -get_history_depth() const { - return _history.size(); -} - -/** - * Returns the particular frame number whose data this flame graph reflects. - * Returns -1 if we're looking at a moving average instead. - */ -INLINE int PStatFlameGraph:: -get_frame_number() const { - return _frame_number; -} - -/** - * Returns the amount of total time the width of the horizontal axis - * represents. - */ -INLINE double PStatFlameGraph:: -get_horizontal_scale() const { - return _time_width; -} - -/** - * Changes the average_mode flag. When true, the strip chart will average out - * the color values over pstats_average_time seconds, which hides spikes and - * makes the overall trends easier to read. When false, the strip chart shows - * the actual data as it is happening. - * - * If you set this to true, you need to call animate() periodically so that the - * averages are smoothly updated over time. - */ -INLINE void PStatFlameGraph:: -set_average_mode(bool average_mode) { - if (_average_mode != average_mode) { - _average_mode = average_mode; - _stack.reset_averages(); - if (!average_mode) { - _time_width = _stack.get_net_value(false); - normal_guide_bars(); - } - force_redraw(); - } -} - -/** - * Returns the current state of the average_mode flag. When true, the strip - * chart will average out the color values over pstats_average_time seconds, - * which hides spikes and makes the overall trends easier to read. When - * false, the strip chart shows the actual data as it is happening. - */ -INLINE bool PStatFlameGraph:: -get_average_mode() const { - return _average_mode; -} - -/** - * Converts a value (i.e. a "height" in the strip chart) to a horizontal - * pixel offset. - */ -INLINE int PStatFlameGraph:: -height_to_pixel(double value) const { - return (int)((double)_xsize * value / _time_width); -} - -/** - * Converts a horizontal pixel offset to a value (a "height" in the strip - * chart). - */ -INLINE double PStatFlameGraph:: -pixel_to_height(int x) const { - return _time_width * (double)x / (double)_xsize; -} - -/** - * Returns true if get_title_text() has never yet returned an answer, false if - * it has. - */ -INLINE bool PStatFlameGraph:: -is_title_unknown() const { - return _title_unknown; -} -/** - * Returns the net value of this stack level. - */ -INLINE double PStatFlameGraph::StackLevel:: -get_net_value(bool average) const { - if (_collector_index >= 0) { - return average ? _avg_net_value : _net_value; - } else { - double sum = 0.0; - for (auto &item : _children) { - sum += item.second.get_net_value(average); - } - return sum; - } -} diff --git a/pandatool/src/pstatserver/pStatFlameGraph.cxx b/pandatool/src/pstatserver/pStatFlameGraph.cxx deleted file mode 100644 index 93436829..00000000 --- a/pandatool/src/pstatserver/pStatFlameGraph.cxx +++ /dev/null @@ -1,773 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatFlameGraph.cxx - * @author rdb - * @date 2022-01-28 - */ - -#include "pStatFlameGraph.h" - -#include "pStatFrameData.h" -#include "pStatCollectorDef.h" -#include "string_utils.h" -#include "config_pstatclient.h" - -#include -#include - -/** - * - */ -PStatFlameGraph:: -PStatFlameGraph(PStatMonitor *monitor, int thread_index, int collector_index, - int frame_number, int xsize, int ysize) : - PStatGraph(monitor, xsize, ysize), - _thread_index(thread_index), - _collector_index(collector_index), - _orig_collector_index(collector_index), - _frame_number(frame_number) -{ - _average_mode = true; - _average_cursor = 0; - _current_frame = -1; - - _title_unknown = true; - - // NB. This won't call force_redraw() (which we can't do yet) because average - // mode is true - update(); - _time_width = _stack.get_net_value(false); - if (_time_width == 0.0) { - _time_width = 1.0 / pstats_target_frame_rate; - } - - _guide_bar_units = GBU_ms | GBU_hz | GBU_show_units; - - monitor->_flame_graphs.insert(this); -} - -/** - * - */ -PStatFlameGraph:: -~PStatFlameGraph() { - _monitor->_flame_graphs.erase(this); -} - -/** - * Updates the chart with the latest data. - */ -void PStatFlameGraph:: -update() { - const PStatClientData *client_data = _monitor->get_client_data(); - - // Don't bother to update the thread data until we know at least something - // about the collectors and threads. - if (client_data->get_num_collectors() != 0 && - client_data->get_num_threads() != 0) { - const PStatThreadData *thread_data = - client_data->get_thread_data(_thread_index); - if (!thread_data->is_empty()) { - if (_frame_number >= 0) { - if (thread_data->has_frame(_frame_number)) { - if (_current_frame != _frame_number) { - _current_frame = _frame_number; - update_data(); - } - } - } else { - int frame_number = thread_data->get_latest_frame_number(); - if (frame_number != _current_frame) { - _current_frame = frame_number; - - update_data(); - } - } - } - } - - idle(); -} - -/** - * Changes the collector represented by this flame graph. This may force a - * redraw. - * - * Leaves the history stack untouched. - */ -void PStatFlameGraph:: -set_collector_index(int collector_index) { - if (collector_index == -1) { - // First go back to the collector where we originally opened this graph, - // and only then go back to the root. - collector_index = _orig_collector_index; - if (_collector_index == _orig_collector_index) { - collector_index = -1; - _orig_collector_index = -1; - } - } - if (_collector_index != collector_index) { - _collector_index = collector_index; - _title_unknown = true; - _stack.clear(); - update_data(); - - if (_average_mode) { - _stack.update_averages(_average_cursor); - _time_width = _stack.get_net_value(true); - if (_time_width == 0.0) { - _time_width = 1.0 / pstats_target_frame_rate; - } - normal_guide_bars(); - } - } -} - -/** - * Goes to a different collector, but remembers the previous collector. - */ -void PStatFlameGraph:: -push_collector_index(int collector_index) { - if (_collector_index != collector_index) { - _history.push_back(_collector_index); - set_collector_index(collector_index); - } -} - -/** - * Goes to the previous visited collector. Returns true if the history stack - * was non-empty. - */ -bool PStatFlameGraph:: -pop_collector_index() { - if (!_history.empty()) { - int collector_index = _history.back(); - _history.pop_back(); - set_collector_index(collector_index); - return true; - } - return false; -} - -/** - * Changes the frame number shown by this flame graph. This may force a redraw. - */ -void PStatFlameGraph:: -set_frame_number(int frame_number) { - if (_frame_number != frame_number) { - _frame_number = frame_number; - _current_frame = frame_number; - _title_unknown = true; - _stack.clear(); - update_data(); - - if (_average_mode) { - _stack.update_averages(_average_cursor); - _time_width = _stack.get_net_value(true); - if (_time_width == 0.0) { - _time_width = 1.0 / pstats_target_frame_rate; - } - normal_guide_bars(); - } - } -} - -/** - * Sets the frame number to the oldest available frame. - */ -bool PStatFlameGraph:: -first_frame() { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data == nullptr) { - return false; - } - - const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); - if (thread_data == nullptr || thread_data->is_empty()) { - return false; - } - - int oldest = thread_data->get_oldest_frame_number(); - if (_frame_number != oldest && thread_data->has_frame(oldest)) { - set_frame_number(oldest); - return true; - } - return false; -} - -/** - * Advances to the next available frame. Returns true if the frame number was - * changed after a call to this method. - */ -bool PStatFlameGraph:: -next_frame() { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data == nullptr) { - return false; - } - - const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); - if (thread_data == nullptr || thread_data->is_empty()) { - return false; - } - - int latest = thread_data->get_latest_frame_number(); - if (_frame_number < 0 || _frame_number > latest) { - set_frame_number(latest); - return true; - } - - for (int i = _frame_number + 1; i <= latest; ++i) { - if (thread_data->has_frame(i)) { - set_frame_number(i); - return true; - } - } - - return false; -} - -/** - * Reverts to the previous frame. Returns true if the frame number was changed - * after a call to this method. - */ -bool PStatFlameGraph:: -prev_frame() { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data == nullptr) { - return false; - } - - const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); - if (thread_data == nullptr || thread_data->is_empty()) { - return false; - } - - int oldest = thread_data->get_oldest_frame_number(); - - int i; - if (_frame_number < 0) { - i = thread_data->get_latest_frame_number(); - } else { - i = _frame_number - 1; - } - while (i >= oldest) { - if (thread_data->has_frame(i)) { - set_frame_number(i); - return true; - } - --i; - } - - return false; -} - -/** - * Sets the frame number to the latest available frame. - */ -bool PStatFlameGraph:: -last_frame() { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data == nullptr) { - return false; - } - - const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); - if (thread_data == nullptr || thread_data->is_empty()) { - return false; - } - - int latest = thread_data->get_latest_frame_number(); - if (_frame_number != latest && thread_data->has_frame(latest)) { - set_frame_number(latest); - return true; - } - return false; -} - -/** - * Returns the text suitable for the title label on the top line. - */ -std::string PStatFlameGraph:: -get_title_text() { - std::string text; - - _title_unknown = false; - - const PStatClientData *client_data = _monitor->get_client_data(); - if (_collector_index >= 0) { - if (client_data->has_collector(_collector_index)) { - text = client_data->get_collector_fullname(_collector_index); - text += " flame graph"; - } else { - _title_unknown = true; - } - - if (_thread_index != 0) { - if (client_data->has_thread(_thread_index)) { - text += " (" + client_data->get_thread_name(_thread_index) + " thread)"; - } else { - _title_unknown = true; - } - } - } - else if (client_data->has_thread(_thread_index)) { - text += client_data->get_thread_name(_thread_index) + " thread flame graph"; - } - else { - _title_unknown = true; - } - - if (_frame_number >= 0) { - text += " (frame " + format_string(_frame_number) + ")"; - } - - return text; -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string PStatFlameGraph:: -get_bar_tooltip(int depth, int x) const { - const StackLevel *level = _stack.locate(depth, pixel_to_height(x), _average_mode); - if (level != nullptr) { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data != nullptr && client_data->has_collector(level->_collector_index)) { - std::ostringstream text; - text << client_data->get_collector_fullname(level->_collector_index); - text << " (" << format_number(level->get_net_value(_average_mode), GBU_show_units | GBU_ms); - if (level->_count > 1) { - text << " / " << level->_count << "x"; - } - text << ")"; - return text.str(); - } - } - return std::string(); -} - -/** - * Returns the collector index corresponding to the bar at the given location. - */ -int PStatFlameGraph:: -get_bar_collector(int depth, int x) const { - const StackLevel *level = _stack.locate(depth, pixel_to_height(x), _average_mode); - if (level != nullptr) { - return level->_collector_index; - } - return -1; -} - -/** - * Writes the graph state to a datagram. - */ -void PStatFlameGraph:: -write_datagram(Datagram &dg) const { - dg.add_int16(_orig_collector_index); - dg.add_float64(_time_width); - dg.add_bool(_average_mode); - - PStatGraph::write_datagram(dg); -} - -/** - * Restores the graph state from a datagram. - */ -void PStatFlameGraph:: -read_datagram(DatagramIterator &scan) { - _orig_collector_index = scan.get_int16(); - _time_width = scan.get_float64(); - _average_mode = scan.get_bool(); - - PStatGraph::read_datagram(scan); - - _current_frame = -1; - _stack.clear(); - update(); - if (_average_mode) { - _time_width = _stack.get_net_value(false); - if (_time_width == 0.0) { - _time_width = 1.0 / pstats_target_frame_rate; - } - normal_guide_bars(); - force_redraw(); - } -} - -/** - * - */ -void PStatFlameGraph:: -update_data() { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data == nullptr) { - return; - } - - const PStatThreadData *thread_data = client_data->get_thread_data(_thread_index); - if (thread_data == nullptr || thread_data->is_empty()) { - return; - } - - const PStatFrameData &frame_data = thread_data->get_frame(_current_frame); - - bool first_time = _stack._children.empty(); - - StackLevel *top = &_stack; - top->reset(); - - size_t num_events = frame_data.get_num_events(); - for (size_t ei = 0; ei < num_events; ++ei) { - int collector_index = frame_data.get_time_collector(ei); - double time = frame_data.get_time(ei); - - if (frame_data.is_start(ei)) { - // If we have a collector index, use it to determine which bottom-level - // stack frames we are interested in. - if (_collector_index < 0 || - _collector_index == collector_index || - top != &_stack) { - top = top->start(collector_index, time); - } - else { - // Check whether one of the parents matches, perhaps. - int parent_index = collector_index; - do { - const PStatCollectorDef &def = client_data->get_collector_def(parent_index); - if (parent_index == def._parent_index) { - break; - } - parent_index = def._parent_index; - if (parent_index == _collector_index) { - // Yes, let it through. - top = top->start(collector_index, time); - break; - } - } - while (parent_index >= 0 && client_data->has_collector(parent_index)); - } - } - else { - top = top->stop(collector_index, time); - } - } - top = top->stop_all(frame_data.get_end()); - nassertv(top == &_stack); - - if (first_time) { - _stack.reset_averages(); - } - - if (!_average_mode) { - // Redraw right away, except in average mode, where it's done in animate(). - _time_width = _stack.get_net_value(false); - if (_time_width == 0.0) { - _time_width = 1.0 / pstats_target_frame_rate; - } - normal_guide_bars(); - force_redraw(); - } -} - -/** - * To be called by the user class when the widget size has changed. This - * updates the chart's internal data and causes it to issue redraw commands to - * reflect the new size. - */ -void PStatFlameGraph:: -changed_size(int xsize, int ysize) { - if (xsize != _xsize || ysize != _ysize) { - _xsize = xsize; - _ysize = ysize; - - normal_guide_bars(); - force_redraw(); - } -} - -/** - * To be called by the user class when the whole thing needs to be redrawn for - * some reason. - */ -void PStatFlameGraph:: -force_redraw() { - begin_draw(); - r_draw_level(_stack); - end_draw(); -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void PStatFlameGraph:: -normal_guide_bars() { - // We want vaguely 100 pixels between guide bars. - int num_bars = get_xsize() / 100; - - _guide_bars.clear(); - - double dist = _time_width / num_bars; - - for (int i = 1; i < num_bars; ++i) { - _guide_bars.push_back(make_guide_bar(i * dist)); - } - - _guide_bars_changed = true; -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any bars in the chart. - */ -void PStatFlameGraph:: -begin_draw() { -} - -/** - * Should be overridden by the user class. Should draw a single bar at the - * indicated location. - */ -void PStatFlameGraph:: -draw_bar(int depth, int from_x, int to_x, int collector_index, int parent_index) { -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars in the chart. - */ -void PStatFlameGraph:: -end_draw() { -} - -/** - * Should be overridden by the user class to perform any other updates might - * be necessary after the bars have been redrawn. - */ -void PStatFlameGraph:: -idle() { -} - -/** - * Should be called periodically to update any animated values. Returns false - * to indicate that the animation is done and no longer needs to be called. - */ -bool PStatFlameGraph:: -animate(double time, double dt) { - if (!_average_mode) { - return false; - } - - if (_stack.update_averages(_average_cursor)) { - _time_width = _stack.get_net_value(true); - if (_time_width == 0.0) { - _time_width = 1.0 / pstats_target_frame_rate; - } - normal_guide_bars(); - } - - // Always use force_redraw, since the mouse position may have changed. - force_redraw(); - - // Cycle through the ring buffers. - _average_cursor = (_average_cursor + 1) % _num_average_frames; - return true; -} - -/** - * Resets all the nodes by setting their _net_value to 0.0. - */ -void PStatFlameGraph::StackLevel:: -reset() { - _start_time = 0.0; - _net_value = 0.0; - _count = 0; - _started = false; - - for (auto &item : _children) { - item.second.reset(); - } -} - -/** - * Starts the given collector, which starts a new stack frame as a child of - * the current one. Returns the new child, which is the new stack top. - */ -PStatFlameGraph::StackLevel *PStatFlameGraph::StackLevel:: -start(int collector_index, double time) { - StackLevel &child = _children[collector_index]; - child._parent = this; - child._collector_index = collector_index; - child._start_time = std::max(_start_time, time); - child._count++; - child._started = true; - return &child; -} - -/** - * Stops the given collector, which is assumed to be somewhere up the - * hierarchy. Should only be called on the top of the stack, usually. - * Returns the new top of the stack. - */ -PStatFlameGraph::StackLevel *PStatFlameGraph::StackLevel:: -stop(int collector_index, double time) { - StackLevel *new_top = r_stop(collector_index, time); - if (new_top != nullptr) { - return new_top; - } - // We have a stop event without a preceding start event. Measure the - // the time from the start of the current stack frame to the stop time. - // Actually, don't do this, because it means that a child may end up with - // more time than the parent. Need a better solution for this - or not? - //start(collector_index, _start_time)->stop(collector_index, time); - return this; -} - -/** - * Stops all still started collectors. Returns the bottom of the stack, - * which is also the new top of the stack. - */ -PStatFlameGraph::StackLevel *PStatFlameGraph::StackLevel:: -stop_all(double time) { - if (_parent != nullptr) { - nassertr(_started, this); - _net_value += time - _start_time; - return _parent->stop_all(time); - } else { - return this; - } -} - -/** - * Resets the average calculator, used when first enabling average mode. - */ -void PStatFlameGraph::StackLevel:: -reset_averages() { - double net_value = get_net_value(false); - - for (double &value : _values) { - value = net_value; - } - _avg_net_value = net_value; - - for (auto &item : _children) { - item.second.reset_averages(); - } -} - -/** - * Recursively calculates the averages. Returns true if any value was changed. - */ -bool PStatFlameGraph::StackLevel:: -update_averages(size_t cursor) { - _values[cursor] = get_net_value(false); - - bool changed = false; - - double sum = 0; - for (double value : _values) { - sum += value; - } - double avg = sum / _num_average_frames; - if (avg != _avg_net_value) { - _avg_net_value = avg; - changed = true; - } - - for (auto &item : _children) { - if (item.second.update_averages(cursor)) { - changed = true; - } - } - - return changed; -} - -/** - * Locates a stack level at the given depth and the given time offset. - */ -const PStatFlameGraph::StackLevel *PStatFlameGraph::StackLevel:: -locate(int depth, double time, bool average) const { - if (time < 0.0) { - return nullptr; - } - for (const auto &item : _children) { - double value = item.second.get_net_value(average); - if (time < value) { - if (depth == 0) { - // This is it. - return &item.second; - } else { - // Recurse. - return item.second.locate(depth - 1, time, average); - } - } - time -= value; - } - return nullptr; -} - -/** - * Clears everything. - */ -void PStatFlameGraph::StackLevel:: -clear() { - _children.clear(); - _count = 0; - _net_value = 0.0; -} - -/** - * Recursive helper used by stop(). - */ -PStatFlameGraph::StackLevel *PStatFlameGraph::StackLevel:: -r_stop(int collector_index, double time) { - if (_collector_index == collector_index) { - // Found it. - nassertr(_started, nullptr); - _net_value += time - _start_time; - _started = false; - nassertr(_parent != nullptr, nullptr); - return _parent; - } - else if (_parent != nullptr) { - StackLevel *level = _parent->r_stop(collector_index, time); - if (level != nullptr) { - nassertr(_started, nullptr); - _net_value += time - _start_time; - _started = false; - return level; - } - } - return nullptr; -} - -/** - * Recursively draws a level. - */ -void PStatFlameGraph:: -r_draw_level(const StackLevel &level, int depth, double offset) { - for (const auto &item : level._children) { - const StackLevel &child = item.second; - - double value = child.get_net_value(_average_mode); - - int from_x = height_to_pixel(offset); - int to_x = height_to_pixel(offset + value); - - // No need to recurse if the bars have become smaller than a pixel. - if (to_x > from_x) { - draw_bar(depth, from_x, to_x, child._collector_index, level._collector_index); - r_draw_level(child, depth + 1, offset); - } - - offset += value; - } -} diff --git a/pandatool/src/pstatserver/pStatFlameGraph.h b/pandatool/src/pstatserver/pStatFlameGraph.h deleted file mode 100644 index 5e742383..00000000 --- a/pandatool/src/pstatserver/pStatFlameGraph.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatFlameGraph.h - * @author rdb - * @date 2022-01-28 - */ - -#ifndef PSTATFLAMEGRAPH_H -#define PSTATFLAMEGRAPH_H - -#include "pandatoolbase.h" - -#include "pStatGraph.h" -#include "pStatMonitor.h" -#include "pStatClientData.h" - -#include "pmap.h" -#include "pdeque.h" - -class PStatFrameData; - -/** - * This is an abstract class that presents the interface for drawing a flame - * chart: it shows the time spent in each of a number of collectors - * as a horizontal bar of color, with time as the horizontal axis. - * - * This class just manages all the flame chart logic; the actual nuts and bolts - * of drawing pixels is left to a user-derived class. - */ -class PStatFlameGraph : public PStatGraph { -public: - PStatFlameGraph(PStatMonitor *monitor, - int thread_index, int collector_index, int frame_number, - int xsize, int ysize); - virtual ~PStatFlameGraph(); - - void update(); - - INLINE int get_thread_index() const; - INLINE int get_collector_index() const; - void set_collector_index(int collector_index); - void push_collector_index(int collector_index); - bool pop_collector_index(); - INLINE void clear_history(); - INLINE size_t get_history_depth() const; - - INLINE int get_frame_number() const; - void set_frame_number(int collector_index); - bool first_frame(); - bool next_frame(); - bool prev_frame(); - bool last_frame(); - - INLINE double get_horizontal_scale() const; - - INLINE void set_average_mode(bool average_mode); - INLINE bool get_average_mode() const; - - INLINE int height_to_pixel(double value) const; - INLINE double pixel_to_height(int y) const; - - INLINE bool is_title_unknown() const; - std::string get_title_text(); - - std::string get_bar_tooltip(int depth, int x) const; - int get_bar_collector(int depth, int x) const; - - virtual void write_datagram(Datagram &dg) const final; - virtual void read_datagram(DatagramIterator &scan) final; - -protected: - void update_data(); - void changed_size(int xsize, int ysize); - void force_redraw(); - virtual void normal_guide_bars(); - - virtual void begin_draw(); - virtual void draw_bar(int depth, int from_x, int to_x, - int collector_index, int parent_index); - virtual void end_draw(); - virtual void idle(); - - bool animate(double time, double dt); - -private: - static const size_t _num_average_frames = 150; - - class StackLevel { - public: - void reset(); - - StackLevel *start(int collector_index, double time); - StackLevel *stop(int collector_index, double time); - StackLevel *stop_all(double time); - - INLINE double get_net_value(bool average) const; - void reset_averages(); - bool update_averages(size_t cursor); - - const StackLevel *locate(int depth, double time, bool average) const; - - void clear(); - - private: - StackLevel *r_stop(int collector_index, double time); - - double _net_value = 0.0; - double _avg_net_value = 0.0; - - // This is updated like a ring buffer, initialized with all the same value - // at first, then always at _average_cursor. - double _values[_num_average_frames] = {0.0}; - - double _start_time = 0.0; - int _count = 0; - bool _started = false; - - int _collector_index = -1; - StackLevel *_parent = nullptr; - pmap _children; - - friend class PStatFlameGraph; - }; - - void r_draw_level(const StackLevel &level, int depth = 0, double offset = 0.0); - - StackLevel _stack; - int _thread_index; - int _collector_index; - int _orig_collector_index; - int _frame_number; - bool _average_mode; - size_t _average_cursor; - - double _time_width; - int _current_frame; - bool _title_unknown; - - std::vector _history; -}; - -#include "pStatFlameGraph.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatGraph.I b/pandatool/src/pstatserver/pStatGraph.I deleted file mode 100644 index 3bda0ced..00000000 --- a/pandatool/src/pstatserver/pStatGraph.I +++ /dev/null @@ -1,131 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatGraph.I - * @author drose - * @date 2000-07-19 - */ - -/** - * Returns the monitor associated with this chart. - */ -INLINE PStatMonitor *PStatGraph:: -get_monitor() const { - return _monitor; -} - -/** - * Returns the number of labels to be drawn for this chart. - */ -INLINE int PStatGraph:: -get_num_labels() const { - return _labels.size(); -} - -/** - * Returns the collector index associated with the nth label. - */ -INLINE int PStatGraph:: -get_label_collector(int n) const { - nassertr(n >= 0 && n < (int)_labels.size(), 0); - return _labels[n]; -} - -/** - * Returns the text associated with the nth label. - */ -INLINE std::string PStatGraph:: -get_label_name(int n) const { - nassertr(n >= 0 && n < (int)_labels.size(), std::string()); - return _monitor->get_client_data()->get_collector_name(_labels[n]); -} - -/** - * Returns the color associated with the nth label. - */ -INLINE LRGBColor PStatGraph:: -get_label_color(int n) const { - nassertr(n >= 0 && n < (int)_labels.size(), LRGBColor(0.0, 0.0, 0.0)); - return _monitor->get_collector_color(_labels[n]); -} - -/** - * Sets the target frame rate of the application in Hz. This only affects the - * choice of initial scale and the placement of guide bars. - */ -INLINE void PStatGraph:: -set_target_frame_rate(double frame_rate) { - if (_target_frame_rate != frame_rate) { - _target_frame_rate = frame_rate; - normal_guide_bars(); - } -} - -/** - * Returns the indicated target frame rate in Hz. See - * set_target_frame_rate(). - */ -INLINE double PStatGraph:: -get_target_frame_rate() const { - return _target_frame_rate; -} - -/** - * Returns the width of the chart in pixels. - */ -INLINE int PStatGraph:: -get_xsize() const { - return _xsize; -} - -/** - * Returns the height of the chart in pixels. - */ -INLINE int PStatGraph:: -get_ysize() const { - return _ysize; -} - -/** - * Sets the units that are displayed for the guide bar labels. This may be a - * union of one or more members of the GuideBarUnits enum. - */ -INLINE void PStatGraph:: -set_guide_bar_units(int guide_bar_units) { - if (_guide_bar_units != guide_bar_units) { - _guide_bar_units = guide_bar_units; - normal_guide_bars(); - } -} - -/** - * Returns the units that are displayed for the guide bar labels. This may be - * a union of one or more members of the GuideBarUnits enum. - */ -INLINE int PStatGraph:: -get_guide_bar_units() const { - return _guide_bar_units; -} - -/** - * Sets the name of the units to be used for the guide bars if the units type - * is set to GBU_named | GBU_show_units. - */ -INLINE void PStatGraph:: -set_guide_bar_unit_name(const std::string &unit_name) { - _unit_name = unit_name; -} - -/** - * Returns the name of the units to be used for the guide bars if the units - * type is set to GBU_named | GBU_show_units. - */ -INLINE const std::string &PStatGraph:: -get_guide_bar_unit_name() const { - return _unit_name; -} diff --git a/pandatool/src/pstatserver/pStatGraph.cxx b/pandatool/src/pstatserver/pStatGraph.cxx deleted file mode 100644 index a0d1a5da..00000000 --- a/pandatool/src/pstatserver/pStatGraph.cxx +++ /dev/null @@ -1,371 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatGraph.cxx - * @author drose - * @date 2000-07-19 - */ - -#include "pStatGraph.h" -#include "pStatServer.h" -#include "pStatFrameData.h" -#include "pStatCollectorDef.h" -#include "string_utils.h" -#include "config_pstatclient.h" - -#include // for sprintf - -using std::string; - -/** - * - */ -PStatGraph::GuideBar:: -GuideBar(double height, const string &label, PStatGraph::GuideBarStyle style) : - _height(height), - _label(label), - _style(style) -{ -} - -/** - * - */ -PStatGraph::GuideBar:: -GuideBar(const PStatGraph::GuideBar ©) : - _height(copy._height), - _label(copy._label), - _style(copy._style) -{ -} - -/** - * - */ -PStatGraph:: -PStatGraph(PStatMonitor *monitor, int xsize, int ysize) : - _monitor(monitor), - _xsize(xsize), - _ysize(ysize) -{ - _target_frame_rate = pstats_target_frame_rate; - _labels_changed = false; - _guide_bars_changed = false; - _guide_bar_units = GBU_ms; -} - -/** - * - */ -PStatGraph:: -~PStatGraph() { -} - -/** - * Returns the number of horizontal guide bars that should be drawn, based on - * the indicated target frame rate. Not all of these may be visible; some may - * be off the top of the chart because of the vertical scale. - */ -int PStatGraph:: -get_num_guide_bars() const { - return _guide_bars.size(); -} - -/** - * Returns the nth horizontal guide bar. This should be drawn as a horizontal - * line across the chart at the y pixel location determined by - * height_to_pixel(bar._height). - * - * It is possible that this bar will be off the top of the chart. - */ -const PStatGraph::GuideBar &PStatGraph:: -get_guide_bar(int n) const { -#ifndef NDEBUG - static GuideBar bogus_bar(0.0, "bogus", GBS_normal); - nassertr(n >= 0 && n < (int)_guide_bars.size(), bogus_bar); -#endif - return _guide_bars[n]; -} - -/** - * Returns the current number of user-defined guide bars. Not all of these - * may be visible. - */ -int PStatGraph:: -get_num_user_guide_bars() const { - return _monitor->get_server()->get_num_user_guide_bars(); -} - -/** - * Returns the nth user-defined guide bar. - */ -PStatGraph::GuideBar PStatGraph:: -get_user_guide_bar(int n) const { - double height = _monitor->get_server()->get_user_guide_bar_height(n); - return make_guide_bar(height, GBS_user); -} - -/** - * Adjusts the height of the nth user-defined guide bar. - */ -void PStatGraph:: -move_user_guide_bar(int n, double height) { - _monitor->get_server()->move_user_guide_bar(n, height); -} - -/** - * Creates a new user guide bar and returns its index number. - */ -int PStatGraph:: -add_user_guide_bar(double height) { - return _monitor->get_server()->add_user_guide_bar(height); -} - -/** - * Removes the user guide bar with the indicated index number. All subsequent - * index numbers are adjusted down one. - */ -void PStatGraph:: -remove_user_guide_bar(int n) { - _monitor->get_server()->remove_user_guide_bar(n); -} - -/** - * Returns the index number of the first user guide bar found whose height is - * within the indicated range, or -1 if no user guide bars fall within the - * range. - */ -int PStatGraph:: -find_user_guide_bar(double from_height, double to_height) const { - return _monitor->get_server()->find_user_guide_bar(from_height, to_height); -} - - -/** - * Returns a string representing the value nicely formatted for its range. - */ -string PStatGraph:: -format_number(double value) { - char buffer[128]; - - if (value < 0.01) { - sprintf(buffer, "%0.4f", value); - } else if (value < 0.1) { - sprintf(buffer, "%0.3f", value); - } else if (value < 1.0) { - sprintf(buffer, "%0.2f", value); - } else if (value < 10.0) { - sprintf(buffer, "%0.1f", value); - } else { - sprintf(buffer, "%0.0f", value); - } - - return buffer; -} - -/** - * Returns a string representing the value nicely formatted for its range, - * including the units as indicated. - */ -string PStatGraph:: -format_number(double value, int guide_bar_units, const string &unit_name) { - string label; - - if ((guide_bar_units & GBU_named) != 0) { - // Units are whatever is specified by unit_name, not a time unit at all. - int int_value = (int)value; - if ((double)int_value == value) { - // Probably a counter or something, don't display .0 suffix. - label = format_string(int_value); - } else { - label = format_number(value); - } - if ((guide_bar_units & GBU_show_units) != 0 && !unit_name.empty()) { - label += " "; - label += unit_name; - } - } - else { - // Units are either milliseconds or hz, or both. - if ((guide_bar_units & GBU_ms) != 0) { - if ((guide_bar_units & GBU_show_units) != 0 && - value > 0 && value < 0.000001) { - double ns = value * 1000000000.0; - label += format_number(ns); - label += " ns"; - } - else if ((guide_bar_units & GBU_show_units) != 0 && - value > 0 && value < 0.001) { - double us = value * 1000000.0; - label += format_number(us); -#ifdef _WIN32 - label += " \xb5s"; -#else - label += " \xc2\xb5s"; -#endif - } - else if ((guide_bar_units & GBU_show_units) == 0 || value < 1.0) { - double ms = value * 1000.0; - label += format_number(ms); - if ((guide_bar_units & GBU_show_units) != 0) { - label += " ms"; - } - } - else { - label += format_number(value); - label += " s"; - } - } - - if ((guide_bar_units & GBU_hz) != 0) { - double hz = 1.0 / value; - - if ((guide_bar_units & GBU_show_units) != 0 && - (guide_bar_units & GBU_ms) == 0) { - if (hz >= 1000000000) { - label += format_number(hz / 1000000000); - label += " GHz"; - } - else if (hz >= 1000000) { - label += format_number(hz / 1000000); - label += " MHz"; - } - else if (hz >= 1000) { - label += format_number(hz / 1000); - label += " kHz"; - } - else { - label += format_number(hz); - label += " Hz"; - } - } - else { - if ((guide_bar_units & GBU_ms) != 0) { - label += " ("; - } - label += format_number(hz); - if ((guide_bar_units & GBU_show_units) != 0) { - label += " Hz"; - } - if ((guide_bar_units & GBU_ms) != 0) { - label += ")"; - } - } - } - } - - return label; -} - -/** - * Writes the graph state to a datagram. - */ -void PStatGraph:: -write_datagram(Datagram &dg) const { - int x, y, width, height; - bool minimized, maximized; - if (get_window_state(x, y, width, height, minimized, maximized)) { - dg.add_bool(true); - dg.add_int32(x); - dg.add_int32(y); - dg.add_int32(width); - dg.add_int32(height); - dg.add_bool(minimized); - dg.add_bool(maximized); - } - else { - dg.add_bool(false); - } -} - -/** - * Restores the graph state from a datagram. - */ -void PStatGraph:: -read_datagram(DatagramIterator &scan) { - if (scan.get_bool()) { - int x = scan.get_int32(); - int y = scan.get_int32(); - int width = scan.get_int32(); - int height = scan.get_int32(); - bool minimized = scan.get_bool(); - bool maximized = scan.get_bool(); - set_window_state(x, y, width, height, minimized, maximized); - } -} - -/** - * Resets the list of guide bars. - */ -void PStatGraph:: -update_guide_bars(int num_bars, double scale) { - _guide_bars.clear(); - - // We'd like to draw about num_bars bars on the chart. But we also want the - // bars to be harmonics of the target frame rate, so that the bottom bar is - // at tfrn or n * tfr, where n is an integer, and the upper bars are even - // multiples of that. - - // Choose a suitable harmonic of the target frame rate near the bottom part - // of the chart. - - double bottom = (double)num_bars / scale; - - double harmonic; - if (_target_frame_rate < bottom) { - // n * tfr - harmonic = floor(bottom / _target_frame_rate + 0.5) * _target_frame_rate; - - } else { - // tfr n - harmonic = _target_frame_rate / floor(_target_frame_rate / bottom + 0.5); - } - - // Now, make a few bars at k harmonic. - for (int k = 1; k / harmonic <= scale; k++) { - _guide_bars.push_back(make_guide_bar(k / harmonic)); - } - - _guide_bars_changed = true; -} - -/** - * Makes a guide bar for the indicated elapsed time or level units. - */ -PStatGraph::GuideBar PStatGraph:: -make_guide_bar(double value, PStatGraph::GuideBarStyle style) const { - string label = format_number(value, _guide_bar_units, _unit_name); - - if ((style == GBS_normal) && - (_guide_bar_units & GBU_named) == 0) { - // If it's a time unit, check to see if it matches our target frame rate. - double hz = 1.0 / value; - if (IS_THRESHOLD_EQUAL(hz, _target_frame_rate, 0.001)) { - style = GBS_target; - } - } - - return GuideBar(value, label, style); -} - -/** - * Returns the current window dimensions. - */ -bool PStatGraph:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - return false; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void PStatGraph:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { -} diff --git a/pandatool/src/pstatserver/pStatGraph.h b/pandatool/src/pstatserver/pStatGraph.h deleted file mode 100644 index 6c9168a4..00000000 --- a/pandatool/src/pstatserver/pStatGraph.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatGraph.h - * @author drose - * @date 2000-07-19 - */ - -#ifndef PSTATGRAPH_H -#define PSTATGRAPH_H - -#include "pandatoolbase.h" - -#include "pStatMonitor.h" -#include "pStatClientData.h" - -#include "luse.h" -#include "vector_int.h" - -#include "pmap.h" - -class PStatView; - -/** - * This is an abstract base class for several different kinds of graphs that - * have a few things in common, like labels and guide bars. - */ -class PStatGraph { -public: - PStatGraph(PStatMonitor *monitor, int xsize, int ysize); - virtual ~PStatGraph(); - - INLINE PStatMonitor *get_monitor() const; - - INLINE int get_num_labels() const; - INLINE int get_label_collector(int n) const; - INLINE std::string get_label_name(int n) const; - INLINE LRGBColor get_label_color(int n) const; - - INLINE void set_target_frame_rate(double frame_rate); - INLINE double get_target_frame_rate() const; - - INLINE int get_xsize() const; - INLINE int get_ysize() const; - - enum GuideBarStyle { - GBS_normal, - GBS_target, - GBS_user, - GBS_frame, - }; - - class GuideBar { - public: - GuideBar(double height, const std::string &label, GuideBarStyle style); - GuideBar(const GuideBar ©); - - double _height; - std::string _label; - GuideBarStyle _style; - }; - - enum GuideBarUnits { - GBU_hz = 0x0001, - GBU_ms = 0x0002, - GBU_named = 0x0004, - GBU_show_units = 0x0008, - }; - - int get_num_guide_bars() const; - const GuideBar &get_guide_bar(int n) const; - - int get_num_user_guide_bars() const; - GuideBar get_user_guide_bar(int n) const; - void move_user_guide_bar(int n, double height); - int add_user_guide_bar(double height); - void remove_user_guide_bar(int n); - int find_user_guide_bar(double from_height, double to_height) const; - - INLINE void set_guide_bar_units(int unit_mask); - INLINE int get_guide_bar_units() const; - INLINE void set_guide_bar_unit_name(const std::string &unit_name); - INLINE const std::string &get_guide_bar_unit_name() const; - - static std::string format_number(double value); - static std::string format_number(double value, int guide_bar_units, - const std::string &unit_name = std::string()); - - virtual void write_datagram(Datagram &dg) const; - virtual void read_datagram(DatagramIterator &scan); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - -protected: - virtual void normal_guide_bars()=0; - void update_guide_bars(int num_bars, double scale); - GuideBar make_guide_bar(double value, GuideBarStyle style = GBS_normal) const; - - bool _labels_changed; - bool _guide_bars_changed; - - PT(PStatMonitor) _monitor; - - double _target_frame_rate; - - int _xsize; - int _ysize; - - // Table of the collectors that should be drawn as labels, in order from - // bottom to top. - typedef vector_int Labels; - Labels _labels; - - typedef pvector GuideBars; - GuideBars _guide_bars; - int _guide_bar_units; - std::string _unit_name; -}; - -#include "pStatGraph.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatListener.cxx b/pandatool/src/pstatserver/pStatListener.cxx deleted file mode 100644 index c2f7bb35..00000000 --- a/pandatool/src/pstatserver/pStatListener.cxx +++ /dev/null @@ -1,50 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatListener.cxx - * @author drose - * @date 2000-07-09 - */ - -#include "pStatListener.h" -#include "pStatServer.h" -#include "pStatReader.h" - -/** - * - */ -PStatListener:: -PStatListener(PStatServer *manager) : - ConnectionListener(manager, manager->is_thread_safe() ? 1 : 0), - _manager(manager) -{ -} - -/** - * An internal function called by ConnectionListener() when a new TCP - * connection has been established. - */ -void PStatListener:: -connection_opened(const PT(Connection) &, - const NetAddress &address, - const PT(Connection) &new_connection) { - PStatMonitor *monitor = _manager->make_monitor(address); - if (monitor == nullptr) { - nout << "Couldn't create monitor!\n"; - return; - } - - nout << "Got new connection from " << address << "\n"; - - // Make sure this connection doesn't queue up TCP packets we write to it. - new_connection->set_collect_tcp(false); - - PStatReader *reader = new PStatReader(_manager, monitor); - _manager->add_reader(new_connection, reader); - reader->set_tcp_connection(new_connection); -} diff --git a/pandatool/src/pstatserver/pStatListener.h b/pandatool/src/pstatserver/pStatListener.h deleted file mode 100644 index b4d27690..00000000 --- a/pandatool/src/pstatserver/pStatListener.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatListener.h - * @author drose - * @date 2000-07-09 - */ - -#ifndef PSTATLISTENER_H -#define PSTATLISTENER_H - -#include "pandatoolbase.h" - -#include "connectionListener.h" -#include "referenceCount.h" - -class PStatServer; -class PStatMonitor; - -/** - * This is the TCP rendezvous socket listener. We need one of these to listen - * for new connections on the socket(s) added to the PStatServer. - */ -class PStatListener : public ConnectionListener { -public: - PStatListener(PStatServer *manager); - -protected: - virtual void connection_opened(const PT(Connection) &rendezvous, - const NetAddress &address, - const PT(Connection) &new_connection); - -private: - PStatServer *_manager; -}; - -#endif diff --git a/pandatool/src/pstatserver/pStatMonitor.I b/pandatool/src/pstatserver/pStatMonitor.I deleted file mode 100644 index 482102eb..00000000 --- a/pandatool/src/pstatserver/pStatMonitor.I +++ /dev/null @@ -1,95 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatMonitor.I - * @author drose - * @date 2000-07-14 - */ - -/** - * Returns the server that owns this monitor. - */ -INLINE PStatServer *PStatMonitor:: -get_server() { - return _server; -} - -/** - * Returns the client data associated with this monitor. - */ -INLINE const PStatClientData *PStatMonitor:: -get_client_data() const { - return _client_data; -} - -/** - * Returns the name of the indicated collector, if it is known. - */ -INLINE std::string PStatMonitor:: -get_collector_name(int collector_index) { - if (!_client_data.is_null() && - _client_data->has_collector(collector_index)) { - return _client_data->get_collector_name(collector_index); - } - return "Unknown"; -} - -/** - * Returns true if we've yet received the "hello" message from the client - * indicating its name, etc. - */ -INLINE bool PStatMonitor:: -is_client_known() const { - return _client_known; -} - -/** - * Returns the hostname of the client we're connected to, if known. This may - * not be known immediately at creation time, but should be learned shortly - * thereafter when we receive the client's "hello" message. See - * is_client_known(). - */ -INLINE std::string PStatMonitor:: -get_client_hostname() const { - return _client_hostname; -} - -/** - * Returns the program name of the client we're connected to, if known. This - * may not be known immediately at creation time, but should be learned - * shortly thereafter when we receive the client's "hello" message. See - * is_client_known(). - */ -INLINE std::string PStatMonitor:: -get_client_progname() const { - return _client_progname; -} - -/** - * Returns the process id of the client, or -1 if it is not known. - */ -INLINE int PStatMonitor:: -get_client_pid() const { - return _client_pid; -} - -/** - * Returns true if the session data was loaded from a file. - */ -INLINE bool PStatMonitor:: -has_read_filename() const { - return !_read_filename.empty(); -} - -/** - * Returns the filename this session data was loaded from. - */ -INLINE const Filename &PStatMonitor:: -get_read_filename() const { - return _read_filename; -} diff --git a/pandatool/src/pstatserver/pStatMonitor.cxx b/pandatool/src/pstatserver/pStatMonitor.cxx deleted file mode 100644 index cbc49a71..00000000 --- a/pandatool/src/pstatserver/pStatMonitor.cxx +++ /dev/null @@ -1,799 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatMonitor.cxx - * @author drose - * @date 2000-07-09 - */ - -#include "pStatMonitor.h" - -#include "datagramInputFile.h" -#include "datagramOutputFile.h" -#include "pandaVersion.h" -#include "pStatCollectorDef.h" -#include "pStatTimeline.h" -#include "pStatStripChart.h" -#include "pStatFlameGraph.h" -#include "pStatPianoRoll.h" - -using std::string; - -static const string session_file_header("pstat\0\n\r", 8); -static const string layout_file_header("pslyt\0\n\r", 8); - -static const Filename layout_filename = Filename::binary_filename( -#ifdef _WIN32 - Filename::expand_from("$USER_APPDATA/Panda3D-" PANDA_ABI_VERSION_STR "/pstats-layout") -#elif defined(__APPLE__) - Filename::expand_from("$HOME/Library/Caches/Panda3D-" PANDA_ABI_VERSION_STR "/pstats-layout") -#else - Filename::expand_from("$XDG_STATE_HOME/panda3d/pstats-layout") -#endif -); - -/** - * - */ -PStatMonitor:: -PStatMonitor(PStatServer *server) : _server(server) { - _client_known = false; -} - -/** - * - */ -PStatMonitor:: -~PStatMonitor() { - close(); -} - -/** - * Called shortly after startup time with the greeting from the client. This - * indicates the client's reported hostname and program name. - */ -void PStatMonitor:: -hello_from(const string &hostname, const string &progname, int pid) { - _client_known = true; - _client_hostname = hostname; - _client_progname = progname; - _client_pid = pid; - got_hello(); -} - -/** - * Called shortly after startup time with the greeting from the client. In - * this case, the client seems to have an incompatible version and will be - * automatically disconnected; the server should issue a message to that - * effect. - */ -void PStatMonitor:: -bad_version(const string &hostname, const string &progname, int pid, - int client_major, int client_minor, - int server_major, int server_minor) { - _client_known = true; - _client_hostname = hostname; - _client_progname = progname; - _client_pid = 0; - got_bad_version(client_major, client_minor, - server_major, server_minor); -} - -/** - * Called by the PStatServer at setup time to set the new data pointer for the - * first time. - */ -void PStatMonitor:: -set_client_data(PStatClientData *client_data) { - _client_data = client_data; - initialized(); -} - -/** - * Writes the data and the UI state to the given file. - */ -bool PStatMonitor:: -write(const Filename &fn) const { - DatagramOutputFile dof; - if (!dof.open(fn)) { - return false; - } - if (!dof.write_header(session_file_header)) { - return false; - } - Datagram dg; - dg.set_stdfloat_double(false); - dg.add_uint16(1); - dg.add_uint16(1); - write_datagram(dg); - dof.put_datagram(dg); - dof.close(); - return true; -} - -/** - * Reads the data and the UI state from the given file. - */ -bool PStatMonitor:: -read(const Filename &fn) { - close(); - - DatagramInputFile dif; - if (!dif.open(fn)) { - nout << "Failed to open " << fn << " for reading.\n"; - return false; - } - string header; - if (!dif.read_header(header, 8) || header != session_file_header) { - nout << "Session file contains invalid header.\n"; - return false; - } - Datagram dg; - dg.set_stdfloat_double(false); - - if (!dif.get_datagram(dg)) { - nout << "Failed to read datagram from session file.\n"; - return false; - } - - DatagramIterator scan(dg); - int version = scan.get_uint16(); - if (version != 1) { - nout << "Unsupported session file version " << version << ".\n"; - return false; - } - // Room for a minor version number - scan.get_uint16(); - - read_datagram(scan); - dif.close(); - - idle(); - - _read_filename = fn; - _client_data->clear_dirty(); - - return true; -} - -/** - * Opens the default set of graphs. - */ -void PStatMonitor:: -open_default_graphs() { - DatagramInputFile dif; - if (!dif.open(layout_filename)) { - open_strip_chart(0, 0, false); - return; - } - string header; - if (!dif.read_header(header, 8) || header != layout_file_header) { - nout << "Layout file contains invalid header.\n"; - open_strip_chart(0, 0, false); - return; - } - Datagram dg; - dg.set_stdfloat_double(false); - - if (!dif.get_datagram(dg)) { - nout << "Failed to read datagram from layout file.\n"; - open_strip_chart(0, 0, false); - return; - } - - DatagramIterator scan(dg); - int version = scan.get_uint16(); - if (version != 1) { - nout << "Unsupported layout file version " << version << ".\n"; - open_strip_chart(0, 0, false); - return; - } - // Room for a minor version number - scan.get_uint16(); - - size_t num_colors = scan.get_uint32(); - for (size_t i = 0; i < num_colors; ++i) { - int key = scan.get_int32(); - LRGBColor &color = _colors[key]; - color[0] = scan.get_float32(); - color[1] = scan.get_float32(); - color[2] = scan.get_float32(); - } - - PStatGraph *graph; - - size_t num_timelines = scan.get_uint16(); - for (size_t i = 0; i < num_timelines; ++i) { - int x = scan.get_int32(); - int y = scan.get_int32(); - int width = scan.get_int32(); - int height = scan.get_int32(); - bool minimized = scan.get_bool(); - bool maximized = scan.get_bool(); - graph = open_timeline(); - graph->set_window_state(x, y, width, height, minimized, maximized); - } - - size_t num_strip_charts = scan.get_uint16(); - for (size_t i = 0; i < num_strip_charts; ++i) { - std::string thread_name = scan.get_string(); - std::string collector_name = scan.get_string(); - bool show_level = scan.get_bool(); - int thread_index = _client_data->find_thread(thread_name); - int collector_index = _client_data->find_collector(collector_name); - int x = scan.get_int32(); - int y = scan.get_int32(); - int width = scan.get_int32(); - int height = scan.get_int32(); - bool minimized = scan.get_bool(); - bool maximized = scan.get_bool(); - if (thread_index != -1) { - graph = open_strip_chart(thread_index, collector_index, show_level); - graph->set_window_state(x, y, width, height, minimized, maximized); - } - } - - size_t num_flame_graphs = scan.get_uint16(); - for (size_t i = 0; i < num_flame_graphs; ++i) { - std::string thread_name = scan.get_string(); - std::string collector_name = scan.get_string(); - int thread_index = _client_data->find_thread(thread_name); - int collector_index = collector_name.empty() ? -1 : _client_data->find_collector(collector_name); - int x = scan.get_int32(); - int y = scan.get_int32(); - int width = scan.get_int32(); - int height = scan.get_int32(); - bool minimized = scan.get_bool(); - bool maximized = scan.get_bool(); - if (thread_index != -1) { - graph = open_flame_graph(thread_index, collector_index); - graph->set_window_state(x, y, width, height, minimized, maximized); - } - } - - size_t num_piano_rolls = scan.get_uint16(); - for (size_t i = 0; i < num_piano_rolls; ++i) { - std::string thread_name = scan.get_string(); - int thread_index = _client_data->find_thread(thread_name); - int x = scan.get_int32(); - int y = scan.get_int32(); - int width = scan.get_int32(); - int height = scan.get_int32(); - bool minimized = scan.get_bool(); - bool maximized = scan.get_bool(); - if (thread_index != -1) { - graph = open_piano_roll(thread_index); - graph->set_window_state(x, y, width, height, minimized, maximized); - } - } - - dif.close(); - if (num_timelines + num_strip_charts + num_flame_graphs + num_piano_rolls == 0) { - open_strip_chart(0, 0, false); - } -} - -/** - * Saves the current graph layout as the default graph layout. - */ -bool PStatMonitor:: -save_default_graphs() const { - layout_filename.make_dir(); - - DatagramOutputFile dof; - if (!dof.open(layout_filename)) { - return false; - } - if (!dof.write_header(layout_file_header)) { - return false; - } - Datagram dg; - dg.set_stdfloat_double(false); - dg.add_uint16(1); - dg.add_uint16(1); - - dg.add_uint32((uint32_t)_colors.size()); - for (const auto &item : _colors) { - dg.add_int32(item.first); - dg.add_float32(item.second[0]); - dg.add_float32(item.second[1]); - dg.add_float32(item.second[2]); - } - - dg.add_uint16(_timelines.size()); - for (PStatGraph *graph : _timelines) { - int x, y, width, height; - bool minimized, maximized; - if (graph->get_window_state(x, y, width, height, minimized, maximized)) { - dg.add_int32(x); - dg.add_int32(y); - dg.add_int32(width); - dg.add_int32(height); - dg.add_bool(minimized); - dg.add_bool(maximized); - } - } - - dg.add_uint16(_strip_charts.size()); - for (PStatGraph *graph : _strip_charts) { - int x, y, width, height; - bool minimized, maximized; - if (graph->get_window_state(x, y, width, height, minimized, maximized)) { - dg.add_string(_client_data->get_thread_name(((PStatStripChart *)graph)->get_thread_index())); - dg.add_string(_client_data->get_collector_fullname(((PStatStripChart *)graph)->get_collector_index())); - dg.add_bool(((PStatStripChart *)graph)->get_view().get_show_level()); - dg.add_int32(x); - dg.add_int32(y); - dg.add_int32(width); - dg.add_int32(height); - dg.add_bool(minimized); - dg.add_bool(maximized); - } - } - - dg.add_uint16(_flame_graphs.size()); - for (PStatGraph *graph : _flame_graphs) { - int x, y, width, height; - bool minimized, maximized; - if (graph->get_window_state(x, y, width, height, minimized, maximized)) { - int collector_index = ((PStatFlameGraph *)graph)->get_collector_index(); - dg.add_string(_client_data->get_thread_name(((PStatFlameGraph *)graph)->get_thread_index())); - dg.add_string(collector_index >= 0 ? _client_data->get_collector_fullname(collector_index) : ""); - dg.add_int32(x); - dg.add_int32(y); - dg.add_int32(width); - dg.add_int32(height); - dg.add_bool(minimized); - dg.add_bool(maximized); - } - } - - dg.add_uint16(_piano_rolls.size()); - for (PStatGraph *graph : _piano_rolls) { - int x, y, width, height; - bool minimized, maximized; - if (graph->get_window_state(x, y, width, height, minimized, maximized)) { - dg.add_string(_client_data->get_thread_name(((PStatPianoRoll *)graph)->get_thread_index())); - dg.add_int32(x); - dg.add_int32(y); - dg.add_int32(width); - dg.add_int32(height); - dg.add_bool(minimized); - dg.add_bool(maximized); - } - } - - // Reserved for future graph type - dg.add_uint16(0); - - dof.put_datagram(dg); - dof.close(); - return true; -} - -/** - * Returns true if the client is alive and connected, false otherwise. - */ -bool PStatMonitor:: -is_alive() const { - if (_client_data.is_null()) { - // Not yet, but in a second probably. - return false; - } - return _client_data->is_alive(); -} - -/** - * Closes the client connection if it is active. - */ -void PStatMonitor:: -close() { - if (!_client_data.is_null()) { - _client_data->close(); - } -} - -/** - * Returns the color associated with the indicated collector. If the - * collector has no associated color, or is unknown, a new color will be made - * up on the spot and associated with this collector for the rest of the - * session. - */ -const LRGBColor &PStatMonitor:: -get_collector_color(int collector_index) { - Colors::iterator ci; - ci = _colors.find(collector_index); - if (ci != _colors.end()) { - return (*ci).second; - } - - // Ask the client data about the color. - if (!_client_data.is_null() && - _client_data->has_collector(collector_index)) { - const PStatCollectorDef &def = - _client_data->get_collector_def(collector_index); - - LRGBColor sc(def._suggested_color.r, - def._suggested_color.g, - def._suggested_color.b); - if (sc != LRGBColor::zero()) { - ci = _colors.insert(Colors::value_type(collector_index, sc)).first; - return (*ci).second; - } - - // Use the fullname of the collector as a hash to seed the random number - // generator (consulted below), so we get the same color for a given name - // across sessions. - string fullname = _client_data->get_collector_fullname(collector_index); - unsigned int hash = 0; - for (string::const_iterator ci = fullname.begin(); ci != fullname.end(); ++ci) { - hash = hash * 37 + (unsigned int)(*ci); - } - srand(hash); - } - - // We didn't have a color for the collector; make one up. - LRGBColor random_color; - random_color[0] = (double)rand() / (double)RAND_MAX; - random_color[1] = (double)rand() / (double)RAND_MAX; - random_color[2] = (double)rand() / (double)RAND_MAX; - - ci = _colors.insert(Colors::value_type(collector_index, random_color)).first; - return (*ci).second; -} - -/** - * Sets a custom color associated with the given collector. - */ -void PStatMonitor:: -set_collector_color(int collector_index, const LRGBColor &color) { - _colors[collector_index] = color; -} - -/** - * Clears any custom custom color associated with the given collector. - */ -void PStatMonitor:: -clear_collector_color(int collector_index) { - _colors.erase(collector_index); -} - -/** - * Returns a view on the given thread index. If there is no such view already - * for the indicated thread, this will create one. This view can be used to - * examine the accumulated data for the given thread. - */ -PStatView &PStatMonitor:: -get_view(int thread_index) { - Views::iterator vi; - vi = _views.find(thread_index); - if (vi == _views.end()) { - vi = _views.insert(Views::value_type(thread_index, PStatView())).first; - (*vi).second.set_thread_data(_client_data->get_thread_data(thread_index)); - } - return (*vi).second; -} - -/** - * Returns a view on the level value (as opposed to elapsed time) for the - * given collector over the given thread. If there is no such view already - * for the indicated thread, this will create one. - */ -PStatView &PStatMonitor:: -get_level_view(int collector_index, int thread_index) { - LevelViews::iterator lvi; - lvi = _level_views.find(collector_index); - if (lvi == _level_views.end()) { - lvi = _level_views.insert(LevelViews::value_type(collector_index, Views())).first; - } - Views &views = (*lvi).second; - - Views::iterator vi; - vi = views.find(thread_index); - if (vi == views.end()) { - vi = views.insert(Views::value_type(thread_index, PStatView())).first; - (*vi).second.set_thread_data(_client_data->get_thread_data(thread_index)); - (*vi).second.constrain(collector_index, true); - } - return (*vi).second; -} - -/** - * Called after the monitor has been fully set up. At this time, it will have - * a valid _client_data pointer, and things like is_alive() and close() will - * be meaningful. However, we may not yet know who we're connected to - * (is_client_known() may return false), and we may not know anything about - * the threads or collectors we're about to get data on. - */ -void PStatMonitor:: -initialized() { -} - -/** - * Called when the "hello" message has been received from the client. At this - * time, the client's hostname and program name will be known. - */ -void PStatMonitor:: -got_hello() { -} - -/** - * Like got_hello(), this is called when the "hello" message has been received - * from the client. At this time, the client's hostname and program name will - * be known. However, the client appears to be an incompatible version and - * the connection will be terminated; the monitor should issue a message to - * that effect. - */ -void PStatMonitor:: -got_bad_version(int, int, int, int) { -} - -/** - * Called whenever a new Collector definition is received from the client. - * Generally, the client will send all of its collectors over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Collector definitions midstream. - */ -void PStatMonitor:: -new_collector(int) { -} - -/** - * Called whenever a new Thread definition is received from the client. - * Generally, the client will send all of its threads over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Thread definitions midstream. - */ -void PStatMonitor:: -new_thread(int) { -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. The use of the PStatFrameData / PStatView objects to report the - * data will facilitate this. - */ -void PStatMonitor:: -new_data(int thread_index, int frame_number) { - const PStatClientData *client_data = get_client_data(); - - // Don't bother to update the thread data until we know at least something - // about the collectors and threads. - if (client_data->get_num_collectors() != 0 && - client_data->get_num_threads() != 0) { - PStatView &view = get_view(thread_index); - const PStatThreadData *thread_data = view.get_thread_data(); - if (!thread_data->is_empty()) { - int latest = thread_data->get_latest_frame_number(); - if (frame_number == latest) { - view.set_to_frame(thread_data->get_frame(frame_number)); - } - } - } -} - -/** - * Called when a thread should be removed from the list of threads. - */ -void PStatMonitor:: -remove_thread(int) { -} - -/** - * Called whenever the connection to the client has been lost. This is a - * permanent state change. The monitor should update its display to represent - * this, and may choose to close down automatically. - */ -void PStatMonitor:: -lost_connection() { -} - -/** - * If has_idle() returns true, this will be called periodically to allow the - * monitor to update its display or whatever it needs to do. - */ -void PStatMonitor:: -idle() { -} - -/** - * Should be redefined to return true if you want to redefine idle() and - * expect it to be called. - */ -bool PStatMonitor:: -has_idle() { - return false; -} - -/** - * Should be redefined to return true if this monitor class can handle running - * in a sub-thread. - * - * This is not related to the question of whether it can handle multiple - * different PStatThreadDatas; this is strictly a question of whether or not - * the monitor itself wants to run in a sub-thread. - */ -bool PStatMonitor:: -is_thread_safe() { - return false; -} - -/** - * Called when the user guide bars have been changed. - */ -void PStatMonitor:: -user_guide_bars_changed() { -} - -/** - * Opens a new timeline. - */ -PStatGraph *PStatMonitor:: -open_timeline() { - return nullptr; -} - -/** - * Opens a new strip chart showing the indicated data. - */ -PStatGraph *PStatMonitor:: -open_strip_chart(int thread_index, int collector_index, bool show_level) { - return nullptr; -} - -/** - * Opens a new flame graph showing the indicated data. - */ -PStatGraph *PStatMonitor:: -open_flame_graph(int thread_index, int collector_index, int frame_number) { - return nullptr; -} - -/** - * Opens a new piano roll showing the indicated data. - */ -PStatGraph *PStatMonitor:: -open_piano_roll(int thread_index) { - return nullptr; -} - -/** - * Writes the client data and open graphs to a datagram. - */ -void PStatMonitor:: -write_datagram(Datagram &dg) const { - dg.add_bool(_client_known); - dg.add_string(_client_hostname); - dg.add_string(_client_progname); - dg.add_int32(_client_pid); - - get_client_data()->write_datagram(dg); - - dg.add_uint32((uint32_t)_colors.size()); - for (const auto &item : _colors) { - dg.add_int32(item.first); - dg.add_float32(item.second[0]); - dg.add_float32(item.second[1]); - dg.add_float32(item.second[2]); - } - - dg.add_uint16(_timelines.size()); - for (PStatGraph *graph : _timelines) { - graph->write_datagram(dg); - } - - dg.add_uint16(_strip_charts.size()); - for (PStatGraph *graph : _strip_charts) { - dg.add_int16(((PStatStripChart *)graph)->get_thread_index()); - dg.add_int16(((PStatStripChart *)graph)->get_collector_index()); - dg.add_bool(((PStatStripChart *)graph)->get_view().get_show_level()); - graph->write_datagram(dg); - } - - dg.add_uint16(_flame_graphs.size()); - for (PStatGraph *graph : _flame_graphs) { - dg.add_int16(((PStatFlameGraph *)graph)->get_thread_index()); - dg.add_int16(((PStatFlameGraph *)graph)->get_collector_index()); - graph->write_datagram(dg); - } - - dg.add_uint16(_piano_rolls.size()); - for (PStatGraph *graph : _piano_rolls) { - dg.add_int16(((PStatPianoRoll *)graph)->get_thread_index()); - graph->write_datagram(dg); - } - - // Reserved for future graph type - dg.add_uint16(0); -} - -/** - * Restores the client data and open graphs from a datagram. - */ -void PStatMonitor:: -read_datagram(DatagramIterator &scan) { - _client_known = scan.get_bool(); - _client_hostname = scan.get_string(); - _client_progname = scan.get_string(); - _client_pid = scan.get_int32(); - - PStatClientData *client_data = new PStatClientData; - client_data->read_datagram(scan); - set_client_data(client_data); - - size_t num_colors = scan.get_uint32(); - for (size_t i = 0; i < num_colors; ++i) { - int key = scan.get_int32(); - LRGBColor &color = _colors[key]; - color[0] = scan.get_float32(); - color[1] = scan.get_float32(); - color[2] = scan.get_float32(); - } - - int num_collectors = client_data->get_num_collectors(); - for (int collector_index = 0; collector_index < num_collectors; ++collector_index) { - if (client_data->has_collector(collector_index)) { - new_collector(collector_index); - } - } - - int num_threads = client_data->get_num_threads(); - for (int thread_index = 0; thread_index < num_threads; ++thread_index) { - if (client_data->has_thread(thread_index)) { - const PStatThreadData *thread_data = client_data->get_thread_data(thread_index); - if (!thread_data->is_empty()) { - const PStatFrameData &frame_data = thread_data->get_latest_frame(); - get_view(thread_index).set_to_frame(frame_data); - - int num_collectors = client_data->get_num_toplevel_collectors(); - for (int i = 0; i < num_collectors; ++i) { - int collector_index = client_data->get_toplevel_collector(i); - if (client_data->has_collector(collector_index)) { - get_level_view(collector_index, thread_index).set_to_frame(thread_data->get_latest_frame()); - } - } - } - new_thread(thread_index); - } - } - - PStatGraph *graph; - - size_t num_timelines = scan.get_uint16(); - for (size_t i = 0; i < num_timelines; ++i) { - graph = open_timeline(); - graph->read_datagram(scan); - } - - size_t num_strip_charts = scan.get_uint16(); - for (size_t i = 0; i < num_strip_charts; ++i) { - int thread_index = scan.get_int16(); - int collector_index = scan.get_int16(); - graph = open_strip_chart(thread_index, collector_index, scan.get_bool()); - graph->read_datagram(scan); - } - - size_t num_flame_graphs = scan.get_uint16(); - for (size_t i = 0; i < num_flame_graphs; ++i) { - int thread_index = scan.get_int16(); - int collector_index = scan.get_int16(); - graph = open_flame_graph(thread_index, collector_index); - graph->read_datagram(scan); - } - - size_t num_piano_rolls = scan.get_uint16(); - for (size_t i = 0; i < num_piano_rolls; ++i) { - int thread_index = scan.get_int16(); - graph = open_piano_roll(thread_index); - graph->read_datagram(scan); - } -} diff --git a/pandatool/src/pstatserver/pStatMonitor.h b/pandatool/src/pstatserver/pStatMonitor.h deleted file mode 100644 index d98ce2b9..00000000 --- a/pandatool/src/pstatserver/pStatMonitor.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatMonitor.h - * @author drose - * @date 2000-07-08 - */ - -#ifndef PSTATMONITOR_H -#define PSTATMONITOR_H - -#include "pandatoolbase.h" - -#include "pStatClientData.h" -#include "pStatView.h" - -#include "referenceCount.h" -#include "pointerTo.h" -#include "luse.h" - -#include "pmap.h" - -class PStatCollectorDef; -class PStatGraph; -class PStatServer; - -/** - * This is an abstract class that presents the interface to any number of - * different front-ends for the stats monitor. One of these will be created - * by the PStatMonitor as each client is connected; this class is responsible - * for opening up a new strip-chart graph or whatever is appropriate. It - * defines a number of empty virtual functions that will be called as new data - * becomes available. - */ -class PStatMonitor : public ReferenceCount { -public: - // The following functions are primarily for use by internal classes to set - // up the monitor. - PStatMonitor(PStatServer *server = nullptr); - virtual ~PStatMonitor(); - - void hello_from(const std::string &hostname, const std::string &progname, - int pid); - void bad_version(const std::string &hostname, const std::string &progname, - int pid, - int client_major, int client_minor, - int server_major, int server_minor); - void set_client_data(PStatClientData *client_data); - - bool write(const Filename &fn) const; - bool read(const Filename &fn); - - void open_default_graphs(); - bool save_default_graphs() const; - - // The following functions are for use by user code to determine information - // about the client data available. - bool is_alive() const; - void close(); - - INLINE PStatServer *get_server(); - INLINE const PStatClientData *get_client_data() const; - INLINE std::string get_collector_name(int collector_index); - const LRGBColor &get_collector_color(int collector_index); - void set_collector_color(int collector_index, const LRGBColor &color); - void clear_collector_color(int collector_index); - - INLINE bool is_client_known() const; - INLINE std::string get_client_hostname() const; - INLINE std::string get_client_progname() const; - INLINE int get_client_pid() const; - INLINE bool has_read_filename() const; - INLINE const Filename &get_read_filename() const; - - PStatView &get_view(int thread_index); - PStatView &get_level_view(int collector_index, int thread_index); - - // The following virtual methods may be overridden by a derived monitor - // class to customize behavior. - - virtual std::string get_monitor_name()=0; - - virtual void initialized(); - virtual void got_hello(); - virtual void got_bad_version(int client_major, int client_minor, - int server_major, int server_minor); - virtual void new_collector(int collector_index); - virtual void new_thread(int thread_index); - virtual void new_data(int thread_index, int frame_number); - virtual void remove_thread(int thread_index); - - virtual void lost_connection(); - virtual void idle(); - virtual bool has_idle(); - - virtual bool is_thread_safe(); - - virtual void user_guide_bars_changed(); - - virtual PStatGraph *open_timeline(); - virtual PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - virtual PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); - virtual PStatGraph *open_piano_roll(int thread_index); - - void write_datagram(Datagram &dg) const; - void read_datagram(DatagramIterator &scan); - -protected: - PStatServer *_server; - -private: - PT(PStatClientData) _client_data; - - bool _client_known; - std::string _client_hostname; - std::string _client_progname; - int _client_pid; - Filename _read_filename; - - typedef pmap Views; - Views _views; - typedef pmap LevelViews; - LevelViews _level_views; - - typedef pmap Colors; - Colors _colors; - -public: - typedef pset Graphs; - Graphs _timelines; - Graphs _strip_charts; - Graphs _flame_graphs; - Graphs _piano_rolls; -}; - -#include "pStatMonitor.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatPianoRoll.I b/pandatool/src/pstatserver/pStatPianoRoll.I deleted file mode 100644 index 8f5bfcc8..00000000 --- a/pandatool/src/pstatserver/pStatPianoRoll.I +++ /dev/null @@ -1,76 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatPianoRoll.I - * @author drose - * @date 2000-07-18 - */ - -/** - * Returns the particular thread whose data this piano roll reflects. - */ -INLINE int PStatPianoRoll:: -get_thread_index() const { - return _thread_index; -} - -/** - * Changes the amount of time the width of the horizontal axis represents. - * This may force a redraw. - */ -INLINE void PStatPianoRoll:: -set_horizontal_scale(double time_width) { - if (_time_width != time_width) { - _time_width = time_width; - normal_guide_bars(); - force_redraw(); - } -} - -/** - * Returns the amount of total time the width of the horizontal axis - * represents. - */ -INLINE double PStatPianoRoll:: -get_horizontal_scale() const { - return _time_width; -} - -/** - * Converts a timestamp to a horizontal pixel offset. - */ -INLINE int PStatPianoRoll:: -timestamp_to_pixel(double time) const { - return (int)((double)_xsize * (time - _start_time) / _time_width); -} - -/** - * Converts a horizontal pixel offset to a timestamp. - */ -INLINE double PStatPianoRoll:: -pixel_to_timestamp(int x) const { - return _time_width * (double)x / (double)_xsize + _start_time; -} - -/** - * Converts a value (i.e. a "height" in the strip chart) to a horizontal - * pixel offset. - */ -INLINE int PStatPianoRoll:: -height_to_pixel(double value) const { - return (int)((double)_xsize * value / _time_width); -} - -/** - * Converts a horizontal pixel offset to a value (a "height" in the strip - * chart). - */ -INLINE double PStatPianoRoll:: -pixel_to_height(int x) const { - return _time_width * (double)x / (double)_xsize; -} diff --git a/pandatool/src/pstatserver/pStatPianoRoll.cxx b/pandatool/src/pstatserver/pStatPianoRoll.cxx deleted file mode 100644 index ba95cc3f..00000000 --- a/pandatool/src/pstatserver/pStatPianoRoll.cxx +++ /dev/null @@ -1,360 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatPianoRoll.cxx - * @author drose - * @date 2000-07-18 - */ - -#include "pStatPianoRoll.h" - -#include "pStatFrameData.h" -#include "pStatCollectorDef.h" -#include "string_utils.h" -#include "config_pstatclient.h" - -#include - -/** - * This class is used internally to build up the set of color bars defined by - * a frame's worth of data. - */ -PStatPianoRoll::BarBuilder:: -BarBuilder() { - _is_new = true; -} - -/** - * Resets the data in the BarBuilder for a new frame. - */ -void PStatPianoRoll::BarBuilder:: -clear() { - _is_new = false; - _color_bars.clear(); -} - -/** - * Adds a new data point. The first data point for a given collector turns in - * on (starts the bar), the second data point turns it off (ends the bar). - */ -void PStatPianoRoll::BarBuilder:: -add_data_point(double time, bool is_start) { - if (is_start) { - // This is a "start" data point: start the bar. - if (_color_bars.empty() || _color_bars.back()._end >= 0.0) { - ColorBar bar; - bar._start = time; - bar._end = -1.0; - _color_bars.push_back(bar); - } - - } else { - // This is a "stop" data point: end the bar. - if (_color_bars.empty()) { - // A "stop" in the middle of the frame implies a "start" at time 0. - ColorBar bar; - bar._start = 0.0; - bar._end = time; - _color_bars.push_back(bar); - - } else { - _color_bars.back()._end = time; - } - } -} - -/** - * Makes sure that each start-bar data point was matched by a corresponding - * end-bar data point. - */ -void PStatPianoRoll::BarBuilder:: -finish(double time) { - if (!_color_bars.empty() && _color_bars.back()._end < 0.0) { - _color_bars.back()._end = time; - } -} - -/** - * - */ -PStatPianoRoll:: -PStatPianoRoll(PStatMonitor *monitor, int thread_index, int xsize, int ysize) : - PStatGraph(monitor, xsize, ysize), - _thread_index(thread_index) -{ - _time_width = 1.0 / pstats_target_frame_rate; - _start_time = 0.0; - _current_frame = -1; - - // If we already have data, load it in now. - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data->get_num_collectors() != 0 && - client_data->get_num_threads() != 0) { - const PStatThreadData *thread_data = - client_data->get_thread_data(thread_index); - if (!thread_data->is_empty()) { - int frame_number = thread_data->get_latest_frame_number(); - compute_page(thread_data->get_frame(frame_number)); - } - } - - _guide_bar_units = GBU_ms | GBU_hz | GBU_show_units; - normal_guide_bars(); - - monitor->_piano_rolls.insert(this); -} - -/** - * - */ -PStatPianoRoll:: -~PStatPianoRoll() { - _monitor->_piano_rolls.erase(this); -} - -/** - * Updates the chart with the latest data. - */ -void PStatPianoRoll:: -update() { - const PStatClientData *client_data = _monitor->get_client_data(); - - // Don't bother to update the thread data until we know at least something - // about the collectors and threads. - if (client_data->get_num_collectors() != 0 && - client_data->get_num_threads() != 0) { - const PStatThreadData *thread_data = - client_data->get_thread_data(_thread_index); - if (!thread_data->is_empty()) { - int frame_number = thread_data->get_latest_frame_number(); - if (frame_number != _current_frame) { - compute_page(thread_data->get_frame(frame_number)); - _current_frame = frame_number; - force_redraw(); - } - } - } - - idle(); -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string PStatPianoRoll:: -get_label_tooltip(int collector_index) const { - const PStatClientData *client_data = _monitor->get_client_data(); - if (!client_data->has_collector(collector_index)) { - return std::string(); - } - - return client_data->get_collector_fullname(collector_index); -} - -/** - * Writes the graph state to a datagram. - */ -void PStatPianoRoll:: -write_datagram(Datagram &dg) const { - dg.add_float64(_time_width); - dg.add_float64(_start_time); - - PStatGraph::write_datagram(dg); -} - -/** - * Restores the graph state from a datagram. - */ -void PStatPianoRoll:: -read_datagram(DatagramIterator &scan) { - _time_width = scan.get_float64(); - _start_time = scan.get_float64(); - - PStatGraph::read_datagram(scan); - - _current_frame = -1; - normal_guide_bars(); - update(); -} - -/** - * To be called by the user class when the widget size has changed. This - * updates the chart's internal data and causes it to issue redraw commands to - * reflect the new size. - */ -void PStatPianoRoll:: -changed_size(int xsize, int ysize) { - if (xsize != _xsize || ysize != _ysize) { - _xsize = xsize; - _ysize = ysize; - - normal_guide_bars(); - force_redraw(); - } -} - -/** - * To be called by the user class when the whole thing needs to be redrawn for - * some reason. - */ -void PStatPianoRoll:: -force_redraw() { - if (!_labels.empty()) { - begin_draw(); - for (int i = 0; i < (int)_labels.size(); i++) { - int collector_index = _labels[i]; - const ColorBars &bars = _page_data[collector_index]._color_bars; - - begin_row(i); - ColorBars::const_iterator bi; - for (bi = bars.begin(); bi != bars.end(); ++bi) { - const ColorBar &bar = (*bi); - draw_bar(i, timestamp_to_pixel(bar._start), timestamp_to_pixel(bar._end)); - } - end_row(i); - } - end_draw(); - } -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void PStatPianoRoll:: -normal_guide_bars() { - // We want vaguely 100 pixels between guide bars. - update_guide_bars(get_xsize() / 100, _time_width); -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any bars in the chart. - */ -void PStatPianoRoll:: -begin_draw() { -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any one row of bars. These bars correspond to the collector whose - * index is get_row_collector(row), and in the color get_row_color(row). - */ -void PStatPianoRoll:: -begin_row(int) { -} - -/** - * Draws a single bar in the chart for the indicated row, in the color - * get_row_color(row), for the indicated horizontal pixel range. - */ -void PStatPianoRoll:: -draw_bar(int, int, int) { -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars for a single row. - */ -void PStatPianoRoll:: -end_row(int) { -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars in the chart. - */ -void PStatPianoRoll:: -end_draw() { -} - -/** - * Should be overridden by the user class to perform any other updates might - * be necessary after the bars have been redrawn. - */ -void PStatPianoRoll:: -idle() { -} - - -// STL function object for sorting labels in order by the collector's sort -// index, used in compute_page(), below. -class SortCollectorLabels1 { -public: - SortCollectorLabels1(const PStatClientData *client_data) : - _client_data(client_data) { - } - bool operator () (int a, int b) const { - return - _client_data->get_collector_def(a)._sort > - _client_data->get_collector_def(b)._sort; - } - const PStatClientData *_client_data; -}; - -/** - * Examines the given frame data and rebuilds the _page_data to match it. - */ -void PStatPianoRoll:: -compute_page(const PStatFrameData &frame_data) { - _start_time = frame_data.get_start(); - - // Clear out the page data and copy it to previous, so we can fill it up - // again and then check to see if we changed the set of bars this frame. - PageData previous; - _page_data.swap(previous); - - int num_events = frame_data.get_num_events(); - for (int i = 0; i < num_events; i++) { - int collector_index = frame_data.get_time_collector(i); - double time = frame_data.get_time(i); - bool is_start = frame_data.is_start(i); - _page_data[collector_index].add_data_point(time, is_start); - } - - // Now check to see if the set of bars has changed. - bool changed_bars = (_page_data.size() != previous.size()); - - if (!changed_bars) { - PageData::const_iterator ai, bi; - ai = _page_data.begin(); - bi = previous.begin(); - while (ai != _page_data.end() && !changed_bars) { - changed_bars = ((*ai).first == (*bi).first); - ++ai; - ++bi; - } - } - - if (changed_bars) { - // If we added or removed some new bars this time, we'll have to update - // our list. - const PStatClientData *client_data = _monitor->get_client_data(); - - _labels.clear(); - PageData::const_iterator pi; - for (pi = _page_data.begin(); pi != _page_data.end(); ++pi) { - int collector_index = (*pi).first; - if (client_data->has_collector(collector_index)) { - _labels.push_back(collector_index); - } - } - - SortCollectorLabels1 sort_labels(client_data); - sort(_labels.begin(), _labels.end(), sort_labels); - - _labels_changed = true; - } - - // Finally, make sure all of the bars are closed. - double time = frame_data.get_end(); - PageData::iterator pi; - for (pi = _page_data.begin(); pi != _page_data.end(); ++pi) { - (*pi).second.finish(time); - } -} diff --git a/pandatool/src/pstatserver/pStatPianoRoll.h b/pandatool/src/pstatserver/pStatPianoRoll.h deleted file mode 100644 index 7ba4ac2e..00000000 --- a/pandatool/src/pstatserver/pStatPianoRoll.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatPianoRoll.h - * @author drose - * @date 2000-07-18 - */ - -#ifndef PSTATPIANOROLL_H -#define PSTATPIANOROLL_H - -#include "pandatoolbase.h" - -#include "pStatGraph.h" -#include "pStatMonitor.h" -#include "pStatClientData.h" - -#include "luse.h" -#include "vector_int.h" - -#include "pmap.h" - -class PStatFrameData; - -/** - * This is an abstract class that presents the interface for drawing a piano- - * roll type chart: it shows the time spent in each of a number of collectors - * as a horizontal bar of color, with time as the horizontal axis. - * - * This class just manages all the piano-roll logic; the actual nuts and bolts - * of drawing pixels is left to a user-derived class. - */ -class PStatPianoRoll : public PStatGraph { -public: - PStatPianoRoll(PStatMonitor *monitor, int thread_index, - int xsize, int ysize); - virtual ~PStatPianoRoll(); - - void update(); - - INLINE int get_thread_index() const; - - INLINE void set_horizontal_scale(double time_width); - INLINE double get_horizontal_scale() const; - - INLINE int timestamp_to_pixel(double time) const; - INLINE double pixel_to_timestamp(int x) const; - INLINE int height_to_pixel(double value) const; - INLINE double pixel_to_height(int y) const; - - std::string get_label_tooltip(int collector_index) const; - - virtual void write_datagram(Datagram &dg) const final; - virtual void read_datagram(DatagramIterator &scan) final; - -protected: - void changed_size(int xsize, int ysize); - void force_redraw(); - virtual void normal_guide_bars(); - - virtual void begin_draw(); - virtual void begin_row(int row); - virtual void draw_bar(int row, int from_x, int to_x); - virtual void end_row(int row); - virtual void end_draw(); - virtual void idle(); - -private: - void compute_page(const PStatFrameData &frame_data); - -protected: - int _thread_index; - -private: - double _time_width; - double _start_time; - - class ColorBar { - public: - double _start; - double _end; - }; - typedef pvector ColorBars; - - class BarBuilder { - public: - BarBuilder(); - void clear(); - void add_data_point(double time, bool is_start); - void finish(double time); - - bool _is_new; - ColorBars _color_bars; - }; - - typedef pmap PageData; - PageData _page_data; - int _current_frame; -}; - -#include "pStatPianoRoll.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatReader.cxx b/pandatool/src/pstatserver/pStatReader.cxx deleted file mode 100644 index 7436b92d..00000000 --- a/pandatool/src/pstatserver/pStatReader.cxx +++ /dev/null @@ -1,340 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatReader.cxx - * @author drose - * @date 2000-07-09 - */ - -#include "pStatReader.h" -#include "pStatServer.h" -#include "pStatMonitor.h" - -#include "pStatClientControlMessage.h" -#include "pStatServerControlMessage.h" -#include "pStatFrameData.h" -#include "pStatProperties.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "connectionManager.h" - -/** - * - */ -PStatReader:: -PStatReader(PStatServer *manager, PStatMonitor *monitor) : -#ifdef HAVE_THREADS - ConnectionReader(manager, monitor->is_thread_safe() ? 1 : 0), -#else // HAVE_THREADS - ConnectionReader(manager, 0), -#endif // HAVE_THREADS - _manager(manager), - _monitor(monitor), - _writer(manager, 0) -{ - set_tcp_header_size(4); - _writer.set_tcp_header_size(4); - _udp_port = 0; - _client_data = new PStatClientData(this); - _monitor->set_client_data(_client_data); -} - -/** - * - */ -PStatReader:: -~PStatReader() { - _manager->release_udp_port(_udp_port); -} - -/** - * This will be called by the PStatClientData in response to its close() call. - * It will tell the server to let go of the reader so it can shut down its - * connection. - */ -void PStatReader:: -close() { - _manager->remove_reader(_tcp_connection, this); - lost_connection(); -} - -/** - * This is intended to be called only once, immediately after construction, by - * the PStatListener that created it. It tells the reader about the newly- - * established TCP connection to a client. - */ -void PStatReader:: -set_tcp_connection(Connection *tcp_connection) { - _tcp_connection = tcp_connection; - add_connection(_tcp_connection); - - _udp_port = _manager->get_udp_port(); - _udp_connection = _manager->open_UDP_connection(_udp_port); - while (_udp_connection.is_null()) { - // That UDP port was no good. Try another. - _udp_port = _manager->get_udp_port(); - _udp_connection = _manager->open_UDP_connection(_udp_port); - } - - add_connection(_udp_connection); - - send_hello(); -} - -/** - * This is called by the PStatServer when it detects that the connection has - * been lost. It should clean itself up and shut down nicely. - */ -void PStatReader:: -lost_connection() { - _client_data->_is_alive = false; - _monitor->lost_connection(); - _manager->lost_connection(_monitor); - _client_data.clear(); - - _manager->close_connection(_tcp_connection); - _manager->close_connection(_udp_connection); - _tcp_connection.clear(); - _udp_connection.clear(); -} - -/** - * Called each frame to do what needs to be done for the monitor's user- - * defined idle routines. - */ -void PStatReader:: -idle() { - dequeue_frame_data(); - _monitor->idle(); -} - -/** - * Returns the monitor that this reader serves. - */ -PStatMonitor *PStatReader:: -get_monitor() { - return _monitor; -} - -/** - * Returns the current machine's hostname. - */ -std::string PStatReader:: -get_hostname() { - if (_hostname.empty()) { - _hostname = ConnectionManager::get_host_name(); - if (_hostname.empty()) { - _hostname = "unknown"; - } - } - return _hostname; -} - -/** - * Sends the initial greeting message to the client. - */ -void PStatReader:: -send_hello() { - PStatServerControlMessage message; - message._type = PStatServerControlMessage::T_hello; - message._server_hostname = get_hostname(); - message._server_progname = _monitor->get_monitor_name(); - message._udp_port = _udp_port; - - Datagram datagram; - message.encode(datagram); - _writer.send(datagram, _tcp_connection); -} - -/** - * Called by the net code whenever a new datagram is detected on a either the - * TCP or UDP connection. - */ -void PStatReader:: -receive_datagram(const NetDatagram &datagram) { - Connection *connection = datagram.get_connection(); - - if (connection == _tcp_connection) { - PStatClientControlMessage message; - if (message.decode(datagram, _client_data)) { - handle_client_control_message(message); - - } else if (message._type == PStatClientControlMessage::T_datagram) { - handle_client_udp_data(datagram); - - } else { - nout << "Got unexpected message from client.\n"; - } - - } else if (connection == _udp_connection) { - handle_client_udp_data(datagram); - - } else { - nout << "Got datagram from unexpected socket.\n"; - } -} - -/** - * Called when a control message has been received by the client over the TCP - * connection. - */ -void PStatReader:: -handle_client_control_message(const PStatClientControlMessage &message) { - switch (message._type) { - case PStatClientControlMessage::T_hello: - { - _client_data->set_version(message._major_version, message._minor_version); - int server_major_version = get_current_pstat_major_version(); - int server_minor_version = get_current_pstat_minor_version(); - - if (message._major_version != server_major_version || - (message._major_version == server_major_version && - message._minor_version > server_minor_version)) { - _monitor->bad_version(message._client_hostname, message._client_progname, - message._client_pid, - message._major_version, message._minor_version, - server_major_version, server_minor_version); - _monitor->close(); - } else { - _monitor->hello_from(message._client_hostname, message._client_progname, - message._client_pid); - } - } - break; - - case PStatClientControlMessage::T_define_collectors: - { - for (int i = 0; i < (int)message._collectors.size(); i++) { - _client_data->add_collector(message._collectors[i]); - _monitor->new_collector(message._collectors[i]->_index); - } - } - break; - - case PStatClientControlMessage::T_define_threads: - { - // See if we can clean up old threads, so that we don't clutter up the - // view if we are creating many threads. - for (int thread_index = 0; thread_index < _client_data->get_num_threads(); ++thread_index) { - if (_client_data->has_thread(thread_index) && !_client_data->is_thread_alive(thread_index)) { - PStatThreadData *thread_data = (PStatThreadData *)_client_data->get_thread_data(thread_index); - if (thread_data->prune_history(_client_data->get_latest_time())) { - _client_data->remove_thread(thread_index); - _monitor->remove_thread(thread_index); - } - } - } - - for (int i = 0; i < (int)message._names.size(); i++) { - int thread_index = message._first_thread_index + i; - std::string name = message._names[i]; - _client_data->define_thread(thread_index, name, true); - _monitor->new_thread(thread_index); - } - } - break; - - case PStatClientControlMessage::T_expire_thread: - if (_client_data->has_thread(message._first_thread_index)) { - // Remove the thread right away if it has no recent data. - PStatThreadData *thread_data = (PStatThreadData *)_client_data->get_thread_data(message._first_thread_index); - if (thread_data->prune_history(_client_data->get_latest_time())) { - _client_data->remove_thread(message._first_thread_index); - _monitor->remove_thread(message._first_thread_index); - } else { - // Otherwise, just mark it as expired, and we'll remove it later. - _client_data->expire_thread(message._first_thread_index); - } - } - break; - - default: - nout << "Invalid control message received from client.\n"; - } -} - -/** - * Called when a UDP datagram has been received by the client. This should be - * a single frame's worth of data. - */ -void PStatReader:: -handle_client_udp_data(const Datagram &datagram) { - if (!_monitor->is_client_known()) { - // If we haven't heard a "hello" from the client yet, we don't know what - // version data it will be sending us, so we can't decode the data. - // Chances are good we can't display it sensibly yet anyway. Ignore frame - // data until we get that hello. - return; - } - - DatagramIterator source(datagram); - - if (_client_data->is_at_least(2, 1)) { - // Throw away the zero byte at the beginning. - int initial_byte = source.get_uint8(); - nassertv(initial_byte == 0); - } - - if (!_queued_frame_data.full()) { - FrameData data; - data._thread_index = source.get_uint16(); - data._frame_number = source.get_uint32(); - data._frame_data = new PStatFrameData; - data._frame_data->read_datagram(source, _client_data); - - // Queue up the data till we're ready to handle it in a single-threaded - // way. - _queued_frame_data.push_back(data); - } -} - -/** - * Called during the idle loop to pull out all the frame data that we might - * have read while the threaded reader was running. - */ -void PStatReader:: -dequeue_frame_data() { - if (_queued_frame_data.empty()) { - return; - } - - do { - const FrameData &data = _queued_frame_data.front(); - nassertv(_client_data != nullptr); - - // Check to see if any new collectors have level data. - int num_levels = data._frame_data->get_num_levels(); - for (int i = 0; i < num_levels; i++) { - int collector_index = data._frame_data->get_level_collector(i); - if (!_client_data->get_collector_has_level(collector_index, data._thread_index)) { - // This collector is now reporting level data, and it wasn't before. - _client_data->set_collector_has_level(collector_index, data._thread_index, true); - _monitor->new_collector(collector_index); - } - } - - _client_data->record_new_frame(data._thread_index, - data._frame_number, - data._frame_data); - _monitor->new_data(data._thread_index, data._frame_number); - - _queued_frame_data.pop_front(); - } - while (!_queued_frame_data.empty()); - - // Clean up old threads. - for (int thread_index = 0; thread_index < _client_data->get_num_threads(); ++thread_index) { - if (_client_data->has_thread(thread_index) && !_client_data->is_thread_alive(thread_index)) { - PStatThreadData *thread_data = (PStatThreadData *)_client_data->get_thread_data(thread_index); - if (thread_data->prune_history(_client_data->get_latest_time())) { - _client_data->remove_thread(thread_index); - _monitor->remove_thread(thread_index); - } - } - } -} diff --git a/pandatool/src/pstatserver/pStatReader.h b/pandatool/src/pstatserver/pStatReader.h deleted file mode 100644 index 40d1d9b5..00000000 --- a/pandatool/src/pstatserver/pStatReader.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatReader.h - * @author drose - * @date 2000-07-09 - */ - -#ifndef PSTATREADER_H -#define PSTATREADER_H - -#include "pandatoolbase.h" - -#include "pStatClientData.h" -#include "pStatMonitor.h" - -#include "connectionReader.h" -#include "connectionWriter.h" -#include "referenceCount.h" -#include "circBuffer.h" - -class PStatServer; -class PStatMonitor; -class PStatClientControlMessage; -class PStatFrameData; - -// This is the maximum number of frame records that will be queued up from -// this particular client between processing loops. -static const int queued_frame_records = 500; - -/** - * This is the class that does all the work for handling communications from a - * single Panda client. It reads sockets received from the client and boils - * them down into PStatData. - */ -class PStatReader : public ConnectionReader { -public: - PStatReader(PStatServer *manager, PStatMonitor *monitor); - ~PStatReader(); - - void close(); - - void set_tcp_connection(Connection *tcp_connection); - void lost_connection(); - void idle(); - - PStatMonitor *get_monitor(); - -private: - std::string get_hostname(); - void send_hello(); - - virtual void receive_datagram(const NetDatagram &datagram); - - void handle_client_control_message(const PStatClientControlMessage &message); - void handle_client_udp_data(const Datagram &datagram); - void dequeue_frame_data(); - -private: - PStatServer *_manager; - PT(PStatMonitor) _monitor; - ConnectionWriter _writer; - - PT(Connection) _tcp_connection; - PT(Connection) _udp_connection; - int _udp_port; - - PT(PStatClientData) _client_data; - - std::string _hostname; - - class FrameData { - public: - int _thread_index; - int _frame_number; - PStatFrameData *_frame_data; - }; - typedef CircBuffer QueuedFrameData; - QueuedFrameData _queued_frame_data; -}; - -#endif diff --git a/pandatool/src/pstatserver/pStatServer.cxx b/pandatool/src/pstatserver/pStatServer.cxx deleted file mode 100644 index 095a8706..00000000 --- a/pandatool/src/pstatserver/pStatServer.cxx +++ /dev/null @@ -1,306 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatServer.cxx - * @author drose - * @date 2000-07-09 - */ - -#include "pStatServer.h" -#include "pStatReader.h" -#include "thread.h" -#include "config_pstatclient.h" - -/** - * - */ -PStatServer:: -PStatServer() { - _listener = new PStatListener(this); - _next_udp_port = 0; -} - -/** - * - */ -PStatServer:: -~PStatServer() { - stop_listening(); - - delete _listener; -} - -/** - * Establishes a port number that the manager will listen on for TCP - * connections. This may be called more than once to listen simulataneously - * on multiple connections, as if that were at all useful. - * - * The default parameter, -1, indicates the use of whatever port number has - * been indicated in the Config file. - * - * This function returns true if the port was successfully opened, or false if - * it could not open the port. - */ -bool PStatServer:: -listen(int port) { - stop_listening(); - - if (port < 0) { - port = pstats_port; - } - - // Now try to listen to the port. - _rendezvous = open_TCP_server_rendezvous(port, 5); - - if (_rendezvous.is_null()) { - // Couldn't get it. - return false; - } - - // Tell the listener about the new port. - _listener->add_connection(_rendezvous); - - if (_next_udp_port == 0) { - _next_udp_port = port + 1; - } - return true; -} - -/** - * Stops listening. - */ -void PStatServer:: -stop_listening() { - if (_rendezvous != nullptr) { - close_connection(_rendezvous); - _rendezvous.clear(); - } -} - -/** - * Checks for any network activity and handles it, if appropriate, and then - * returns. This must be called periodically unless is_thread_safe() is - * redefined to return true on this class and also on all PStatMonitors in - * use. - * - * Alternatively, a program may call main_loop() and yield control of the - * program entirely to the PStatServer. - */ -void PStatServer:: -poll() { - // Delete all the readers that we couldn't delete before. - while (!_lost_readers.empty()) { - PStatReader *reader = _lost_readers.back(); - _lost_readers.pop_back(); - - reader->lost_connection(); - delete reader; - } - while (!_removed_readers.empty()) { - PStatReader *reader = _removed_readers.back(); - _removed_readers.pop_back(); - delete reader; - } - - _listener->poll(); - - Readers::const_iterator ri = _readers.begin(); - while (ri != _readers.end()) { - // Preincrement the iterator, in case we remove it as a result of calling - // poll(). - Readers::const_iterator rnext = ri; - ++rnext; - PStatReader *reader = (*ri).second; - - reader->poll(); - reader->idle(); - - ri = rnext; - } -} - -/** - * An alternative to repeatedly calling poll(), this function yields control - * of the program to the PStatServer. It does not return until the program is - * done. - * - * If interrupt_flag is non-NULL, it is the address of a bool variable that is - * initially false, and may be asynchronously set true to indicate the loop - * should terminate. - */ -void PStatServer:: -main_loop(bool *interrupt_flag) { - while (interrupt_flag == nullptr || !*interrupt_flag) { - poll(); - Thread::sleep(0.1); - } -} - -/** - * Adds the newly-created PStatReader to the list of currently active readers. - */ -void PStatServer:: -add_reader(Connection *connection, PStatReader *reader) { - _readers[connection] = reader; -} - -/** - * Removes the indicated reader. - */ -void PStatServer:: -remove_reader(Connection *connection, PStatReader *reader) { - Readers::iterator ri; - ri = _readers.find(connection); - if (ri == _readers.end() || (*ri).second != reader) { - nout << "Attempt to remove undefined reader.\n"; - } else { - _readers.erase(ri); - _removed_readers.push_back(reader); - } -} - -/** - * Returns a new port number that will probably be free to use as a UDP port. - * The caller should be prepared to accept the possibility that it will be - * already in use by another process, however. - */ -int PStatServer:: -get_udp_port() { - if (_available_udp_ports.empty()) { - return _next_udp_port++; - } - int udp_port = _available_udp_ports.front(); - _available_udp_ports.pop_front(); - return udp_port; -} - -/** - * Indicates that the given UDP port is once again free for use. - */ -void PStatServer:: -release_udp_port(int port) { - _available_udp_ports.push_back(port); -} - -/** - * Returns the current number of user-defined guide bars. - */ -int PStatServer:: -get_num_user_guide_bars() const { - return _user_guide_bars.size(); -} - -/** - * Returns the height of the nth user-defined guide bar. - */ -double PStatServer:: -get_user_guide_bar_height(int n) const { - nassertr(n >= 0 && n < (int)_user_guide_bars.size(), 0.0f); - return _user_guide_bars[n]; -} - -/** - * Adjusts the height of the nth user-defined guide bar. - */ -void PStatServer:: -move_user_guide_bar(int n, double height) { - nassertv(n >= 0 && n < (int)_user_guide_bars.size()); - _user_guide_bars[n] = height; - user_guide_bars_changed(); -} - -/** - * Creates a new user guide bar and returns its index number. - */ -int PStatServer:: -add_user_guide_bar(double height) { - int n = (int)_user_guide_bars.size(); - _user_guide_bars.push_back(height); - user_guide_bars_changed(); - - return n; -} - -/** - * Removes the user guide bar with the indicated index number. All subsequent - * index numbers are adjusted down one. - */ -void PStatServer:: -remove_user_guide_bar(int n) { - nassertv(n >= 0 && n < (int)_user_guide_bars.size()); - _user_guide_bars.erase(_user_guide_bars.begin() + n); - user_guide_bars_changed(); -} - -/** - * Returns the index number of the first user guide bar found whose height is - * within the indicated range, or -1 if no user guide bars fall within the - * range. - */ -int PStatServer:: -find_user_guide_bar(double from_height, double to_height) const { - GuideBars::const_iterator gbi; - for (gbi = _user_guide_bars.begin(); - gbi != _user_guide_bars.end(); - ++gbi) { - double height = (*gbi); - if (height >= from_height && height <= to_height) { - return (int)(gbi - _user_guide_bars.begin()); - } - } - - return -1; -} - -/** - * Called when the user guide bars have been changed. - */ -void PStatServer:: -user_guide_bars_changed() { - Readers::iterator ri; - for (ri = _readers.begin(); ri != _readers.end(); ++ri) { - (*ri).second->get_monitor()->user_guide_bars_changed(); - } -} - -/** - * This should be redefined to return true in derived classes that want to - * deal with multithreaded readers and such. If this returns true, the - * manager will create the listener in its own thread, and thus the - * PStatReader constructors at least will run in a different thread. - * - * This is not related to the question of whether the reader can handle - * multiple different PStatThreadDatas; it's strictly a question of whether - * the readers themselves can run in a separate thread. - */ -bool PStatServer:: -is_thread_safe() { - return false; -} - -/** - * Called when a lost connection is detected by the net code, this should pass - * the word on to the interested parties and clean up gracefully. - */ -void PStatServer:: -connection_reset(const PT(Connection) &connection, bool okflag) { - // Was this a client connection? Tell the reader about it if it was. - close_connection(connection); - - Readers::iterator ri; - ri = _readers.find(connection); - if (ri != _readers.end()) { - PStatReader *reader = (*ri).second; - _readers.erase(ri); - - // Unfortunately, we can't delete the reader right away, because we might - // have been called from a method on the reader! We'll have to save the - // reader pointer and delete it some time later. - _lost_readers.push_back(reader); - } -} diff --git a/pandatool/src/pstatserver/pStatServer.h b/pandatool/src/pstatserver/pStatServer.h deleted file mode 100644 index b4d53ed1..00000000 --- a/pandatool/src/pstatserver/pStatServer.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatServer.h - * @author drose - * @date 2000-07-09 - */ - -#ifndef PSTATSERVER_H -#define PSTATSERVER_H - -#include "pandatoolbase.h" -#include "pStatListener.h" -#include "connectionManager.h" -#include "vector_stdfloat.h" -#include "pmap.h" -#include "pdeque.h" - -class PStatReader; - -/** - * The overall manager of the network connections. This class gets the ball - * rolling; to use this package, you need to derive from this and define - * make_monitor() to allocate and return a PStatMonitor of the suitable type. - * - * Then create just one PStatServer object and call listen() with the port(s) - * you would like to listen on. It will automatically create PStatMonitors as - * connections are established and mark the connections closed as they are - * lost. - */ -class PStatServer : public ConnectionManager { -public: - PStatServer(); - ~PStatServer(); - - bool listen(int port = -1); - void stop_listening(); - - void poll(); - void main_loop(bool *interrupt_flag = nullptr); - - virtual PStatMonitor *make_monitor(const NetAddress &address)=0; - virtual void lost_connection(PStatMonitor *monitor) {} - - void add_reader(Connection *connection, PStatReader *reader); - void remove_reader(Connection *connection, PStatReader *reader); - - int get_udp_port(); - void release_udp_port(int port); - - int get_num_user_guide_bars() const; - double get_user_guide_bar_height(int n) const; - void move_user_guide_bar(int n, double height); - int add_user_guide_bar(double height); - void remove_user_guide_bar(int n); - int find_user_guide_bar(double from_height, double to_height) const; - - virtual bool is_thread_safe(); - -protected: - virtual void connection_reset(const PT(Connection) &connection, - bool okflag); - -private: - void user_guide_bars_changed(); - - PStatListener *_listener; - PT(Connection) _rendezvous; - - typedef pmap Readers; - Readers _readers; - typedef pvector LostReaders; - LostReaders _lost_readers; - LostReaders _removed_readers; - - typedef pdeque Ports; - Ports _available_udp_ports; - int _next_udp_port; - - typedef vector_stdfloat GuideBars; - GuideBars _user_guide_bars; -}; - -#endif diff --git a/pandatool/src/pstatserver/pStatStripChart.I b/pandatool/src/pstatserver/pStatStripChart.I deleted file mode 100644 index 3e924a1b..00000000 --- a/pandatool/src/pstatserver/pStatStripChart.I +++ /dev/null @@ -1,186 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatStripChart.I - * @author drose - * @date 2000-07-15 - */ - -/** - * Returns the View this chart represents. - */ -INLINE PStatView &PStatStripChart:: -get_view() const { - return _view; -} - -/** - * Returns the particular thread whose data this strip chart reflects. - */ -INLINE int PStatStripChart:: -get_thread_index() const { - return _thread_index; -} - -/** - * Returns the particular collector whose data this strip chart reflects. - */ -INLINE int PStatStripChart:: -get_collector_index() const { - return _collector_index; -} - -/** - * Changes the amount of time the width of the horizontal axis represents. - * This may force a redraw. - */ -INLINE void PStatStripChart:: -set_horizontal_scale(double time_width) { - if (_time_width != time_width) { - if (_scroll_mode) { - _start_time += _time_width - time_width; - } else { - force_reset(); - } - _time_width = time_width; - } -} - -/** - * Returns the amount of total time the width of the horizontal axis - * represents. - */ -INLINE double PStatStripChart:: -get_horizontal_scale() const { - return _time_width; -} - -/** - * Changes the value the height of the vertical axis represents. This may - * force a redraw. - */ -INLINE void PStatStripChart:: -set_vertical_scale(double value_height) { - if (_value_height != value_height) { - _value_height = value_height; - normal_guide_bars(); - force_redraw(); - } -} - -/** - * Returns total value the height of the vertical axis represents. - */ -INLINE double PStatStripChart:: -get_vertical_scale() const { - return _value_height; -} - -/** - * Changes the scroll_mode flag. When true, the strip chart will update - * itself by scrolling to the left; when false, the strip chart will wrap - * around at the right and restart at the left end without scrolling. - */ -INLINE void PStatStripChart:: -set_scroll_mode(bool scroll_mode) { - if (_scroll_mode != scroll_mode) { - _scroll_mode = scroll_mode; - _first_data = true; - } -} - -/** - * Returns the current state of the scroll_mode flag. When true, the strip - * chart will update itself by scrolling to the left; when false, the strip - * chart will wrap around at the right and restart at the left end without - * scrolling. - */ -INLINE bool PStatStripChart:: -get_scroll_mode() const { - return _scroll_mode; -} - -/** - * Changes the average_mode flag. When true, the strip chart will average out - * the color values over pstats_average_time seconds, which hides spikes and - * makes the overall trends easier to read. When false, the strip chart shows - * the actual data as it is happening. - */ -INLINE void PStatStripChart:: -set_average_mode(bool average_mode) { - if (_average_mode != average_mode) { - _average_mode = average_mode; - force_redraw(); - } -} - -/** - * Returns the current state of the average_mode flag. When true, the strip - * chart will average out the color values over pstats_average_time seconds, - * which hides spikes and makes the overall trends easier to read. When - * false, the strip chart shows the actual data as it is happening. - */ -INLINE bool PStatStripChart:: -get_average_mode() const { - return _average_mode; -} - -/** - * Converts a timestamp to a horizontal pixel offset. - */ -INLINE int PStatStripChart:: -timestamp_to_pixel(double time) const { - return (int)((double)get_xsize() * (time - _start_time) / _time_width); -} - -/** - * Converts a horizontal pixel offset to a timestamp. - */ -INLINE double PStatStripChart:: -pixel_to_timestamp(int x) const { - return _time_width * (double)x / (double)get_xsize() + _start_time; -} - -/** - * Converts a value (i.e. a "height" in the strip chart) to a vertical pixel - * offset. - */ -INLINE int PStatStripChart:: -height_to_pixel(double value) const { - return get_ysize() - (int)((double)get_ysize() * value / _value_height); -} - -/** - * Converts a vertical pixel offset to a value (a "height" in the strip - * chart). - */ -INLINE double PStatStripChart:: -pixel_to_height(int x) const { - return _value_height * (double)(get_ysize() - x) / (double)get_ysize(); -} - -/** - * Returns true if get_title_text() has never yet returned an answer, false if - * it has. - */ -INLINE bool PStatStripChart:: -is_title_unknown() const { - return _title_unknown; -} - -/** - * Returns true if the indicated collector appears anywhere on the chart at - * the current time, false otherwise. - */ -INLINE bool PStatStripChart:: -is_label_used(int collector_index) const { - if (collector_index < (int)_label_usage.size()) { - return _label_usage[collector_index] > 0; - } - return false; -} diff --git a/pandatool/src/pstatserver/pStatStripChart.cxx b/pandatool/src/pstatserver/pStatStripChart.cxx deleted file mode 100644 index d961b7c0..00000000 --- a/pandatool/src/pstatserver/pStatStripChart.cxx +++ /dev/null @@ -1,1128 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatStripChart.cxx - * @author drose - * @date 2000-07-15 - */ - -#include "pStatStripChart.h" -#include "pStatClientData.h" -#include "pStatMonitor.h" - -#include "pStatFrameData.h" -#include "pStatCollectorDef.h" -#include "string_utils.h" -#include "config_pstatclient.h" - -#include - -using std::max; -using std::min; - -/** - * - */ -PStatStripChart:: -PStatStripChart(PStatMonitor *monitor, - int thread_index, int collector_index, bool show_level, - int xsize, int ysize) : - PStatGraph(monitor, xsize, ysize), - _thread_index(thread_index), - _view(show_level ? monitor->get_level_view(0, thread_index) : monitor->get_view(thread_index)), - _collector_index(collector_index) -{ - _scroll_mode = pstats_scroll_mode; - _average_mode = false; - - _next_frame = 0; - _first_data = true; - _cursor_pixel = 0; - - _time_width = 20.0; - _value_height = 1.0/10.0; - _start_time = 0.0; - - _level_index = -1; - _title_unknown = true; - - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data->has_collector(_collector_index)) { - const PStatCollectorDef &def = client_data->get_collector_def(_collector_index); - _unit_name = def._level_units; - } - - set_auto_vertical_scale(); - - monitor->_strip_charts.insert(this); -} - -/** - * - */ -PStatStripChart:: -~PStatStripChart() { - _monitor->_strip_charts.erase(this); -} - -/** - * Indicates that new data has become available. - */ -void PStatStripChart:: -new_data(int frame_number) { - // If the new frame is older than the last one we've drawn, we'll need to - // back up and redraw it. This can happen when frames arrive out of order - // from the client. - _next_frame = min(frame_number, _next_frame); -} - -/** - * Updates the chart with the latest data. - */ -void PStatStripChart:: -update() { - const PStatClientData *client_data = get_monitor()->get_client_data(); - - // Don't bother to update the thread data until we know at least something - // about the collectors and threads. - if (client_data->get_num_collectors() != 0 && - client_data->get_num_threads() != 0) { - const PStatThreadData *thread_data = _view.get_thread_data(); - if (!thread_data->is_empty()) { - int latest = thread_data->get_latest_frame_number(); - - if (latest > _next_frame) { - draw_frames(_next_frame, latest); - } - _next_frame = latest; - - // Clean out the old data. - double oldest_time = - thread_data->get_frame(latest).get_start() - _time_width; - - Data::iterator di; - di = _data.begin(); - while (di != _data.end() && - thread_data->get_frame((*di).first).get_start() < oldest_time) { - dec_label_usage((*di).second); - _data.erase(di); - di = _data.begin(); - } - } - } - - if (_level_index != _view.get_level_index()) { - update_labels(); - } - - idle(); -} - -/** - * Returns true if the chart has seen its first data appear on it, false if it - * is still a virgin chart. - */ -bool PStatStripChart:: -first_data() const { - return _first_data; -} - -/** - * Changes the collector represented by this strip chart. This may force a - * redraw. - */ -void PStatStripChart:: -set_collector_index(int collector_index) { - if (_collector_index != collector_index) { - _collector_index = collector_index; - _title_unknown = true; - _data.clear(); - clear_label_usage(); - set_auto_vertical_scale(); - force_redraw(); - update_labels(); - } -} - -/** - * Sets the vertical scale according to the suggested scale of the base - * collector, if any, or to center the target frame rate bar otherwise. - */ -void PStatStripChart:: -set_default_vertical_scale() { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data->has_collector(_collector_index)) { - const PStatCollectorDef &def = - client_data->get_collector_def(_collector_index); - if (def._suggested_scale != 0.0) { - set_vertical_scale(def._suggested_scale); - return; - } - } - - set_vertical_scale(2.0 / get_target_frame_rate()); -} - -/** - * Sets the vertical scale to make all the data visible. - */ -void PStatStripChart:: -set_auto_vertical_scale() { - const PStatThreadData *thread_data = _view.get_thread_data(); - - // Calculate the median value. - std::vector values; - - if (thread_data != nullptr && !thread_data->is_empty()) { - // Find the oldest visible frame. - double start_time = pixel_to_timestamp(0); - int oldest_frame = std::max( - thread_data->get_frame_number_at_time(start_time), - thread_data->get_oldest_frame_number()); - int latest_frame = thread_data->get_latest_frame_number(); - - for (int frame_number = oldest_frame; frame_number <= latest_frame; ++frame_number) { - if (thread_data->has_frame(frame_number)) { - const FrameData &frame = get_frame_data(frame_number); - values.push_back(frame._net_value); - } - } - } - - if (values.empty()) { - set_default_vertical_scale(); - return; - } - - double median; - size_t half = values.size() / 2; - if (values.size() % 2 == 0) { - std::sort(values.begin(), values.end()); - median = (values[half] + values[half + 1]) / 2.0; - } else { - std::nth_element(values.begin(), values.begin() + half, values.end()); - median = values[half]; - } - - if (median > 0.0) { - // Take 1.5 times the median value as the vertical scale. - set_vertical_scale(median * 1.5); - } else { - set_default_vertical_scale(); - } -} - -/** - * Return the collector index associated with the particular band of color at - * the indicated pixel location, or -1 if no band of color was at the pixel. - */ -int PStatStripChart:: -get_collector_under_pixel(int xpoint, int ypoint) { - // First, we need to know what frame it was; to know that, we need to - // determine the time corresponding to the x pixel. - double time = pixel_to_timestamp(xpoint); - - // Now use that time to determine the frame. - const PStatThreadData *thread_data = _view.get_thread_data(); - - if (time < thread_data->get_oldest_time()) { - return -1; - } - - // And now we can determine which collector within the frame, based on the - // value height. - if (_average_mode) { - double start_time = pixel_to_timestamp(xpoint); - int then_i = thread_data->get_frame_number_at_time(start_time - pstats_average_time); - int now_i = thread_data->get_frame_number_at_time(start_time, then_i); - - FrameData fdata; - compute_average_pixel_data(fdata, then_i, now_i, start_time); - double overall_value = 0.0; - int y = get_ysize(); - - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - overall_value += cd._net_value; - y = height_to_pixel(overall_value); - if (y <= ypoint) { - return cd._collector_index; - } - } - - } else { - int frame_number = thread_data->get_frame_number_at_time(time); - const FrameData &fdata = get_frame_data(frame_number); - double overall_value = 0.0; - int y = get_ysize(); - - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - overall_value += cd._net_value; - y = height_to_pixel(overall_value); - if (y <= ypoint) { - return cd._collector_index; - } - } - } - - return -1; -} - -/** - * Returns the text suitable for the title label on the top line. - */ -std::string PStatStripChart:: -get_title_text() { - std::string text; - - _title_unknown = false; - - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data->has_collector(_collector_index)) { - text = client_data->get_collector_fullname(_collector_index); - const PStatCollectorDef &def = client_data->get_collector_def(_collector_index); - if (_view.get_show_level()) { - if (!def._level_units.empty()) { - text += " (" + def._level_units + ")"; - } - } else { - text += " time"; - } - } else { - _title_unknown = true; - } - - if (_thread_index != 0) { - if (client_data->has_thread(_thread_index)) { - text += " (" + client_data->get_thread_name(_thread_index) + " thread)"; - } else { - _title_unknown = true; - } - } - - return text; -} - -/** - * Returns the text suitable for the total label above the graph. - */ -std::string PStatStripChart:: -get_total_text() { - std::string text = format_number(get_average_net_value(), get_guide_bar_units(), get_guide_bar_unit_name()); - if (get_collector_index() != 0 && !_view.get_show_level()) { - const PStatViewLevel *level = _view.get_level(get_collector_index()); - if (level != nullptr && level->get_count() > 0) { - text += " / " + format_string(level->get_count()) + "x"; - } - } - return text; -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string PStatStripChart:: -get_label_tooltip(int collector_index) const { - const PStatClientData *client_data = _monitor->get_client_data(); - if (!client_data->has_collector(collector_index)) { - return std::string(); - } - - const PStatThreadData *thread_data = _view.get_thread_data(); - - std::ostringstream text; - text << client_data->get_collector_fullname(collector_index); - - double value; - if (collector_index == _collector_index) { - value = get_average_net_value(); - } - else { - int now_i, then_i; - if (!thread_data->get_elapsed_frames(then_i, now_i)) { - return text.str(); - } - double now = _time_width + _start_time; - double then = now - pstats_average_time; - - double net_value = 0.0; - double net_time = 0.0; - - // We start with just the portion of frame then_i that actually does fall - // within our "then to now" window (usually some portion of it will). - const PStatFrameData &frame_data = thread_data->get_frame(then_i); - if (frame_data.get_end() > then) { - double this_time = (frame_data.get_end() - then); - for (const ColorData &cd : get_frame_data(then_i)) { - if (cd._collector_index == collector_index) { - net_value += cd._net_value * this_time; - net_time += this_time; - break; - } - } - } - // Then we get all of each of the remaining frames. - for (int frame_number = then_i + 1; - frame_number <= now_i; - frame_number++) { - const PStatFrameData &frame_data = thread_data->get_frame(frame_number); - for (const ColorData &cd : get_frame_data(frame_number)) { - if (cd._collector_index == collector_index) { - double this_time = frame_data.get_net_time(); - net_value += cd._net_value * this_time; - net_time += this_time; - break; - } - } - } - - if (net_time == 0) { - return text.str(); - } - value = net_value / net_time; - } - - text << " (" << format_number(value, get_guide_bar_units(), get_guide_bar_unit_name()); - - if (collector_index != 0) { - const FrameData &frame = get_frame_data(thread_data->get_latest_frame_number()); - - for (const ColorData &cd : frame) { - if (cd._collector_index == collector_index) { - if (cd._count > 0) { - text << " / " << cd._count << "x"; - } - break; - } - } - } - - text << ")"; - return text.str(); -} - -/** - * Writes the graph state to a datagram. - */ -void PStatStripChart:: -write_datagram(Datagram &dg) const { - dg.add_bool(_scroll_mode); - dg.add_bool(_average_mode); - dg.add_float64(_time_width); - dg.add_float64(_start_time); - dg.add_float64(_value_height); - - // Not really necessary, we reconstructed this from the client data. - //for (const auto &item : _data) { - // dg.add_int32(item.first); - // dg.add_uint32(item.second.size()); - // - // for (const ColorData &cd : item.second) { - // dg.add_uint16(cd._collector_index); - // dg.add_uint16(cd._i); - // dg.add_float64(cd._net_value); - // } - //} - //dg.add_int32(-1); - - PStatGraph::write_datagram(dg); -} - -/** - * Restores the graph state from a datagram. - */ -void PStatStripChart:: -read_datagram(DatagramIterator &scan) { - _next_frame = 0; - force_reset(); - - _scroll_mode = scan.get_bool(); - _average_mode = scan.get_bool(); - _time_width = scan.get_float64(); - _start_time = scan.get_float64(); - _value_height = scan.get_float64(); - - //int key; - //while ((key = scan.get_int32()) != -1) { - // FrameData &fdata = _data[key]; - // fdata.resize(scan.get_uint32()); - // - // for (ColorData &cd : fdata) { - // cd._collector_index = scan.get_uint16(); - // cd._i = scan.get_uint16(); - // cd._net_value = scan.get_float64(); - // } - //} - - PStatGraph::read_datagram(scan); - - normal_guide_bars(); - update(); -} - -/** - * Adds the data from additional into the data from fdata, after applying the - * scale weight. - */ -void PStatStripChart:: -accumulate_frame_data(FrameData &fdata, const FrameData &additional, - double weight) { - FrameData::iterator ai; - FrameData::const_iterator bi; - - ai = fdata.begin(); - bi = additional.begin(); - - FrameData result; - - if (fdata.size() == additional.size()) { - // Start out assuming that fdata and additional contain exactly the same - // set of collectors. If we discover otherwise, we'll have to bail at - // that point. - while (ai != fdata.end() && - (*ai)._collector_index == (*bi)._collector_index) { - (*ai)._net_value += ((*bi)._net_value * weight); - ++ai; - ++bi; - } - - if (ai == fdata.end()) { - // If we successfully reached the end of the list, great! We're done - // without any merging. - return; - } - - // Otherwise, the two lists weren't identical. In that case, copy the - // accumulated data so far and continue from this point with the full- - // blown merge. - result.reserve(max(fdata.size(), additional.size())); - FrameData::const_iterator ci; - for (ci = fdata.begin(); ci != ai; ++ci) { - result.push_back(*ci); - } - - } else { - // If the two lists had different lengths, clearly they aren't identical. - result.reserve(max(fdata.size(), additional.size())); - } - - while (ai != fdata.end() && bi != additional.end()) { - if ((*ai)._i < (*bi)._i) { - // Here's a data value that's in data, but not in additional. - result.push_back(*ai); - ++ai; - - } else if ((*bi)._i < (*ai)._i) { - // Here's a data value that's in additional, but not in data. - ColorData scaled; - scaled._collector_index = (*bi)._collector_index; - scaled._i = (*bi)._i; - scaled._count = 0; - scaled._net_value = (*bi)._net_value * weight; - result.push_back(scaled); - ++bi; - - } else { - // Here's a data value that's in both. - ColorData combined; - combined._collector_index = (*ai)._collector_index; - combined._i = (*bi)._i; - combined._count = 0; - combined._net_value = (*ai)._net_value + (*bi)._net_value * weight; - result.push_back(combined); - ++ai; - ++bi; - } - } - - while (ai != fdata.end()) { - // Here's a data value that's in data, but not in additional. - result.push_back(*ai); - ++ai; - } - - while (bi != additional.end()) { - // Here's a data value that's in additional, but not in data. - ColorData scaled; - scaled._collector_index = (*bi)._collector_index; - scaled._i = (*bi)._i; - scaled._count = 0; - scaled._net_value = (*bi)._net_value * weight; - result.push_back(scaled); - ++bi; - } - - fdata.swap(result); -} - -/** - * Applies the indicated scale to all collector values in data. - */ -void PStatStripChart:: -scale_frame_data(FrameData &fdata, double factor) { - FrameData::iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - (*fi)._net_value *= factor; - } -} - - -/** - * Returns the cached FrameData associated with the given frame number. This - * describes the lengths of the color bands for a single vertical stripe in - * the chart. - */ -const PStatStripChart::FrameData &PStatStripChart:: -get_frame_data(int frame_number) const { - Data::const_iterator di; - di = _data.find(frame_number); - if (di != _data.end()) { - return (*di).second; - } - - const PStatThreadData *thread_data = _view.get_thread_data(); - //assert(thread_data->has_frame(frame_number)); - const PStatFrameData &frame_data = thread_data->get_frame(frame_number); - _view.set_to_frame(frame_data); - - FrameData &fdata = _data[frame_number]; - fdata._start = frame_data.get_start(); - fdata._end = frame_data.get_end(); - fdata._net_time = frame_data.get_net_time(); - - double net_value = 0.0; - - const PStatViewLevel *level = _view.get_level(_collector_index); - int num_children = level->get_num_children(); - for (int i = 0; i < num_children; i++) { - const PStatViewLevel *child = level->get_child(i); - ColorData cd; - cd._collector_index = (unsigned short)child->get_collector(); - cd._i = (unsigned short)i; - cd._count = child->get_count(); - cd._net_value = child->get_net_value(); - if (cd._net_value != 0.0) { - fdata.push_back(cd); - net_value += cd._net_value; - } - } - - // Also, there might be some value in the overall Collector that wasn't - // included in all of the children. - ColorData cd; - cd._collector_index = (unsigned short)level->get_collector(); - cd._i = (unsigned short)num_children; - cd._count = level->get_count(); - cd._net_value = level->get_value_alone(); - if (cd._net_value > 0.0) { - fdata.push_back(cd); - net_value += cd._net_value; - } - - fdata._net_value = net_value; - - ((PStatStripChart *)this)->inc_label_usage(fdata); - - return fdata; -} - -/** - * Fills the indicated FrameData structure with the color data for the - * indicated pixel, averaged over the past pstats_average_time seconds. - * - * now is the timestamp for which we are computing the data; then_i and now_i - * are the frame numbers that bound (now - pstats_average_time) and now. At - * function initialization time, these should be at or below the actual - * values; they will be incremented as needed by this function. This allows - * the function to be called repeatedly for successive pixels. - */ -void PStatStripChart:: -compute_average_pixel_data(PStatStripChart::FrameData &result, - int &then_i, int &now_i, double now) { - result.clear(); - - const PStatThreadData *thread_data = _view.get_thread_data(); - if (thread_data->is_empty() || thread_data->get_oldest_time() > now) { - // No data. - return; - } - - double then = now - pstats_average_time; - then_i = thread_data->get_frame_number_after(then, then_i); - now_i = thread_data->get_frame_number_after(now, now_i); - - const FrameData *fdata = &get_frame_data(then_i); - then = max(then, fdata->_start); - double then_end = fdata->_end; - - // Sum up a weighted average of all of the individual frames we pass. - - // We start with just the portion of frame then_i that actually does fall - // within our "then to now" window. - accumulate_frame_data(result, *fdata, then_end - then); - double last = then_end; - - // Then we get all of each of the middle frames. - double weight = 0.0; - for (int frame_number = then_i + 1; - frame_number < now_i; - frame_number++) { - if (thread_data->has_frame(frame_number)) { - if (weight > 0.0) { - accumulate_frame_data(result, *fdata, weight); - weight = 0.0; - } - fdata = &get_frame_data(frame_number); - } - weight += fdata->_end - last; - last = fdata->_end; - } - - if (weight > 0.0) { - accumulate_frame_data(result, *fdata, weight); - } - - // And finally, we get the remainder as now_i. - if (last <= now) { - accumulate_frame_data(result, get_frame_data(now_i), now - last); - } - - scale_frame_data(result, 1.0f / (now - then)); -} - -/** - * Computes the average value of the chart's collector over the past - * pstats_average_time number of seconds. - */ -double PStatStripChart:: -get_average_net_value() const { - const PStatThreadData *thread_data = _view.get_thread_data(); - int now_i, then_i; - if (!thread_data->get_elapsed_frames(then_i, now_i)) { - return 0.0; - } - double now = _time_width + _start_time; - double then = now - pstats_average_time; - - int num_frames = now_i - then_i + 1; - - if (_collector_index == 0 && !_view.get_show_level()) { - // If we're showing the time for the whole frame, compute this from the - // total elapsed time, rather than summing up individual frames. This is - // more accurate and exactly matches what is reported by - // thread_data->get_frame_rate(). - - const PStatFrameData &now_frame_data = thread_data->get_frame(now_i); - const PStatFrameData &then_frame_data = thread_data->get_frame(then_i); - double now = now_frame_data.get_end(); - double elapsed_time = (now - then_frame_data.get_start()); - return elapsed_time / (double)num_frames; - - } else { - // On the other hand, if we're showing the time for some sub-frame, we - // have to do it the less-accurate way of summing up individual frames, - // which might introduce errors if we are missing data for some frames, - // but what can you do? - - const PStatThreadData *thread_data = _view.get_thread_data(); - - double net_value = 0.0; - double net_time = 0.0; - - // We start with just the portion of frame then_i that actually does fall - // within our "then to now" window (usually some portion of it will). - const PStatFrameData &frame_data = thread_data->get_frame(then_i); - const FrameData *frame = &get_frame_data(then_i); - if (frame_data.get_end() > then) { - double this_time = (frame->_end - then); - net_value += frame->_net_value * this_time; - net_time += this_time; - } - // Then we get all of each of the remaining frames. - for (int frame_number = then_i + 1; - frame_number <= now_i; - frame_number++) { - if (thread_data->has_frame(frame_number)) { - frame = &get_frame_data(frame_number); - } - double this_time = frame->_net_time; - net_value += frame->_net_value * this_time; - net_time += this_time; - } - - return net_value / net_time; - } -} - -/** - * To be called by the user class when the widget size has changed. This - * updates the chart's internal data and causes it to issue redraw commands to - * reflect the new size. - */ -void PStatStripChart:: -changed_size(int xsize, int ysize) { - if (xsize != _xsize || ysize != _ysize) { - _xsize = xsize; - _ysize = ysize; - if (_xsize > 0 && _ysize > 0) { - _cursor_pixel = xsize * _cursor_pixel / _xsize; - - if (!_first_data) { - if (_scroll_mode) { - draw_pixels(0, _xsize); - - } else { - // Redraw the stats that were there before. - double old_start_time = _start_time; - - // Back up a bit to draw the stuff to the right of the cursor. - _start_time -= _time_width; - draw_pixels(_cursor_pixel, _xsize); - - // Now draw the stuff to the left of the cursor. - _start_time = old_start_time; - draw_pixels(0, _cursor_pixel); - } - } - } - } -} - -/** - * To be called by the user class when the whole thing needs to be redrawn for - * some reason. - */ -void PStatStripChart:: -force_redraw() { - if (!_first_data) { - draw_pixels(0, _xsize); - } -} - -/** - * To be called by the user class to cause the chart to reset to empty and - * start filling again. - */ -void PStatStripChart:: -force_reset() { - clear_region(); - _first_data = true; -} - - -/** - * Should be overridden by the user class to wipe out the entire strip chart - * region. - */ -void PStatStripChart:: -clear_region() { -} - -/** - * Should be overridden by the user class to copy a region of the chart from - * one part of the chart to another. This is used to implement scrolling. - */ -void PStatStripChart:: -copy_region(int, int, int) { -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any color bars in the strip chart; it gives the pixel range that's - * about to be redrawn. - */ -void PStatStripChart:: -begin_draw(int, int) { -} - -/** - * Should be overridden by the user class to draw a single vertical slice in - * the strip chart at the indicated pixel, with the data for the indicated - * frame. - */ -void PStatStripChart:: -draw_slice(int, int, const PStatStripChart::FrameData &fdata) { -} - -/** - * This is similar to draw_slice(), except it should draw a vertical line of - * the background color to represent a portion of the chart that has no data. - */ -void PStatStripChart:: -draw_empty(int, int) { -} - -/** - * This is similar to draw_slice(), except that it should draw the black - * vertical stripe that represents the current position when not in scrolling - * mode. - */ -void PStatStripChart:: -draw_cursor(int) { -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars in the strip chart; it gives the pixel range - * that was just redrawn. - */ -void PStatStripChart:: -end_draw(int, int) { -} - -/** - * Should be overridden by the user class to perform any other updates might - * be necessary after the color bars have been redrawn. For instance, it - * could check the state of _labels_changed, and redraw the labels if it is - * true. - */ -void PStatStripChart:: -idle() { -} - -// STL function object for sorting labels in order by the collector's sort -// index, used in update_labels(), below. -class SortCollectorLabels2 { -public: - SortCollectorLabels2(const PStatClientData *client_data) : - _client_data(client_data) { - } - bool operator () (int a, int b) const { - return - _client_data->get_collector_def(a)._sort > - _client_data->get_collector_def(b)._sort; - } - const PStatClientData *_client_data; -}; - -/** - * Resets the list of labels. - */ -void PStatStripChart:: -update_labels() { - const PStatViewLevel *level = _view.get_level(_collector_index); - _labels.clear(); - - int num_children = level->get_num_children(); - for (int i = 0; i < num_children; i++) { - const PStatViewLevel *child = level->get_child(i); - int collector_index = child->get_collector(); - if (is_label_used(collector_index)) { - _labels.push_back(collector_index); - } - } - - SortCollectorLabels2 sort_labels(get_monitor()->get_client_data()); - sort(_labels.begin(), _labels.end(), sort_labels); - - int collector_index = level->get_collector(); - _labels.push_back(collector_index); - - _labels_changed = true; - _level_index = _view.get_level_index(); -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void PStatStripChart:: -normal_guide_bars() { - update_guide_bars(4, _value_height); -} - - -/** - * Draws the levels for the indicated frame range. - */ -void PStatStripChart:: -draw_frames(int first_frame, int last_frame) { - const PStatThreadData *thread_data = _view.get_thread_data(); - - last_frame = min(last_frame, thread_data->get_latest_frame_number()); - - if (_first_data) { - if (_scroll_mode) { - _start_time = - thread_data->get_frame(last_frame).get_start() - _time_width; - } else { - _start_time = thread_data->get_frame(first_frame).get_start(); - _cursor_pixel = 0; - } - } - - int first_pixel; - if (thread_data->has_frame(first_frame)) { - first_pixel = - timestamp_to_pixel(thread_data->get_frame(first_frame).get_start()); - } else { - first_pixel = 0; - } - - int last_pixel = - timestamp_to_pixel(thread_data->get_frame(last_frame).get_start()); - - if (_first_data && !_scroll_mode) { - first_pixel = min(_cursor_pixel, first_pixel); - } - _first_data = false; - - if (last_pixel - first_pixel >= _xsize) { - // If we're drawing the whole thing all in this one swoop, just start - // over. - _start_time = thread_data->get_frame(last_frame).get_start() - _time_width; - first_pixel = 0; - last_pixel = _xsize; - } - - if (last_pixel <= _xsize) { - // It all fits in one block. - _cursor_pixel = last_pixel; - draw_pixels(first_pixel, last_pixel); - - } else { - if (_scroll_mode) { - // In scrolling mode, slide the world back. - int slide_pixels = last_pixel - _xsize; - // This is really slow on macOS, just redraw instead -#ifdef __APPLE__ - draw_pixels(0, first_pixel - slide_pixels); -#else - copy_region(slide_pixels, first_pixel, 0); -#endif - first_pixel -= slide_pixels; - last_pixel -= slide_pixels; - _start_time += (double)slide_pixels / (double)_xsize * _time_width; - draw_pixels(first_pixel, last_pixel); - - } else { - // In wrapping mode, do it in two blocks. - _cursor_pixel = -1; - draw_pixels(first_pixel, _xsize); - _start_time = pixel_to_timestamp(_xsize); - last_pixel -= _xsize; - _cursor_pixel = last_pixel; - draw_pixels(0, last_pixel); - } - } -} - -/** - * Draws the levels for the indicated pixel range. - */ -void PStatStripChart:: -draw_pixels(int first_pixel, int last_pixel) { - begin_draw(first_pixel, last_pixel); - const PStatThreadData *thread_data = _view.get_thread_data(); - - if (_average_mode && !thread_data->is_empty()) { - // In average mode, we have to calculate the average value for each pixel. - double start_time = pixel_to_timestamp(first_pixel); - int then_i = thread_data->get_frame_number_at_time(start_time - pstats_average_time); - int now_i = thread_data->get_frame_number_at_time(start_time, then_i); - for (int x = first_pixel; x <= last_pixel; x++) { - if (x == _cursor_pixel && !_scroll_mode) { - draw_cursor(x); - } else { - FrameData fdata; - compute_average_pixel_data(fdata, then_i, now_i, pixel_to_timestamp(x)); - draw_slice(x, 1, fdata); - } - } - - } else { - // When average mode is false, we are in frame mode; just show the actual - // frame data. - int frame_number = -1; - int x = first_pixel; - while (x <= last_pixel) { - if (x == _cursor_pixel && !_scroll_mode) { - draw_cursor(x); - x++; - - } else { - double time = pixel_to_timestamp(x); - frame_number = thread_data->get_frame_number_at_time(time, frame_number); - int w = 1; - int stop_pixel = last_pixel; - if (!_scroll_mode) { - stop_pixel = min(stop_pixel, _cursor_pixel); - } - while (x + w < stop_pixel && - thread_data->get_frame_number_at_time(pixel_to_timestamp(x + w), frame_number) == frame_number) { - w++; - } - if (thread_data->has_frame(frame_number)) { - draw_slice(x, w, get_frame_data(frame_number)); - } else { - draw_empty(x, w); - } - x += w; - } - } - } - - end_draw(first_pixel, last_pixel); -} - -/** - * Erases all elements from the label usage data. - */ -void PStatStripChart:: -clear_label_usage() { - _label_usage.clear(); -} - -/** - * Erases the indicated frame data from the current label usage. This - * indicates that the given FrameData has fallen off the end of the chart. - * This must have been proceeded by an earlier call to inc_label_usage() for - * the same FrameData - */ -void PStatStripChart:: -dec_label_usage(const FrameData &fdata) { - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - nassertv(cd._collector_index < (int)_label_usage.size()); - nassertv(_label_usage[cd._collector_index] > 0); - _label_usage[cd._collector_index]--; - if (_label_usage[cd._collector_index] == 0) { - // If a label drops out of usage, it's time to regenerate labels. - _level_index = -1; - } - } -} - -/** - * Records the labels named in the indicated FrameData in the table of current - * labels in use. This should be called when the given FrameData has been - * added to the chart; it will increment the reference count for each - * collector named in the FrameData. The reference count will eventually be - * decremented when dec_label_usage() is called later. - */ -void PStatStripChart:: -inc_label_usage(const FrameData &fdata) { - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - while (cd._collector_index >= (int)_label_usage.size()) { - _label_usage.push_back(0); - } - nassertv(_label_usage[cd._collector_index] >= 0); - _label_usage[cd._collector_index]++; - if (_label_usage[cd._collector_index] == 1) { - // If a label appears for the first time, it's time to regenerate - // labels. - _level_index = -1; - } - } -} diff --git a/pandatool/src/pstatserver/pStatStripChart.h b/pandatool/src/pstatserver/pStatStripChart.h deleted file mode 100644 index 0a68fee6..00000000 --- a/pandatool/src/pstatserver/pStatStripChart.h +++ /dev/null @@ -1,158 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatStripChart.h - * @author drose - * @date 2000-07-15 - */ - -#ifndef PSTATSTRIPCHART_H -#define PSTATSTRIPCHART_H - -#include "pandatoolbase.h" - -#include "pStatGraph.h" -#include "pStatMonitor.h" -#include "pStatClientData.h" - -#include "luse.h" -#include "vector_int.h" - -#include "pmap.h" - -class PStatView; - -/** - * This is an abstract class that presents the interface for drawing a basic - * strip-chart, showing the relative value over an interval of time for - * several different collectors, differentiated by bands of color. - * - * This class just manages all the strip-chart logic; the actual nuts and - * bolts of drawing pixels is left to a user-derived class. - */ -class PStatStripChart : public PStatGraph { -public: - PStatStripChart(PStatMonitor *monitor, - int thread_index, int collector_index, bool show_level, - int xsize, int ysize); - virtual ~PStatStripChart(); - - void new_data(int frame_number); - void update(); - bool first_data() const; - - INLINE PStatView &get_view() const; - INLINE int get_thread_index() const; - INLINE int get_collector_index() const; - void set_collector_index(int collector_index); - - INLINE void set_horizontal_scale(double time_width); - INLINE double get_horizontal_scale() const; - INLINE void set_vertical_scale(double value_height); - void set_default_vertical_scale(); - void set_auto_vertical_scale(); - INLINE double get_vertical_scale() const; - - INLINE void set_scroll_mode(bool scroll_mode); - INLINE bool get_scroll_mode() const; - - INLINE void set_average_mode(bool average_mode); - INLINE bool get_average_mode() const; - - int get_collector_under_pixel(int xpoint, int ypoint); - INLINE int timestamp_to_pixel(double time) const; - INLINE double pixel_to_timestamp(int x) const; - INLINE int height_to_pixel(double value) const; - INLINE double pixel_to_height(int y) const; - - INLINE bool is_title_unknown() const; - std::string get_title_text(); - std::string get_total_text(); - std::string get_label_tooltip(int collector_index) const; - - virtual void write_datagram(Datagram &dg) const final; - virtual void read_datagram(DatagramIterator &scan) final; - -protected: - class ColorData { - public: - unsigned short _collector_index; - unsigned short _i; - int _count; - double _net_value; - }; - class FrameData : public pvector { - public: - double _start, _end; - double _net_value, _net_time; - }; - typedef pmap Data; - - static void accumulate_frame_data(FrameData &fdata, - const FrameData &additional, double weight); - static void scale_frame_data(FrameData &fdata, double factor); - - const FrameData &get_frame_data(int frame_number) const; - void compute_average_pixel_data(PStatStripChart::FrameData &result, - int &then_i, int &now_i, double now); - double get_average_net_value() const; - - void changed_size(int xsize, int ysize); - void force_redraw(); - void force_reset(); - virtual void update_labels(); - virtual void normal_guide_bars(); - - virtual void clear_region(); - virtual void copy_region(int start_x, int end_x, int dest_x); - virtual void begin_draw(int from_x, int to_x); - virtual void draw_slice(int x, int w, const FrameData &fdata); - virtual void draw_empty(int x, int w); - virtual void draw_cursor(int x); - virtual void end_draw(int from_x, int to_x); - virtual void idle(); - - INLINE bool is_label_used(int collector_index) const; - -private: - void draw_frames(int first_frame, int last_frame); - void draw_pixels(int first_pixel, int last_pixel); - - void clear_label_usage(); - void dec_label_usage(const FrameData &fdata); - void inc_label_usage(const FrameData &fdata); - -protected: - int _thread_index; - -private: - PStatView &_view; - int _collector_index; - bool _scroll_mode; - bool _average_mode; - - mutable Data _data; - - int _next_frame; - bool _first_data; - int _cursor_pixel; - - int _level_index; - - double _time_width; - double _start_time; - double _value_height; - bool _title_unknown; - - typedef vector_int LabelUsage; - LabelUsage _label_usage; -}; - -#include "pStatStripChart.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatThreadData.I b/pandatool/src/pstatserver/pStatThreadData.I deleted file mode 100644 index aecd834c..00000000 --- a/pandatool/src/pstatserver/pStatThreadData.I +++ /dev/null @@ -1,28 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatThreadData.I - * @author drose - * @date 2000-07-10 - */ - -/** - * Returns a pointer to the ClientData structure associated with this data. - */ -INLINE const PStatClientData *PStatThreadData:: -get_client_data() const { - return _client_data; -} - -/** - * Returns true if the structure contains no frames, false otherwise. - */ -INLINE bool PStatThreadData:: -is_empty() const { - return _frames.empty(); -} diff --git a/pandatool/src/pstatserver/pStatThreadData.cxx b/pandatool/src/pstatserver/pStatThreadData.cxx deleted file mode 100644 index f7bf9e2c..00000000 --- a/pandatool/src/pstatserver/pStatThreadData.cxx +++ /dev/null @@ -1,462 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatThreadData.cxx - * @author drose - * @date 2000-07-09 - */ - -#include "pStatThreadData.h" - -#include "pStatFrameData.h" -#include "pStatCollectorDef.h" -#include "config_pstatclient.h" - - -PStatFrameData PStatThreadData::_null_frame; - -/** - * - */ -PStatThreadData:: -PStatThreadData(const PStatClientData *client_data) : - _client_data(client_data) -{ - _first_frame_number = 0; - _history = pstats_history; - _computed_elapsed_frames = false; -} - -/** - * - */ -PStatThreadData:: -~PStatThreadData() { -} - -/** - * Returns the frame number of the most recent frame stored in the data. - */ -int PStatThreadData:: -get_latest_frame_number() const { - nassertr(!_frames.empty(), 0); - return _first_frame_number + _frames.size() - 1; -} - -/** - * Returns the frame number of the oldest frame still stored in the data. - */ -int PStatThreadData:: -get_oldest_frame_number() const { - nassertr(!_frames.empty(), 0); - return _first_frame_number; -} - -/** - * Returns true if we have received data for the indicated frame number from - * the client and we still have it stored, or false otherwise. - */ -bool PStatThreadData:: -has_frame(int frame_number) const { - int rel_frame = frame_number - _first_frame_number; - - return (rel_frame >= 0 && rel_frame < (int)_frames.size() && - _frames[rel_frame] != nullptr); -} - -/** - * Returns a FrameData structure associated with the indicated frame number. - * If the frame data has not yet been received from the client, returns the - * newest frame older than the requested frame. - */ -const PStatFrameData &PStatThreadData:: -get_frame(int frame_number) const { - int rel_frame = frame_number - _first_frame_number; - int num_frames = _frames.size(); - if (rel_frame >= num_frames) { - rel_frame = num_frames - 1; - } - - while (rel_frame >= 0 && _frames[rel_frame] == nullptr) { - rel_frame--; - } - if (rel_frame < 0) { - // No frame data that old. Return the oldest frame we've got. - rel_frame = 0; - while (rel_frame < num_frames && - _frames[rel_frame] == nullptr) { - rel_frame++; - } - } - - if (rel_frame >= 0 && rel_frame < num_frames) { - PStatFrameData *frame = _frames[rel_frame]; - nassertr(frame != nullptr, _null_frame); - nassertr(frame->get_start() >= 0.0, _null_frame); - return *frame; - } - - nassertr(_null_frame.get_start() >= 0.0, _null_frame); - return _null_frame; -} - -/** - * Returns the timestamp (in seconds elapsed since connection) of the latest - * available frame. - */ -double PStatThreadData:: -get_latest_time() const { - nassertr(!_frames.empty(), 0.0); - return _frames.back()->get_start(); -} - -/** - * Returns the timestamp (in seconds elapsed since connection) of the oldest - * available frame. - */ -double PStatThreadData:: -get_oldest_time() const { - nassertr(!_frames.empty(), 0.0); - return _frames.front()->get_start(); -} - -/** - * Returns the FrameData structure associated with the latest frame not later - * than the indicated time. - */ -const PStatFrameData &PStatThreadData:: -get_frame_at_time(double time) const { - return get_frame(get_frame_number_at_time(time)); -} - -/** - * Returns the frame number of the latest frame not later than the indicated - * time. If no frames were found, returns get_oldest_frame_number() - 1. - * - * If the hint is nonnegative, it represents a frame number (for which - * has_frame() must return true) we believe the correct answer to be after and - * close by, which may speed the search for the frame. - */ -int PStatThreadData:: -get_frame_number_at_time(double time, int hint) const { - hint -= _first_frame_number; - if (hint >= 0 && hint < (int)_frames.size()) { - if (_frames[hint] != nullptr && - _frames[hint]->get_start() <= time) { - // The hint might be right. Scan forward from there. - int i = hint + 1; - while (i < (int)_frames.size() && - (_frames[i] == nullptr || - _frames[i]->get_start() <= time)) { - if (_frames[i] != nullptr) { - hint = i; - } - ++i; - } - return _first_frame_number + hint; - } - } - - // The hint is wrong, we have to search the entire set. - int first_i = 0; - int last_i = _frames.size() - 1; - while (first_i < last_i && _frames[first_i] == nullptr) { - ++first_i; - } - while (first_i < last_i && _frames[last_i] == nullptr) { - --last_i; - } - - if (first_i >= last_i) { - // There are no frames. - return _first_frame_number - 1; - } - - // Take a guess by interpolating based on the first and last frame times. - double first = _frames[first_i]->get_start(); - if (time < first) { - return _first_frame_number - 1; - } - - double last = _frames[last_i]->get_start(); - double t = (time - first) / (last - first); - hint = std::max(0, (int)(t * (last_i - first_i))) + first_i; - - // Find a frame around the guess that has data. - if (_frames[hint] == nullptr) { - if (hint <= first_i) { - hint = first_i; - } - else do { - // Skip backward until we find a frame with data. - --hint; - } while (_frames[hint] == nullptr); - } - - if (_frames[hint]->get_start() <= time) { - // Search forward. - for (int i = hint + 1; i < (int)_frames.size(); ++i) { - const PStatFrameData *frame = _frames[i]; - if (frame != nullptr) { - if (frame->get_start() <= time) { - hint = i; - } else { - break; - } - } - } - return _first_frame_number + hint; - } - - // Search backward. - for (int i = hint - 1; i >= 0; --i) { - const PStatFrameData *frame = _frames[i]; - if (frame != nullptr && frame->get_start() <= time) { - return _first_frame_number + i; - } - } - - return _first_frame_number - 1; -} - -/** - * Returns the frame number of the first frame later than the indicated time - * and start frame number. - */ -int PStatThreadData:: -get_frame_number_after(double time, int start_at) const { - int i = std::max(0, start_at - _first_frame_number); - double end = get_frame(i).get_end(); - - while (end < time) { - ++i; - if ((size_t)i >= _frames.size()) { - break; - } - if (_frames[i] != nullptr) { - end = _frames[i]->get_end(); - } - } - - return _first_frame_number + i; -} - -/** - * Returns the FrameData associated with the most recent frame. - */ -const PStatFrameData &PStatThreadData:: -get_latest_frame() const { - nassertr(!_frames.empty(), _null_frame); - return *_frames.back(); -} - -/** - * Computes the oldest frame number not older than pstats_average_time - * seconds, and the newest frame number. Handy for computing average frame - * rate over a time. Returns true if there is any data in that range, false - * otherwise. - */ -bool PStatThreadData:: -get_elapsed_frames(int &then_i, int &now_i) const { - if (!_computed_elapsed_frames) { - compute_elapsed_frames(); - } - - now_i = _now_i; - then_i = _then_i; - return _got_elapsed_frames; -} - -/** - * Computes the average frame rate over the past pstats_average_time seconds, - * by counting up the number of frames elapsed in that time interval. - */ -double PStatThreadData:: -get_frame_rate() const { - int then_i, now_i; - if (!get_elapsed_frames(then_i, now_i)) { - return 0.0f; - } - - int num_frames = now_i - then_i + 1; - double now = _frames[now_i - _first_frame_number]->get_end(); - double elapsed_time = (now - _frames[then_i - _first_frame_number]->get_start()); - return (double)num_frames / elapsed_time; -} - - -/** - * Sets the number of seconds worth of frames that will be retained by the - * ThreadData structure as each new frame is added. This affects how old the - * oldest frame that may be queried is. - */ -void PStatThreadData:: -set_history(double time) { - _history = time; -} - -/** - * Returns the number of seconds worth of frames that will be retained by the - * ThreadData structure as each new frame is added. This affects how old the - * oldest frame that may be queried is. - */ -double PStatThreadData:: -get_history() const { - return _history; -} - -/** - * Given a timestamp representing the time of the latest known frame, removes - * any frames older than the configured history. Returns true if the data is - * now empty. - */ -bool PStatThreadData:: -prune_history(double time) { - double oldest_allowable_time = time - _history; - while (!_frames.empty() && - (_frames.front() == nullptr || - _frames.front()->is_time_empty() || - _frames.front()->get_start() < oldest_allowable_time)) { - delete _frames.front(); - _frames.pop_front(); - _first_frame_number++; - } - - return _frames.empty(); -} - -/** - * Makes room for and stores a new frame's worth of data. Calling this - * function may cause old frame data to be discarded to make room, according - * to the amount of time set up via set_history(). - * - * The pointer will become owned by the PStatThreadData object and will be - * freed on destruction. - */ -void PStatThreadData:: -record_new_frame(int frame_number, PStatFrameData *frame_data) { - nassertv(frame_data != nullptr); - nassertv(!frame_data->is_empty()); - - // First, remove all the old frames that fall outside of our history window. - // Then, add enough empty frame definitions to account for the latest frame - // number. This might involve some skips, since we don't guarantee that we - // get all the frames in order or even at all. - if (prune_history(frame_data->get_start())) { - _first_frame_number = frame_number; - _frames.push_back(nullptr); - } - else { - while (_first_frame_number + (int)_frames.size() <= frame_number) { - _frames.push_back(nullptr); - } - } - - int index = frame_number - _first_frame_number; - - // It's possible to receive frames out of order. - while (index < 0) { - _frames.push_front(nullptr); - ++index; - --_first_frame_number; - } - - nassertv(index >= 0 && index < (int)_frames.size()); - - if (_frames[index] != nullptr) { - nout << "Got repeated frame data for frame " << frame_number << "\n"; - delete _frames[index]; - } - - _frames[index] = frame_data; - _computed_elapsed_frames = false; -} - -/** - * Writes the thread data to a datagram. - */ -void PStatThreadData:: -write_datagram(Datagram &dg) const { - int frame_number = _first_frame_number; - - for (PStatFrameData *frame_data : _frames) { - if (frame_data != nullptr) { - dg.add_int32(frame_number); - frame_data->write_datagram(dg); - } - ++frame_number; - } - dg.add_int32(-1); -} - -/** - * Restores the thread data from a datagram. - */ -void PStatThreadData:: -read_datagram(DatagramIterator &scan, PStatClientVersion *version) { - int frame_number; - while ((frame_number = scan.get_int32()) != -1) { - PStatFrameData *frame_data = new PStatFrameData; - frame_data->read_datagram(scan, version); - - record_new_frame(frame_number, frame_data); - } - - compute_elapsed_frames(); -} - -/** - * Computes the frame numbers returned by get_elapsed_frames(). - */ -void PStatThreadData:: -compute_elapsed_frames() const { - if (_frames.empty()) { - // No frames in the data at all. - _got_elapsed_frames = false; - } - else { - _now_i = _frames.size() - 1; - while (_now_i > 0 && _frames[_now_i] == nullptr) { - _now_i--; - } - if (_now_i < 0) { - // No frames have any real data. - _got_elapsed_frames = false; - } - else { - nassertv(_frames[_now_i] != nullptr); - - double now = _frames[_now_i]->get_end(); - double then = now - pstats_average_time; - - int old_i = _now_i; - _then_i = _now_i; - - while (old_i >= 0) { - const PStatFrameData *frame = _frames[old_i]; - if (frame != nullptr) { - if (frame->get_start() > then) { - _then_i = old_i; - } else { - break; - } - } - old_i--; - } - - nassertv(_then_i >= 0); - nassertv(_frames[_then_i] != nullptr); - _got_elapsed_frames = true; - - _now_i += _first_frame_number; - _then_i += _first_frame_number; - } - } - - _computed_elapsed_frames = true; -} diff --git a/pandatool/src/pstatserver/pStatThreadData.h b/pandatool/src/pstatserver/pStatThreadData.h deleted file mode 100644 index 471312d2..00000000 --- a/pandatool/src/pstatserver/pStatThreadData.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatThreadData.h - * @author drose - * @date 2000-07-08 - */ - -#ifndef PSTATTHREADDATA_H -#define PSTATTHREADDATA_H - -#include "pandatoolbase.h" -#include "datagram.h" -#include "datagramIterator.h" -#include "referenceCount.h" - -#include "pdeque.h" - -class PStatCollectorDef; -class PStatFrameData; -class PStatClientData; -class PStatClientVersion; - -/** - * A collection of FrameData structures for recently-received frames within a - * particular thread. This holds the raw data as reported by the client, and - * it automatically handles frames received out-of-order or skipped. You can - * ask for a particular frame by frame number or time and receive the data for - * the nearest frame. - */ -class PStatThreadData : public ReferenceCount { -public: - PStatThreadData(const PStatClientData *client_data); - ~PStatThreadData(); - - INLINE const PStatClientData *get_client_data() const; - - INLINE bool is_empty() const; - - int get_latest_frame_number() const; - int get_oldest_frame_number() const; - bool has_frame(int frame_number) const; - const PStatFrameData &get_frame(int frame_number) const; - - double get_latest_time() const; - double get_oldest_time() const; - const PStatFrameData &get_frame_at_time(double time) const; - int get_frame_number_at_time(double time, int hint = -1) const; - int get_frame_number_after(double time, int start_at = 0) const; - - const PStatFrameData &get_latest_frame() const; - - bool get_elapsed_frames(int &then_i, int &now_i) const; - double get_frame_rate() const; - - - void set_history(double time); - double get_history() const; - bool prune_history(double time); - - void record_new_frame(int frame_number, PStatFrameData *frame_data); - - void write_datagram(Datagram &dg) const; - void read_datagram(DatagramIterator &scan, PStatClientVersion *version); - -private: - void compute_elapsed_frames() const; - - const PStatClientData *_client_data; - - typedef pdeque Frames; - Frames _frames; - int _first_frame_number; - double _history; - - // Cached values, updated by compute_elapsed_frames(). - mutable bool _computed_elapsed_frames; - mutable bool _got_elapsed_frames; - mutable int _then_i; - mutable int _now_i; - - static PStatFrameData _null_frame; -}; - -#include "pStatThreadData.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatTimeline.I b/pandatool/src/pstatserver/pStatTimeline.I deleted file mode 100644 index e3daa44a..00000000 --- a/pandatool/src/pstatserver/pStatTimeline.I +++ /dev/null @@ -1,151 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatTimeline.I - * @author rdb - * @date 2022-02-11 - */ - -/** - * Changes the amount of time the width of the horizontal axis represents. - * This may force a redraw. - */ -INLINE void PStatTimeline:: -set_horizontal_scale(double time_width) { - double max_time_width = (_highest_end_time - _lowest_start_time) * 2.0; - time_width = (std::min)(time_width, max_time_width); - - double scale = time_width / get_xsize(); - if (_time_scale != scale) { - _time_scale = scale; - _target_time_scale = scale; - _zoom_speed = 0.0; - normal_guide_bars(); - force_redraw(); - } -} - -/** - * Returns the amount of total time the width of the horizontal axis - * represents. - */ -INLINE double PStatTimeline:: -get_horizontal_scale() const { - return _time_scale * get_xsize(); -} - -/** - * This may force a redraw. - */ -INLINE void PStatTimeline:: -set_horizontal_scroll(double start_time) { - start_time = (std::max)((std::min)(start_time, _highest_end_time), _lowest_start_time); - if (_start_time != start_time) { - _start_time = start_time; - _target_start_time = start_time; - _scroll_speed = 0.0; - normal_guide_bars(); - force_redraw(); - } -} - -/** - * Returns the amount of total time the width of the horizontal axis - * represents. - */ -INLINE double PStatTimeline:: -get_horizontal_scroll() const { - return _start_time; -} - -/** - * Smoothly zooms to the given time width, around the given focal point. - */ -INLINE void PStatTimeline:: -zoom_to(double time_width, double center) { - // Don't allow zooming out to beyond 2x the size of the entire timeline. - // There's a limit of zooming beyond 1 ns per bar, there's just no point... - double max_time_width = (_highest_end_time - _lowest_start_time) * 2.0; - time_width = (std::min)((std::max)(1e-7, time_width), max_time_width); - _target_time_scale = time_width / get_xsize(); - _zoom_center = center; - - double pivot_x = (_zoom_center - _start_time) / _time_scale; - scroll_to(_zoom_center - pivot_x * _target_time_scale); -} - -/** - * Smoothly zooms by the given amount, where 1.0 is a single "tick" of zooming - * in and -1.0 is a single "tick" of zooming out. - */ -INLINE void PStatTimeline:: -zoom_by(double amount, double center) { - zoom_to(_target_time_scale * pow(0.8, amount) * get_xsize(), center); -} - -/** - * Smoothly scrolls to the given time point. - */ -INLINE void PStatTimeline:: -scroll_to(double start_time) { - _target_start_time = (std::max)((std::min)(start_time, _highest_end_time), _lowest_start_time); -} - -/** - * Smoothly scrolls by the given amount. - */ -INLINE void PStatTimeline:: -scroll_by(double delta) { - scroll_to(_target_start_time + delta); -} - -/** - * Converts a timestamp to a horizontal pixel offset. - */ -INLINE int PStatTimeline:: -timestamp_to_pixel(double time) const { - return (int)((double)_xsize * (time - _start_time) / get_horizontal_scale()); -} - -/** - * Converts a horizontal pixel offset to a timestamp. - */ -INLINE double PStatTimeline:: -pixel_to_timestamp(int x) const { - return _time_scale * (double)x + _start_time; -} - -/** - * Converts a value (i.e. a "height" in the strip chart) to a horizontal - * pixel offset. - */ -INLINE int PStatTimeline:: -height_to_pixel(double value) const { - return (int)((double)_xsize * value / get_horizontal_scale()); -} - -/** - * Converts a horizontal pixel offset to a value (a "height" in the strip - * chart). - */ -INLINE double PStatTimeline:: -pixel_to_height(int x) const { - return _time_scale * (double)x; -} - -/** - * Returns the total number of rows. - */ -INLINE int PStatTimeline:: -get_num_rows() const { - if (_threads.empty()) { - return 0; - } else { - return _threads.back()._row_offset + _threads.back()._rows.size(); - } -} diff --git a/pandatool/src/pstatserver/pStatTimeline.cxx b/pandatool/src/pstatserver/pStatTimeline.cxx deleted file mode 100644 index d8d0fdfb..00000000 --- a/pandatool/src/pstatserver/pStatTimeline.cxx +++ /dev/null @@ -1,915 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatTimeline.cxx - * @author rdb - * @date 2022-02-11 - */ - -#include "pStatTimeline.h" - -#include "pStatFrameData.h" -#include "pStatCollectorDef.h" -#include "string_utils.h" -#include "config_pstatclient.h" - -#include - -/** - * - */ -PStatTimeline:: -PStatTimeline(PStatMonitor *monitor, int xsize, int ysize) : - PStatGraph(monitor, xsize, ysize) -{ - // Default to 1 millisecond per 10 pixels. - _time_scale = 1 / 10000.0; - _target_time_scale = _time_scale; - - _guide_bar_units = GBU_ms | GBU_show_units; - - // Load in the initial data, so that the user can see everything back to the - // beginning (or as far as pstats-history goes back to). - const PStatClientData *client_data = monitor->get_client_data(); - if (client_data != nullptr) { - size_t row_offset = 0; - - // Ignore this nasty "inverted" collector, which messes up everything. - _app_collector_index = client_data->find_collector("App:Show code:General"); - - for (int thread_index = 0; thread_index < client_data->get_num_threads(); ++thread_index) { - _threads.emplace_back(); - ThreadRow &thread_row = _threads.back(); - thread_row._row_offset = row_offset; - - if (!client_data->has_thread(thread_index)) { - continue; - } - thread_row._visible = true; - - const PStatThreadData *thread_data = client_data->get_thread_data(thread_index); - if (thread_data != nullptr) { - _threads_changed = true; - - if (!thread_data->is_empty()) { - int oldest_frame = thread_data->get_oldest_frame_number(); - int latest_frame = thread_data->get_latest_frame_number(); - - double oldest_start_time = thread_data->get_frame(oldest_frame).get_start(); - double latest_end_time = thread_data->get_frame(latest_frame).get_end(); - - if (!_have_start_time) { - _have_start_time = true; - _lowest_start_time = oldest_start_time; - } - else { - _lowest_start_time = std::min(_lowest_start_time, oldest_start_time); - } - _highest_end_time = std::max(_highest_end_time, latest_end_time + _clock_skew); - - for (int frame = oldest_frame; frame <= latest_frame; ++frame) { - if (thread_data->has_frame(frame)) { - update_bars(thread_index, frame); - } - } - } - } - - row_offset += thread_row._rows.size() + 1; - } - } - - _start_time = _lowest_start_time; - _target_start_time = _start_time; - - monitor->_timelines.insert(this); -} - -/** - * - */ -PStatTimeline:: -~PStatTimeline() { - _monitor->_timelines.erase(this); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void PStatTimeline:: -new_data(int thread_index, int frame_number) { - const PStatClientData *client_data = _monitor->get_client_data(); - - if (client_data != nullptr) { - const PStatThreadData *thread_data = - client_data->get_thread_data(thread_index); - - if (thread_data != nullptr && thread_data->has_frame(frame_number)) { - const PStatFrameData &frame_data = thread_data->get_frame(frame_number); - double frame_start = frame_data.get_start() + _clock_skew; - double frame_end = frame_data.get_end() + _clock_skew; - - if (thread_index == 0 && _app_collector_index == -1) { - _app_collector_index = client_data->find_collector("App:Show code:General"); - } - - if (!_have_start_time) { - _start_time = frame_start; - _have_start_time = true; - _lowest_start_time = _start_time; - } - else if (_start_time < _lowest_start_time) { - _lowest_start_time = _start_time; - } - if (frame_end > _highest_end_time) { - _highest_end_time = frame_end; - } - - while (thread_index >= (int)_threads.size()) { - _threads_changed = true; - if (_threads.size() == 0) { - _threads.resize(1); - } else { - _threads.resize(_threads.size() + 1); - _threads[_threads.size() - 1]._row_offset = - _threads[_threads.size() - 2]._row_offset; - if (_threads[_threads.size() - 2]._visible) { - _threads[_threads.size() - 1]._row_offset += - _threads[_threads.size() - 2]._rows.size() + 1; - } - } - } - - if (update_bars(thread_index, frame_number)) { - // The number of rows was changed. - // Change the offset of all subsequent ThreadRows. - ThreadRow &thread_row = _threads[thread_index]; - size_t offset = thread_row._row_offset + thread_row._rows.size() + 1; - for (size_t ti = (size_t)(thread_index + 1); ti < _threads.size(); ++ti) { - _threads[ti]._row_offset = offset; - if (_threads[ti]._visible) { - offset += _threads[ti]._rows.size() + 1; - } - } - _threads_changed = true; - normal_guide_bars(); - force_redraw(); - } - else if (frame_end >= _start_time || frame_start <= _start_time + get_horizontal_scale()) { - normal_guide_bars(); - begin_draw(); - draw_thread(thread_index, frame_start, frame_end); - end_draw(); - } - } - } - - idle(); -} - -/** - * Called by new_data(). Updates the bars without doing any drawing. Returns - * true if the number of rows was changed (forcing a full redraw), false if - * only new bars were added on the right side. - */ -bool PStatTimeline:: -update_bars(int thread_index, int frame_number) { - const PStatClientData *client_data = _monitor->get_client_data(); - const PStatThreadData *thread_data = client_data->get_thread_data(thread_index); - const PStatFrameData &frame_data = thread_data->get_frame(frame_number); - ThreadRow &thread_row = _threads[thread_index]; - thread_row._label = client_data->get_thread_name(thread_index); - bool changed_num_rows = false; - - if (!thread_row._visible) { - thread_row._visible = true; - changed_num_rows = true; - } - - // pair - pvector > stack; - bool had_children = false; - - double frame_start = frame_data.get_start() + _clock_skew; - double prev = frame_start; - - // There may still be open collectors from the previous frame. Rebuild the - // stack based on that so we can close them properly. - for (size_t i = 0; i < thread_row._rows.size(); ++i) { - Row &row = thread_row._rows[i]; - - // Keep iterating from the back until we get to the previous frame. - for (size_t j = 0; j < row.size(); ++j) { - ColorBar &bar = row[row.size() - j - 1]; - if (bar._frame_number < frame_number) { - // Was this collector left unstopped at the end of the last frame? - if (bar._open_end && bar._frame_number == frame_number - 1) { - if (i >= stack.size()) { - stack.resize(i + 1, std::make_pair(-1, 0.0)); - } - stack[i] = std::make_pair(bar._collector_index, bar._start); - - // Remove this bar for now, we'll recreate it when we close it. - row.erase(row.begin() + (row.size() - j - 1)); - } - break; - } - } - } - - size_t num_events = frame_data.get_num_events(); - for (size_t i = 0; i < num_events; ++i) { - int collector_index = frame_data.get_time_collector(i); - double time = frame_data.get_time(i) + _clock_skew; - - if (time < prev) { - // Apparently, it is too hard to ask for monotonically increasing time - // values! Don't be tempted to sort the values, or think this is a bug, - // the client can arbitrarily move back the clock if it feels like it! - // I had some fancy mechanism that handled clock skew properly for - // multiple out-of-order frames, but I gave up when I realised it's not - // possible to solve this problem for multiple threads, so we just assume - // this is done just once at startup before the other threads exist. - double delta = prev - time; - _clock_skew += delta; - _highest_end_time += delta; - time = prev; - nout << "Correcting for clock skew of " - << format_number(delta, GBU_show_units | GBU_ms) - << " in frame " << frame_number << " of thread " - << thread_index << "\n"; - - // Move all bars after this frame to the right by this amount. - for (ThreadRow &thread_row : _threads) { - for (Row &row : thread_row._rows) { - for (ColorBar &bar : row) { - if (bar._frame_number > frame_number) { - bar._start += delta; - bar._end += delta; - } - } - } - } - } - prev = time; - - if (collector_index == _app_collector_index) { - continue; - } - - if (frame_data.is_start(i)) { - if (collector_index == 0 && !stack.empty()) { - // Collector 0 always goes at the top, no matter what. - stack[0].first = 0; - stack[0].second = std::max(time, _start_time); - } else { - stack.push_back(std::make_pair(collector_index, std::max(time, _start_time))); - if (stack.size() > thread_row._rows.size()) { - thread_row._rows.resize(stack.size()); - changed_num_rows = true; - } - had_children = false; - } - } - else if (!stack.empty() && stack.back().first == collector_index) { - // Most likely case, ending the most recent collector that is still open. - double start_time = stack.back().second; - stack.pop_back(); - thread_row._rows[stack.size()].push_back({ - start_time, time, collector_index, thread_index, frame_number, false, false}); - - // Pop off stack levels for prematurely ended collectors (see below). - while (!stack.empty() && stack.back().first < 0) { - stack.pop_back(); - } - had_children = true; - } - else { - // Unlikely case: ending a collector before a "child" has ended. - // Go back and clear the row where this collector started. - // Don't decrement the row index. - size_t i; - for (i = 0; i < stack.size(); ++i) { - auto &item = stack[stack.size() - 1 - i]; - - if (item.first == collector_index) { - thread_row._rows[stack.size() - 1 - i].push_back({ - item.second, time, collector_index, thread_index, frame_number, false, false}); - item.first = -1; - break; - } - } - if (i == stack.size()) { - // We stopped a collector that wasn't started at all. That means it - // must have already been running when this frame started, which we - // normally handle by pre-populating the stack with the open collectors - // from last frame, but maybe we didn't get the last frame (yet). - // Unfortunately we need to add it above any bars we've already started - // and stopped, which means we need to shift everything down belonging - // to this frame, except for the top-level Frame collector. This is - // probably pretty inefficient, but it should be pretty rare for frames - // to arrive out-of-order in this manner. - nassertd(!stack.empty()) continue; - stack.insert(stack.begin() + 1, std::make_pair(-1, 0.0)); - - const size_t num_rows = thread_row._rows.size(); - for (size_t j = num_rows - 1; j >= 1; --j) { - size_t row_size = thread_row._rows[j].size(); - for (size_t k = row_size; k > 0; --k) { - Row &row = thread_row._rows[j]; - ColorBar bar = row[k - 1]; - if (bar._frame_number == frame_number) { - row.erase(row.begin() + (k - 1)); - if (j + 1 >= thread_row._rows.size()) { - thread_row._rows.resize(j + 2); - changed_num_rows = true; - } - - // Insert it into the row below while retaining sorting. - Row &row2 = thread_row._rows[j + 1]; - row2.insert(std::upper_bound(row2.begin(), row2.end(), bar), bar); - } - else if (bar._frame_number < frame_number) { - break; - } - } - } - - // Now insert the bar, just below Frame level. - if (thread_row._rows.size() < 2) { - thread_row._rows.resize(2); - changed_num_rows = true; - } - thread_row._rows[1].push_back({ - frame_start, time, collector_index, thread_index, - frame_number, true, false}); - } - else if (i > 0 && !had_children) { - // Figure out if the currently active collector could actually be - // slotted higher. This prevents the staircase effect where - // overlapping collectors will cause the number of rows to continue - // to grow at every overlap. We only do this if the current - // collector has not had children yet, that'd be too confusing. - int j = stack.size() - 3; - while (j > 0) { - auto &item = stack[j]; - if (item.first >= 0) { - // Nope, can't do. - break; - } - // Yes, does this row have enough space? - Row &row = thread_row._rows[j]; - if (row.empty() || row.back()._end < stack.back().second) { - // It does. - item = std::move(stack.back()); - stack.pop_back(); - while (!stack.empty() && stack.back().first < 0) { - stack.pop_back(); - } - break; - } - --j; - } - } - } - } - - // Add all unclosed bars, marking them as open-ended, for later gluing. - while (!stack.empty()) { - int collector_index = stack.back().first; - if (collector_index >= 0) { - double start_time = stack.back().second; - thread_row._rows[stack.size() - 1].push_back({ - start_time, frame_data.get_end() + _clock_skew, - collector_index, thread_index, frame_number, false, true, - }); - } - stack.pop_back(); - } - - if (thread_row._last_frame >= 0 && frame_number < thread_row._last_frame) { - // Added a frame out of order. - for (Row &row : thread_row._rows) { - // Sort by end time. - std::sort(row.begin(), row.end()); - - // Glue together open ends and beginnings that match up. - size_t end = row.size() - 1; - for (size_t i = 0; i < end;) { - ColorBar &left = row[i]; - ColorBar &right = row[i + 1]; - if (left._collector_index == right._collector_index && - left._frame_number + 1 == right._frame_number && - left._open_end && right._open_begin) { - // Erase the left one, to maintain the sorting by end time. - right._open_begin = false; - right._start = left._start; - row.erase(row.begin() + i); - --end; - } else { - ++i; - } - } - } - } else { - thread_row._last_frame = frame_number; - } - - return changed_num_rows; -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string PStatTimeline:: -get_bar_tooltip(int row, int x) const { - ColorBar bar; - if (find_bar(row, x, bar)) { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data != nullptr && client_data->has_collector(bar._collector_index)) { - std::ostringstream text; - text << client_data->get_collector_fullname(bar._collector_index); - text << " ("; - if (bar._open_begin || bar._open_end) { - text << "at least "; - } - text << format_number(bar._end - bar._start, GBU_show_units | GBU_ms) << ")"; - return text.str(); - } - } - return std::string(); -} - -/** - * Writes the graph state to a datagram. - */ -void PStatTimeline:: -write_datagram(Datagram &dg) const { - dg.add_float64(_time_scale); - dg.add_float64(_start_time); - dg.add_float64(_lowest_start_time); - dg.add_float64(_highest_end_time); - - PStatGraph::write_datagram(dg); -} - -/** - * Restores the graph state from a datagram. - */ -void PStatTimeline:: -read_datagram(DatagramIterator &scan) { - _time_scale = scan.get_float64(); - _start_time = scan.get_float64(); - _lowest_start_time = scan.get_float64(); - _highest_end_time = scan.get_float64(); - - _scroll_speed = 0.0; - _zoom_speed = 0.0; - - _have_start_time = true; - _target_start_time = _start_time; - _target_time_scale = _time_scale; - - PStatGraph::read_datagram(scan); - - normal_guide_bars(); - force_redraw(); -} - -/** - * To be called by the user class when the widget size has changed. This - * updates the chart's internal data and causes it to issue redraw commands to - * reflect the new size. - */ -void PStatTimeline:: -changed_size(int xsize, int ysize) { - if (xsize != _xsize || ysize != _ysize) { - _xsize = xsize; - _ysize = ysize; - - normal_guide_bars(); - force_redraw(); - } -} - -/** - * To be called by the user class when the whole thing needs to be redrawn for - * some reason. - */ -void PStatTimeline:: -force_redraw() { - clear_region(); - - begin_draw(); - - for (const GuideBar &bar : _guide_bars) { - int x = timestamp_to_pixel(bar._height); - if (x > 0 && x < get_xsize() - 1) { - draw_guide_bar(x, bar._style); - } - } - - double start_time = _start_time; - double end_time = start_time + get_horizontal_scale(); - - int num_rows = 0; - - for (size_t ti = 0; ti < _threads.size(); ++ti) { - ThreadRow &thread_row = _threads[ti]; - if (thread_row._visible) { - for (size_t ri = 0; ri < thread_row._rows.size(); ++ri) { - draw_row((int)ti, (int)ri, start_time, end_time); - ++num_rows; - } - draw_separator(num_rows++); - } - } - - end_draw(); -} - -/** - * To be called by the user class when the whole thing needs to be redrawn for - * some reason. - */ -void PStatTimeline:: -force_redraw(int row, int from_x, int to_x) { - double start_time = std::max(_start_time, pixel_to_timestamp(from_x)); - double end_time = std::min(_start_time + get_horizontal_scale(), pixel_to_timestamp(to_x)); - - begin_draw(); - - for (size_t ti = 0; ti < _threads.size(); ++ti) { - ThreadRow &thread_row = _threads[ti]; - if (!thread_row._visible || (int)thread_row._row_offset > row) { - break; - } - - int row_index = row - (int)thread_row._row_offset; - if (row_index < (int)thread_row._rows.size()) { - draw_row((int)ti, row_index, start_time, end_time); - } - } - - end_draw(); -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void PStatTimeline:: -normal_guide_bars() { - double start_time = get_horizontal_scroll(); - double time_width = get_horizontal_scale(); - double end_time = start_time + time_width; - - // We want vaguely 150 pixels between guide bars. - int max_frames = get_xsize() / 100; - int l = (int)std::floor(3.0 * log10(pixel_to_height(150)) + 0.5); - double interval = pow(10.0, std::ceil(l / 3.0)); - if ((l + 3000) % 3 == 1) { - interval /= 5; - } - else if ((l + 3000) % 3 == 2) { - interval /= 2; - } - - _guide_bars.clear(); - - // Rather than getting the client data, we look in the color bar data for - // the first row, because the client data gets wiped after a while. - if (!_threads.empty() && !_threads[0]._rows.empty()) { - const Row &row = _threads[0]._rows[0]; - - // Look for the last Frame bar with end time lower than our start time. - Row::const_iterator it = std::lower_bound(row.begin(), row.end(), ColorBar {0.0, start_time}); - while (it != row.end() && it->_collector_index != 0) { - ++it; - } - - int num_frames = 0; - - while (it != row.end() && it->_start <= end_time) { - double frame_start = it->_start; - double frame_end = it->_end; - int frame_number = it->_frame_number; - - if (frame_start > start_time) { - if (!_guide_bars.empty() && height_to_pixel(frame_start - _guide_bars.back()._height) < 30) { - // Get rid of last label, it is in the way. - _guide_bars.back()._label.clear(); - } - std::string label = "#"; - label += format_string(frame_number); - _guide_bars.push_back(GuideBar(frame_start, label, GBS_frame)); - - if (++num_frames > max_frames) { - // Forget it, this is becoming too many lines. - _guide_bars.clear(); - break; - } - } - - do { - ++it; - } - while (it != row.end() && it->_collector_index != 0); - - double frame_width; - if (it != row.end()) { - // Only go up to the start of the next frame, limiting to however much - // fits in the graph. - frame_width = std::min(frame_end - frame_start, end_time - frame_start); - } else { - // Reached the end; just continue to the end of the graph. - frame_width = end_time - frame_start; - } - - if (interval > 0.0) { - int first_bar = std::max((int)((start_time - frame_start) / interval), 1); - int num_bars = (int)std::round(frame_width / interval); - - for (int i = first_bar; i < num_bars; ++i) { - double offset = i * interval; - std::string label = "+"; - label += format_number(offset, GBU_show_units | GBU_ms); - _guide_bars.push_back(GuideBar(frame_start + offset, label, GBS_normal)); - } - } - - // If there's a gap between frames, add another line. - if (it->_start > frame_end && it->_frame_number > frame_number + 1) { - std::string label; - if (it->_start - frame_end >= interval) { - label = "#" + format_string(frame_number + 1); - if (it->_frame_number > frame_number + 2) { - label += "-" + format_string(it->_frame_number - 1); - } - label += " (dropped)"; - } - _guide_bars.push_back(GuideBar(frame_end, label, GBS_frame)); - } - } - } - - if (_guide_bars.empty() && interval > 0.0) { - int first_bar = std::max((int)(start_time / interval), 1); - int num_bars = (int)std::round(end_time / interval); - - for (int i = first_bar; i < num_bars; ++i) { - double time = i * interval; - std::string label = format_number(time, GBU_show_units | GBU_ms); - _guide_bars.push_back(GuideBar(time, label, GBS_frame)); - } - } - - _guide_bars_changed = true; -} - -/** - * Should be overridden by the user class to wipe out the entire strip chart - * region. - */ -void PStatTimeline:: -clear_region() { -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any bars in the chart. - */ -void PStatTimeline:: -begin_draw() { -} - -/** - * - */ -void PStatTimeline:: -draw_thread(int thread_index, double start_time, double end_time) { - if (thread_index < 0 || (size_t)thread_index > _threads.size()) { - return; - } - - ThreadRow &thread_row = _threads[(size_t)thread_index]; - if (thread_row._visible) { - for (size_t ri = 0; ri < thread_row._rows.size(); ++ri) { - draw_row(thread_index, (int)ri, start_time, end_time); - } - } -} - -/** - * - */ -void PStatTimeline:: -draw_row(int thread_index, int row_index, double start_time, double end_time) { - ThreadRow &thread_row = _threads[thread_index]; - Row &row = thread_row._rows[row_index]; - - const PStatClientData *client_data = _monitor->get_client_data(); - - // Find the first element whose end time is larger than our start time. - // Then iterate until at least the end of the frame. - Row::iterator it = std::lower_bound(row.begin(), row.end(), ColorBar {0.0, start_time}); - if (it == row.end()) { - return; - } - - int frame_number = it->_frame_number; - do { - ColorBar &bar = *it; - - int from_x = timestamp_to_pixel(bar._start); - int to_x = timestamp_to_pixel(bar._end); - - if (to_x >= 0 && to_x > from_x && from_x < get_xsize()) { - if (bar._collector_index != 0) { - const PStatCollectorDef &def = client_data->get_collector_def(bar._collector_index); - if (to_x - from_x >= 32 && def._parent_index > 0) { - // Try including the parent name. - const PStatCollectorDef &parent_def = client_data->get_collector_def(def._parent_index); - std::string long_name = parent_def._name + ":" + def._name; - draw_bar(thread_row._row_offset + row_index, from_x, to_x, - bar._collector_index, long_name); - } else { - draw_bar(thread_row._row_offset + row_index, from_x, to_x, - bar._collector_index, def._name); - } - } else { - draw_bar(thread_row._row_offset + row_index, from_x, to_x, - bar._collector_index, - std::string("Frame ") + format_string(bar._frame_number)); - } - } - - ++it; - } - while (it != row.end() && (it->_start <= end_time || it->_frame_number == frame_number)); -} - -/** - * Draws a horizontal separator. - */ -void PStatTimeline:: -draw_separator(int) { -} - -/** - * Draws a vertical guide bar. If the row is -1, draws it in all rows. - */ -void PStatTimeline:: -draw_guide_bar(int x, GuideBarStyle style) { -} - -/** - * Draws a single bar in the chart for the indicated row, in the color for the - * given collector, for the indicated horizontal pixel range. - */ -void PStatTimeline:: -draw_bar(int, int, int, int, const std::string &) { -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars in the chart. - */ -void PStatTimeline:: -end_draw() { -} - -/** - * Should be overridden by the user class to perform any other updates might - * be necessary after the bars have been redrawn. - */ -void PStatTimeline:: -idle() { -} - -/** - * Should be called periodically to update any animated values. Returns false - * to indicate that the animation is done and no longer needs to be called. - */ -bool PStatTimeline:: -animate(double time, double dt) { - int hmove = ((_keys_held & (F_right | F_d)) != 0) - - ((_keys_held & (F_left | F_a)) != 0); - int vmove = ((_keys_held & F_w) != 0) - - ((_keys_held & F_s) != 0); - - if (hmove > 0) { - if (_scroll_speed < 0) { - _scroll_speed = 1.0; - } - _scroll_speed += 1.0; - } - else if (hmove < 0) { - if (_scroll_speed > 0) { - _scroll_speed = -1.0; - } - _scroll_speed -= 1.0; - } - else if (_scroll_speed != 0.0) { - _scroll_speed *= std::exp(-12.0 * dt); - if (std::abs(_scroll_speed) < 0.2) { - _scroll_speed = 0.0; - } - } - - if (vmove > 0) { - if (_zoom_speed < 0) { - _zoom_speed = 1.0; - } - _zoom_speed += 1.0; - } - else if (vmove < 0) { - if (_zoom_speed > 0) { - _zoom_speed = -1.0; - } - _zoom_speed -= 1.0; - } - else if (_zoom_speed != 0.0) { - _zoom_speed *= std::exp(-12.0 * dt); - if (std::abs(_zoom_speed) < 0.2) { - _zoom_speed = 0.0; - } - } - - if (_zoom_speed != 0.0) { - zoom_to(get_horizontal_scale() * pow(0.5, _zoom_speed * dt), _zoom_center); - } - - if (_scroll_speed != 0.0) { - scroll_by(_scroll_speed * 300 * _time_scale * dt); - } - - if (_target_start_time != _start_time) { - double dist = _target_start_time - _start_time; - // When the difference is less than 2 pixels, snap to target position. - if (std::abs(dist) < _time_scale * 2) { - _start_time = _target_start_time; - } else { - dist *= 1.0 - std::exp(-12.0 * dt); - _start_time += dist; - } - } - - if (_target_time_scale != _time_scale) { - //double dist = std::log(_target_time_scale) - std::log(_time_scale); - double dist = _target_time_scale - _time_scale; - if (_target_start_time == _start_time && std::abs(dist) < 0.01) { - _time_scale = _target_time_scale; - } else { - dist *= 1.0 - std::exp(-12.0 * dt); - //_time_scale *= std::exp(dist); - _time_scale += dist; - } - } - - normal_guide_bars(); - force_redraw(); - - // Stop the animation when the speed is 0 and no key is still held. - return _keys_held != 0 - || _scroll_speed != 0 - || _zoom_speed != 0 - || _target_start_time != _start_time - || _target_time_scale != _time_scale; -} - -/** - * Return the ColorBar at the indicated position. - */ -bool PStatTimeline:: -find_bar(int row, int x, ColorBar &bar) const { - double time = pixel_to_timestamp(x); - - for (size_t ti = 0; ti < _threads.size(); ++ti) { - const ThreadRow &thread_row = _threads[ti]; - if ((int)thread_row._row_offset > row) { - break; - } - - int row_index = row - (int)thread_row._row_offset; - if (row_index < (int)thread_row._rows.size()) { - // Find the first element whose end time is larger than the given time. - const Row &bars = thread_row._rows[row_index]; - Row::const_iterator it = std::lower_bound(bars.begin(), bars.end(), ColorBar {time, time}); - if (it != bars.end() && it->_start <= time) { - bar = *it; - return true; - } - } - } - - return false; -} diff --git a/pandatool/src/pstatserver/pStatTimeline.h b/pandatool/src/pstatserver/pStatTimeline.h deleted file mode 100644 index ebf5a30d..00000000 --- a/pandatool/src/pstatserver/pStatTimeline.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatTimeline.h - * @author rdb - * @date 2022-02-11 - */ - -#ifndef PSTATTIMELINE_H -#define PSTATTIMELINE_H - -#include "pandatoolbase.h" - -#include "pStatGraph.h" -#include "pStatMonitor.h" -#include "pStatClientData.h" -#include "pdeque.h" - -class PStatFrameData; - -/** - * This is an abstract class that presents the interface for drawing a piano- - * roll type chart: it shows the time spent in each of a number of collectors - * as a horizontal bar of color, with time as the horizontal axis. - * - * This class just pnages all the piano-roll logic; the actual nuts and bolts - * of drawing pixels is left to a user-derived class. - */ -class PStatTimeline : public PStatGraph { -public: - PStatTimeline(PStatMonitor *monitor, int xsize, int ysize); - virtual ~PStatTimeline(); - - void new_data(int thread_index, int frame_number); - bool update_bars(int thread_index, int frame_number); - - INLINE void set_horizontal_scale(double time_width); - INLINE double get_horizontal_scale() const; - INLINE void set_horizontal_scroll(double time_start); - INLINE double get_horizontal_scroll() const; - - INLINE void zoom_to(double time_width, double pivot); - INLINE void zoom_by(double amount, double center); - INLINE void scroll_to(double time_start); - INLINE void scroll_by(double time_start); - - INLINE int timestamp_to_pixel(double time) const; - INLINE double pixel_to_timestamp(int x) const; - INLINE int height_to_pixel(double value) const; - INLINE double pixel_to_height(int y) const; - INLINE int get_num_rows() const; - - std::string get_bar_tooltip(int row, int x) const; - - virtual void write_datagram(Datagram &dg) const final; - virtual void read_datagram(DatagramIterator &scan) final; - -protected: - void changed_size(int xsize, int ysize); - void force_redraw(); - void force_redraw(int row, int from_x, int to_x); - void normal_guide_bars(); - - virtual void clear_region(); - virtual void begin_draw(); - void draw_thread(int thread_index, double start_time, double end_time); - void draw_row(int thread_index, int row_index, double start_time, double end_time); - virtual void draw_separator(int row); - virtual void draw_guide_bar(int x, GuideBarStyle style); - virtual void draw_bar(int row, int from_x, int to_x, int collector_index, - const std::string &collector_name); - virtual void end_draw(); - virtual void idle(); - - bool animate(double time, double dt); - - class ColorBar { - public: - double _start, _end; - int _collector_index; - int _thread_index; - int _frame_number; - bool _open_begin : 8, _open_end : 8; - - bool operator < (const ColorBar &other) const { - return _end < other._end; - } - }; - typedef pvector Row; - typedef pvector Rows; - - bool find_bar(int row, int x, ColorBar &bar) const; - - class ThreadRow { - public: - std::string _label; - Rows _rows; - size_t _row_offset = 0; - int _last_frame = -1; - bool _visible = false; - }; - typedef pvector ThreadRows; - ThreadRows _threads; - bool _threads_changed = true; - double _clock_skew = 0.0; - int _app_collector_index = -1; - - enum KeyFlag { - F_left = 1, - F_right = 2, - F_w = 4, - F_a = 8, - F_s = 16, - F_d = 32, - }; - int _keys_held = 0; - double _scroll_speed = 0.0; - double _zoom_speed = 0.0; - double _zoom_center = 0.0; - -private: - double _time_scale; - double _start_time = 0.0; - double _lowest_start_time = 0.0; - double _highest_end_time = 0.0; - bool _have_start_time = false; - double _target_start_time = 0.0; - double _target_time_scale; -}; - -#include "pStatTimeline.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatView.I b/pandatool/src/pstatserver/pStatView.I deleted file mode 100644 index 3066ba0f..00000000 --- a/pandatool/src/pstatserver/pStatView.I +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatView.I - * @author drose - * @date 2000-07-12 - */ - -/** - * Returns the current PStatThreadData associated with the view. This was set - * by a previous call to set_thread_data(). - */ -INLINE const PStatThreadData *PStatView:: -get_thread_data() { - return _thread_data; -} - -/** - * Returns the current PStatClientData associated with the view. This was - * also set by a previous call to set_thread_data(). - */ -INLINE const PStatClientData *PStatView:: -get_client_data() { - return _client_data; -} - - -/** - * Sets to a particular frame number (or the nearest available), extracted - * from the View's PStatThreadData pointer. See the comments in the other - * flavor of set_to_frame(). - */ -INLINE void PStatView:: -set_to_frame(int frame_number) { - set_to_frame(_thread_data->get_frame(frame_number)); -} - -/** - * Sets to the frame that occurred at the indicated time (or the nearest - * available frame), extracted from the View's PStatThreadData pointer. See - * the comments in set_to_frame. - */ -INLINE void PStatView:: -set_to_time(double time) { - set_to_frame(_thread_data->get_frame_at_time(time)); -} - -/** - * Returns true if we are showing level data, false if time data. - */ -INLINE bool PStatView:: -get_show_level() const { - return _show_level; -} - -/** - * Returns an index number that can be used to determine when the set of known - * levels has changed. Each time the set of levels in the view changes - * (because of new data arriving from the client, for instance), this number - * is incremented. - */ -INLINE int PStatView:: -get_level_index() const { - return _level_index; -} diff --git a/pandatool/src/pstatserver/pStatView.cxx b/pandatool/src/pstatserver/pStatView.cxx deleted file mode 100644 index c72213bf..00000000 --- a/pandatool/src/pstatserver/pStatView.cxx +++ /dev/null @@ -1,550 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatView.cxx - * @author drose - * @date 2000-07-10 - */ - -#include "pStatView.h" - -#include "pStatFrameData.h" -#include "pStatCollectorDef.h" - -#include -#include - -/** - * This class is used within this module only--in fact, within - * PStatView::set_to_frame() only--to help collect event data out of the - * PStatFrameData object and boil it down to a list of elapsed times. - */ -class FrameSample { -public: - void start(double time, FrameSample *started) { - // Keep track of nested start/stop pairs. We only consider the outer one. - if (_started++ > 0) { - return; - } - - nassertv(!_pushed); - _net_time -= time; - push_all(time, started); - nassertv(_next == nullptr && _prev == nullptr); - _prev = started->_prev; - _next = started; - _prev->_next = this; - started->_prev = this; - } - - void stop(double time, FrameSample *started) { - nassertv(_started > 0); - if (--_started > 0) { - return; - } - - nassertv(_next != nullptr && _prev != nullptr); - - if (_pushed) { - _prev->_next = _next; - _next->_prev = _prev; - _next = _prev = nullptr; - } else { - _net_time += time; - _prev->_next = _next; - _next->_prev = _prev; - _next = _prev = nullptr; - pop_one(time, started); - } - } - -private: - void push(double time) { - if (!_pushed) { - _pushed = true; - if (_started > 0) { - _net_time += time; - } - } - } - - void pop(double time) { - if (_pushed) { - _pushed = false; - if (_started > 0) { - _net_time -= time; - } - } - } - - void push_all(double time, FrameSample *started) { - for (FrameSample *sample = started->_next; - sample != started; sample = sample->_next) { - sample->push(time); - } - } - - void pop_one(double time, FrameSample *started) { - for (FrameSample *sample = started->_prev; - sample != started; sample = sample->_prev) { - if (sample->_pushed) { - sample->pop(time); - return; - } - } - } - -public: - FrameSample *_next = nullptr; - FrameSample *_prev = nullptr; - double _net_time = 0.0; - int _started = 0; - int _count = 0; - bool _pushed = false; - bool _is_new = false; -}; - -/** - * - */ -PStatView:: -PStatView() { - _constraint = 0; - _show_level = false; - _all_collectors_known = false; - _level_index = 0; -} - -/** - * - */ -PStatView:: -~PStatView() { - clear_levels(); -} - -/** - * Changes the focus of the View. By default, the View reports the entire - * time for the frame, and all of the Collectors that are directly parented to - * "Frame". By constraining the view to a particular collector, you cause the - * View to zoom in on that collector's data, reporting only the collector and - * its immediate parents. - * - * When you constrain the view, you may also specify whether the view should - * show time data or level data for the indicated collector. If level data, - * it reports the levels for the collector, and all of its children; - * otherwise, it collects the elapsed time. - * - * Changing the constraint causes the current frame's data to become - * invalidated; you must then call set_to_frame() again to get any useful data - * out. - */ -void PStatView:: -constrain(int collector, bool show_level) { - _constraint = collector; - _show_level = show_level; - clear_levels(); -} - -/** - * Restores the view to the full frame. This is equivalent to calling - * constrain(0). - */ -void PStatView:: -unconstrain() { - constrain(0, false); -} - -/** - * - */ -void PStatView:: -set_thread_data(const PStatThreadData *thread_data) { - _thread_data = thread_data; - _client_data = thread_data->get_client_data(); - clear_levels(); - _all_collectors_known = false; -} - -/** - * Supplies the View with the data for the current frame. This causes the - * View to update all of its internal data to reflect the frame's data, - * subject to the current constraint. - * - * It is possible that calling this will increase the total number of reported - * levels (for instance, if this frame introduced a new collector that hadn't - * been active previously). In this case, the caller must update its display - * or whatever to account for the new level. - */ -void PStatView:: -set_to_frame(const PStatFrameData &frame_data) { - nassertv(!_thread_data.is_null()); - nassertv(!_client_data.is_null()); - - if (_show_level) { - update_level_data(frame_data); - } else { - update_time_data(frame_data); - } -} - - -/** - * After a call to set_to_frame(), this returns true if all collectors in the - * FrameData are known by the PStatsData object, or false if some are still - * unknown (even those that do not appear in the view). - */ -bool PStatView:: -all_collectors_known() const { - return _all_collectors_known; -} - -/** - * Returns the total value accounted for by the frame (or by whatever - * Collector we are constrained to). This is the sum of all of the individual - * levels' get_net_value() value. - */ -double PStatView:: -get_net_value() const { - double net = 0.0; - Levels::const_iterator li; - for (li = _levels.begin(); li != _levels.end(); ++li) { - net += (*li).second->_value_alone; - } - - return net; -} - -/** - * Returns a pointer to the level that corresponds to the Collector we've - * constrained to. This is the top of a graph of levels; typically the next - * level down--the children of this level--will be the levels you want to - * display to the user. - */ -const PStatViewLevel *PStatView:: -get_top_level() { - return get_level(_constraint); -} - -/** - * Returns true if there is a level defined for the particular collector, - * false otherwise. - */ -bool PStatView:: -has_level(int collector) const { - Levels::const_iterator li; - li = _levels.find(collector); - return (li != _levels.end()); -} - -/** - * Returns a pointer to the level that corresponds to the indicated Collector. - * If there is no such level in the view, one will be created--use with - * caution. Check has_level() first if you don't want this behavior. - */ -PStatViewLevel *PStatView:: -get_level(int collector) { - Levels::const_iterator li; - li = _levels.find(collector); - if (li != _levels.end()) { - return (*li).second; - } - - PStatViewLevel *level = new PStatViewLevel; - level->_collector = collector; - level->_parent = nullptr; - _levels[collector] = level; - - reset_level(level); - return level; -} - -/** - * The implementation of set_to_frame() for views that show elapsed time. - */ -void PStatView:: -update_time_data(const PStatFrameData &frame_data) { - int num_events = frame_data.get_num_events(); - int num_collectors = _client_data->get_num_collectors(); - - typedef std::vector Samples; - Samples samples(num_collectors); - - // Keep a linked list of started samples. - FrameSample started; - started._next = &started; - started._prev = &started; - - _all_collectors_known = true; - - int new_collectors = 0; - int i; - for (i = 0; i < num_events; i++) { - int collector_index = frame_data.get_time_collector(i); - bool is_start = frame_data.is_start(i); - - if (!_client_data->has_collector(collector_index)) { - _all_collectors_known = false; - - } else { - nassertv(collector_index >= 0 && collector_index < num_collectors); - - if (_client_data->get_child_distance(_constraint, collector_index) >= 0) { - // Here's a data point we care about: anything at constraint level or - // below. - if (is_start) { - samples[collector_index].start(frame_data.get_time(i), &started); - samples[collector_index]._count++; - } else { - // A "stop" in the middle of a frame implies a "start" since time - // 0 (that is, since the first data point in the frame). - if (samples[collector_index]._started == 0) { - samples[collector_index].start(frame_data.get_time(0), &started); - } - samples[collector_index].stop(frame_data.get_time(i), &started); - } - - if (!samples[collector_index]._is_new) { - samples[collector_index]._is_new = true; - ++new_collectors; - } - } - } - } - - // Make sure everything is stopped. - Samples::iterator si; - for (i = 0, si = samples.begin(); si != samples.end(); ++i, ++si) { - if ((*si)._started > 0) { - (*si).stop(frame_data.get_end(), &started); - } - } - - nassertv(started._next == &started && started._prev == &started); - - bool any_new_levels = false; - - // Now match these samples we got up with those we already had in the - // levels. - Levels::iterator li, lnext; - li = _levels.begin(); - while (li != _levels.end()) { - // Be careful while traversing a container and calling functions that - // could modify that container. - lnext = li; - ++lnext; - - PStatViewLevel *level = (*li).second; - if (reset_level(level)) { - any_new_levels = true; - } - - int collector_index = level->_collector; - if (samples[collector_index]._is_new) { - level->_value_alone = samples[collector_index]._net_time; - level->_count = samples[collector_index]._count; - samples[collector_index]._is_new = false; - --new_collectors; - } - - li = lnext; - } - - // Finally, any samples left over in the got_samples set are new collectors - // that we need to add to the Levels list. - if (new_collectors > 0) { - any_new_levels = true; - - for (int collector_index = 0; collector_index < num_collectors; ++collector_index) { - if (samples[collector_index]._is_new) { - PStatViewLevel *level = get_level(collector_index); - level->_value_alone = samples[collector_index]._net_time; - level->_count = samples[collector_index]._count; - } - } - } - - if (any_new_levels) { - _level_index++; - } -} - -/** - * The implementation of set_to_frame() for views that show level values. - */ -void PStatView:: -update_level_data(const PStatFrameData &frame_data) { - _all_collectors_known = true; - - - // This tracks the set of level values we got. - typedef pmap GotValues; - GotValues net_values; - - int i; - int num_levels = frame_data.get_num_levels(); - for (i = 0; i < num_levels; i++) { - int collector_index = frame_data.get_level_collector(i); - double value = frame_data.get_level(i); - - if (!_client_data->has_collector(collector_index)) { - _all_collectors_known = false; - - } else { - if (_client_data->get_child_distance(_constraint, collector_index) >= 0) { - net_values[collector_index] = value; - } - } - } - - // Now that we've counted up the net level for each collector, compute the - // level for each collector alone by subtracting out each child from its - // parents. If a parent has no data, nothing is subtracted. - GotValues alone_values = net_values; - - GotValues::iterator gi; - for (gi = net_values.begin(); gi != net_values.end(); ++gi) { - int collector_index = (*gi).first; - double value = (*gi).second; - - // Walk up to the top, but stop when we find a parent with actual data. - while (collector_index != 0 && collector_index != _constraint) { - const PStatCollectorDef &def = - _client_data->get_collector_def(collector_index); - int parent_index = def._parent_index; - GotValues::iterator pi = alone_values.find(parent_index); - if (pi != alone_values.end()) { - // The parent has data; subtract it. - (*pi).second -= value; - break; - } - collector_index = parent_index; - } - } - - - bool any_new_levels = false; - - // Now match these samples we got up with those we already had in the - // levels. - Levels::iterator li, lnext; - li = _levels.begin(); - while (li != _levels.end()) { - // Be careful while traversing a container and calling functions that - // could modify that container. - lnext = li; - ++lnext; - - PStatViewLevel *level = (*li).second; - if (reset_level(level)) { - any_new_levels = true; - } - - int collector_index = level->_collector; - GotValues::iterator gi; - gi = alone_values.find(collector_index); - if (gi != alone_values.end()) { - level->_value_alone = (*gi).second; - alone_values.erase(gi); - } - - li = lnext; - } - - // Finally, any values left over in the alone_values set are new collectors - // that we need to add to the Levels list. - if (!alone_values.empty()) { - any_new_levels = true; - - GotValues::const_iterator gi; - for (gi = alone_values.begin(); gi != alone_values.end(); ++gi) { - int collector_index = (*gi).first; - PStatViewLevel *level = get_level(collector_index); - level->_value_alone = (*gi).second; - } - } - - if (any_new_levels) { - _level_index++; - } -} - -/** - * Resets all the levels that have been defined so far. - */ -void PStatView:: -clear_levels() { - Levels::iterator li; - for (li = _levels.begin(); li != _levels.end(); ++li) { - delete (*li).second; - } - _levels.clear(); -} - -/** - * Resets the total value of the Level to zero, and also makes sure it is - * parented to the right Level corresponding to its Collector's parent. Since - * the client might change its mind from time to time about who the Collector - * is parented to, we have to update this dynamically. - * - * Returns true if any change was made to the level's hierarchy, false - * otherwise. - */ -bool PStatView:: -reset_level(PStatViewLevel *level) { - bool any_changed = false; - level->_value_alone = 0.0; - level->_count = 0; - - if (level->_collector == _constraint) { - return false; - } - - if (_client_data->has_collector(level->_collector)) { - int parent_index = - _client_data->get_collector_def(level->_collector)._parent_index; - - if (level->_parent == nullptr) { - // This level didn't know its parent before, but now it does. - if (level->_collector != 0 || parent_index != 0) { - PStatViewLevel *parent_level = get_level(parent_index); - nassertr(parent_level != level, true); - level->_parent = parent_level; - parent_level->_children.push_back(level); - parent_level->sort_children(_client_data); - any_changed = true; - } - } - else if (level->_parent->_collector != parent_index) { - // This level knew about its parent, but now it's something different. - PStatViewLevel *old_parent_level = level->_parent; - nassertr(old_parent_level != level, true); - - if (parent_index != 0) { - PStatViewLevel *new_parent_level = get_level(parent_index); - nassertr(new_parent_level != level, true); - level->_parent = new_parent_level; - new_parent_level->_children.push_back(level); - new_parent_level->sort_children(_client_data); - } else { - level->_parent = nullptr; - } - - PStatViewLevel::Children::iterator ci = - find(old_parent_level->_children.begin(), - old_parent_level->_children.end(), - level); - - nassertr(ci != old_parent_level->_children.end(), true); - old_parent_level->_children.erase(ci); - any_changed = true; - } - } - - return any_changed; -} diff --git a/pandatool/src/pstatserver/pStatView.h b/pandatool/src/pstatserver/pStatView.h deleted file mode 100644 index 3bae72b1..00000000 --- a/pandatool/src/pstatserver/pStatView.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatView.h - * @author drose - * @date 2000-07-10 - */ - -#ifndef PSTATVIEW_H -#define PSTATVIEW_H - -#include "pandatoolbase.h" - -#include "pStatClientData.h" -#include "pStatThreadData.h" -#include "pStatViewLevel.h" -#include "pmap.h" -#include "pointerTo.h" - -/** - * A View boils down the frame data to a linear list of times spent in a - * number of different Collectors, within a particular thread. This - * automatically accounts for overlapping start/stop times and nested - * Collectors in a sensible way. - */ -class PStatView { -public: - PStatView(); - ~PStatView(); - - void constrain(int collector, bool show_level); - void unconstrain(); - - void set_thread_data(const PStatThreadData *thread_data); - INLINE const PStatThreadData *get_thread_data(); - INLINE const PStatClientData *get_client_data(); - - void set_to_frame(const PStatFrameData &frame_data); - INLINE void set_to_frame(int frame_number); - INLINE void set_to_time(double time); - - bool all_collectors_known() const; - double get_net_value() const; - - const PStatViewLevel *get_top_level(); - - bool has_level(int collector) const; - PStatViewLevel *get_level(int collector); - - INLINE bool get_show_level() const; - INLINE int get_level_index() const; - -private: - void update_time_data(const PStatFrameData &frame_data); - void update_level_data(const PStatFrameData &frame_data); - - void clear_levels(); - bool reset_level(PStatViewLevel *level); - - int _constraint; - bool _show_level; - bool _all_collectors_known; - - typedef pmap Levels; - Levels _levels; - - int _level_index; - - CPT(PStatClientData) _client_data; - CPT(PStatThreadData) _thread_data; -}; - -#include "pStatView.I" - -#endif diff --git a/pandatool/src/pstatserver/pStatViewLevel.I b/pandatool/src/pstatserver/pStatViewLevel.I deleted file mode 100644 index 38fdec95..00000000 --- a/pandatool/src/pstatserver/pStatViewLevel.I +++ /dev/null @@ -1,37 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatViewLevel.I - * @author drose - * @date 2000-07-19 - */ - -/** - * Returns the Collector index associated with this level. - */ -INLINE int PStatViewLevel:: -get_collector() const { - return _collector; -} - -/** - * Returns the total level value (or elapsed time value) for this Collector, - * not including any values accounted for by its child Collectors. - */ -INLINE double PStatViewLevel:: -get_value_alone() const { - return _value_alone; -} - -/** - * Returns the number of start/stop pairs for this collector. - */ -INLINE int PStatViewLevel:: -get_count() const { - return _count; -} diff --git a/pandatool/src/pstatserver/pStatViewLevel.cxx b/pandatool/src/pstatserver/pStatViewLevel.cxx deleted file mode 100644 index 47ed1fae..00000000 --- a/pandatool/src/pstatserver/pStatViewLevel.cxx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatViewLevel.cxx - * @author drose - * @date 2000-07-11 - */ - -#include "pStatViewLevel.h" -#include "pStatClientData.h" - -#include "pStatCollectorDef.h" -#include "pnotify.h" - -#include - -/** - * Returns the total level value (or elapsed time) represented by this - * Collector, including all values in its child Collectors. - */ -double PStatViewLevel:: -get_net_value() const { - double net = _value_alone; - - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - net += (*ci)->get_net_value(); - } - - return net; -} - - -// STL function object for sorting children in order by the collector's sort -// index, used in sort_children(), below. -class SortCollectorLevels { -public: - SortCollectorLevels(const PStatClientData *client_data) : - _client_data(client_data) { - } - bool operator () (const PStatViewLevel *a, const PStatViewLevel *b) const { - return - _client_data->get_collector_def(a->get_collector())._sort > - _client_data->get_collector_def(b->get_collector())._sort; - } - const PStatClientData *_client_data; -}; - -/** - * Sorts the children of this view level into order as specified by the - * client's sort index. - */ -void PStatViewLevel:: -sort_children(const PStatClientData *client_data) { - SortCollectorLevels sort_levels(client_data); - - sort(_children.begin(), _children.end(), sort_levels); -} - -/** - * Returns the number of children of this Level/Collector. These are the - * Collectors whose value is considered to be part of the total value of this - * level's Collector. - */ -int PStatViewLevel:: -get_num_children() const { - return _children.size(); -} - -/** - * Returns the nth child of this Level/Collector. - */ -const PStatViewLevel *PStatViewLevel:: -get_child(int n) const { - nassertr(n >= 0 && n < (int)_children.size(), nullptr); - return _children[n]; -} diff --git a/pandatool/src/pstatserver/pStatViewLevel.h b/pandatool/src/pstatserver/pStatViewLevel.h deleted file mode 100644 index 802850c0..00000000 --- a/pandatool/src/pstatserver/pStatViewLevel.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file pStatViewLevel.h - * @author drose - * @date 2000-07-11 - */ - -#ifndef PSTATVIEWLEVEL_H -#define PSTATVIEWLEVEL_H - -#include "pandatoolbase.h" - -#include "pvector.h" - -class PStatClientData; - -/** - * This is a single level value, or band of color, within a View. - * - * It generally indicates either the elapsed time, or the "level" value, for a - * particular Collector within a given frame for a particular thread. - */ -class PStatViewLevel { -public: - INLINE int get_collector() const; - INLINE double get_value_alone() const; - double get_net_value() const; - INLINE int get_count() const; - - void sort_children(const PStatClientData *client_data); - - int get_num_children() const; - const PStatViewLevel *get_child(int n) const; - -private: - int _collector; - int _count = 0; - double _value_alone; - PStatViewLevel *_parent; - - typedef pvector Children; - Children _children; - - friend class PStatView; -}; - -#include "pStatViewLevel.I" - -#endif diff --git a/pandatool/src/ptloader/CMakeLists.txt b/pandatool/src/ptloader/CMakeLists.txt deleted file mode 100644 index f4d4ab9f..00000000 --- a/pandatool/src/ptloader/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3PTLOADER_HEADERS - config_ptloader.h - loaderFileTypePandatool.h -) - -set(P3PTLOADER_SOURCES - config_ptloader.cxx - loaderFileTypePandatool.cxx -) - -composite_sources(p3ptloader P3PTLOADER_SOURCES) -add_library(p3ptloader ${MODULE_TYPE} ${P3PTLOADER_HEADERS} ${P3PTLOADER_SOURCES}) -set_target_properties(p3ptloader PROPERTIES DEFINE_SYMBOL BUILDING_PTLOADER) -target_link_libraries(p3ptloader PRIVATE - p3dxfegg p3fltegg p3lwoegg p3vrmlegg p3xfileegg - p3converter) - -if(HAVE_FCOLLADA) - target_link_libraries(p3ptloader PRIVATE p3daeegg) - target_compile_definitions(p3ptloader PRIVATE HAVE_FCOLLADA) -endif() - -if(BUILD_SHARED_LIBS) - # We can't install this if we're doing a static build, because it depends on - # a bunch of static libraries that aren't installed. - install(TARGETS p3ptloader EXPORT Tools COMPONENT Tools DESTINATION ${MODULE_DESTINATION}) -endif() diff --git a/pandatool/src/ptloader/config_ptloader.cxx b/pandatool/src/ptloader/config_ptloader.cxx deleted file mode 100644 index a9c4b54d..00000000 --- a/pandatool/src/ptloader/config_ptloader.cxx +++ /dev/null @@ -1,116 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_ptloader.cxx - * @author drose - * @date 2001-04-26 - */ - -#include "config_ptloader.h" - -// This needs to be included first to work around a bug in OSX 10.4. -#if defined(HAVE_FCOLLADA) && defined(IS_OSX) -#include "daeToEggConverter.h" -#endif - -#include "loaderFileTypePandatool.h" - -#include "config_flt.h" -#include "fltToEggConverter.h" -#include "config_lwo.h" -#include "lwoToEggConverter.h" -#include "dxfToEggConverter.h" -#include "vrmlToEggConverter.h" -//#include "objToEggConverter.h" -//#include "eggToObjConverter.h" -#include "config_xfile.h" -#include "xFileToEggConverter.h" - -// Windows freaks out if this input is placed earlier. -#if defined(HAVE_FCOLLADA) && !defined(IS_OSX) -#include "daeToEggConverter.h" -#endif - -#include "dconfig.h" -#include "loaderFileTypeRegistry.h" -#include "eggData.h" - -ConfigureDef(config_ptloader); -NotifyCategoryDef(ptloader, ""); - -ConfigureFn(config_ptloader) { - init_libptloader(); -} - -ConfigVariableEnum ptloader_units -("ptloader-units", DU_invalid, - PRC_DESC("Specifies the preferred units into which models will be converted " - "when using libptloader to automatically convert files to Panda " - "at load time, via e.g. \"pview myMayaFile.mb\".")); - -ConfigVariableBool ptloader_load_node -("ptloader-load-node", true, - PRC_DESC("Specify true to allow libptloader to invoke the more efficient " - "but possibly-experimental code to load model files directly into " - "PandaNode when possible. Specify false to force the loading to " - "always go through the egg library, which is more likely to be " - "reliable.")); - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libptloader() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - LoaderFileTypePandatool::init_type(); - - LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr(); - - init_liblwo(); - init_libflt(); - - FltToEggConverter *flt = new FltToEggConverter; - reg->register_type(new LoaderFileTypePandatool(flt)); - - LwoToEggConverter *lwo = new LwoToEggConverter; - reg->register_type(new LoaderFileTypePandatool(lwo)); - - DXFToEggConverter *dxf = new DXFToEggConverter; - reg->register_type(new LoaderFileTypePandatool(dxf)); - - VRMLToEggConverter *vrml = new VRMLToEggConverter; - reg->register_type(new LoaderFileTypePandatool(vrml)); - - init_libxfile(); - XFileToEggConverter *xfile = new XFileToEggConverter; - reg->register_type(new LoaderFileTypePandatool(xfile)); - - //ObjToEggConverter *obj_egg = new ObjToEggConverter; - //EggToObjConverter *egg_obj = new EggToObjConverter; - //reg->register_type(new LoaderFileTypePandatool(obj_egg, egg_obj)); - -// #ifdef HAVE_FCOLLADA DAEToEggConverter *dae = new DAEToEggConverter; -// reg->register_type(new LoaderFileTypePandatool(dae)); #endif - -#ifdef HAVE_MAYA - // Register the Maya converter as a deferred type. We don't compile it in - // directly, because it's big and bulky; we don't need to force people to - // load up libmayaloader (and, along with it, all of the Maya API libraries) - // until they actually try to load a Maya file. - reg->register_deferred_type("mb", "mayaloader"); - reg->register_deferred_type("ma", "mayaloader"); -#endif -} diff --git a/pandatool/src/ptloader/config_ptloader.h b/pandatool/src/ptloader/config_ptloader.h deleted file mode 100644 index fc324dc9..00000000 --- a/pandatool/src/ptloader/config_ptloader.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_ptloader.h - * @author drose - * @date 2001-04-26 - */ - -#ifndef CONFIG_PTLOADER_H -#define CONFIG_PTLOADER_H - -#include "pandatoolbase.h" -#include "notifyCategoryProxy.h" -#include "dconfig.h" -#include "distanceUnit.h" -#include "configVariableEnum.h" -#include "configVariableBool.h" - -ConfigureDecl(config_ptloader, EXPCL_PTLOADER, EXPTP_PTLOADER); -NotifyCategoryDecl(ptloader, EXPCL_PTLOADER, EXPTP_PTLOADER); - -extern ConfigVariableEnum ptloader_units; -extern ConfigVariableBool ptloader_load_node; - -extern EXPCL_PTLOADER void init_libptloader(); - -#endif diff --git a/pandatool/src/ptloader/loaderFileTypePandatool.cxx b/pandatool/src/ptloader/loaderFileTypePandatool.cxx deleted file mode 100644 index 9536b3fe..00000000 --- a/pandatool/src/ptloader/loaderFileTypePandatool.cxx +++ /dev/null @@ -1,223 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file loaderFileTypePandatool.cxx - * @author drose - * @date 2001-04-26 - */ - -#include "loaderFileTypePandatool.h" -#include "config_ptloader.h" -#include "somethingToEggConverter.h" -#include "eggToSomethingConverter.h" -#include "config_putil.h" -#include "load_egg_file.h" -#include "save_egg_file.h" -#include "eggData.h" -#include "loaderOptions.h" -#include "bamCacheRecord.h" - -TypeHandle LoaderFileTypePandatool::_type_handle; - -/** - * - */ -LoaderFileTypePandatool:: -LoaderFileTypePandatool(SomethingToEggConverter *loader, - EggToSomethingConverter *saver) : - _loader(loader), _saver(saver) -{ - if (_loader != nullptr) { - _loader->set_merge_externals(true); - } -} - -/** - * - */ -LoaderFileTypePandatool:: -~LoaderFileTypePandatool() { -} - -/** - * - */ -std::string LoaderFileTypePandatool:: -get_name() const { - if (_loader != nullptr) { - return _loader->get_name(); - } - return _saver->get_name(); -} - -/** - * - */ -std::string LoaderFileTypePandatool:: -get_extension() const { - if (_loader != nullptr) { - return _loader->get_extension(); - } - return _saver->get_extension(); -} - -/** - * Returns a space-separated list of extension, in addition to the one - * returned by get_extension(), that are recognized by this converter. - */ -std::string LoaderFileTypePandatool:: -get_additional_extensions() const { - if (_loader != nullptr) { - return _loader->get_additional_extensions(); - } - return _saver->get_additional_extensions(); -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz or .gz extension), false otherwise. - */ -bool LoaderFileTypePandatool:: -supports_compressed() const { - if (_loader != nullptr) { - return _loader->supports_compressed(); - } - return _saver->supports_compressed(); -} - -/** - * Returns true if the file type can be used to load files, and load_file() is - * supported. Returns false if load_file() is unimplemented and will always - * fail. - */ -bool LoaderFileTypePandatool:: -supports_load() const { - return (_loader != nullptr); -} - -/** - * Returns true if the file type can be used to save files, and save_file() is - * supported. Returns false if save_file() is unimplemented and will always - * fail. - */ -bool LoaderFileTypePandatool:: -supports_save() const { - return (_saver != nullptr); -} - -/** - * Searches for the indicated filename on whatever paths are appropriate to - * this file type, and updates it if it is found. - */ -void LoaderFileTypePandatool:: -resolve_filename(Filename &path) const { - path.resolve_filename(get_model_path(), get_extension()); -} - -/** - * - */ -PT(PandaNode) LoaderFileTypePandatool:: -load_file(const Filename &path, const LoaderOptions &options, - BamCacheRecord *record) const { - if (_loader == nullptr) { - return nullptr; - } - - if (record != nullptr) { - record->add_dependent_file(path); - } - - PT(PandaNode) result; - - SomethingToEggConverter *loader = _loader->make_copy(); - - DSearchPath file_path; - file_path.append_directory(path.get_dirname()); - loader->get_path_replace()->_path = file_path; - - // Convert animation, if the converter supports it. - switch (options.get_flags() & LoaderOptions::LF_convert_anim) { - case LoaderOptions::LF_convert_anim: - loader->set_animation_convert(AC_both); - break; - - case LoaderOptions::LF_convert_skeleton: - loader->set_animation_convert(AC_model); - break; - - case LoaderOptions::LF_convert_channels: - loader->set_animation_convert(AC_chan); - break; - - default: - break; - } - - // Try to convert directly to PandaNode first, if the converter type - // supports it. - if (ptloader_load_node && loader->supports_convert_to_node(options)) { - result = loader->convert_to_node(options, path); - if (!result.is_null()) { - return result; - } - } - - // If the converter type doesn't support the direct PandaNode conversion, - // take the slower route through egg instead. - PT(EggData) egg_data = new EggData; - loader->set_egg_data(egg_data); - - if (loader->convert_file(path)) { - DistanceUnit input_units = loader->get_input_units(); - if (input_units != DU_invalid && ptloader_units != DU_invalid && - input_units != ptloader_units) { - // Convert the file to the units specified by the ptloader-units - // Configrc variable. - ptloader_cat.info() - << "Converting from " << format_long_unit(input_units) - << " to " << format_long_unit(ptloader_units) << "\n"; - double scale = convert_units(input_units, ptloader_units); - egg_data->transform(LMatrix4d::scale_mat(scale)); - } - - if (!egg_data->has_primitives()) { - egg_data->make_point_primitives(); - } else if (!egg_data->has_normals()) { - egg_data->recompute_polygon_normals(); - } - - result = load_egg_data(egg_data); - } - delete loader; - - return result; -} - -/** - * - */ -bool LoaderFileTypePandatool:: -save_file(const Filename &path, const LoaderOptions &options, - PandaNode *node) const { - if (_saver == nullptr) { - return false; - } - - PT(EggData) egg_data = new EggData; - if (!save_egg_data(egg_data, node)) { - return false; - } - - EggToSomethingConverter *saver = _saver->make_copy(); - saver->set_egg_data(egg_data); - - bool result = saver->write_file(path); - delete saver; - return result; -} diff --git a/pandatool/src/ptloader/loaderFileTypePandatool.h b/pandatool/src/ptloader/loaderFileTypePandatool.h deleted file mode 100644 index f50400cd..00000000 --- a/pandatool/src/ptloader/loaderFileTypePandatool.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file loaderFileTypePandatool.h - * @author drose - * @date 2000-06-20 - */ - -#ifndef LOADERFILETYPEPANDATOOL_H -#define LOADERFILETYPEPANDATOOL_H - -#include "pandatoolbase.h" - -#include "loaderFileType.h" - -class SomethingToEggConverter; -class EggToSomethingConverter; - -/** - * This defines the Loader interface to files whose converters are defined - * within the Pandatool package and inherit from SomethingToEggConverter, like - * FltToEggConverter and LwoToEggConverter. - */ -class EXPCL_PTLOADER LoaderFileTypePandatool : public LoaderFileType { -public: - LoaderFileTypePandatool(SomethingToEggConverter *loader, - EggToSomethingConverter *saver = nullptr); - virtual ~LoaderFileTypePandatool(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual std::string get_additional_extensions() const; - virtual bool supports_compressed() const; - - virtual bool supports_load() const; - virtual bool supports_save() const; - - virtual void resolve_filename(Filename &path) const; - virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &options, - BamCacheRecord *record) const; - virtual bool save_file(const Filename &path, const LoaderOptions &options, - PandaNode *node) const; - -private: - SomethingToEggConverter *_loader; - EggToSomethingConverter *_saver; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - LoaderFileType::init_type(); - register_type(_type_handle, "LoaderFileTypePandatool", - LoaderFileType::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; -}; - -#endif diff --git a/pandatool/src/text-stats/CMakeLists.txt b/pandatool/src/text-stats/CMakeLists.txt deleted file mode 100644 index a2c976d2..00000000 --- a/pandatool/src/text-stats/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT HAVE_NET) - return() -endif() - -set(TEXTSTATS_HEADERS - textMonitor.h textMonitor.I - textStats.h -) - -set(TEXTSTATS_SOURCES - textMonitor.cxx - textStats.cxx -) - -composite_sources(text-stats TEXTSTATS_SOURCES) -add_executable(text-stats ${TEXTSTATS_HEADERS} ${TEXTSTATS_SOURCES}) -target_link_libraries(text-stats p3progbase p3pstatserver) - -install(TARGETS text-stats EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/text-stats/textMonitor.I b/pandatool/src/text-stats/textMonitor.I deleted file mode 100644 index d5aba895..00000000 --- a/pandatool/src/text-stats/textMonitor.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textMonitor.I - * @author drose - * @date 2007-07-13 - */ diff --git a/pandatool/src/text-stats/textMonitor.cxx b/pandatool/src/text-stats/textMonitor.cxx deleted file mode 100644 index acaa421d..00000000 --- a/pandatool/src/text-stats/textMonitor.cxx +++ /dev/null @@ -1,247 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textMonitor.cxx - * @author drose - * @date 2000-07-12 - */ - -#include "textMonitor.h" -#include "textStats.h" -#include "pStatCollectorDef.h" -#include "pStatFrameData.h" -#include "indent.h" -#include // sprintf - -/** - * - */ -TextMonitor:: -TextMonitor(TextStats *server, std::ostream *outStream, bool show_raw_data, bool json) : PStatMonitor(server) { - _outStream = outStream; //[PECI] - _show_raw_data = show_raw_data; - _json = json; -} - -/** - * Returns the server that owns this monitor. - */ -TextStats *TextMonitor:: -get_server() { - return (TextStats *)PStatMonitor::get_server(); -} - -/** - * Should be redefined to return a descriptive name for the type of - * PStatsMonitor this is. - */ -std::string TextMonitor:: -get_monitor_name() { - return "Text Stats"; -} - -/** - * Called when the "hello" message has been received from the client. At this - * time, the client's hostname and program name will be known. - */ -void TextMonitor:: -got_hello() { - nout << "Now connected to " << get_client_progname() << " on host " - << get_client_hostname() << "\n"; -} - -/** - * Like got_hello(), this is called when the "hello" message has been received - * from the client. At this time, the client's hostname and program name will - * be known. However, the client appears to be an incompatible version and - * the connection will be terminated; the monitor should issue a message to - * that effect. - */ -void TextMonitor:: -got_bad_version(int client_major, int client_minor, - int server_major, int server_minor) { - nout - << "Rejected connection by " << get_client_progname() - << " from " << get_client_hostname() - << ". Client uses PStats version " - << client_major << "." << client_minor - << ", while server expects PStats version " - << server_major << "." << server_minor << ".\n"; -} - -/** - * Called whenever a new Thread definition is received from the client. - * Generally, the client will send all of its threads over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Thread definitions midstream. - */ -void TextMonitor:: -new_thread(int thread_index) { - if (_json) { - const PStatClientData *client_data = get_client_data(); - - int pid = get_client_pid(); - if (pid < 0) { - pid = _dummy_pid; - } - - (*_outStream) - << "{\"name\":\"thread_name\",\"ph\":\"M\",\"pid\":" << pid - << ",\"tid\":" << thread_index << ",\"args\":{\"name\":\"" - << client_data->get_thread_name(thread_index) << "\"}},\n"; - } -} - -/** - * Called as each frame's data is made available. There is no gurantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void TextMonitor:: -new_data(int thread_index, int frame_number) { - PStatView &view = get_view(thread_index); - const PStatThreadData *thread_data = view.get_thread_data(); - - view.set_to_frame(frame_number); - - if (true) { - const PStatClientData *client_data = get_client_data(); - - if (_json) { - int pid = get_client_pid(); - if (pid < 0) { - pid = _dummy_pid; - } - - const PStatFrameData &frame_data = thread_data->get_frame(frame_number); - size_t num_events = frame_data.get_num_events(); - for (size_t i = 0; i < num_events; ++i) { - int collector_index = frame_data.get_time_collector(i); - (*_outStream) - << "{\"name\":\"" << client_data->get_collector_fullname(collector_index) - << "\",\"ts\":" << (uint64_t)(frame_data.get_time(i) * 1000000) - << ",\"ph\":\"" << (frame_data.is_start(i) ? 'B' : 'E') << "\"" - << ",\"tid\":" << thread_index << ",\"pid\":" << pid << "},\n"; - } - } - else { - (*_outStream) << "\rThread " - << client_data->get_thread_name(thread_index) - << " frame " << frame_number << ", " - << view.get_net_value() * 1000.0 << " ms (" - << thread_data->get_frame_rate() << " Hz):\n"; - - if (_show_raw_data) { - const PStatFrameData &frame_data = thread_data->get_frame(frame_number); - (*_outStream) << "raw data:\n"; - size_t num_events = frame_data.get_num_events(); - for (size_t i = 0; i < num_events; ++i) { - // The iomanipulators are much too clumsy. - char formatted[32]; - sprintf(formatted, "%15.06lf", frame_data.get_time(i)); - (*_outStream) << formatted; - - if (frame_data.is_start(i)) { - (*_outStream) << " start "; - } else { - (*_outStream) << " stop "; - } - - int collector_index = frame_data.get_time_collector(i); - (*_outStream) << client_data->get_collector_fullname(collector_index) << "\n"; - } - } - - const PStatViewLevel *level = view.get_top_level(); - int num_children = level->get_num_children(); - for (int i = 0; i < num_children; i++) { - show_ms(level->get_child(i), 2); - } - - int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); - for (int tc = 0; tc < num_toplevel_collectors; tc++) { - int collector = client_data->get_toplevel_collector(tc); - if (client_data->has_collector(collector) && - client_data->get_collector_has_level(collector, thread_index)) { - - PStatView &level_view = get_level_view(collector, thread_index); - level_view.set_to_frame(frame_number); - const PStatViewLevel *level = level_view.get_top_level(); - show_level(level, 2); - } - } - } - } - _outStream->flush(); -} - - -/** - * Called whenever the connection to the client has been lost. This is a - * permanent state change. The monitor should update its display to represent - * this, and may choose to close down automatically. - */ -void TextMonitor:: -lost_connection() { - nout << "Lost connection.\n"; - ++_dummy_pid; -} - -/** - * Should be redefined to return true if this monitor class can handle running - * in a sub-thread. - * - * This is not related to the question of whether it can handle multiple - * different PStatThreadDatas; this is strictly a question of whether or not - * the monitor itself wants to run in a sub-thread. - */ -bool TextMonitor:: -is_thread_safe() { - return false; -} - -/** - * - */ -void TextMonitor:: -show_ms(const PStatViewLevel *level, int indent_level) { - int collector_index = level->get_collector(); - - const PStatClientData *client_data = get_client_data(); - const PStatCollectorDef &def = client_data->get_collector_def(collector_index); - - indent((*_outStream), indent_level) - << def._name << " = " << level->get_net_value() * 1000.0 << " ms\n" ; - - int num_children = level->get_num_children(); - for (int i = 0; i < num_children; i++) { - show_ms(level->get_child(i), indent_level + 2); - } -} - -/** - * - */ -void TextMonitor:: -show_level(const PStatViewLevel *level, int indent_level) { - int collector_index = level->get_collector(); - - const PStatClientData *client_data = get_client_data(); - const PStatCollectorDef &def = client_data->get_collector_def(collector_index); - - indent((*_outStream), indent_level) - << def._name << " = " << level->get_net_value() << " " - << def._level_units << "\n"; - - int num_children = level->get_num_children(); - for (int i = 0; i < num_children; i++) { - show_level(level->get_child(i), indent_level + 2); - } -} diff --git a/pandatool/src/text-stats/textMonitor.h b/pandatool/src/text-stats/textMonitor.h deleted file mode 100644 index 13cfa860..00000000 --- a/pandatool/src/text-stats/textMonitor.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textMonitor.h - * @author drose - * @date 2000-07-12 - */ - -#ifndef TEXTMONITOR_H -#define TEXTMONITOR_H - -#include "pandatoolbase.h" -#include "pStatMonitor.h" - -// [PECI] -#include -#include - -class TextStats; - -/** - * A simple, scrolling-text stats monitor. Guaranteed to compile on every - * platform. - */ -class TextMonitor : public PStatMonitor { -public: - TextMonitor(TextStats *server, std::ostream *outStream, bool show_raw_data, bool json = false); - TextStats *get_server(); - - virtual std::string get_monitor_name(); - - virtual void got_hello(); - virtual void got_bad_version(int client_major, int client_minor, - int server_major, int server_minor); - virtual void new_thread(int thread_index); - virtual void new_data(int thread_index, int frame_number); - virtual void lost_connection(); - virtual bool is_thread_safe(); - - void show_ms(const PStatViewLevel *level, int indent_level); - void show_level(const PStatViewLevel *level, int indent_level); - -private: - std::ostream *_outStream; //[PECI] - bool _show_raw_data; - bool _json; - int _dummy_pid = 0; -}; - -#include "textMonitor.I" - -#endif diff --git a/pandatool/src/text-stats/textStats.cxx b/pandatool/src/text-stats/textStats.cxx deleted file mode 100644 index 2aa927f3..00000000 --- a/pandatool/src/text-stats/textStats.cxx +++ /dev/null @@ -1,120 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textStats.cxx - * @author drose - * @date 2000-07-12 - */ - -#include "textStats.h" -#include "textMonitor.h" - -#include "pStatServer.h" -#include "config_pstatclient.h" - -#include - -static bool user_interrupted = false; - -// This simple signal handler lets us know when the user has pressed -// control-C, so we can clean up nicely. -static void signal_handler(int) { - user_interrupted = true; -} - -/** - * - */ -TextStats:: -TextStats() { - set_program_brief("text-based PStats client"); - set_program_description - ("This is a simple PStats server that listens on a TCP port for a " - "connection from a PStatClient in a Panda player. It will then report " - "frame rate and timing information sent by the player."); - - add_option - ("p", "port", 0, - "Specify the TCP port to listen for connections on. By default, this " - "is taken from the pstats-port Config variable.", - &TextStats::dispatch_int, nullptr, &_port); - - add_option - ("r", "", 0, - "Show the raw frame data, in addition to boiling it down to a total " - "time per collector.", - &TextStats::dispatch_none, &_show_raw_data, nullptr); - - add_option - ("j", "", 0, - "Output data in JSON format.", - &TextStats::dispatch_none, &_json, nullptr); - - add_option - ("o", "filename", 0, - "Filename where to print. If not given then stderr is being used.", - &TextStats::dispatch_string, &_got_outputFileName, &_outputFileName); - - _outFile = nullptr; - _port = pstats_port; -} - - -/** - * - */ -PStatMonitor *TextStats:: -make_monitor(const NetAddress &address) { - - return new TextMonitor(this, _outFile, _show_raw_data, _json); -} - - -/** - * - */ -void TextStats:: -run() { - // Set up a global signal handler to catch Interrupt (Control-C) so we can - // clean up nicely if the user stops us. - signal(SIGINT, &signal_handler); - - if (!listen(_port)) { - nout << "Unable to open port.\n"; - exit(1); - } - - nout << "Listening for connections.\n"; - - if (_got_outputFileName) { - _outFile = new std::ofstream(_outputFileName.c_str(), std::ios::out | std::ios::trunc); - } else { - _outFile = &(nout); - } - - if (_json) { - (*_outFile) << "[\n"; - } - - main_loop(&user_interrupted); - nout << "Exiting.\n"; - - if (_json) { - // Remove the last comma. - _outFile->seekp(-3, std::ios::cur); - (*_outFile) << "\n]\n"; - } -} - - -int main(int argc, char *argv[]) { - TextStats prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/text-stats/textStats.h b/pandatool/src/text-stats/textStats.h deleted file mode 100644 index 92ce71a7..00000000 --- a/pandatool/src/text-stats/textStats.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file textStats.h - * @author drose - * @date 2000-07-12 - */ - -#ifndef TEXTSTATS_H -#define TEXTSTATS_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "pStatServer.h" - -#include -#include - -/** - * A simple, scrolling-text stats server. Guaranteed to compile on every - * platform. - */ -class TextStats : public ProgramBase, public PStatServer { -public: - TextStats(); - - virtual PStatMonitor *make_monitor(const NetAddress &address); - - void run(); - -private: - int _port; - bool _show_raw_data; - bool _json = false; - - // [PECI] - bool _got_outputFileName; - std::string _outputFileName; - std::ostream *_outFile; -}; - -#endif diff --git a/pandatool/src/vrml/CMakeLists.txt b/pandatool/src/vrml/CMakeLists.txt deleted file mode 100644 index 235ccbff..00000000 --- a/pandatool/src/vrml/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -set(P3VRML_HEADERS - parse_vrml.h - standard_nodes.h - vrmlLexerDefs.h - vrmlNode.h - vrmlNodeType.h - vrmlParserDefs.h -) - -set(P3VRML_SOURCES - parse_vrml.cxx - standard_nodes.cxx - vrmlNode.cxx - vrmlNodeType.cxx -) - -set(P3VRML_PARSER_SOURCES - vrmlParser.cxx - vrmlLexer.cxx -) - -add_bison_target(vrmlParser.cxx vrmlParser.yxx DEFINES vrmlParser.h PREFIX vrmlyy) -add_flex_target(vrmlLexer.cxx vrmlLexer.lxx CASE_INSENSITIVE PREFIX vrmlyy) - -composite_sources(p3vrml P3VRML_SOURCES) -add_library(p3vrml STATIC ${P3VRML_HEADERS} ${P3VRML_SOURCES} ${P3VRML_PARSER_SOURCES}) -target_link_libraries(p3vrml p3pandatoolbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/vrml/parse_vrml.cxx b/pandatool/src/vrml/parse_vrml.cxx deleted file mode 100644 index 9ec700f1..00000000 --- a/pandatool/src/vrml/parse_vrml.cxx +++ /dev/null @@ -1,140 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parse_vrml.cxx - * @author drose - * @date 2004-10-01 - */ - -/************************************************** - * VRML 2.0, Draft 2 Parser - * Copyright (C) 1996 Silicon Graphics, Inc. - * - * Author(s) : Gavin Bell - * Daniel Woods (first port) - ************************************************** - */ - -#include "pandatoolbase.h" - -#include "parse_vrml.h" -#include "vrmlParserDefs.h" -#include "vrmlNodeType.h" -#include "vrmlNode.h" -#include "standard_nodes.h" -#include "zStream.h" -#include "virtualFileSystem.h" - -using std::istream; -using std::istringstream; -using std::string; - -extern int vrmlyyparse(); -extern void vrmlyyResetLineNumber(); -extern int vrmlyydebug; -extern int vrmlyy_flex_debug; - -extern VrmlScene *parsed_scene; - -/** - * Loads the set of standard VRML node definitions into the parser, if it has - * not already been loaded. - */ -static bool -get_standard_nodes() { - static bool got_standard_nodes = false; - static bool read_ok = true; - if (got_standard_nodes) { - return read_ok; - } - - // The standardNodes.wrl file has been compiled into this binary. Extract - // it out. - - string data((const char *)standard_nodes_data, standard_nodes_data_len); - -#ifdef HAVE_ZLIB - // The data is stored compressed; decompress it on-the-fly. - istringstream inz(data); - IDecompressStream in(&inz, false); - -#else - // The data is stored uncompressed, so just load it. - istringstream in(data); -#endif // HAVE_ZLIB - - vrml_init_parser(in, "standardNodes.wrl"); - if (vrmlyyparse() != 0) { - read_ok = false; - } - vrml_cleanup_parser(); - - got_standard_nodes = true; - return read_ok; -} - -/** - * Reads the named VRML file and returns a corresponding VrmlScene, or NULL if - * there is a parse error. - */ -VrmlScene * -parse_vrml(Filename filename) { - filename.set_text(); - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - istream *in = vfs->open_read_file(filename, true); - if (in == nullptr) { - nout << "Cannot open " << filename << " for reading.\n"; - return nullptr; - } - VrmlScene *result = parse_vrml(*in, filename); - vfs->close_read_file(in); - return result; -} - -/** - * Reads the indicated input stream and returns a corresponding VrmlScene, or - * NULL if there is a parse error. - */ -VrmlScene * -parse_vrml(istream &in, const string &filename) { - if (!get_standard_nodes()) { - std::cerr << "Internal error--unable to parse VRML.\n"; - return nullptr; - } - - VrmlScene *scene = nullptr; - VrmlNodeType::pushNameSpace(); - - vrml_init_parser(in, filename); - if (vrmlyyparse() == 0) { - scene = parsed_scene; - } - vrml_cleanup_parser(); - - VrmlNodeType::popNameSpace(); - - return scene; -} - -#if 0 -int -main(int argc, char *argv[]) { - if (argc < 2) { - std::cerr << "parse_vrml filename.wrl\n"; - exit(1); - } - - VrmlScene *scene = parse_vrml(argv[1]); - if (scene == nullptr) { - exit(1); - } - - std::cout << *scene << "\n"; - return (0); -} -#endif diff --git a/pandatool/src/vrml/parse_vrml.h b/pandatool/src/vrml/parse_vrml.h deleted file mode 100644 index 81a04847..00000000 --- a/pandatool/src/vrml/parse_vrml.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file parse_vrml.h - * @author drose - * @date 1999-06-24 - */ - -#ifndef PARSE_VRML_H -#define PARSE_VRML_H - -#include "vrmlNode.h" -#include "filename.h" - -VrmlScene *parse_vrml(Filename filename); -VrmlScene *parse_vrml(std::istream &in, const std::string &filename); - -#endif diff --git a/pandatool/src/vrml/standardNodes.wrl b/pandatool/src/vrml/standardNodes.wrl deleted file mode 100644 index 1764f41f..00000000 --- a/pandatool/src/vrml/standardNodes.wrl +++ /dev/null @@ -1,488 +0,0 @@ -#VRML V2.0 utf8 -# -# ************************************************** -# * VRML 2.0 Parser -# * Copyright (C) 1996 Silicon Graphics, Inc. -# * -# * Author(s) : Gavin Bell -# * Daniel Woods (first port) -# ************************************************** -# -# Definitions for all of the nodes built-in to the spec. -# Taken almost directly from the VRML 2.0 final spec: - -PROTO Anchor [ - eventIn MFNode addChildren - eventIn MFNode removeChildren - exposedField MFNode children [] - exposedField SFString description "" - exposedField MFString parameter [] - exposedField MFString url [] - field SFVec3f bboxCenter 0 0 0 - field SFVec3f bboxSize -1 -1 -1 -] { } - -PROTO Appearance [ - exposedField SFNode material NULL - exposedField SFNode texture NULL - exposedField SFNode textureTransform NULL -] { } - -PROTO AudioClip [ - exposedField SFString description "" - exposedField SFBool loop FALSE - exposedField SFFloat pitch 1.0 - exposedField SFTime startTime 0 - exposedField SFTime stopTime 0 - exposedField MFString url [] - eventOut SFTime duration_changed - eventOut SFBool isActive -] { } - -PROTO Background [ - eventIn SFBool set_bind - exposedField MFFloat groundAngle [] - exposedField MFColor groundColor [] - exposedField MFString backUrl [] - exposedField MFString bottomUrl [] - exposedField MFString frontUrl [] - exposedField MFString leftUrl [] - exposedField MFString rightUrl [] - exposedField MFString topUrl [] - exposedField MFFloat skyAngle [] - exposedField MFColor skyColor [ 0 0 0 ] - eventOut SFBool isBound -] { } - -PROTO Billboard [ - eventIn MFNode addChildren - eventIn MFNode removeChildren - exposedField SFVec3f axisOfRotation 0 1 0 - exposedField MFNode children [] - field SFVec3f bboxCenter 0 0 0 - field SFVec3f bboxSize -1 -1 -1 -] { } - -PROTO Box [ - field SFVec3f size 2 2 2 -] { } - -PROTO Collision [ - eventIn MFNode addChildren - eventIn MFNode removeChildren - exposedField MFNode children [] - exposedField SFBool collide TRUE - field SFVec3f bboxCenter 0 0 0 - field SFVec3f bboxSize -1 -1 -1 - field SFNode proxy NULL - eventOut SFTime collideTime -] { } - -PROTO Color [ - exposedField MFColor color [] -] { } - -PROTO ColorInterpolator [ - eventIn SFFloat set_fraction - exposedField MFFloat key [] - exposedField MFColor keyValue [] - eventOut SFColor value_changed -] { } - -PROTO Cone [ - field SFFloat bottomRadius 1 - field SFFloat height 2 - field SFBool side TRUE - field SFBool bottom TRUE -] { } - -PROTO Coordinate [ - exposedField MFVec3f point [] -] { } - -PROTO CoordinateInterpolator [ - eventIn SFFloat set_fraction - exposedField MFFloat key [] - exposedField MFVec3f keyValue [] - eventOut MFVec3f value_changed -] { } - -PROTO Cylinder [ - field SFBool bottom TRUE - field SFFloat height 2 - field SFFloat radius 1 - field SFBool side TRUE - field SFBool top TRUE -] { } - -PROTO CylinderSensor [ - exposedField SFBool autoOffset TRUE - exposedField SFFloat diskAngle 0.262 - exposedField SFBool enabled TRUE - exposedField SFFloat maxAngle -1 - exposedField SFFloat minAngle 0 - exposedField SFFloat offset 0 - eventOut SFBool isActive - eventOut SFRotation rotation_changed - eventOut SFVec3f trackPoint_changed -] { } - -PROTO DirectionalLight [ - exposedField SFFloat ambientIntensity 0 - exposedField SFColor color 1 1 1 - exposedField SFVec3f direction 0 0 -1 - exposedField SFFloat intensity 1 - exposedField SFBool on TRUE -] { } - -PROTO ElevationGrid [ - eventIn MFFloat set_height - exposedField SFNode color NULL - exposedField SFNode normal NULL - exposedField SFNode texCoord NULL - field SFBool ccw TRUE - field SFBool colorPerVertex TRUE - field SFFloat creaseAngle 0 - field MFFloat height [] - field SFBool normalPerVertex TRUE - field SFBool solid TRUE - field SFInt32 xDimension 0 - field SFFloat xSpacing 0.0 - field SFInt32 zDimension 0 - field SFFloat zSpacing 0.0 - -] { } - -PROTO Extrusion [ - eventIn MFVec2f set_crossSection - eventIn MFRotation set_orientation - eventIn MFVec2f set_scale - eventIn MFVec3f set_spine - field SFBool beginCap TRUE - field SFBool ccw TRUE - field SFBool convex TRUE - field SFFloat creaseAngle 0 - field MFVec2f crossSection [ 1 1, 1 -1, -1 -1, -1 1, 1 1 ] - field SFBool endCap TRUE - field MFRotation orientation 0 0 1 0 - field MFVec2f scale 1 1 - field SFBool solid TRUE - field MFVec3f spine [ 0 0 0, 0 1 0 ] -] { } - -PROTO Fog [ - exposedField SFColor color 1 1 1 - exposedField SFString fogType "LINEAR" - exposedField SFFloat visibilityRange 0 - eventIn SFBool set_bind - eventOut SFBool isBound -] { } - -PROTO FontStyle [ - field SFString family "SERIF" - field SFBool horizontal TRUE - field MFString justify "BEGIN" - field SFString language "" - field SFBool leftToRight TRUE - field SFFloat size 1.0 - field SFFloat spacing 1.0 - field SFString style "PLAIN" - field SFBool topToBottom TRUE -] { } - -PROTO Group [ - eventIn MFNode addChildren - eventIn MFNode removeChildren - exposedField MFNode children [] - field SFVec3f bboxCenter 0 0 0 - field SFVec3f bboxSize -1 -1 -1 -] { } - -PROTO ImageTexture [ - exposedField MFString url [] - field SFBool repeatS TRUE - field SFBool repeatT TRUE -] { } - -PROTO IndexedFaceSet [ - eventIn MFInt32 set_colorIndex - eventIn MFInt32 set_coordIndex - eventIn MFInt32 set_normalIndex - eventIn MFInt32 set_texCoordIndex - exposedField SFNode color NULL - exposedField SFNode coord NULL - exposedField SFNode normal NULL - exposedField SFNode texCoord NULL - field SFBool ccw TRUE - field MFInt32 colorIndex [] - field SFBool colorPerVertex TRUE - field SFBool convex TRUE - field MFInt32 coordIndex [] - field SFFloat creaseAngle 0 - field MFInt32 normalIndex [] - field SFBool normalPerVertex TRUE - field SFBool solid TRUE - field MFInt32 texCoordIndex [] -] { } - -PROTO IndexedLineSet [ - eventIn MFInt32 set_colorIndex - eventIn MFInt32 set_coordIndex - exposedField SFNode color NULL - exposedField SFNode coord NULL - field MFInt32 colorIndex [] - field SFBool colorPerVertex TRUE - field MFInt32 coordIndex [] -] { } - -PROTO Inline [ - exposedField MFString url [] - field SFVec3f bboxCenter 0 0 0 - field SFVec3f bboxSize -1 -1 -1 -] { } - -PROTO LOD [ - exposedField MFNode level [] - field SFVec3f center 0 0 0 - field MFFloat range [] -] { } - -PROTO Material [ - exposedField SFFloat ambientIntensity 0.2 - exposedField SFColor diffuseColor 0.8 0.8 0.8 - exposedField SFColor emissiveColor 0 0 0 - exposedField SFFloat shininess 0.2 - exposedField SFColor specularColor 0 0 0 - exposedField SFFloat transparency 0 -] { } - -PROTO MovieTexture [ - exposedField SFBool loop FALSE - exposedField SFFloat speed 1 - exposedField SFTime startTime 0 - exposedField SFTime stopTime 0 - exposedField MFString url [] - field SFBool repeatS TRUE - field SFBool repeatT TRUE - eventOut SFFloat duration_changed - eventOut SFBool isActive -] { } - -PROTO NavigationInfo [ - eventIn SFBool set_bind - exposedField MFFloat avatarSize [ 0.25, 1.6, 0.75 ] - exposedField SFBool headlight TRUE - exposedField SFFloat speed 1.0 - exposedField MFString type "WALK" - exposedField SFFloat visibilityLimit 0.0 - eventOut SFBool isBound -] { } - -PROTO Normal [ - exposedField MFVec3f vector [] -] { } - -PROTO NormalInterpolator [ - eventIn SFFloat set_fraction - exposedField MFFloat key [] - exposedField MFVec3f keyValue [] - eventOut MFVec3f value_changed -] { } - -PROTO OrientationInterpolator [ - eventIn SFFloat set_fraction - exposedField MFFloat key [] - exposedField MFRotation keyValue [] - eventOut SFRotation value_changed -] { } - -PROTO PixelTexture [ - exposedField SFImage image 0 0 0 - field SFBool repeatS TRUE - field SFBool repeatT TRUE -] { } - -PROTO PlaneSensor [ - exposedField SFBool autoOffset TRUE - exposedField SFBool enabled TRUE - exposedField SFVec2f maxPosition -1 -1 - exposedField SFVec2f minPosition 0 0 - exposedField SFVec3f offset 0 0 0 - eventOut SFBool isActive - eventOut SFVec3f trackPoint_changed - eventOut SFVec3f translation_changed -] { } - -PROTO PointLight [ - exposedField SFFloat ambientIntensity 0 - exposedField SFVec3f attenuation 1 0 0 - exposedField SFColor color 1 1 1 - exposedField SFFloat intensity 1 - exposedField SFVec3f location 0 0 0 - exposedField SFBool on TRUE - exposedField SFFloat radius 100 -] { } - -PROTO PointSet [ - exposedField SFNode color NULL - exposedField SFNode coord NULL -] { } - -PROTO PositionInterpolator [ - eventIn SFFloat set_fraction - exposedField MFFloat key [] - exposedField MFVec3f keyValue [] - eventOut SFVec3f value_changed -] { } - -PROTO ProximitySensor [ - exposedField SFVec3f center 0 0 0 - exposedField SFVec3f size 0 0 0 - exposedField SFBool enabled TRUE - eventOut SFBool isActive - eventOut SFVec3f position_changed - eventOut SFRotation orientation_changed - eventOut SFTime enterTime - eventOut SFTime exitTime -] { } - -PROTO ScalarInterpolator [ - eventIn SFFloat set_fraction - exposedField MFFloat key [] - exposedField MFFloat keyValue [] - eventOut SFFloat value_changed -] { } - -PROTO Script [ - exposedField MFString url [ ] - field SFBool directOutput FALSE - field SFBool mustEvaluate FALSE -] { } - -PROTO Shape [ - field SFNode appearance NULL - field SFNode geometry NULL -] { } - -PROTO Sound [ - exposedField SFVec3f direction 0 0 1 - exposedField SFFloat intensity 1 - exposedField SFVec3f location 0 0 0 - exposedField SFFloat maxBack 10 - exposedField SFFloat maxFront 10 - exposedField SFFloat minBack 1 - exposedField SFFloat minFront 1 - exposedField SFFloat priority 0 - exposedField SFNode source NULL - field SFBool spatialize TRUE -] { } - -PROTO Sphere [ - field SFFloat radius 1 -] { } - -PROTO SphereSensor [ - exposedField SFBool autoOffset TRUE - exposedField SFBool enabled TRUE - exposedField SFRotation offset 0 1 0 0 - eventOut SFBool isActive - eventOut SFRotation rotation_changed - eventOut SFVec3f trackPoint_changed -] { } - -PROTO SpotLight [ - exposedField SFFloat ambientIntensity 0 - exposedField SFVec3f attenuation 1 0 0 - exposedField SFFloat beamWidth 1.570796 - exposedField SFColor color 1 1 1 - exposedField SFFloat cutOffAngle 0.785398 - exposedField SFVec3f direction 0 0 -1 - exposedField SFFloat intensity 1 - exposedField SFVec3f location 0 0 0 - exposedField SFBool on TRUE - exposedField SFFloat radius 100 -] { } - -PROTO Switch [ - exposedField MFNode choice [] - exposedField SFInt32 whichChild -1 -] { } - -PROTO Text [ - exposedField MFString string [] - field SFNode fontStyle NULL - field MFFloat length [] - field SFFloat maxExtent 0.0 -] { } - -PROTO TextureCoordinate [ - exposedField MFVec2f point [] -] { } - -PROTO TextureTransform [ - exposedField SFVec2f center 0 0 - exposedField SFFloat rotation 0 - exposedField SFVec2f scale 1 1 - exposedField SFVec2f translation 0 0 -] { } - -PROTO TimeSensor [ - exposedField SFTime cycleInterval 1 - exposedField SFBool enabled TRUE - exposedField SFBool loop FALSE - exposedField SFTime startTime 0 - exposedField SFTime stopTime 0 - eventOut SFTime cycleTime - eventOut SFFloat fraction_changed - eventOut SFBool isActive - eventOut SFTime time -] { } - -PROTO TouchSensor [ - exposedField SFBool enabled TRUE - eventOut SFVec3f hitNormal_changed - eventOut SFVec3f hitPoint_changed - eventOut SFVec2f hitTexCoord_changed - eventOut SFBool isActive - eventOut SFBool isOver - eventOut SFTime touchTime -] { } - -PROTO Transform [ - eventIn MFNode addChildren - eventIn MFNode removeChildren - exposedField SFVec3f center 0 0 0 - exposedField MFNode children [] - exposedField SFRotation rotation 0 0 1 0 - exposedField SFVec3f scale 1 1 1 - exposedField SFRotation scaleOrientation 0 0 1 0 - exposedField SFVec3f translation 0 0 0 - field SFVec3f bboxCenter 0 0 0 - field SFVec3f bboxSize -1 -1 -1 -] { } - -PROTO Viewpoint [ - eventIn SFBool set_bind - exposedField SFFloat fieldOfView 0.785398 - exposedField SFBool jump TRUE - exposedField SFRotation orientation 0 0 1 0 - exposedField SFVec3f position 0 0 10 - field SFString description "" - eventOut SFTime bindTime - eventOut SFBool isBound -] { } - -PROTO VisibilitySensor [ - exposedField SFVec3f center 0 0 0 - exposedField SFBool enabled TRUE - exposedField SFVec3f size 0 0 0 - eventOut SFTime enterTime - eventOut SFTime exitTime - eventOut SFBool isActive -] { } - -PROTO WorldInfo [ - field MFString info [] - field SFString title "" -] { } - diff --git a/pandatool/src/vrml/standardNodes.wrl.c b/pandatool/src/vrml/standardNodes.wrl.c deleted file mode 100644 index bef39563..00000000 --- a/pandatool/src/vrml/standardNodes.wrl.c +++ /dev/null @@ -1,1342 +0,0 @@ - -/* - * This table was generated by the command: - * - * bin2c -n standard_nodes_data -o standardNodes.wrl.c standardNodes.wrl - */ - -#include - -const unsigned char standard_nodes_data[] = { - 0x23, 0x56, 0x52, 0x4d, 0x4c, 0x20, 0x56, 0x32, 0x2e, 0x30, 0x20, - 0x75, 0x74, 0x66, 0x38, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x0a, 0x23, 0x20, 0x2a, 0x20, 0x56, 0x52, - 0x4d, 0x4c, 0x20, 0x32, 0x2e, 0x30, 0x20, 0x50, 0x61, 0x72, 0x73, - 0x65, 0x72, 0x0a, 0x23, 0x20, 0x2a, 0x20, 0x43, 0x6f, 0x70, 0x79, - 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x31, - 0x39, 0x39, 0x36, 0x20, 0x53, 0x69, 0x6c, 0x69, 0x63, 0x6f, 0x6e, - 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2c, 0x20, - 0x49, 0x6e, 0x63, 0x2e, 0x0a, 0x23, 0x20, 0x2a, 0x0a, 0x23, 0x20, - 0x2a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x28, 0x73, 0x29, - 0x20, 0x20, 0x20, 0x20, 0x3a, 0x20, 0x47, 0x61, 0x76, 0x69, 0x6e, - 0x20, 0x42, 0x65, 0x6c, 0x6c, 0x0a, 0x23, 0x20, 0x2a, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x44, 0x61, 0x6e, 0x69, 0x65, 0x6c, 0x20, 0x57, - 0x6f, 0x6f, 0x64, 0x73, 0x20, 0x28, 0x66, 0x69, 0x72, 0x73, 0x74, - 0x20, 0x70, 0x6f, 0x72, 0x74, 0x29, 0x0a, 0x23, 0x20, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, - 0x2a, 0x2a, 0x2a, 0x2a, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x44, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x62, 0x75, - 0x69, 0x6c, 0x74, 0x2d, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x0a, 0x23, 0x20, - 0x54, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6d, 0x6f, 0x73, - 0x74, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x56, 0x52, - 0x4d, 0x4c, 0x20, 0x32, 0x2e, 0x30, 0x20, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x20, 0x73, 0x70, 0x65, 0x63, 0x3a, 0x0a, 0x0a, 0x50, 0x52, - 0x4f, 0x54, 0x4f, 0x20, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x20, - 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, - 0x65, 0x20, 0x20, 0x20, 0x61, 0x64, 0x64, 0x43, 0x68, 0x69, 0x6c, - 0x64, 0x72, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, - 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, - 0x20, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x22, 0x20, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, - 0x75, 0x72, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x62, - 0x62, 0x6f, 0x78, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, - 0x20, 0x62, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x20, 0x2d, 0x31, - 0x20, 0x2d, 0x31, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, - 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x41, 0x70, 0x70, 0x65, 0x61, - 0x72, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x74, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x65, - 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x74, - 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6c, 0x69, 0x70, - 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x22, 0x22, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, - 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x4c, 0x53, - 0x45, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2e, 0x30, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, - 0x6d, 0x65, 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, - 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, 0x20, - 0x20, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, - 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, - 0x72, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, - 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x69, 0x73, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x65, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, - 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x42, 0x61, 0x63, 0x6b, - 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, - 0x73, 0x65, 0x74, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, - 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x6e, 0x67, 0x6c, 0x65, - 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, - 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x67, 0x72, 0x6f, 0x75, - 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x5b, 0x5d, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x55, 0x72, 0x6c, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x62, - 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x55, 0x72, 0x6c, 0x20, 0x20, 0x20, - 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f, 0x6e, 0x74, - 0x55, 0x72, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x55, 0x72, 0x6c, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x69, - 0x67, 0x68, 0x74, 0x55, 0x72, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x70, 0x55, 0x72, 0x6c, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x20, 0x73, 0x6b, 0x79, 0x41, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, - 0x46, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x73, 0x6b, 0x79, - 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, - 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x20, 0x5d, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, - 0x20, 0x69, 0x73, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x0a, 0x5d, 0x20, - 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, - 0x42, 0x69, 0x6c, 0x6c, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x5b, - 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, - 0x20, 0x20, 0x20, 0x61, 0x64, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, - 0x72, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, - 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, - 0x20, 0x61, 0x78, 0x69, 0x73, 0x4f, 0x66, 0x52, 0x6f, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x30, 0x20, 0x31, 0x20, 0x30, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, - 0x20, 0x20, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, - 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, - 0x20, 0x20, 0x62, 0x62, 0x6f, 0x78, 0x43, 0x65, 0x6e, 0x74, 0x65, - 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, - 0x33, 0x66, 0x20, 0x20, 0x62, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, - 0x20, 0x2d, 0x31, 0x20, 0x2d, 0x31, 0x0a, 0x5d, 0x20, 0x7b, 0x20, - 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x42, 0x6f, - 0x78, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, - 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x20, 0x32, 0x20, 0x32, 0x20, - 0x32, 0x20, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x20, 0x5b, 0x20, 0x0a, 0x20, 0x20, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x61, 0x64, - 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, - 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x69, 0x6c, - 0x64, 0x72, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, - 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x72, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, - 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x69, - 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x62, 0x62, 0x6f, 0x78, - 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x62, 0x62, - 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x2d, 0x31, 0x20, 0x2d, 0x31, 0x20, 0x2d, 0x31, - 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, - 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, - 0x4c, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, - 0x65, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x69, 0x64, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, - 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x5d, 0x20, 0x7b, 0x20, - 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x43, 0x6f, - 0x6c, 0x6f, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, - 0x61, 0x74, 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x65, 0x74, - 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x6b, 0x65, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, - 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, - 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, - 0x43, 0x6f, 0x6e, 0x65, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x74, 0x74, - 0x6f, 0x6d, 0x52, 0x61, 0x64, 0x69, 0x75, 0x73, 0x20, 0x31, 0x0a, - 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x20, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x32, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, - 0x20, 0x20, 0x20, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, - 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, - 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x5d, 0x20, 0x7b, 0x20, - 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x43, 0x6f, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x5b, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, - 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x20, 0x5b, 0x5d, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, - 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x66, - 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6b, 0x65, - 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, - 0x20, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x20, - 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, - 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x56, 0x65, - 0x63, 0x33, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, - 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x43, 0x79, - 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x74, - 0x74, 0x6f, 0x6d, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x20, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x20, 0x20, 0x32, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x20, 0x72, 0x61, 0x64, 0x69, - 0x75, 0x73, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, - 0x6c, 0x20, 0x20, 0x20, 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, - 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x5d, 0x20, 0x7b, - 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x43, - 0x79, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, - 0x74, 0x6f, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x54, 0x52, - 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x6b, - 0x41, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x20, 0x30, 0x2e, 0x32, 0x36, - 0x32, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, - 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x41, 0x6e, 0x67, 0x6c, - 0x65, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x6d, 0x69, 0x6e, 0x41, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x20, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, - 0x61, 0x74, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, - 0x20, 0x20, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, - 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x20, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, - 0x6c, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, - 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x74, 0x79, 0x20, 0x20, 0x30, 0x20, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x63, - 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x31, 0x20, 0x31, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, - 0x66, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, - 0x30, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x74, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x20, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x6f, 0x6e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x20, 0x0a, 0x5d, 0x20, 0x7b, - 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x45, - 0x6c, 0x65, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x69, - 0x64, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x46, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, - 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, - 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, - 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, - 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x63, 0x63, 0x77, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x20, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x41, 0x6e, 0x67, 0x6c, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, - 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, - 0x20, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x65, 0x72, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x20, 0x20, 0x54, 0x52, - 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, - 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x20, 0x78, 0x44, 0x69, - 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x78, 0x53, 0x70, - 0x61, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x20, 0x7a, - 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x7a, - 0x53, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x30, 0x0a, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x45, 0x78, 0x74, 0x72, 0x75, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, - 0x6e, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x20, - 0x20, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, - 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x4d, 0x46, 0x52, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x5f, - 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, - 0x4d, 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x20, 0x20, 0x20, - 0x73, 0x65, 0x74, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x4d, 0x46, - 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, 0x20, 0x73, 0x65, - 0x74, 0x5f, 0x73, 0x70, 0x69, 0x6e, 0x65, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, - 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x65, 0x67, 0x69, - 0x6e, 0x43, 0x61, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, - 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x63, 0x77, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x78, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x20, 0x20, 0x20, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x41, - 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, - 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, - 0x4d, 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x72, 0x6f, 0x73, 0x73, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x20, 0x31, 0x20, 0x31, - 0x2c, 0x20, 0x31, 0x20, 0x2d, 0x31, 0x2c, 0x20, 0x2d, 0x31, 0x20, - 0x2d, 0x31, 0x2c, 0x20, 0x2d, 0x31, 0x20, 0x31, 0x2c, 0x20, 0x31, - 0x20, 0x31, 0x20, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x43, 0x61, 0x70, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, - 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, - 0x30, 0x20, 0x31, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, 0x32, - 0x66, 0x20, 0x20, 0x20, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x31, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, - 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x20, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, - 0x20, 0x20, 0x73, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x20, 0x30, - 0x20, 0x30, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x31, 0x20, 0x30, - 0x20, 0x5d, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x46, 0x6f, 0x67, 0x20, 0x5b, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x31, - 0x20, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x54, 0x79, 0x70, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x22, 0x4c, 0x49, 0x4e, 0x45, 0x41, 0x52, 0x22, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, - 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x73, - 0x65, 0x74, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x69, - 0x73, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, - 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x46, 0x6f, - 0x6e, 0x74, 0x53, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x53, 0x45, 0x52, 0x49, 0x46, - 0x22, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x68, 0x6f, 0x72, - 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x20, 0x20, 0x54, 0x52, - 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6a, 0x75, - 0x73, 0x74, 0x69, 0x66, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, - 0x42, 0x45, 0x47, 0x49, 0x4e, 0x22, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, - 0x20, 0x6c, 0x65, 0x66, 0x74, 0x54, 0x6f, 0x52, 0x69, 0x67, 0x68, - 0x74, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x20, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x31, 0x2e, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x22, 0x50, 0x4c, 0x41, 0x49, 0x4e, 0x22, 0x0a, 0x20, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, 0x6f, - 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x54, 0x6f, 0x42, - 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, - 0x61, 0x64, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, - 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, - 0x20, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x69, - 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, - 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x72, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, - 0x62, 0x62, 0x6f, 0x78, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, - 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x62, 0x62, 0x6f, 0x78, - 0x53, 0x69, 0x7a, 0x65, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x20, 0x2d, - 0x31, 0x20, 0x2d, 0x31, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, - 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x49, 0x6d, 0x61, 0x67, - 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x5b, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x20, 0x75, 0x72, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, - 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, - 0x6c, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x53, - 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, - 0x65, 0x61, 0x74, 0x54, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x5d, - 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x20, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x46, 0x61, 0x63, - 0x65, 0x53, 0x65, 0x74, 0x20, 0x5b, 0x20, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x4d, 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x73, - 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, - 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x6f, - 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, - 0x73, 0x65, 0x74, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, - 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x73, 0x65, 0x74, 0x5f, - 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x53, 0x46, 0x4e, - 0x6f, 0x64, 0x65, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, - 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x63, 0x6f, 0x6f, - 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, - 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, - 0x65, 0x20, 0x20, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, - 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x63, 0x63, 0x77, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x4d, 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x63, 0x6f, - 0x6c, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x63, - 0x6f, 0x6c, 0x6f, 0x72, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, - 0x65, 0x78, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, - 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, - 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x78, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, - 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x49, - 0x6e, 0x74, 0x33, 0x32, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x61, 0x73, - 0x65, 0x41, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, - 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x73, - 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, - 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x20, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, - 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, - 0x54, 0x4f, 0x20, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x4c, - 0x69, 0x6e, 0x65, 0x53, 0x65, 0x74, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, - 0x73, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x63, - 0x6f, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, - 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, - 0x4c, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x53, 0x46, 0x4e, 0x6f, - 0x64, 0x65, 0x20, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, - 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x63, 0x6f, 0x6c, 0x6f, - 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x63, 0x6f, 0x6c, - 0x6f, 0x72, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, - 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x5d, - 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x20, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x20, 0x75, 0x72, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, - 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x62, 0x62, 0x6f, 0x78, 0x43, - 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, - 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, - 0x66, 0x20, 0x20, 0x62, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, - 0x20, 0x20, 0x20, 0x2d, 0x31, 0x20, 0x2d, 0x31, 0x20, 0x2d, 0x31, - 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, - 0x54, 0x4f, 0x20, 0x4c, 0x4f, 0x44, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x6c, - 0x65, 0x76, 0x65, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x20, - 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, - 0x66, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, - 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, - 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x61, 0x6e, 0x67, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x20, 0x0a, 0x5d, 0x20, - 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x5b, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x20, 0x30, 0x2e, 0x32, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x20, 0x64, 0x69, 0x66, 0x66, 0x75, 0x73, 0x65, 0x43, 0x6f, - 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, - 0x38, 0x20, 0x30, 0x2e, 0x38, 0x20, 0x30, 0x2e, 0x38, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, - 0x65, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, - 0x61, 0x74, 0x20, 0x73, 0x68, 0x69, 0x6e, 0x69, 0x6e, 0x65, 0x73, - 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, - 0x2e, 0x32, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x43, 0x6f, - 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x75, 0x6c, 0x61, - 0x72, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x30, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, - 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x4d, 0x6f, 0x76, 0x69, - 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x5b, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, - 0x20, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x73, - 0x70, 0x65, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, - 0x20, 0x20, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, - 0x65, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x73, 0x74, 0x6f, 0x70, - 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, - 0x75, 0x72, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, - 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, - 0x6c, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x53, - 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, - 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x54, 0x20, 0x20, 0x20, 0x20, - 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x64, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, - 0x6c, 0x20, 0x20, 0x20, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, - 0x4f, 0x54, 0x4f, 0x20, 0x4e, 0x61, 0x76, 0x69, 0x67, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, - 0x20, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x20, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x53, 0x69, 0x7a, 0x65, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x20, 0x30, 0x2e, - 0x32, 0x35, 0x2c, 0x20, 0x31, 0x2e, 0x36, 0x2c, 0x20, 0x30, 0x2e, - 0x37, 0x35, 0x20, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x68, 0x65, 0x61, 0x64, - 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x73, 0x70, - 0x65, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x31, 0x2e, 0x30, 0x20, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, - 0x74, 0x79, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x57, 0x41, 0x4c, 0x4b, - 0x22, 0x20, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x20, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x20, 0x20, - 0x30, 0x2e, 0x30, 0x20, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x69, 0x73, 0x42, 0x6f, - 0x75, 0x6e, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, - 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x4e, 0x6f, 0x72, 0x6d, 0x61, - 0x6c, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x56, - 0x65, 0x63, 0x33, 0x66, 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x20, 0x5b, 0x5d, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, - 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x4e, 0x6f, 0x72, 0x6d, 0x61, - 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, - 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x66, - 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6b, 0x65, - 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, - 0x20, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x20, - 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, - 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x56, 0x65, - 0x63, 0x33, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, - 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x20, - 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, - 0x61, 0x74, 0x20, 0x20, 0x20, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x66, - 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x20, - 0x20, 0x6b, 0x65, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x52, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, - 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x50, 0x69, 0x78, 0x65, - 0x6c, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x5b, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x49, 0x6d, 0x61, 0x67, 0x65, - 0x20, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x72, - 0x65, 0x70, 0x65, 0x61, 0x74, 0x53, 0x20, 0x20, 0x20, 0x20, 0x54, - 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, - 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, - 0x74, 0x54, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x65, 0x6e, 0x73, - 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, - 0x20, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x6d, 0x61, - 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x2d, - 0x31, 0x20, 0x2d, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x6d, 0x69, 0x6e, 0x50, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x30, 0x20, 0x30, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, - 0x20, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x69, 0x73, - 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x0a, 0x20, 0x20, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x74, 0x72, 0x61, - 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, - 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x4c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x6d, - 0x62, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x74, 0x79, 0x20, 0x20, 0x30, 0x20, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x61, 0x74, - 0x74, 0x65, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x30, 0x20, 0x30, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x31, - 0x20, 0x31, 0x20, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x74, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, - 0x63, 0x33, 0x66, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x6f, 0x6e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x20, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, - 0x61, 0x64, 0x69, 0x75, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x0a, 0x5d, - 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x20, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x20, 0x5b, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, - 0x65, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x63, - 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, - 0x55, 0x4c, 0x4c, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, - 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x50, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, - 0x61, 0x74, 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x65, 0x74, - 0x5f, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x6b, 0x65, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, - 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, - 0x33, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, - 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, - 0x50, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x69, 0x74, 0x79, 0x53, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, 0x20, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, 0x20, - 0x73, 0x69, 0x7a, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, - 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, - 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x53, 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, - 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x78, 0x69, 0x74, 0x54, 0x69, - 0x6d, 0x65, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, - 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x53, 0x63, 0x61, 0x6c, 0x61, 0x72, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x6f, - 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x72, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x6b, 0x65, 0x79, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x6b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x20, 0x5b, - 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, - 0x61, 0x74, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, - 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, - 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x72, 0x6c, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x5b, 0x20, 0x5d, 0x20, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x64, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x20, 0x46, - 0x41, 0x4c, 0x53, 0x45, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x6d, 0x75, 0x73, 0x74, - 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x20, 0x20, 0x46, - 0x41, 0x4c, 0x53, 0x45, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, - 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x53, 0x68, 0x61, 0x70, - 0x65, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x70, 0x70, - 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x4e, 0x55, 0x4c, - 0x4c, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6f, 0x6d, 0x65, - 0x74, 0x72, 0x79, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, - 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x31, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, - 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x6d, 0x61, 0x78, - 0x42, 0x61, 0x63, 0x6b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x31, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x46, 0x72, 0x6f, - 0x6e, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x6d, 0x69, - 0x6e, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, - 0x6f, 0x61, 0x74, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, - 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, - 0x73, 0x70, 0x61, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x5d, 0x20, 0x7b, - 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x53, - 0x70, 0x68, 0x65, 0x72, 0x65, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, - 0x74, 0x20, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x20, 0x20, 0x31, - 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, - 0x54, 0x4f, 0x20, 0x53, 0x70, 0x68, 0x65, 0x72, 0x65, 0x53, 0x65, - 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x61, 0x75, 0x74, 0x6f, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, - 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, - 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x52, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x31, 0x20, - 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, - 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x73, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, - 0x61, 0x63, 0x6b, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, - 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x53, 0x70, 0x6f, - 0x74, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, - 0x6d, 0x62, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x74, 0x79, 0x20, 0x20, 0x30, 0x20, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x61, - 0x74, 0x74, 0x65, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x30, 0x20, 0x30, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, - 0x74, 0x20, 0x62, 0x65, 0x61, 0x6d, 0x57, 0x69, 0x64, 0x74, 0x68, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2e, - 0x35, 0x37, 0x30, 0x37, 0x39, 0x36, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6c, - 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x31, 0x20, 0x31, 0x20, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x63, 0x75, 0x74, 0x4f, 0x66, 0x66, 0x41, 0x6e, 0x67, 0x6c, - 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, 0x37, - 0x38, 0x35, 0x33, 0x39, 0x38, 0x20, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x2d, 0x31, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, - 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, - 0x66, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, - 0x30, 0x20, 0x30, 0x20, 0x20, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x6f, 0x6e, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x61, - 0x64, 0x69, 0x75, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x0a, 0x5d, 0x20, - 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, - 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, - 0x20, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x20, 0x77, 0x68, - 0x69, 0x63, 0x68, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x2d, 0x31, - 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, - 0x54, 0x4f, 0x20, 0x54, 0x65, 0x78, 0x74, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x20, 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, - 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, - 0x53, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x0a, - 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x46, 0x6c, 0x6f, 0x61, - 0x74, 0x20, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x20, - 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x20, 0x6d, 0x61, 0x78, - 0x45, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x30, 0x2e, 0x30, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x5b, 0x0a, - 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, - 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x5b, 0x5d, 0x0a, 0x5d, - 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x20, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x5b, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x63, - 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, - 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x73, 0x63, - 0x61, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, - 0x20, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, - 0x63, 0x32, 0x66, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x5d, 0x20, - 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, - 0x54, 0x69, 0x6d, 0x65, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x20, - 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, - 0x65, 0x20, 0x20, 0x20, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x31, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x6c, - 0x6f, 0x6f, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x54, - 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x54, - 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0a, - 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, 0x20, - 0x20, 0x20, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x54, 0x69, 0x6d, 0x65, - 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, - 0x74, 0x20, 0x20, 0x66, 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, - 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x0a, 0x20, 0x20, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, - 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, - 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x54, 0x6f, 0x75, 0x63, - 0x68, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x20, 0x54, 0x52, 0x55, - 0x45, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, - 0x33, 0x66, 0x20, 0x68, 0x69, 0x74, 0x4e, 0x6f, 0x72, 0x6d, 0x61, - 0x6c, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, - 0x68, 0x69, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, - 0x46, 0x56, 0x65, 0x63, 0x32, 0x66, 0x20, 0x68, 0x69, 0x74, 0x54, - 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, - 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x69, 0x73, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, - 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x69, 0x73, 0x4f, 0x76, 0x65, 0x72, - 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, - 0x20, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, - 0x0a, 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, - 0x54, 0x4f, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, - 0x6d, 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, - 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x64, - 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x4d, 0x46, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, - 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, - 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x4d, 0x46, 0x4e, 0x6f, - 0x64, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, - 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, - 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x31, - 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, - 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x63, - 0x61, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x31, 0x20, 0x31, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x4f, 0x72, - 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x30, - 0x20, 0x30, 0x20, 0x31, 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, - 0x20, 0x30, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, - 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x62, 0x6f, - 0x78, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x62, 0x62, 0x6f, 0x78, 0x53, 0x69, 0x7a, 0x65, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, - 0x20, 0x2d, 0x31, 0x20, 0x2d, 0x31, 0x0a, 0x5d, 0x20, 0x7b, 0x20, - 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x20, 0x56, 0x69, - 0x65, 0x77, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x69, 0x6e, 0x64, - 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x46, 0x6c, 0x6f, 0x61, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4f, - 0x66, 0x56, 0x69, 0x65, 0x77, 0x20, 0x20, 0x20, 0x20, 0x30, 0x2e, - 0x37, 0x38, 0x35, 0x33, 0x39, 0x38, 0x0a, 0x20, 0x20, 0x65, 0x78, - 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x6a, 0x75, 0x6d, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, - 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x20, 0x53, 0x46, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, 0x31, - 0x20, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, - 0x65, 0x63, 0x33, 0x66, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x30, 0x20, 0x30, 0x20, 0x31, 0x30, 0x0a, 0x20, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x20, - 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x20, 0x20, 0x20, 0x22, 0x22, 0x0a, 0x20, 0x20, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x62, 0x69, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x0a, 0x20, - 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x69, 0x73, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x20, 0x5b, 0x0a, 0x20, - 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x20, 0x20, 0x30, 0x20, - 0x30, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x42, - 0x6f, 0x6f, 0x6c, 0x20, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x20, 0x20, 0x54, 0x52, 0x55, 0x45, 0x0a, 0x20, 0x20, 0x65, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x20, 0x53, 0x46, 0x56, 0x65, 0x63, 0x33, 0x66, 0x20, 0x73, 0x69, - 0x7a, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x30, 0x20, - 0x30, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, - 0x65, 0x20, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x54, 0x69, 0x6d, - 0x65, 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, - 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x54, 0x69, 0x6d, - 0x65, 0x20, 0x20, 0x65, 0x78, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, - 0x0a, 0x20, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4f, 0x75, 0x74, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x46, 0x42, 0x6f, 0x6f, 0x6c, - 0x20, 0x20, 0x69, 0x73, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, - 0x20, 0x5b, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, - 0x4d, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, - 0x66, 0x6f, 0x20, 0x20, 0x5b, 0x5d, 0x0a, 0x20, 0x20, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x20, 0x53, 0x46, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x20, 0x22, 0x22, 0x0a, - 0x5d, 0x20, 0x7b, 0x20, 0x7d, 0x0a, 0x0a -}; - -const int standard_nodes_data_len = 14604; - diff --git a/pandatool/src/vrml/standardNodes.wrl.pz.c b/pandatool/src/vrml/standardNodes.wrl.pz.c deleted file mode 100644 index f573f1c4..00000000 --- a/pandatool/src/vrml/standardNodes.wrl.pz.c +++ /dev/null @@ -1,273 +0,0 @@ - -/* - * This table was generated by the command: - * - * bin2c -n standard_nodes_data -o standardNodes.wrl.pz.c standardNodes.wrl.pz - */ - -#include - -const unsigned char standard_nodes_data[] = { - 0x78, 0x9c, 0xd5, 0x5b, 0x5b, 0x6f, 0xdb, 0x38, 0x16, 0x7e, 0xcf, - 0xaf, 0x20, 0xd2, 0x97, 0x76, 0xd1, 0x09, 0x62, 0x17, 0xbd, 0xcd, - 0x5b, 0x92, 0x26, 0x45, 0xb0, 0x69, 0x12, 0x44, 0x6e, 0xfa, 0x50, - 0x14, 0x03, 0x5a, 0xa2, 0x6d, 0x4e, 0x64, 0x51, 0xa0, 0x28, 0xd7, - 0xee, 0x62, 0xff, 0xfb, 0xf2, 0x2e, 0x4a, 0xbc, 0x58, 0xdd, 0x66, - 0x3a, 0x1d, 0xa5, 0x45, 0xd3, 0xf8, 0xd3, 0xe1, 0xe1, 0x39, 0x87, - 0xe7, 0xca, 0x3c, 0xb9, 0xbf, 0xfb, 0x70, 0x05, 0xee, 0xa7, 0x47, - 0xc7, 0xa0, 0x65, 0x8b, 0x37, 0x07, 0x4f, 0x0e, 0x9e, 0x80, 0x7f, - 0x7d, 0xf7, 0x23, 0x5e, 0x02, 0x92, 0x92, 0x20, 0x74, 0x0b, 0x69, - 0x83, 0xa8, 0xfc, 0xd9, 0x19, 0xa9, 0x77, 0x14, 0x2f, 0x57, 0x0c, - 0x3c, 0x3d, 0x7b, 0x06, 0x26, 0x6f, 0xdf, 0xbe, 0x02, 0x19, 0x2e, - 0x71, 0x4e, 0x2a, 0xf0, 0x9e, 0xc2, 0x7a, 0x85, 0xf3, 0xe6, 0x39, - 0xb8, 0xac, 0xf2, 0x23, 0x81, 0x96, 0x6f, 0x9c, 0xb4, 0x6c, 0x45, - 0xe8, 0xd3, 0xe6, 0x19, 0xe0, 0xcf, 0xef, 0xe0, 0x3d, 0xdc, 0xe0, - 0x0a, 0x9c, 0xa2, 0xb2, 0x94, 0x9f, 0x0e, 0x9e, 0x77, 0xb0, 0xc2, - 0xa8, 0x04, 0x9f, 0x08, 0x29, 0x1a, 0xf0, 0x74, 0x81, 0x69, 0xc3, - 0x40, 0x4d, 0x28, 0x7b, 0xf6, 0x7f, 0xee, 0x82, 0xbf, 0xf6, 0x0e, - 0x2d, 0x70, 0x85, 0x19, 0x26, 0x55, 0x03, 0x16, 0x84, 0x02, 0x58, - 0x96, 0x80, 0x2c, 0x00, 0x5b, 0x21, 0x50, 0x91, 0x02, 0x35, 0x60, - 0xde, 0xe2, 0x92, 0xfd, 0xc6, 0x99, 0x62, 0x44, 0xfe, 0xb4, 0xa9, - 0x91, 0x64, 0x7f, 0x06, 0x1f, 0x50, 0xc5, 0xe1, 0x6b, 0xc2, 0x99, - 0x28, 0x30, 0x45, 0x39, 0x2b, 0x77, 0x60, 0x41, 0xc9, 0x5a, 0xc2, - 0xac, 0x74, 0x38, 0x79, 0x58, 0xca, 0xb7, 0x7e, 0x3f, 0x38, 0xb8, - 0xbd, 0xbb, 0x99, 0xdd, 0x80, 0x93, 0x2a, 0xe7, 0x7b, 0x06, 0x9f, - 0x0f, 0x00, 0x40, 0x1b, 0x54, 0xb1, 0xcb, 0x4a, 0x6d, 0xef, 0xc3, - 0xc5, 0x35, 0x5f, 0x92, 0x7f, 0x03, 0x8b, 0xe2, 0x6c, 0x85, 0xcb, - 0x82, 0xa2, 0x2a, 0x8a, 0xa1, 0x68, 0x4d, 0x36, 0xc8, 0x85, 0x6d, - 0x6b, 0xd2, 0xa0, 0xe2, 0x82, 0x4b, 0xa8, 0xe8, 0x60, 0xb9, 0x06, - 0x18, 0x11, 0x7e, 0xfe, 0x32, 0x84, 0x66, 0x17, 0x19, 0xa3, 0xb8, - 0x5a, 0x02, 0xbe, 0xdb, 0x9c, 0xe2, 0x5a, 0xc8, 0x42, 0x42, 0x0f, - 0x0f, 0x81, 0x4f, 0x56, 0x63, 0x6b, 0x48, 0xe1, 0x1a, 0x31, 0x44, - 0xa3, 0x64, 0x2d, 0xb4, 0xa5, 0x65, 0x4f, 0x89, 0x12, 0xba, 0x90, - 0x18, 0xfd, 0x64, 0x17, 0xf7, 0x28, 0x7f, 0xb1, 0x00, 0x60, 0x3e, - 0x27, 0xdb, 0x33, 0xbe, 0x59, 0x43, 0xf6, 0x58, 0x7c, 0x25, 0xd1, - 0x19, 0xfe, 0x86, 0xcc, 0x07, 0xbf, 0x4d, 0xd4, 0x9f, 0x83, 0x2f, - 0xe0, 0x3f, 0xe0, 0xbf, 0x56, 0xd8, 0x75, 0x8d, 0x38, 0xb3, 0x55, - 0x8e, 0x94, 0xc0, 0xfb, 0x5b, 0x97, 0x52, 0x5a, 0x43, 0xbe, 0x22, - 0x86, 0x0e, 0x9b, 0xd7, 0x1f, 0xaf, 0xae, 0x22, 0x60, 0x86, 0xb6, - 0xac, 0xa5, 0x08, 0x7c, 0x0f, 0x78, 0xc6, 0xd7, 0x6f, 0xb8, 0x75, - 0xad, 0x35, 0xb8, 0xcf, 0x60, 0x5b, 0x60, 0x72, 0x56, 0xe2, 0xda, - 0xe7, 0x0f, 0x44, 0x94, 0x73, 0x78, 0x18, 0x42, 0x9e, 0x12, 0x22, - 0xb6, 0x50, 0x12, 0x52, 0x5b, 0xde, 0x2e, 0x4e, 0xae, 0xb2, 0xf3, - 0x10, 0xf8, 0xa2, 0x24, 0x90, 0x01, 0x50, 0x63, 0x96, 0xaf, 0x0c, - 0x78, 0x72, 0x74, 0x1c, 0x82, 0xce, 0xf0, 0x5a, 0x6c, 0xb7, 0x61, - 0x90, 0x32, 0xfd, 0x3d, 0x48, 0x03, 0x49, 0x6d, 0x70, 0x21, 0x60, - 0xd8, 0x32, 0x94, 0x05, 0x09, 0x53, 0xbf, 0x69, 0x99, 0x55, 0xb5, - 0xa6, 0x53, 0xb4, 0x14, 0x8a, 0xad, 0xff, 0x91, 0xaf, 0x60, 0xb5, - 0x44, 0x45, 0x08, 0xaa, 0xb7, 0x8f, 0x9b, 0x93, 0x9c, 0xe1, 0x0d, - 0xea, 0x0b, 0xf9, 0x14, 0xe6, 0x0f, 0x4b, 0x4a, 0xda, 0xaa, 0xf0, - 0x8f, 0x9d, 0x7d, 0xb5, 0x41, 0xec, 0x8f, 0x39, 0xae, 0x0a, 0xdf, - 0x94, 0xb5, 0xb4, 0x14, 0x85, 0x93, 0x6a, 0x59, 0xa2, 0xb0, 0xc9, - 0x9f, 0x91, 0x92, 0x1f, 0x6c, 0x8d, 0xd3, 0xff, 0x49, 0x1c, 0x8d, - 0x39, 0xe7, 0xea, 0xa3, 0x11, 0x42, 0x0a, 0x47, 0x18, 0x23, 0x6b, - 0x8d, 0x4c, 0xe0, 0xb8, 0xf7, 0xa9, 0x98, 0x21, 0x98, 0xc0, 0x95, - 0x68, 0xc1, 0xc6, 0xac, 0x2b, 0x5d, 0xf9, 0x08, 0x7a, 0x5c, 0xe1, - 0x96, 0x5c, 0x10, 0xa7, 0xe5, 0xd7, 0x3c, 0xec, 0xb4, 0xf0, 0x22, - 0x38, 0x2d, 0x32, 0x8e, 0xd3, 0xdf, 0x09, 0x9c, 0x72, 0x03, 0x00, - 0x78, 0x06, 0xe2, 0xe8, 0xfc, 0x54, 0x08, 0x7c, 0xa0, 0x72, 0x5c, - 0x96, 0x73, 0x02, 0x69, 0x40, 0xe3, 0x8f, 0xe8, 0x68, 0xad, 0x37, - 0x82, 0x5b, 0xdc, 0xdc, 0x2c, 0xee, 0x08, 0x83, 0xea, 0x8c, 0x1e, - 0x83, 0x89, 0x6f, 0xfc, 0x69, 0xb7, 0xfc, 0xf3, 0x9c, 0xe2, 0x29, - 0xd9, 0x4a, 0xa9, 0x58, 0x1a, 0xe6, 0xfd, 0x46, 0xbe, 0x3a, 0x95, - 0x5f, 0xfd, 0x57, 0xb8, 0x42, 0x4a, 0xdc, 0x88, 0xad, 0x7d, 0x06, - 0xbf, 0x4a, 0xe0, 0xd2, 0xea, 0xcf, 0x05, 0x6b, 0x45, 0xe7, 0x92, - 0x67, 0x77, 0x1f, 0xcf, 0xff, 0x6a, 0x71, 0x7a, 0x2f, 0x68, 0xb6, - 0x6b, 0x4a, 0xb6, 0x3b, 0xd0, 0x3d, 0x26, 0x38, 0xf4, 0xed, 0x56, - 0xbb, 0x35, 0xcd, 0xb8, 0xf8, 0x9f, 0x27, 0x6c, 0x93, 0x20, 0x84, - 0x0e, 0x48, 0xde, 0x1d, 0x8e, 0x2f, 0x81, 0x17, 0x2f, 0xc5, 0xee, - 0x6a, 0x52, 0x42, 0x16, 0xca, 0x32, 0x8c, 0xef, 0x17, 0xde, 0x6e, - 0x41, 0x61, 0x2e, 0xcc, 0x35, 0x76, 0x62, 0x1f, 0x90, 0xd9, 0x4b, - 0xfc, 0xb4, 0x72, 0xcc, 0x3d, 0x2c, 0x5b, 0x14, 0x72, 0xe1, 0x99, - 0xc6, 0x6c, 0x04, 0xc0, 0x3a, 0xef, 0x01, 0xc7, 0x15, 0xea, 0xdb, - 0x62, 0x17, 0x9d, 0xb4, 0xe3, 0xbb, 0x83, 0x05, 0x6e, 0x1b, 0x30, - 0x89, 0x80, 0x56, 0x48, 0x66, 0x9c, 0xea, 0x99, 0x0e, 0x40, 0xda, - 0x44, 0xb8, 0x61, 0xa7, 0x0c, 0xa4, 0xc3, 0xa9, 0x15, 0x5d, 0xdc, - 0x80, 0x5b, 0x42, 0x0b, 0x9e, 0xd1, 0xb1, 0x40, 0x36, 0xf1, 0x41, - 0x1b, 0x4d, 0x4d, 0x70, 0xc5, 0x42, 0xaa, 0x31, 0xaf, 0xfe, 0x2c, - 0xfd, 0x28, 0x76, 0x52, 0xfa, 0x31, 0x98, 0x94, 0x7e, 0x76, 0x25, - 0x0f, 0x89, 0x88, 0x0e, 0xfd, 0xc5, 0x50, 0x60, 0x43, 0x99, 0xfa, - 0xfa, 0x99, 0x86, 0x3f, 0xa6, 0x4a, 0xbb, 0x7d, 0xf5, 0xfa, 0x8a, - 0xf3, 0xe9, 0x1b, 0x04, 0xd3, 0xf9, 0x4e, 0x40, 0x5b, 0x9a, 0xf7, - 0x0c, 0x55, 0x4d, 0xe8, 0x3c, 0x75, 0x34, 0x00, 0x6c, 0x19, 0xb9, - 0x59, 0x2c, 0xb8, 0xd0, 0xcd, 0x4a, 0x03, 0xa4, 0x61, 0x97, 0xe7, - 0xfa, 0xcd, 0x83, 0x8e, 0x62, 0xc7, 0x47, 0xd3, 0x57, 0xd3, 0x04, - 0x51, 0x54, 0xc1, 0x79, 0x89, 0x0a, 0x87, 0xfd, 0x18, 0xd1, 0x35, - 0xdc, 0x9a, 0xc8, 0x28, 0x9d, 0x4b, 0x14, 0x87, 0x2b, 0x83, 0xf3, - 0x82, 0x8b, 0x03, 0x23, 0x6a, 0x27, 0xc0, 0xc0, 0x82, 0x51, 0xd3, - 0xc9, 0x95, 0x3c, 0x88, 0x8d, 0x63, 0x54, 0x7f, 0x13, 0xcb, 0xbc, - 0xac, 0xa7, 0xe4, 0x7a, 0xe0, 0xc6, 0xfa, 0x70, 0x2b, 0x8c, 0x3f, - 0x6c, 0x49, 0xef, 0x64, 0x91, 0xc4, 0x69, 0xc1, 0xf2, 0x4a, 0x5a, - 0x44, 0x40, 0x1f, 0x6a, 0x07, 0x70, 0x3d, 0xc7, 0xf2, 0x44, 0x30, - 0xae, 0x38, 0xcc, 0x76, 0xc2, 0x4b, 0xfb, 0xd8, 0xa1, 0x2f, 0x34, - 0xcf, 0x44, 0x7c, 0xc5, 0xe2, 0x74, 0x61, 0x98, 0xb0, 0x70, 0x11, - 0x00, 0xe2, 0x32, 0xc7, 0x1d, 0x0f, 0x96, 0x7c, 0x4c, 0xe3, 0x0e, - 0x51, 0xc7, 0x81, 0x0c, 0xe2, 0xe8, 0x79, 0x89, 0x36, 0x52, 0xa2, - 0xef, 0x29, 0x0e, 0xa6, 0x26, 0x26, 0x57, 0xe2, 0xc7, 0x5f, 0x9d, - 0x9c, 0x48, 0x6d, 0x01, 0x02, 0x5b, 0x4f, 0x94, 0x22, 0x80, 0xd7, - 0xb3, 0x74, 0x0d, 0xcb, 0xd1, 0x70, 0x5e, 0xbb, 0x48, 0x97, 0xe5, - 0xc1, 0x07, 0x81, 0xcf, 0x04, 0xe1, 0xfc, 0x6b, 0x60, 0xf3, 0x71, - 0xb8, 0xe0, 0xfd, 0x16, 0xd1, 0x7b, 0x44, 0xf9, 0x42, 0x71, 0xb8, - 0x96, 0x46, 0x4e, 0x11, 0x6c, 0x50, 0x97, 0x3c, 0x02, 0x3f, 0x66, - 0x5b, 0xc9, 0xf5, 0xe2, 0x81, 0x7c, 0x42, 0xd9, 0x95, 0xe6, 0x43, - 0x09, 0xc5, 0x65, 0x24, 0xc9, 0x76, 0x43, 0x78, 0xc0, 0x1e, 0xb1, - 0x4b, 0x6e, 0xba, 0x2f, 0xa6, 0x00, 0x6c, 0xdf, 0xf1, 0xd0, 0x5e, - 0x35, 0x8e, 0xb9, 0x05, 0x52, 0x0d, 0xcd, 0xf6, 0x36, 0xab, 0x61, - 0x2e, 0xb2, 0x69, 0xfb, 0x1c, 0x1f, 0x05, 0xd0, 0x9a, 0xf2, 0xb7, - 0xef, 0xa0, 0xfc, 0x2d, 0x48, 0x79, 0x60, 0x96, 0x5b, 0x46, 0x5b, - 0x95, 0xde, 0x39, 0x26, 0x29, 0xe3, 0xc3, 0x54, 0x9e, 0x6e, 0x61, - 0x8f, 0x39, 0x25, 0x4d, 0x93, 0x21, 0x1b, 0x92, 0x2c, 0xca, 0xba, - 0x0b, 0x81, 0x22, 0x54, 0x1c, 0x5e, 0xe8, 0x81, 0x7a, 0xa4, 0x9a, - 0x1c, 0x96, 0x68, 0xf8, 0xf1, 0x8b, 0xee, 0xe3, 0x1a, 0x57, 0xc8, - 0xd9, 0x90, 0xe3, 0xb4, 0xe6, 0x68, 0x89, 0xab, 0x33, 0xd8, 0xd5, - 0xb8, 0x03, 0x0d, 0x38, 0x50, 0xcf, 0x26, 0x13, 0x50, 0x52, 0x6d, - 0x94, 0x1d, 0xc6, 0xa0, 0xd6, 0xb9, 0x7a, 0xb6, 0xe8, 0x4a, 0xde, - 0xd9, 0xa6, 0x2b, 0x2d, 0x89, 0xfb, 0x2c, 0x1c, 0xd3, 0x73, 0x20, - 0xf2, 0xc7, 0xe7, 0x2a, 0x8d, 0x94, 0xff, 0xc8, 0x1f, 0x4d, 0xc0, - 0x97, 0x30, 0x63, 0x88, 0x17, 0x92, 0xce, 0x66, 0x3d, 0xc6, 0x1c, - 0xe1, 0x3b, 0x82, 0xd7, 0x8c, 0xd9, 0x2a, 0x24, 0xc0, 0x9e, 0xd4, - 0x80, 0x2b, 0x9c, 0x49, 0x2f, 0x04, 0x3b, 0x2c, 0x78, 0x46, 0xef, - 0xb1, 0xd0, 0xe9, 0x4e, 0xe8, 0xcd, 0x85, 0xea, 0xea, 0xed, 0xb9, - 0xe2, 0x04, 0x0c, 0x72, 0xa2, 0x0b, 0xb2, 0x0c, 0x45, 0x01, 0x5d, - 0xfc, 0x79, 0xfe, 0x2d, 0xe2, 0xd9, 0x4d, 0xf5, 0x4b, 0x96, 0xb3, - 0x5d, 0xed, 0xac, 0x7e, 0x78, 0x75, 0x79, 0x7d, 0x7e, 0x72, 0xe7, - 0x35, 0x4b, 0xac, 0x2e, 0x37, 0xbc, 0xa0, 0x99, 0xe3, 0x92, 0x7b, - 0xf7, 0x3b, 0x11, 0xaf, 0x9c, 0x60, 0x99, 0xec, 0x0d, 0x8c, 0xaf, - 0x41, 0x2f, 0x78, 0x3d, 0x9e, 0xb1, 0x5d, 0xe9, 0x66, 0xb8, 0x1d, - 0xbf, 0x70, 0x8d, 0x4b, 0x15, 0x57, 0x0e, 0xb3, 0xf3, 0xbb, 0xcb, - 0x8b, 0x43, 0x07, 0xa3, 0xa9, 0xae, 0xb8, 0x4e, 0xbf, 0x71, 0x22, - 0xc2, 0x6f, 0xf7, 0xa4, 0x6e, 0x6b, 0xef, 0x3f, 0xdb, 0x86, 0xe1, - 0x85, 0x26, 0x73, 0x7a, 0xfe, 0xfe, 0xf2, 0xfa, 0xd0, 0x5f, 0xaa, - 0xe4, 0xdb, 0x6b, 0xe1, 0x52, 0xca, 0xe6, 0x30, 0xb0, 0x8c, 0x68, - 0x08, 0xcc, 0xc8, 0x9d, 0xf4, 0x9b, 0xbd, 0x65, 0xac, 0xa8, 0x9a, - 0xae, 0x08, 0x9a, 0x38, 0x6e, 0xa9, 0xfb, 0xdc, 0x71, 0x31, 0x7d, - 0x80, 0x66, 0xa1, 0x91, 0x62, 0xd0, 0x8a, 0xb9, 0xbd, 0x3a, 0xe9, - 0xf3, 0xa9, 0xf9, 0x10, 0x9d, 0x23, 0x72, 0xaa, 0x32, 0x4a, 0x3f, - 0x9d, 0x7b, 0x4f, 0x49, 0x5b, 0xc7, 0xab, 0xf9, 0x11, 0xc5, 0xe7, - 0xb8, 0xda, 0xd3, 0x29, 0x3d, 0xe3, 0x75, 0xb9, 0x53, 0x47, 0x26, - 0x4b, 0x48, 0xa7, 0x82, 0x0c, 0xd7, 0xe2, 0x97, 0x6b, 0xae, 0x98, - 0x99, 0xee, 0x2a, 0x06, 0x8a, 0x8a, 0x41, 0xb3, 0x2c, 0x11, 0xcb, - 0x28, 0xaa, 0x11, 0x64, 0x59, 0x3a, 0x82, 0x29, 0xd0, 0x2c, 0x20, - 0xde, 0x4b, 0x9e, 0x2a, 0x6f, 0xf9, 0xba, 0x30, 0x47, 0x19, 0x4f, - 0x1e, 0xfd, 0x32, 0x9f, 0x33, 0xa3, 0xa2, 0x8f, 0x8c, 0x05, 0xaa, - 0xd2, 0xe4, 0xaf, 0xec, 0x81, 0xf1, 0x14, 0x62, 0x3f, 0x4c, 0x85, - 0xe1, 0xfd, 0x38, 0x93, 0x94, 0x58, 0x64, 0xaf, 0xb5, 0x68, 0x72, - 0x97, 0x71, 0x89, 0x91, 0x03, 0xef, 0xa5, 0x39, 0xfb, 0xe0, 0xe3, - 0xf2, 0x28, 0x0b, 0x1f, 0x97, 0x47, 0x59, 0x05, 0x8d, 0xcb, 0xa3, - 0xac, 0x50, 0x3a, 0x35, 0x98, 0x4f, 0x7c, 0x03, 0xe9, 0x68, 0x8f, - 0x4a, 0xba, 0x1c, 0xf8, 0x20, 0x26, 0xee, 0x63, 0xc5, 0x28, 0x26, - 0xc9, 0x8a, 0x72, 0x18, 0x23, 0x12, 0x3a, 0x4b, 0xd8, 0x31, 0x8e, - 0xfd, 0x7b, 0x1c, 0x97, 0xd0, 0x59, 0xf8, 0xb8, 0x84, 0xce, 0xb2, - 0xd2, 0xb3, 0x3f, 0xc3, 0x4a, 0xe8, 0x14, 0x5d, 0xf1, 0x38, 0x28, - 0x4f, 0xd1, 0xe3, 0x1f, 0xa2, 0xbf, 0xd4, 0xe4, 0x7f, 0x9e, 0x95, - 0x25, 0xcd, 0x66, 0x20, 0xd2, 0x12, 0x57, 0x63, 0x7c, 0x63, 0x90, - 0xaf, 0x50, 0xe7, 0x6f, 0x74, 0xd3, 0x2f, 0xec, 0xb2, 0xaf, 0x6e, - 0xde, 0x85, 0xb8, 0x51, 0xa2, 0xe5, 0xf5, 0x1d, 0xd2, 0x8d, 0x7a, - 0x10, 0x5b, 0x22, 0x37, 0x0d, 0xc8, 0x20, 0x23, 0xa6, 0x92, 0xa1, - 0x2a, 0x29, 0x51, 0x94, 0x7a, 0x0c, 0x7c, 0x30, 0x13, 0xab, 0xef, - 0x29, 0xa1, 0x8f, 0x02, 0xad, 0x0a, 0x95, 0x69, 0x15, 0x78, 0xb1, - 0x68, 0x1b, 0xd4, 0xf5, 0xdc, 0x39, 0xf8, 0x8d, 0xf9, 0x1b, 0x7b, - 0x09, 0xad, 0x71, 0xd3, 0xe0, 0x8d, 0xf3, 0x96, 0xd9, 0x4c, 0x90, - 0xa1, 0x66, 0x85, 0x2b, 0xae, 0xc5, 0xa6, 0xb1, 0x06, 0x90, 0x60, - 0x48, 0x8c, 0x4b, 0xdb, 0x12, 0xd2, 0x91, 0xb4, 0x99, 0x98, 0xaf, - 0xd5, 0x90, 0x87, 0xec, 0x5c, 0xd7, 0xe9, 0xc7, 0x03, 0x79, 0x91, - 0x0d, 0x8e, 0xc7, 0xd8, 0xd0, 0xe8, 0x2c, 0x38, 0x38, 0x73, 0xb2, - 0x1d, 0x84, 0xb4, 0xba, 0x02, 0xf9, 0xa8, 0x3f, 0x30, 0x0b, 0x70, - 0xee, 0x0f, 0xcb, 0x02, 0xd3, 0x02, 0xcf, 0xbe, 0x47, 0x44, 0xff, - 0xc8, 0x79, 0xf3, 0x12, 0x80, 0x0e, 0x37, 0x48, 0x68, 0xf5, 0x1e, - 0xf7, 0xcd, 0xdc, 0xf6, 0x4c, 0xdc, 0xae, 0xe1, 0x06, 0x2f, 0x25, - 0x81, 0xcb, 0x6a, 0x41, 0x7e, 0x64, 0xea, 0x06, 0x37, 0x90, 0x4b, - 0xd2, 0xe9, 0xc2, 0x7f, 0x16, 0xa6, 0xf3, 0x92, 0x57, 0x4d, 0x47, - 0xaf, 0x78, 0x5d, 0x71, 0xf4, 0xfa, 0x25, 0x88, 0xcf, 0x06, 0x56, - 0x08, 0x16, 0xa5, 0xdb, 0x0f, 0x48, 0x36, 0xe2, 0x1c, 0xbd, 0x6a, - 0xed, 0x1e, 0xf9, 0x9d, 0xa7, 0x6e, 0xec, 0xd5, 0xab, 0x36, 0xf8, - 0x73, 0xf8, 0xe9, 0xe4, 0xea, 0xdf, 0xfe, 0xd4, 0x3c, 0x50, 0x6f, - 0x5c, 0xe1, 0x35, 0x66, 0xb2, 0x0e, 0x07, 0x09, 0xb9, 0x06, 0x2a, - 0x8a, 0x6b, 0x95, 0x7c, 0x44, 0x9b, 0xcf, 0x1b, 0x5e, 0x6f, 0x8a, - 0x56, 0xe7, 0x97, 0xd0, 0x6b, 0xff, 0xa8, 0xc6, 0xf3, 0x4d, 0x57, - 0xcd, 0x8e, 0xe3, 0x5b, 0xdb, 0xd2, 0x3e, 0xd6, 0xf9, 0x93, 0xe6, - 0xde, 0xd6, 0xd3, 0xe9, 0xc9, 0x86, 0x85, 0x25, 0xf6, 0x70, 0x8b, - 0xb7, 0xa8, 0x4c, 0xf8, 0x1d, 0x99, 0xfb, 0x73, 0x4d, 0xaf, 0x75, - 0x6d, 0x16, 0x1d, 0x47, 0xfd, 0xe0, 0x19, 0xef, 0x33, 0xc5, 0xab, - 0x41, 0xb4, 0xaf, 0x25, 0xee, 0xf4, 0xc3, 0x23, 0x47, 0x46, 0xe1, - 0x9c, 0x16, 0x77, 0x04, 0xa7, 0x1a, 0x0e, 0x6b, 0xb8, 0xbd, 0x25, - 0x8d, 0xbc, 0x68, 0x63, 0x27, 0x68, 0x61, 0x20, 0xae, 0x2c, 0x30, - 0xe8, 0xf2, 0x95, 0xe1, 0x38, 0x1d, 0xee, 0x2e, 0x36, 0x84, 0x8e, - 0x51, 0xbc, 0xc7, 0xad, 0x08, 0x05, 0xba, 0xd6, 0x71, 0x64, 0xd5, - 0x94, 0x7d, 0x9f, 0xd8, 0x17, 0xac, 0xa0, 0xf2, 0x28, 0xad, 0x6d, - 0xb5, 0x20, 0x64, 0x1c, 0xd4, 0x3a, 0xfd, 0x1c, 0xd9, 0x42, 0x09, - 0x88, 0x24, 0xd9, 0x09, 0x8f, 0xba, 0xa3, 0x40, 0x6b, 0x3b, 0xc6, - 0x49, 0x49, 0x72, 0xd8, 0x6b, 0x9a, 0xc7, 0xe2, 0x71, 0xba, 0x11, - 0x1e, 0x61, 0xc4, 0x4c, 0x80, 0x1c, 0xc6, 0x8f, 0x8f, 0x03, 0xa2, - 0xb5, 0xf9, 0xf4, 0xbe, 0x0c, 0x78, 0x6c, 0xea, 0xeb, 0x5f, 0xc6, - 0x31, 0xa6, 0xf7, 0xeb, 0x78, 0xca, 0x6c, 0xbf, 0xa7, 0xbc, 0xa5, - 0x64, 0x2b, 0xe2, 0xc9, 0x2e, 0x7e, 0xa8, 0x6d, 0x83, 0xce, 0x66, - 0x9e, 0x71, 0x1d, 0x76, 0xcd, 0x3c, 0x67, 0xf0, 0x9d, 0xd4, 0x37, - 0x08, 0xfb, 0x81, 0xef, 0x9e, 0x3a, 0xd9, 0x95, 0x6b, 0xad, 0x86, - 0xf8, 0x91, 0x0c, 0x35, 0x3d, 0xe3, 0x68, 0x7b, 0x1d, 0x49, 0xee, - 0x5e, 0xce, 0xdb, 0x13, 0x98, 0x2d, 0x66, 0xfe, 0x48, 0x3e, 0xcb, - 0x21, 0x4f, 0x48, 0x7f, 0x96, 0x5d, 0x58, 0x4c, 0xc2, 0x2e, 0x14, - 0x26, 0x61, 0x17, 0x99, 0xbc, 0x31, 0x36, 0xae, 0x6e, 0x12, 0x7c, - 0x80, 0x50, 0xc1, 0xa2, 0xd5, 0xa6, 0xe6, 0x66, 0x7c, 0xf1, 0x5a, - 0xac, 0x6f, 0xb2, 0xe3, 0x30, 0x76, 0xdd, 0x36, 0xec, 0x5c, 0xf0, - 0x25, 0xc6, 0xe4, 0x1a, 0xdb, 0x67, 0x6c, 0x05, 0xeb, 0x7e, 0x4b, - 0x54, 0x1e, 0x4d, 0xd8, 0x5d, 0xd5, 0xeb, 0x55, 0xa3, 0xfa, 0xe3, - 0x25, 0x22, 0x6b, 0xc4, 0xe8, 0x2e, 0x78, 0x70, 0xb3, 0xee, 0x6e, - 0x57, 0xd0, 0x9a, 0xfb, 0x73, 0x3f, 0xd9, 0x18, 0x8f, 0xa6, 0x69, - 0x7d, 0xc7, 0x18, 0x75, 0x8a, 0x03, 0xaf, 0x98, 0xac, 0x50, 0x44, - 0xfc, 0x13, 0x77, 0xd0, 0xac, 0x7f, 0x4b, 0x01, 0x2f, 0xc4, 0x35, - 0xae, 0xfd, 0x40, 0x5c, 0xb9, 0x14, 0x53, 0x38, 0x97, 0x60, 0x14, - 0x57, 0x53, 0xcc, 0xcf, 0x12, 0xb3, 0x05, 0x54, 0x6c, 0x2e, 0xd8, - 0x90, 0x96, 0xe6, 0xd6, 0x2f, 0x24, 0x67, 0x82, 0xbc, 0x26, 0x63, - 0xbc, 0x4a, 0xd5, 0x6e, 0xc4, 0xcf, 0x44, 0xb2, 0x7a, 0x85, 0x68, - 0xdf, 0x10, 0xfa, 0x11, 0x61, 0x12, 0xc2, 0x3f, 0xc6, 0x34, 0x7f, - 0xfc, 0x88, 0xbe, 0x73, 0x34, 0xce, 0x4c, 0xbd, 0x0b, 0xc4, 0xbf, - 0xc4, 0x64, 0x3d, 0xab, 0xc9, 0xdf, 0x92, 0x77, 0x28, 0xd2, 0x73, - 0x04, 0xd7, 0x9f, 0x70, 0xc1, 0xec, 0x3d, 0x52, 0x5e, 0x35, 0xbd, - 0x7c, 0x7d, 0xfc, 0xfa, 0xed, 0xab, 0xc7, 0xca, 0x54, 0xf2, 0x96, - 0x71, 0x6d, 0xf6, 0x9a, 0x85, 0x47, 0xaf, 0xdf, 0xbc, 0x7c, 0xf1, - 0xf6, 0x4d, 0x74, 0x0f, 0x8f, 0x31, 0xe7, 0x8f, 0x12, 0x8f, 0xa4, - 0x43, 0xa1, 0x17, 0x52, 0x09, 0xd1, 0x0f, 0xe4, 0x43, 0xd9, 0x57, - 0x79, 0x71, 0x37, 0x70, 0x63, 0xd8, 0x99, 0x62, 0x10, 0x9c, 0xc7, - 0xae, 0x5a, 0x82, 0x6e, 0x94, 0xfc, 0x75, 0x85, 0xf3, 0x95, 0x1c, - 0x89, 0x78, 0x7d, 0x2e, 0x51, 0xb9, 0x04, 0xd6, 0xf8, 0xd0, 0xcd, - 0x74, 0xa8, 0x9e, 0xf9, 0x04, 0xdb, 0x81, 0xda, 0x61, 0x2c, 0xec, - 0x10, 0x2c, 0xd2, 0x63, 0xd4, 0x0e, 0xa8, 0x44, 0xd5, 0x52, 0x19, - 0x51, 0xa2, 0x6f, 0x2c, 0xfc, 0xe3, 0xf9, 0x96, 0xeb, 0x8a, 0xc9, - 0x21, 0xb6, 0xc7, 0x2e, 0x2f, 0xb4, 0xf6, 0xde, 0xd1, 0x9a, 0x9a, - 0x3b, 0x5a, 0xc3, 0x2a, 0x79, 0x36, 0xbc, 0xae, 0x1d, 0x8e, 0x27, - 0xd3, 0xc5, 0x30, 0x8d, 0x8a, 0x6a, 0x92, 0x74, 0xe3, 0xd8, 0x70, - 0xa6, 0xc5, 0x69, 0xb9, 0x83, 0xd8, 0xd8, 0xcd, 0x95, 0x69, 0xaf, - 0xfc, 0x90, 0x4b, 0xf6, 0x39, 0xe7, 0xf9, 0x4a, 0xdc, 0x2f, 0x9a, - 0xeb, 0x86, 0xbb, 0xbc, 0x54, 0x97, 0xcf, 0x78, 0x70, 0x0e, 0x2d, - 0xa4, 0xdd, 0x97, 0x9b, 0xcb, 0xa5, 0xab, 0xbf, 0xfe, 0x65, 0xf3, - 0x58, 0xd3, 0x2c, 0x74, 0x81, 0x7c, 0x5c, 0x4b, 0x0c, 0x80, 0x90, - 0x97, 0x75, 0xb7, 0x13, 0xce, 0xe5, 0xb4, 0xad, 0x98, 0x1c, 0x6c, - 0x7c, 0x0b, 0x2b, 0xb6, 0x16, 0xf3, 0xf2, 0xc1, 0x19, 0x69, 0xf3, - 0xd5, 0xbe, 0x50, 0x64, 0x24, 0x19, 0xce, 0x88, 0x95, 0x33, 0x59, - 0x61, 0xa6, 0xba, 0x33, 0xfb, 0x02, 0x01, 0x07, 0xee, 0xaf, 0x53, - 0xa7, 0x12, 0x37, 0xd3, 0x63, 0x8a, 0x7d, 0x1b, 0x8f, 0xef, 0xdb, - 0x7c, 0x7e, 0xb3, 0x41, 0x34, 0x26, 0x15, 0x26, 0x44, 0xe0, 0x67, - 0xca, 0x83, 0xe3, 0x13, 0xbc, 0x04, 0x0c, 0xc6, 0xdd, 0x15, 0x06, - 0xa3, 0xaf, 0x5f, 0x83, 0x7e, 0x69, 0x63, 0x0e, 0x66, 0xe2, 0x0a, - 0x36, 0xf0, 0xef, 0x18, 0x07, 0x2f, 0x19, 0x77, 0x57, 0xba, 0xdd, - 0xd3, 0x6c, 0x17, 0x98, 0xc4, 0x4e, 0xb6, 0xe6, 0x2a, 0x74, 0xcd, - 0x22, 0x74, 0xf6, 0xba, 0x65, 0xe4, 0x1b, 0x4e, 0xf7, 0x6b, 0xd4, - 0x32, 0xae, 0x77, 0xe8, 0x6d, 0x3e, 0x3c, 0xe2, 0x00, 0xfe, 0x45, - 0xe8, 0x71, 0x6f, 0xb8, 0x97, 0xa1, 0x23, 0xd3, 0x91, 0x7b, 0x8c, - 0xbe, 0x6a, 0xff, 0x1a, 0x6d, 0xfa, 0xc6, 0xdb, 0xbe, 0x4e, 0x37, - 0x4f, 0x32, 0x72, 0xb3, 0x10, 0xf4, 0x24, 0x7f, 0x3a, 0xe6, 0x27, - 0xb2, 0xb9, 0x3f, 0xdb, 0x75, 0xe0, 0xaa, 0x4c, 0x34, 0xa3, 0xeb, - 0xdf, 0x97, 0x19, 0x21, 0x66, 0x53, 0x97, 0xba, 0xfa, 0x0f, 0x88, - 0x2c, 0x33, 0x71, 0x71, 0xf0, 0x2b, 0x55, 0xea, 0xf7, 0x76, 0x22, - 0x65, 0xa7, 0x10, 0x46, 0xd8, 0x9b, 0x39, 0x59, 0x65, 0xa0, 0x23, - 0x7c, 0x6f, 0x9b, 0xca, 0xfb, 0xca, 0x7f, 0x6f, 0xea, 0x94, 0xee, - 0xe8, 0x45, 0xdb, 0x79, 0xf6, 0xf7, 0x04, 0x40, 0xb4, 0xf7, 0xa6, - 0x76, 0xb5, 0xb7, 0xda, 0xb6, 0xa5, 0xf6, 0x3e, 0xff, 0xd4, 0xdb, - 0xf1, 0x27, 0x42, 0xcb, 0xc2, 0x4e, 0x15, 0x16, 0xfd, 0x9a, 0x16, - 0x8b, 0x9f, 0xbb, 0x19, 0x84, 0x55, 0x07, 0xc3, 0x8c, 0x9f, 0x44, - 0xae, 0x03, 0x4d, 0xec, 0x7f, 0x09, 0x6f, 0xb6, 0x7d -}; - -const int standard_nodes_data_len = 2847; - diff --git a/pandatool/src/vrml/standard_nodes.cxx b/pandatool/src/vrml/standard_nodes.cxx deleted file mode 100644 index 221efe14..00000000 --- a/pandatool/src/vrml/standard_nodes.cxx +++ /dev/null @@ -1,47 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file standard_nodes.cxx - * @author drose - * @date 2004-10-01 - */ - -#include "standard_nodes.h" - -// The binary data included here was generated from standardNodes.wrl (in this -// directory) file via the utility program bin2c (defined in pandatool). It -// contains the set of VRML definitions that must be loaded before any -// standard VRML file can be properly interpreted. - -#ifndef CPPPARSER - -#if defined(HAVE_ZLIB) - -// If we have zlib available, we can store this file compressed, which is much -// smaller. - -// Regenerate this file with: - -// pcompress standardNodes.wrl standardNodes.wrl.pz bin2c -n -// standard_nodes_data -o standardNodes.wrl.pz.c standardNodes.wrl.pz - -#include "standardNodes.wrl.pz.c" - -#else // HAVE_ZLIB - -// If we don't have zlib, just include the whole uncompressed file. - -// Regenerate this file with: - -// bin2c -n standard_nodes_data -o standardNodes.wrl.c standardNodes.wrl - -#include "standardNodes.wrl.c" - -#endif // HAVE_ZLIB - -#endif // CPPPARSER diff --git a/pandatool/src/vrml/standard_nodes.h b/pandatool/src/vrml/standard_nodes.h deleted file mode 100644 index e97101d6..00000000 --- a/pandatool/src/vrml/standard_nodes.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file standard_nodes.h - * @author drose - * @date 2004-10-01 - */ - -#ifndef STANDARD_NODES_H -#define STANDARD_NODES_H - -#include "pandatoolbase.h" - -#ifndef CPPPARSER - -extern const unsigned char standard_nodes_data[]; -extern const int standard_nodes_data_len; - -#endif // CPPPARSER - -#endif diff --git a/pandatool/src/vrml/vrmlLexer.cxx.prebuilt b/pandatool/src/vrml/vrmlLexer.cxx.prebuilt deleted file mode 100644 index 8022d21f..00000000 --- a/pandatool/src/vrml/vrmlLexer.cxx.prebuilt +++ /dev/null @@ -1,4766 +0,0 @@ -#line 2 "lex.yy.c" - -#line 4 "lex.yy.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define yy_create_buffer vrmlyy_create_buffer -#define yy_delete_buffer vrmlyy_delete_buffer -#define yy_flex_debug vrmlyy_flex_debug -#define yy_init_buffer vrmlyy_init_buffer -#define yy_flush_buffer vrmlyy_flush_buffer -#define yy_load_buffer_state vrmlyy_load_buffer_state -#define yy_switch_to_buffer vrmlyy_switch_to_buffer -#define yyin vrmlyyin -#define yyleng vrmlyyleng -#define yylex vrmlyylex -#define yylineno vrmlyylineno -#define yyout vrmlyyout -#define yyrestart vrmlyyrestart -#define yytext vrmlyytext -#define yywrap vrmlyywrap -#define yyalloc vrmlyyalloc -#define yyrealloc vrmlyyrealloc -#define yyfree vrmlyyfree - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE vrmlyyrestart(vrmlyyin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#define YY_BUF_SIZE 16384 -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -extern int vrmlyyleng; - -extern FILE *vrmlyyin, *vrmlyyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up vrmlyytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up vrmlyytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via vrmlyyrestart()), so that the user can continue scanning by - * just pointing vrmlyyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when vrmlyytext is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int vrmlyyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow vrmlyywrap()'s to do buffer switches - * instead of setting up a fresh vrmlyyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void vrmlyyrestart (FILE *input_file ); -void vrmlyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE vrmlyy_create_buffer (FILE *file,int size ); -void vrmlyy_delete_buffer (YY_BUFFER_STATE b ); -void vrmlyy_flush_buffer (YY_BUFFER_STATE b ); -void vrmlyypush_buffer_state (YY_BUFFER_STATE new_buffer ); -void vrmlyypop_buffer_state (void ); - -static void vrmlyyensure_buffer_stack (void ); -static void vrmlyy_load_buffer_state (void ); -static void vrmlyy_init_buffer (YY_BUFFER_STATE b,FILE *file ); - -#define YY_FLUSH_BUFFER vrmlyy_flush_buffer(YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE vrmlyy_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE vrmlyy_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE vrmlyy_scan_bytes (yyconst char *bytes,int len ); - -void *vrmlyyalloc (yy_size_t ); -void *vrmlyyrealloc (void *,yy_size_t ); -void vrmlyyfree (void * ); - -#define yy_new_buffer vrmlyy_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - vrmlyyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - vrmlyy_create_buffer(vrmlyyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - vrmlyyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - vrmlyy_create_buffer(vrmlyyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -typedef unsigned char YY_CHAR; - -FILE *vrmlyyin = (FILE *) 0, *vrmlyyout = (FILE *) 0; - -typedef int yy_state_type; - -extern int vrmlyylineno; - -int vrmlyylineno = 1; - -extern char *vrmlyytext; -#define yytext_ptr vrmlyytext - -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up vrmlyytext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - vrmlyyleng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; - -#define YY_NUM_RULES 48 -#define YY_END_OF_BUFFER 49 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[977] = - { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 47, 45, 46, 45, 14, - 45, 15, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 47, 47, 47, 47, 47, 47, 47, 47, - 24, 47, 47, 47, 47, 22, 22, 47, 47, 47, - 37, 35, 37, 37, 47, 47, 34, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 18, 19, 47, - - 47, 25, 47, 23, 23, 47, 47, 47, 38, 36, - 38, 38, 47, 47, 47, 47, 47, 47, 40, 40, - 41, 40, 40, 42, 47, 44, 44, 45, 45, 46, - 45, 45, 45, 14, 15, 14, 14, 7, 14, 14, - 14, 6, 14, 14, 14, 14, 0, 16, 0, 0, - 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, - 0, 0, 0, 22, 22, 0, 0, 0, 0, 0, - 0, 37, 37, 37, 16, 0, 34, 34, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 17, 0, 25, - - 25, 0, 23, 23, 0, 0, 0, 0, 0, 0, - 38, 38, 38, 17, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, - 40, 39, 44, 44, 45, 4, 14, 14, 14, 14, - 5, 14, 14, 14, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, - 43, 43, 0, 0, 0, 0, 43, 43, 0, 22, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 34, 0, 0, 26, 0, 0, 0, 0, - 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 25, 23, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 27, 0, 0, 0, 0, 0, 27, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 44, 45, 14, 9, 14, 14, 14, 14, - 14, 0, 20, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 43, 43, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 26, 0, 26, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 27, 0, 27, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 45, 14, 2, - 8, 14, 14, 12, 21, 0, 0, 32, 0, 0, - 0, 0, 0, 32, 0, 0, 0, 0, 32, 0, - 0, 0, 32, 0, 0, 0, 0, 0, 32, 0, - 0, 0, 43, 43, 43, 43, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 26, 0, 0, 26, 0, 0, - - 28, 0, 0, 0, 0, 0, 28, 0, 0, 0, - 0, 28, 0, 0, 0, 28, 0, 0, 0, 0, - 0, 28, 0, 0, 0, 0, 0, 33, 0, 0, - 0, 0, 0, 33, 0, 0, 0, 0, 33, 0, - 0, 0, 33, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 27, 0, 0, 27, 0, 0, 29, 0, 0, 0, - 0, 0, 29, 0, 0, 0, 0, 29, 0, 0, - - 0, 29, 0, 0, 0, 0, 0, 29, 0, 0, - 0, 45, 14, 14, 14, 14, 32, 0, 32, 0, - 32, 0, 32, 0, 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 28, 0, 28, - 0, 28, 0, 28, 0, 28, 0, 33, 0, 33, - 0, 33, 0, 33, 0, 33, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, - 29, 0, 29, 0, 29, 0, 29, 0, 45, 14, - - 10, 14, 14, 0, 32, 0, 0, 32, 0, 0, - 32, 0, 32, 0, 0, 32, 0, 0, 30, 0, - 0, 0, 0, 0, 30, 0, 0, 0, 0, 30, - 0, 0, 30, 0, 0, 0, 0, 0, 30, 0, - 0, 0, 0, 0, 30, 0, 0, 0, 30, 0, - 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, - 0, 0, 30, 0, 0, 0, 0, 28, 0, 0, - 28, 0, 0, 28, 0, 28, 0, 0, 28, 0, - 33, 0, 0, 33, 0, 0, 33, 0, 33, 0, - 0, 33, 0, 0, 31, 0, 0, 0, 0, 0, - - 31, 0, 0, 0, 0, 31, 0, 0, 31, 0, - 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, - 31, 0, 0, 0, 31, 0, 0, 0, 0, 0, - 31, 0, 0, 0, 0, 0, 0, 0, 31, 0, - 0, 0, 0, 29, 0, 0, 29, 0, 0, 29, - 0, 29, 0, 0, 29, 45, 14, 11, 14, 30, - 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, - 0, 30, 0, 30, 0, 30, 0, 31, 0, 31, - 0, 31, 0, 31, 0, 31, 0, 31, 0, 31, - 0, 31, 0, 31, 0, 45, 14, 14, 0, 30, - - 0, 0, 30, 0, 0, 30, 0, 30, 0, 0, - 30, 0, 0, 30, 0, 30, 0, 0, 30, 0, - 0, 30, 0, 31, 0, 0, 31, 0, 0, 31, - 0, 31, 0, 0, 31, 0, 0, 31, 0, 31, - 0, 0, 31, 0, 0, 31, 45, 14, 14, 45, - 3, 14, 45, 13, 45, 45, 45, 45, 1, 1, - 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0 - } ; - -static yyconst flex_int32_t yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 5, 6, 7, 8, 6, 6, 6, 1, 6, - 6, 6, 9, 2, 10, 11, 6, 12, 13, 14, - 13, 13, 13, 13, 13, 15, 13, 6, 6, 6, - 6, 6, 6, 6, 16, 17, 17, 18, 19, 20, - 6, 6, 21, 6, 6, 22, 23, 24, 25, 26, - 6, 27, 28, 29, 30, 31, 6, 32, 6, 6, - 33, 34, 35, 6, 6, 6, 17, 17, 17, 36, - - 37, 38, 6, 6, 39, 6, 6, 40, 6, 41, - 42, 43, 6, 6, 44, 45, 46, 47, 6, 48, - 6, 6, 1, 6, 1, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6 - } ; - -static yyconst flex_int32_t yy_meta[49] = - { 0, - 1, 2, 3, 2, 2, 4, 5, 6, 1, 4, - 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 8, 1, 8, 7, 7, 7, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4 - } ; - -static yyconst flex_int16_t yy_base[1120] = - { 0, - 0, 7, 15, 0, 62, 90, 118, 0, 61, 74, - 89, 102, 130, 136, 142, 148, 162, 169, 174, 181, - 187, 193, 199, 205, 211, 237, 263, 289, 315, 341, - 367, 393, 427, 461, 487, 513, 539, 565, 226, 233, - 261, 278, 328, 354, 1038, 8632, 251, 0, 231, 0, - 1019, 0, 1006, 992, 985, 981, 983, 974, 972, 968, - 21, 946, 967, 954, 944, 66, 93, 599, 123, 166, - 278, 293, 635, 77, 304, 377, 319, 346, 332, 682, - 0, 8632, 391, 941, 372, 358, 404, 425, 398, 718, - 431, 437, 754, 442, 458, 790, 940, 8632, 8632, 463, - - 471, 476, 491, 497, 502, 524, 518, 826, 0, 8632, - 554, 929, 529, 551, 862, 556, 569, 898, 0, 586, - 8632, 6, 947, 8632, 607, 612, 616, 591, 935, 0, - 933, 932, 234, 0, 0, 914, 900, 0, 892, 883, - 877, 0, 886, 867, 855, 847, 857, 8632, 848, 620, - 0, 640, 934, 948, 649, 656, 661, 690, 698, 0, - 726, 962, 740, 702, 0, 737, 0, 763, 976, 990, - 770, 0, 806, 813, 0, 774, 835, 843, 873, 810, - 0, 878, 1004, 1018, 906, 882, 0, 911, 1032, 1046, - 918, 1050, 0, 1055, 1069, 1083, 1090, 8632, 1094, 1099, - - 1107, 1115, 1119, 0, 1125, 0, 1134, 1148, 1162, 1169, - 0, 1183, 1190, 0, 1187, 1224, 1192, 1260, 1274, 1199, - 1207, 1288, 1233, 1324, 1338, 1240, 0, 1304, 89, 280, - 306, 8632, 1244, 0, 271, 0, 852, 847, 839, 830, - 0, 811, 794, 792, 791, 797, 1302, 1306, 1352, 1388, - 1402, 0, 0, 1360, 1416, 1364, 1452, 1368, 1372, 1413, - 1426, 1417, 1473, 1487, 0, 0, 195, 0, 1440, 0, - 1457, 1437, 1501, 1537, 1551, 0, 0, 1509, 1565, 1513, - 1601, 1517, 1521, 1563, 1567, 1574, 1615, 0, 0, 0, - 1582, 442, 1586, 1629, 1634, 1638, 1652, 1688, 0, 0, - - 0, 1660, 1675, 1672, 1711, 1693, 1715, 1729, 1765, 0, - 0, 0, 1737, 1752, 1749, 1788, 1769, 1773, 0, 1793, - 1797, 1811, 1847, 0, 0, 0, 1819, 1834, 1831, 1870, - 1852, 1874, 1879, 1915, 0, 0, 0, 1887, 536, 1891, - 1929, 1896, 1900, 1943, 1979, 0, 0, 0, 1951, 1966, - 1963, 2002, 0, 160, 785, 0, 782, 787, 755, 755, - 760, 728, 8632, 1984, 2016, 2030, 2037, 2051, 2079, 2115, - 2129, 2059, 0, 2133, 2064, 2170, 2184, 2071, 2198, 2226, - 2262, 2276, 2290, 2087, 2095, 2326, 2362, 2376, 2412, 2426, - 2145, 2440, 2476, 2490, 2504, 2518, 2532, 2568, 2582, 2152, - - 2596, 2632, 2646, 2660, 2674, 2688, 2724, 2738, 2206, 2752, - 2788, 2802, 2816, 2830, 2210, 2218, 2844, 2880, 2894, 2930, - 2944, 2239, 2958, 2994, 3008, 3022, 3036, 119, 694, 0, - 0, 376, 652, 0, 8632, 2100, 2243, 2305, 3050, 3064, - 0, 0, 2247, 578, 2298, 3078, 3092, 3106, 3120, 3156, - 2335, 2339, 3170, 3206, 0, 0, 0, 2343, 586, 2347, - 2384, 3185, 0, 3222, 289, 560, 2389, 2393, 3269, 3305, - 3319, 0, 0, 2397, 2867, 2448, 3333, 3347, 3361, 3375, - 3411, 2453, 2457, 3425, 3461, 0, 0, 0, 2461, 3143, - 2540, 2544, 3475, 2548, 2552, 3511, 3525, 662, 2605, 2609, - - 3530, 3566, 3580, 0, 0, 2613, 663, 2617, 3594, 3608, - 3622, 3636, 3672, 2697, 2701, 3686, 3722, 0, 0, 0, - 2705, 669, 2709, 2760, 3701, 2765, 2769, 3728, 3764, 3778, - 0, 0, 2773, 709, 2852, 3792, 3806, 3820, 3834, 3870, - 2865, 2902, 3884, 3920, 0, 0, 0, 2906, 716, 2910, - 2914, 3899, 2967, 2971, 3935, 3971, 3985, 0, 0, 2975, - 3398, 2979, 3999, 4013, 4027, 4041, 4077, 3129, 3140, 4091, - 4127, 0, 0, 0, 3178, 3448, 3277, 3281, 4141, 3285, - 3289, 4177, 4191, 735, 3384, 3395, 4196, 4232, 4246, 0, - 0, 3433, 744, 3445, 4260, 4274, 4288, 4302, 4338, 3484, - - 3488, 4352, 4388, 0, 0, 0, 3492, 807, 3496, 3538, - 4367, 416, 653, 601, 560, 549, 3644, 3545, 4403, 4439, - 4453, 4489, 4503, 3652, 4539, 4575, 4589, 4625, 4639, 3694, - 4653, 4689, 4703, 4717, 4731, 4745, 4781, 4795, 4809, 4823, - 4837, 4873, 3736, 4887, 4923, 4937, 4951, 3842, 3743, 4965, - 5001, 5015, 5051, 5065, 3850, 5101, 5137, 3943, 3892, 5151, - 5187, 5201, 5237, 5251, 3951, 5287, 5323, 5337, 5373, 5387, - 4049, 5401, 5437, 5451, 5465, 5479, 5493, 5529, 5543, 5557, - 5571, 5585, 5621, 4056, 5635, 5671, 5685, 5699, 4099, 4107, - 5713, 5749, 5763, 5799, 5813, 4149, 5849, 5885, 413, 530, - - 0, 502, 501, 3549, 3656, 5899, 5913, 814, 5927, 5941, - 4325, 3747, 5955, 5969, 5983, 816, 3855, 3955, 4518, 5997, - 6011, 0, 0, 4060, 823, 4111, 6025, 6039, 6053, 6067, - 4154, 4158, 6103, 6139, 6153, 0, 0, 4162, 824, 4204, - 4208, 5080, 6167, 6181, 6195, 6231, 4213, 4217, 6245, 6281, - 0, 0, 0, 4310, 936, 4322, 4360, 5266, 4411, 6295, - 6309, 6323, 6337, 4415, 4419, 5828, 4423, 4461, 6373, 6387, - 1098, 6401, 6415, 4476, 4473, 6429, 6443, 6457, 1104, 4511, - 4547, 6471, 6485, 1149, 6499, 6513, 4562, 4559, 6527, 6541, - 6555, 1152, 4598, 4602, 6076, 6569, 6583, 0, 0, 4606, - - 1196, 4610, 6597, 6611, 6625, 6639, 4662, 4666, 6675, 6711, - 6725, 0, 0, 4670, 1205, 4674, 4753, 6648, 6739, 6753, - 6767, 6803, 4758, 4762, 6817, 6853, 0, 0, 0, 4766, - 1232, 4845, 4849, 6832, 4853, 6868, 6882, 6896, 6910, 4857, - 4895, 6919, 4899, 4903, 6955, 6969, 1261, 6983, 6997, 5038, - 4907, 7011, 7025, 7039, 1285, 246, 482, 0, 428, 5345, - 4973, 7053, 7089, 7103, 7139, 7153, 4980, 7189, 7225, 7239, - 7275, 7289, 5023, 7325, 7361, 7375, 7411, 5409, 5035, 5501, - 5073, 4985, 5109, 5114, 5121, 5593, 5159, 5164, 5171, 5210, - 5217, 5643, 5259, 5222, 5295, 633, 404, 385, 5299, 5303, - - 449, 471, 1701, 483, 509, 7425, 5307, 7461, 607, 647, - 1860, 656, 668, 7475, 5353, 7511, 682, 715, 1930, 751, - 761, 7525, 5357, 5417, 5421, 5509, 6084, 5513, 5601, 7168, - 5605, 7561, 5651, 5655, 6111, 5721, 5725, 7304, 5729, 5733, - 5771, 5775, 6203, 5779, 5783, 7434, 315, 395, 354, 263, - 0, 327, 601, 0, 726, 782, 1476, 1490, 5829, 5867, - 1604, 5872, 5877, 6127, 6221, 6261, 6268, 6355, 6273, 6360, - 6365, 6666, 6693, 6700, 6785, 8632, 7576, 7584, 7592, 7600, - 7608, 7616, 7621, 7625, 7632, 7640, 7648, 7655, 7663, 7671, - 7679, 7687, 7694, 328, 7701, 7709, 7717, 7725, 304, 7733, - - 7741, 7749, 7757, 7765, 7773, 238, 7781, 7786, 7793, 7801, - 7808, 168, 7815, 111, 7823, 7831, 83, 7839, 7847, 7855, - 7863, 7871, 7879, 7887, 7895, 7903, 7911, 7919, 7927, 7935, - 7943, 7951, 7959, 7967, 7972, 7979, 7987, 7995, 0, 8003, - 8011, 8019, 8027, 8035, 8043, 8051, 8059, 8067, 8075, 8083, - 8091, 8099, 8107, 8115, 8123, 8131, 8139, 8144, 8151, 8159, - 8167, 8175, 8183, 8191, 8199, 8207, 8215, 8223, 8231, 8239, - 8247, 8255, 8263, 8271, 8279, 8287, 8295, 8303, 8311, 8319, - 8327, 8335, 8343, 8348, 8355, 8363, 8371, 8379, 8387, 8395, - 8403, 8411, 8419, 8427, 8435, 8443, 8451, 8459, 8467, 8475, - - 8483, 8491, 8499, 8507, 8515, 8523, 8531, 8539, 8547, 8552, - 8559, 8567, 8575, 8583, 8591, 8599, 8607, 8615, 8623 - } ; - -static yyconst flex_int16_t yy_def[1120] = - { 0, - 977, 977, 976, 3, 977, 977, 977, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 978, 978, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 979, 979, 7, 7, 7, 7, 980, 980, - 980, 980, 7, 7, 976, 976, 976, 981, 982, 983, - 982, 984, 983, 983, 983, 983, 983, 983, 983, 983, - 983, 983, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 73, 976, 976, 976, 976, 976, 976, - 985, 976, 986, 985, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - - 976, 976, 976, 976, 976, 976, 976, 976, 987, 976, - 988, 987, 976, 976, 976, 976, 976, 976, 989, 989, - 976, 990, 989, 976, 976, 976, 976, 976, 982, 981, - 982, 982, 982, 983, 984, 983, 983, 983, 983, 983, - 983, 983, 983, 983, 983, 983, 976, 976, 976, 976, - 68, 68, 976, 991, 976, 976, 976, 976, 976, 74, - 74, 992, 993, 976, 994, 976, 80, 80, 976, 995, - 976, 985, 986, 986, 985, 976, 976, 976, 976, 976, - 90, 90, 976, 996, 976, 976, 93, 93, 976, 997, - 976, 976, 96, 96, 976, 998, 976, 976, 976, 976, - - 976, 976, 976, 999, 976, 108, 108, 976, 1000, 976, - 987, 1001, 1001, 987, 976, 976, 216, 976, 1002, 976, - 976, 976, 222, 976, 1003, 976, 1004, 1004, 1005, 1005, - 1005, 976, 976, 1006, 1007, 1008, 1008, 1008, 1008, 1008, - 1008, 1008, 1008, 1008, 976, 976, 976, 976, 976, 1009, - 1009, 251, 251, 251, 251, 976, 976, 976, 976, 976, - 976, 976, 1010, 1010, 264, 264, 264, 264, 1011, 1012, - 976, 976, 976, 1013, 1013, 275, 275, 275, 275, 976, - 976, 976, 976, 976, 976, 976, 996, 287, 287, 287, - 287, 287, 976, 976, 976, 976, 976, 997, 298, 298, - - 298, 298, 298, 976, 976, 976, 976, 976, 998, 309, - 309, 309, 309, 309, 976, 976, 976, 976, 1014, 976, - 976, 976, 1000, 323, 323, 323, 323, 323, 976, 976, - 976, 976, 976, 1002, 334, 334, 334, 334, 334, 976, - 976, 976, 976, 976, 1003, 345, 345, 345, 345, 345, - 976, 976, 1006, 1007, 1008, 1008, 1008, 1008, 1008, 1008, - 1008, 976, 976, 249, 976, 1015, 976, 251, 368, 976, - 1016, 251, 1017, 264, 273, 976, 1018, 976, 275, 379, - 976, 1019, 379, 976, 976, 1020, 1020, 976, 976, 1021, - 976, 1022, 1022, 976, 1023, 1022, 976, 976, 1024, 976, - - 1025, 1025, 976, 1026, 1025, 976, 976, 1027, 976, 1028, - 1028, 976, 1029, 1028, 976, 976, 1030, 1030, 976, 976, - 1031, 976, 1032, 1032, 976, 1033, 1032, 1034, 1035, 1035, - 1035, 1035, 1035, 1035, 976, 976, 976, 976, 1036, 1036, - 440, 440, 440, 440, 976, 976, 1037, 1037, 448, 1038, - 976, 976, 976, 1038, 454, 454, 454, 454, 454, 448, - 448, 449, 1039, 976, 464, 464, 976, 976, 976, 1040, - 1040, 471, 471, 471, 471, 976, 976, 1041, 1041, 479, - 1042, 976, 976, 976, 1042, 485, 485, 485, 485, 485, - 479, 479, 479, 976, 976, 1043, 1043, 497, 976, 976, - - 976, 1044, 1044, 503, 503, 503, 503, 976, 976, 1045, - 1045, 511, 1046, 976, 976, 976, 1046, 517, 517, 517, - 517, 517, 511, 511, 512, 976, 976, 976, 1047, 1047, - 530, 530, 530, 530, 976, 976, 1048, 1048, 538, 1049, - 976, 976, 976, 1049, 544, 544, 544, 544, 544, 538, - 538, 539, 976, 976, 976, 1050, 1050, 557, 557, 557, - 557, 976, 976, 1051, 1051, 565, 1052, 976, 976, 976, - 1052, 571, 571, 571, 571, 571, 565, 565, 565, 976, - 976, 1053, 1053, 583, 976, 976, 976, 1054, 1054, 589, - 589, 589, 589, 976, 976, 1055, 1055, 597, 1056, 976, - - 976, 976, 1056, 603, 603, 603, 603, 603, 597, 597, - 598, 1057, 1058, 1058, 1058, 1058, 976, 976, 1059, 1059, - 1060, 1060, 976, 976, 1061, 1061, 976, 976, 1062, 976, - 1063, 1063, 976, 1064, 1063, 1065, 1065, 976, 1066, 1065, - 976, 1064, 976, 1067, 1067, 1066, 1067, 976, 976, 1068, - 1068, 1069, 1069, 976, 976, 1070, 1070, 976, 976, 1071, - 1071, 1072, 1072, 976, 976, 1073, 1073, 976, 976, 1074, - 976, 1075, 1075, 976, 1076, 1075, 1077, 1077, 976, 1078, - 1077, 976, 1076, 976, 1079, 1079, 1078, 1079, 976, 976, - 1080, 1080, 1081, 1081, 976, 976, 1082, 1082, 1083, 1084, - - 1084, 1084, 1084, 976, 976, 1085, 1085, 707, 1086, 1086, - 710, 976, 976, 1087, 1087, 715, 976, 976, 976, 1088, - 1088, 721, 721, 721, 721, 976, 976, 1089, 1089, 729, - 976, 976, 976, 1090, 1090, 735, 735, 735, 735, 729, - 729, 730, 1091, 1091, 744, 1092, 976, 976, 976, 1092, - 750, 750, 750, 750, 750, 744, 744, 745, 976, 976, - 1093, 1093, 762, 762, 762, 763, 976, 976, 1094, 1094, - 770, 1095, 1095, 773, 976, 976, 1096, 1096, 778, 976, - 976, 1097, 1097, 783, 1098, 1098, 786, 976, 976, 1099, - 1099, 791, 976, 976, 976, 1100, 1100, 797, 797, 797, - - 797, 976, 976, 1101, 1101, 805, 976, 976, 976, 1102, - 1102, 811, 811, 811, 811, 805, 805, 806, 1103, 1103, - 820, 1104, 976, 976, 976, 1104, 826, 826, 826, 826, - 826, 820, 820, 821, 976, 976, 1105, 1105, 838, 838, - 838, 839, 976, 976, 1106, 1106, 846, 1107, 1107, 849, - 976, 976, 1108, 1108, 854, 1109, 1110, 1110, 1110, 976, - 976, 1111, 1111, 1112, 1112, 976, 976, 1113, 1113, 1114, - 1114, 976, 976, 1115, 1115, 1116, 1116, 976, 976, 797, - 797, 806, 805, 809, 976, 811, 811, 821, 820, 825, - 976, 826, 826, 839, 838, 1109, 1110, 1110, 976, 976, - - 863, 863, 863, 865, 865, 865, 976, 976, 869, 869, - 869, 871, 871, 871, 976, 976, 875, 875, 875, 877, - 877, 877, 976, 976, 797, 797, 797, 805, 805, 806, - 976, 976, 811, 811, 811, 820, 820, 821, 976, 836, - 826, 826, 826, 838, 838, 839, 1109, 1110, 1110, 1109, - 1110, 1110, 1109, 1110, 1109, 1109, 1117, 1117, 976, 1117, - 1117, 976, 976, 1118, 1117, 976, 1117, 1119, 1118, 1118, - 1118, 1119, 1119, 1119, 1119, 0, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976 - } ; - -static yyconst flex_int16_t yy_nxt[8681] = - { 0, - 976, 47, 48, 47, 47, 976, 463, 49, 47, 48, - 47, 47, 131, 231, 49, 46, 47, 48, 47, 47, - 50, 46, 51, 46, 46, 46, 52, 52, 52, 52, - 50, 50, 53, 54, 50, 55, 50, 50, 56, 50, - 57, 58, 50, 59, 60, 50, 50, 46, 46, 46, - 50, 61, 62, 50, 50, 50, 50, 50, 50, 50, - 50, 50, 50, 47, 48, 47, 47, 144, 145, 51, - 69, 70, 71, 71, 71, 71, 150, 151, 151, 151, - 151, 63, 64, 69, 70, 71, 71, 71, 71, 463, - 65, 47, 48, 47, 47, 131, 231, 51, 72, 46, - - 73, 74, 74, 74, 152, 152, 152, 152, 976, 63, - 64, 72, 46, 73, 74, 74, 74, 319, 65, 47, - 48, 47, 47, 612, 976, 51, 132, 66, 67, 68, - 68, 68, 68, 156, 157, 157, 157, 157, 64, 75, - 46, 76, 77, 77, 77, 75, 46, 76, 77, 77, - 77, 78, 79, 80, 80, 80, 80, 78, 79, 80, - 80, 80, 80, 47, 48, 47, 47, 132, 82, 83, - 47, 48, 47, 47, 270, 82, 83, 158, 158, 158, - 158, 428, 84, 85, 86, 87, 87, 87, 87, 84, - 85, 86, 87, 87, 87, 87, 88, 89, 90, 90, - - 90, 90, 88, 89, 90, 90, 90, 90, 91, 92, - 93, 93, 93, 93, 91, 92, 93, 93, 93, 93, - 94, 95, 96, 96, 96, 96, 374, 120, 48, 120, - 120, 97, 121, 122, 120, 48, 120, 120, 132, 121, - 122, 132, 374, 98, 353, 99, 94, 95, 96, 96, - 96, 96, 128, 132, 128, 128, 896, 97, 129, 123, - 235, 133, 120, 48, 120, 120, 123, 124, 122, 98, - 132, 99, 100, 101, 102, 102, 102, 102, 132, 120, - 48, 120, 120, 97, 124, 122, 131, 231, 156, 157, - 157, 157, 157, 354, 123, 98, 159, 99, 100, 101, - - 102, 102, 102, 102, 160, 160, 160, 160, 953, 97, - 319, 123, 131, 231, 159, 164, 164, 164, 164, 950, - 263, 98, 132, 99, 103, 46, 104, 105, 105, 105, - 164, 164, 164, 164, 270, 97, 263, 125, 46, 126, - 127, 127, 127, 168, 168, 168, 168, 98, 46, 99, - 103, 46, 104, 105, 105, 105, 166, 167, 167, 167, - 167, 97, 954, 125, 46, 126, 127, 127, 127, 178, - 178, 178, 178, 98, 46, 99, 106, 107, 108, 108, - 108, 108, 176, 177, 177, 177, 177, 97, 164, 164, - 164, 164, 131, 952, 131, 131, 614, 131, 174, 98, - - 615, 99, 106, 107, 108, 108, 108, 108, 165, 182, - 182, 182, 182, 97, 176, 177, 177, 177, 177, 951, - 132, 949, 179, 132, 165, 98, 856, 99, 47, 48, - 47, 47, 948, 110, 111, 180, 181, 181, 181, 181, - 179, 186, 187, 187, 187, 187, 699, 112, 188, 188, - 188, 188, 192, 193, 193, 193, 193, 720, 723, 98, - 387, 99, 47, 48, 47, 47, 898, 110, 111, 194, - 194, 194, 194, 199, 200, 200, 200, 200, 387, 720, - 723, 112, 201, 201, 201, 201, 199, 200, 200, 200, - 200, 470, 473, 98, 202, 99, 113, 114, 115, 115, - - 115, 115, 203, 203, 203, 203, 897, 97, 203, 203, - 203, 203, 202, 203, 203, 203, 203, 470, 473, 98, - 859, 99, 113, 114, 115, 115, 115, 115, 204, 207, - 207, 207, 207, 97, 205, 206, 206, 206, 206, 215, - 216, 216, 216, 216, 204, 98, 858, 99, 116, 117, - 118, 118, 118, 118, 418, 131, 857, 131, 131, 97, - 131, 213, 217, 217, 217, 217, 221, 222, 222, 222, - 222, 98, 418, 99, 116, 117, 118, 118, 118, 118, - 223, 223, 223, 223, 703, 97, 131, 228, 131, 228, - 228, 263, 128, 229, 128, 128, 620, 98, 129, 99, - - 153, 153, 153, 153, 626, 702, 154, 263, 132, 150, - 151, 151, 151, 151, 620, 734, 737, 155, 233, 233, - 233, 233, 626, 233, 233, 233, 233, 233, 233, 233, - 233, 152, 152, 152, 152, 155, 161, 161, 161, 161, - 132, 701, 162, 234, 947, 955, 160, 160, 160, 160, - 976, 152, 152, 152, 152, 734, 737, 256, 256, 234, - 257, 257, 257, 257, 274, 277, 163, 158, 158, 158, - 158, 156, 157, 157, 157, 157, 274, 277, 700, 159, - 387, 651, 163, 169, 169, 169, 169, 657, 616, 170, - 750, 753, 166, 167, 167, 167, 167, 159, 387, 651, - - 171, 158, 158, 158, 158, 657, 258, 258, 159, 259, - 259, 259, 259, 164, 164, 164, 164, 613, 171, 183, - 183, 183, 183, 750, 753, 184, 159, 661, 180, 181, - 181, 181, 181, 132, 667, 260, 185, 261, 262, 262, - 262, 161, 161, 161, 161, 661, 435, 162, 168, 168, - 168, 168, 667, 418, 185, 189, 189, 189, 189, 485, - 488, 190, 692, 956, 186, 187, 187, 187, 187, 485, - 488, 418, 191, 976, 168, 168, 168, 168, 280, 280, - 692, 281, 281, 281, 281, 178, 178, 178, 178, 132, - 191, 195, 195, 195, 195, 434, 957, 196, 433, 432, - - 192, 193, 193, 193, 193, 431, 430, 131, 197, 131, - 131, 429, 131, 174, 131, 363, 131, 131, 362, 131, - 174, 182, 182, 182, 182, 698, 197, 208, 208, 208, - 208, 361, 620, 209, 626, 360, 205, 206, 206, 206, - 206, 863, 869, 698, 210, 176, 177, 177, 177, 177, - 620, 359, 626, 179, 178, 178, 178, 178, 358, 863, - 869, 179, 210, 218, 218, 218, 218, 357, 356, 219, - 355, 179, 215, 216, 216, 216, 216, 246, 245, 179, - 220, 282, 282, 244, 283, 283, 283, 283, 976, 182, - 182, 182, 182, 188, 188, 188, 188, 243, 220, 224, - - 224, 224, 224, 242, 241, 225, 240, 239, 221, 222, - 222, 222, 222, 238, 293, 293, 226, 294, 294, 294, - 294, 976, 188, 188, 188, 188, 304, 304, 237, 305, - 305, 305, 305, 236, 226, 153, 153, 153, 153, 132, - 132, 154, 132, 247, 248, 249, 249, 249, 249, 251, - 153, 251, 251, 232, 875, 252, 214, 253, 254, 255, - 255, 255, 255, 264, 161, 264, 264, 198, 175, 265, - 149, 266, 875, 267, 268, 268, 268, 169, 169, 169, - 169, 148, 147, 170, 146, 271, 272, 273, 273, 273, - 273, 275, 169, 275, 275, 143, 142, 276, 141, 277, - - 278, 279, 279, 279, 279, 183, 183, 183, 183, 140, - 139, 184, 138, 284, 285, 286, 286, 286, 286, 288, - 183, 288, 288, 137, 136, 289, 132, 290, 291, 292, - 292, 292, 292, 189, 189, 189, 189, 976, 976, 190, - 976, 295, 296, 297, 297, 297, 297, 299, 189, 299, - 299, 976, 976, 300, 976, 301, 302, 303, 303, 303, - 303, 194, 194, 194, 194, 976, 194, 194, 194, 194, - 195, 195, 195, 195, 976, 976, 196, 976, 306, 307, - 308, 308, 308, 308, 310, 195, 310, 310, 976, 976, - 311, 976, 312, 313, 314, 314, 314, 314, 315, 315, - - 976, 316, 316, 316, 316, 201, 201, 201, 201, 199, - 200, 200, 200, 200, 976, 976, 651, 202, 201, 201, - 201, 201, 657, 317, 317, 202, 318, 318, 318, 318, - 203, 203, 203, 203, 651, 202, 207, 207, 207, 207, - 657, 976, 976, 202, 976, 207, 207, 207, 207, 208, - 208, 208, 208, 976, 976, 209, 976, 320, 321, 322, - 322, 322, 322, 324, 208, 324, 324, 661, 976, 325, - 667, 326, 327, 328, 328, 328, 328, 329, 329, 976, - 330, 330, 330, 330, 131, 661, 131, 131, 667, 131, - 213, 131, 976, 131, 131, 976, 131, 213, 217, 217, - - 217, 217, 976, 217, 217, 217, 217, 340, 340, 976, - 341, 341, 341, 341, 881, 131, 976, 131, 223, 223, - 223, 223, 131, 887, 131, 218, 218, 218, 218, 976, - 976, 219, 881, 976, 215, 216, 216, 216, 216, 976, - 976, 887, 220, 976, 223, 223, 223, 223, 351, 351, - 893, 352, 352, 352, 352, 233, 233, 233, 233, 976, - 220, 218, 218, 218, 218, 976, 976, 219, 893, 331, - 332, 333, 333, 333, 333, 335, 218, 335, 335, 692, - 976, 336, 976, 337, 338, 339, 339, 339, 339, 224, - 224, 224, 224, 976, 976, 225, 976, 692, 221, 222, - - 222, 222, 222, 698, 976, 228, 226, 228, 228, 976, - 976, 229, 248, 249, 249, 249, 249, 364, 364, 364, - 364, 698, 976, 976, 226, 224, 224, 224, 224, 976, - 976, 225, 976, 342, 343, 344, 344, 344, 344, 346, - 224, 346, 346, 976, 976, 347, 976, 348, 349, 350, - 350, 350, 350, 365, 365, 365, 365, 976, 976, 366, - 976, 976, 248, 249, 249, 249, 249, 976, 976, 976, - 367, 368, 368, 368, 368, 257, 257, 257, 257, 259, - 259, 259, 259, 259, 259, 259, 259, 976, 367, 251, - 153, 251, 251, 976, 976, 252, 976, 253, 254, 255, - - 255, 255, 255, 251, 153, 251, 251, 976, 976, 252, - 976, 253, 254, 255, 255, 255, 255, 369, 370, 369, - 369, 976, 976, 371, 262, 262, 262, 262, 262, 262, - 262, 262, 976, 976, 372, 976, 976, 262, 262, 262, - 262, 161, 161, 161, 161, 976, 976, 162, 375, 375, - 375, 375, 372, 153, 153, 153, 153, 373, 976, 154, - 976, 976, 976, 257, 257, 257, 257, 272, 273, 273, - 273, 273, 976, 373, 264, 161, 264, 264, 959, 960, - 265, 976, 266, 961, 267, 268, 268, 268, 264, 161, - 264, 264, 959, 960, 265, 976, 266, 961, 267, 268, - - 268, 268, 376, 376, 376, 376, 976, 976, 377, 976, - 976, 272, 273, 273, 273, 273, 976, 976, 976, 378, - 379, 379, 379, 379, 281, 281, 281, 281, 283, 283, - 283, 283, 283, 283, 283, 283, 976, 378, 275, 169, - 275, 275, 976, 976, 276, 976, 277, 278, 279, 279, - 279, 279, 275, 169, 275, 275, 976, 976, 276, 976, - 277, 278, 279, 279, 279, 279, 380, 381, 380, 380, - 976, 976, 382, 285, 286, 286, 286, 286, 384, 384, - 384, 384, 976, 383, 285, 286, 286, 286, 286, 976, - 976, 976, 385, 386, 386, 386, 386, 294, 294, 294, - - 294, 383, 169, 169, 169, 169, 959, 960, 170, 976, - 385, 961, 281, 281, 281, 281, 288, 183, 288, 288, - 976, 976, 289, 976, 290, 291, 292, 292, 292, 292, - 183, 183, 183, 183, 976, 976, 184, 976, 976, 976, - 294, 294, 294, 294, 296, 297, 297, 297, 297, 388, - 388, 388, 388, 389, 389, 389, 389, 976, 976, 390, - 976, 976, 296, 297, 297, 297, 297, 976, 976, 976, - 391, 392, 392, 392, 392, 976, 393, 394, 393, 393, - 976, 976, 395, 305, 305, 305, 305, 976, 391, 299, - 189, 299, 299, 396, 976, 300, 976, 301, 302, 303, - - 303, 303, 303, 307, 308, 308, 308, 308, 976, 720, - 723, 396, 189, 189, 189, 189, 976, 976, 190, 863, - 976, 976, 305, 305, 305, 305, 397, 397, 397, 397, - 398, 398, 398, 398, 976, 976, 399, 863, 976, 307, - 308, 308, 308, 308, 976, 976, 976, 400, 401, 401, - 401, 401, 976, 402, 403, 402, 402, 976, 976, 404, - 316, 316, 316, 316, 976, 400, 310, 195, 310, 310, - 405, 976, 311, 976, 312, 313, 314, 314, 314, 314, - 318, 318, 318, 318, 318, 318, 318, 318, 405, 195, - 195, 195, 195, 976, 976, 196, 976, 976, 976, 316, - - 316, 316, 316, 321, 322, 322, 322, 322, 406, 406, - 406, 406, 407, 407, 407, 407, 976, 976, 408, 976, - 976, 321, 322, 322, 322, 322, 976, 976, 976, 409, - 410, 410, 410, 410, 976, 411, 412, 411, 411, 976, - 976, 413, 330, 330, 330, 330, 976, 409, 324, 208, - 324, 324, 414, 976, 325, 976, 326, 327, 328, 328, - 328, 328, 332, 333, 333, 333, 333, 976, 734, 737, - 414, 208, 208, 208, 208, 976, 976, 209, 869, 976, - 976, 330, 330, 330, 330, 415, 415, 415, 415, 332, - 333, 333, 333, 333, 976, 976, 869, 416, 417, 417, - - 417, 417, 341, 341, 341, 341, 343, 344, 344, 344, - 344, 419, 419, 419, 419, 416, 335, 218, 335, 335, - 976, 976, 336, 976, 337, 338, 339, 339, 339, 339, - 218, 218, 218, 218, 976, 976, 219, 976, 750, 753, - 341, 341, 341, 341, 420, 420, 420, 420, 875, 976, - 421, 976, 976, 343, 344, 344, 344, 344, 976, 976, - 976, 422, 423, 423, 423, 423, 875, 424, 425, 424, - 424, 976, 976, 426, 352, 352, 352, 352, 976, 422, - 346, 224, 346, 346, 427, 976, 347, 976, 348, 349, - 350, 350, 350, 350, 976, 364, 364, 364, 364, 976, - - 976, 976, 427, 224, 224, 224, 224, 976, 976, 225, - 976, 976, 976, 352, 352, 352, 352, 365, 365, 365, - 365, 976, 976, 366, 976, 436, 437, 438, 438, 438, - 438, 440, 365, 440, 440, 976, 976, 441, 976, 442, - 443, 444, 444, 444, 444, 445, 445, 976, 446, 446, - 446, 446, 369, 370, 369, 369, 976, 976, 371, 976, - 976, 976, 368, 368, 368, 368, 976, 460, 461, 372, - 462, 462, 462, 462, 976, 375, 375, 375, 375, 476, - 476, 976, 477, 477, 477, 477, 976, 372, 447, 448, - 449, 449, 449, 449, 976, 976, 976, 250, 384, 384, - - 384, 384, 976, 494, 494, 385, 495, 495, 495, 495, - 437, 438, 438, 438, 438, 250, 370, 370, 370, 370, - 976, 976, 450, 385, 451, 452, 453, 453, 453, 453, - 455, 370, 455, 455, 976, 976, 456, 976, 457, 458, - 459, 459, 459, 459, 464, 465, 465, 465, 466, 466, - 466, 466, 466, 508, 508, 976, 509, 509, 509, 509, - 535, 535, 976, 536, 536, 536, 536, 976, 466, 466, - 466, 376, 376, 376, 376, 976, 976, 377, 976, 467, - 468, 469, 469, 469, 469, 471, 376, 471, 471, 976, - 976, 472, 976, 473, 474, 475, 475, 475, 475, 380, - - 381, 380, 380, 976, 976, 382, 976, 976, 976, 379, - 379, 379, 379, 976, 562, 562, 383, 563, 563, 563, - 563, 415, 415, 415, 415, 976, 580, 580, 416, 581, - 581, 581, 581, 976, 383, 478, 479, 480, 480, 480, - 480, 976, 976, 976, 274, 976, 416, 594, 594, 976, - 595, 595, 595, 595, 617, 617, 617, 617, 619, 619, - 619, 619, 274, 381, 381, 381, 381, 976, 976, 481, - 976, 482, 483, 484, 484, 484, 484, 486, 381, 486, - 486, 976, 976, 487, 976, 488, 489, 490, 490, 490, - 490, 275, 169, 275, 275, 976, 976, 276, 491, 492, - - 976, 493, 493, 493, 493, 976, 976, 976, 274, 446, - 446, 446, 446, 976, 976, 437, 438, 438, 438, 438, - 976, 976, 976, 618, 976, 976, 274, 288, 183, 288, - 288, 976, 976, 289, 976, 290, 291, 386, 386, 386, - 386, 618, 976, 976, 387, 452, 453, 453, 453, 453, - 623, 623, 623, 623, 625, 625, 625, 625, 462, 462, - 462, 462, 387, 288, 183, 288, 288, 976, 976, 289, - 496, 497, 291, 498, 498, 498, 498, 389, 389, 389, - 389, 976, 976, 390, 976, 976, 976, 388, 388, 388, - 388, 976, 976, 976, 391, 462, 462, 462, 462, 468, - - 469, 469, 469, 469, 627, 627, 627, 627, 631, 631, - 631, 631, 391, 389, 389, 389, 389, 976, 976, 390, - 976, 499, 500, 501, 501, 501, 501, 503, 389, 503, - 503, 976, 976, 504, 976, 505, 506, 507, 507, 507, - 507, 393, 394, 393, 393, 976, 976, 395, 976, 301, - 302, 392, 392, 392, 392, 976, 976, 976, 396, 477, - 477, 477, 477, 483, 484, 484, 484, 484, 641, 641, - 641, 641, 644, 644, 644, 644, 396, 393, 394, 393, - 393, 976, 976, 395, 976, 510, 511, 512, 512, 512, - 512, 394, 394, 394, 394, 976, 976, 513, 976, 514, - - 515, 516, 516, 516, 516, 518, 394, 518, 518, 976, - 976, 519, 976, 520, 521, 522, 522, 522, 522, 299, - 189, 299, 299, 976, 976, 300, 523, 524, 302, 525, - 525, 525, 525, 398, 398, 398, 398, 976, 976, 399, - 976, 976, 976, 397, 397, 397, 397, 976, 976, 976, - 400, 493, 493, 493, 493, 493, 493, 493, 493, 495, - 495, 495, 495, 495, 495, 495, 495, 976, 400, 398, - 398, 398, 398, 976, 976, 399, 976, 526, 527, 528, - 528, 528, 528, 530, 398, 530, 530, 976, 976, 531, - 976, 532, 533, 534, 534, 534, 534, 402, 403, 402, - - 402, 976, 976, 404, 976, 312, 313, 401, 401, 401, - 401, 976, 976, 976, 405, 500, 501, 501, 501, 501, - 648, 648, 648, 648, 650, 650, 650, 650, 509, 509, - 509, 509, 405, 402, 403, 402, 402, 976, 976, 404, - 976, 537, 538, 539, 539, 539, 539, 403, 403, 403, - 403, 976, 976, 540, 976, 541, 542, 543, 543, 543, - 543, 545, 403, 545, 545, 976, 976, 546, 976, 547, - 548, 549, 549, 549, 549, 310, 195, 310, 310, 976, - 976, 311, 550, 551, 313, 552, 552, 552, 552, 407, - 407, 407, 407, 976, 976, 408, 976, 976, 976, 406, - - 406, 406, 406, 976, 976, 976, 409, 515, 516, 516, - 516, 516, 654, 654, 654, 654, 656, 656, 656, 656, - 525, 525, 525, 525, 409, 407, 407, 407, 407, 976, - 976, 408, 976, 553, 554, 555, 555, 555, 555, 557, - 407, 557, 557, 976, 976, 558, 976, 559, 560, 561, - 561, 561, 561, 411, 412, 411, 411, 976, 976, 413, - 976, 326, 327, 410, 410, 410, 410, 976, 976, 976, - 414, 525, 525, 525, 525, 527, 528, 528, 528, 528, - 658, 658, 658, 658, 660, 660, 660, 660, 414, 411, - 412, 411, 411, 976, 976, 413, 976, 564, 565, 566, - - 566, 566, 566, 412, 412, 412, 412, 976, 976, 567, - 976, 568, 569, 570, 570, 570, 570, 572, 412, 572, - 572, 976, 976, 573, 976, 574, 575, 576, 576, 576, - 576, 324, 208, 324, 324, 976, 976, 325, 577, 578, - 327, 579, 579, 579, 579, 335, 218, 335, 335, 976, - 976, 336, 976, 337, 338, 417, 417, 417, 417, 976, - 976, 976, 418, 536, 536, 536, 536, 976, 632, 633, - 632, 632, 976, 976, 634, 542, 543, 543, 543, 543, - 418, 335, 218, 335, 335, 635, 976, 336, 582, 583, - 338, 584, 584, 584, 584, 420, 420, 420, 420, 976, - - 976, 421, 976, 635, 976, 419, 419, 419, 419, 976, - 976, 976, 422, 664, 664, 664, 664, 666, 666, 666, - 666, 552, 552, 552, 552, 552, 552, 552, 552, 976, - 422, 420, 420, 420, 420, 976, 976, 421, 976, 585, - 586, 587, 587, 587, 587, 589, 420, 589, 589, 976, - 976, 590, 976, 591, 592, 593, 593, 593, 593, 424, - 425, 424, 424, 976, 976, 426, 976, 348, 349, 423, - 423, 423, 423, 976, 976, 976, 427, 554, 555, 555, - 555, 555, 668, 668, 668, 668, 672, 672, 672, 672, - 563, 563, 563, 563, 427, 424, 425, 424, 424, 976, - - 976, 426, 976, 596, 597, 598, 598, 598, 598, 425, - 425, 425, 425, 976, 976, 599, 976, 600, 601, 602, - 602, 602, 602, 604, 425, 604, 604, 976, 976, 605, - 976, 606, 607, 608, 608, 608, 608, 346, 224, 346, - 346, 976, 976, 347, 609, 610, 349, 611, 611, 611, - 611, 440, 365, 440, 440, 976, 976, 441, 976, 442, - 443, 444, 444, 444, 444, 440, 365, 440, 440, 976, - 976, 441, 976, 442, 443, 444, 444, 444, 444, 365, - 365, 365, 365, 976, 976, 366, 976, 976, 976, 446, - 446, 446, 446, 251, 153, 251, 251, 976, 976, 252, - - 976, 253, 448, 449, 449, 449, 449, 251, 153, 251, - 251, 976, 976, 252, 976, 253, 254, 621, 621, 621, - 621, 369, 370, 369, 369, 976, 976, 371, 976, 976, - 448, 449, 449, 449, 449, 976, 976, 976, 622, 569, - 570, 570, 570, 570, 645, 638, 645, 645, 976, 976, - 646, 682, 682, 682, 682, 976, 622, 455, 370, 455, - 455, 647, 976, 456, 976, 457, 458, 459, 459, 459, - 459, 365, 365, 365, 365, 976, 976, 366, 976, 647, - 452, 453, 453, 453, 453, 976, 976, 976, 624, 685, - 685, 685, 685, 976, 976, 254, 462, 462, 462, 462, - - 976, 976, 976, 372, 976, 976, 624, 455, 370, 455, - 455, 976, 976, 456, 976, 457, 458, 459, 459, 459, - 459, 372, 263, 264, 161, 264, 264, 263, 263, 265, - 263, 266, 263, 464, 465, 465, 465, 466, 466, 466, - 466, 466, 263, 263, 263, 263, 263, 263, 263, 263, - 263, 263, 263, 374, 263, 263, 263, 466, 466, 466, - 263, 263, 263, 263, 263, 263, 263, 263, 263, 374, - 628, 628, 628, 628, 976, 976, 629, 976, 976, 468, - 469, 469, 469, 469, 976, 976, 976, 630, 579, 579, - 579, 579, 579, 579, 579, 579, 581, 581, 581, 581, - - 581, 581, 581, 581, 976, 630, 471, 376, 471, 471, - 976, 976, 472, 976, 473, 474, 475, 475, 475, 475, - 471, 376, 471, 471, 976, 976, 472, 976, 473, 474, - 475, 475, 475, 475, 376, 376, 376, 376, 976, 976, - 377, 976, 976, 976, 477, 477, 477, 477, 275, 169, - 275, 275, 976, 976, 276, 976, 277, 479, 480, 480, - 480, 480, 275, 169, 275, 275, 976, 976, 276, 976, - 277, 278, 636, 636, 636, 636, 637, 638, 637, 637, - 976, 976, 639, 976, 976, 479, 480, 480, 480, 480, - 976, 976, 976, 640, 586, 587, 587, 587, 587, 673, - - 674, 673, 673, 976, 976, 675, 689, 689, 689, 689, - 976, 640, 486, 381, 486, 486, 676, 976, 487, 976, - 488, 489, 490, 490, 490, 490, 633, 633, 633, 633, - 976, 976, 642, 976, 676, 483, 484, 484, 484, 484, - 976, 976, 976, 643, 691, 691, 691, 691, 976, 686, - 679, 686, 686, 976, 976, 687, 595, 595, 595, 595, - 976, 643, 486, 381, 486, 486, 688, 976, 487, 976, - 488, 489, 490, 490, 490, 490, 380, 381, 380, 380, - 976, 976, 382, 976, 688, 976, 493, 493, 493, 493, - 976, 976, 976, 383, 601, 602, 602, 602, 602, 695, - - 695, 695, 695, 697, 697, 697, 697, 611, 611, 611, - 611, 383, 288, 183, 288, 288, 976, 976, 289, 976, - 290, 291, 498, 498, 498, 498, 288, 183, 288, 288, - 976, 976, 289, 976, 290, 291, 498, 498, 498, 498, - 500, 501, 501, 501, 501, 976, 976, 976, 649, 611, - 611, 611, 611, 704, 704, 976, 705, 705, 705, 705, - 705, 705, 705, 705, 976, 976, 649, 503, 389, 503, - 503, 976, 976, 504, 976, 505, 506, 507, 507, 507, - 507, 503, 389, 503, 503, 976, 976, 504, 976, 505, - 506, 507, 507, 507, 507, 389, 389, 389, 389, 976, - - 976, 390, 976, 976, 976, 509, 509, 509, 509, 299, - 189, 299, 299, 976, 976, 300, 976, 301, 511, 512, - 512, 512, 512, 299, 189, 299, 299, 976, 976, 300, - 976, 301, 302, 652, 652, 652, 652, 393, 394, 393, - 393, 976, 976, 395, 976, 976, 511, 512, 512, 512, - 512, 976, 976, 976, 653, 617, 617, 617, 617, 976, - 712, 712, 618, 713, 713, 713, 713, 705, 705, 705, - 705, 976, 653, 518, 394, 518, 518, 976, 976, 519, - 618, 520, 521, 522, 522, 522, 522, 389, 389, 389, - 389, 976, 976, 390, 976, 976, 515, 516, 516, 516, - - 516, 976, 726, 726, 655, 727, 727, 727, 727, 976, - 976, 302, 525, 525, 525, 525, 976, 976, 976, 396, - 976, 976, 655, 518, 394, 518, 518, 976, 976, 519, - 976, 520, 521, 522, 522, 522, 522, 396, 527, 528, - 528, 528, 528, 976, 759, 759, 659, 760, 760, 760, - 760, 767, 767, 976, 768, 768, 768, 768, 713, 713, - 713, 713, 976, 976, 659, 530, 398, 530, 530, 976, - 976, 531, 976, 532, 533, 534, 534, 534, 534, 530, - 398, 530, 530, 976, 976, 531, 976, 532, 533, 534, - 534, 534, 534, 398, 398, 398, 398, 976, 976, 399, - - 976, 976, 976, 536, 536, 536, 536, 310, 195, 310, - 310, 976, 976, 311, 976, 312, 538, 539, 539, 539, - 539, 310, 195, 310, 310, 976, 976, 311, 976, 312, - 313, 662, 662, 662, 662, 402, 403, 402, 402, 976, - 976, 404, 976, 976, 538, 539, 539, 539, 539, 976, - 976, 976, 663, 648, 648, 648, 648, 976, 775, 775, - 649, 776, 776, 776, 776, 718, 719, 719, 719, 719, - 663, 545, 403, 545, 545, 976, 976, 546, 649, 547, - 548, 549, 549, 549, 549, 398, 398, 398, 398, 976, - 976, 399, 976, 976, 542, 543, 543, 543, 543, 976, - - 780, 780, 665, 781, 781, 781, 781, 976, 976, 313, - 552, 552, 552, 552, 976, 976, 976, 405, 976, 976, - 665, 545, 403, 545, 545, 976, 976, 546, 976, 547, - 548, 549, 549, 549, 549, 405, 669, 669, 669, 669, - 976, 976, 670, 976, 976, 554, 555, 555, 555, 555, - 976, 976, 976, 671, 658, 658, 658, 658, 976, 788, - 788, 659, 789, 789, 789, 789, 860, 860, 860, 860, - 976, 671, 557, 407, 557, 557, 976, 976, 558, 659, - 559, 560, 561, 561, 561, 561, 557, 407, 557, 557, - 976, 976, 558, 976, 559, 560, 561, 561, 561, 561, - - 407, 407, 407, 407, 976, 976, 408, 976, 976, 976, - 563, 563, 563, 563, 324, 208, 324, 324, 976, 976, - 325, 976, 326, 565, 566, 566, 566, 566, 324, 208, - 324, 324, 976, 976, 325, 976, 326, 327, 677, 677, - 677, 677, 678, 679, 678, 678, 976, 976, 680, 976, - 976, 565, 566, 566, 566, 566, 976, 802, 802, 681, - 803, 803, 803, 803, 835, 835, 976, 836, 836, 836, - 836, 862, 862, 862, 862, 976, 976, 681, 572, 412, - 572, 572, 976, 976, 573, 976, 574, 575, 576, 576, - 576, 576, 674, 674, 674, 674, 976, 976, 683, 976, - - 976, 569, 570, 570, 570, 570, 976, 976, 976, 684, - 689, 689, 689, 689, 976, 843, 843, 690, 844, 844, - 844, 844, 727, 727, 727, 727, 976, 684, 572, 412, - 572, 572, 976, 976, 573, 690, 574, 575, 576, 576, - 576, 576, 411, 412, 411, 411, 976, 976, 413, 976, - 976, 976, 579, 579, 579, 579, 976, 851, 851, 414, - 852, 852, 852, 852, 732, 733, 733, 733, 733, 866, - 866, 866, 866, 868, 868, 868, 868, 414, 335, 218, - 335, 335, 976, 976, 336, 976, 337, 338, 584, 584, - 584, 584, 335, 218, 335, 335, 976, 976, 336, 976, - - 337, 338, 584, 584, 584, 584, 586, 587, 587, 587, - 587, 976, 976, 976, 690, 742, 742, 742, 742, 742, - 742, 742, 742, 748, 749, 749, 749, 749, 872, 872, - 872, 872, 690, 589, 420, 589, 589, 976, 976, 590, - 976, 591, 592, 593, 593, 593, 593, 589, 420, 589, - 589, 976, 976, 590, 976, 591, 592, 593, 593, 593, - 593, 420, 420, 420, 420, 976, 976, 421, 976, 976, - 976, 595, 595, 595, 595, 346, 224, 346, 346, 976, - 976, 347, 976, 348, 597, 598, 598, 598, 598, 346, - 224, 346, 346, 976, 976, 347, 976, 348, 349, 693, - - 693, 693, 693, 424, 425, 424, 424, 976, 976, 426, - 976, 976, 597, 598, 598, 598, 598, 976, 976, 976, - 694, 874, 874, 874, 874, 976, 369, 370, 369, 369, - 976, 976, 371, 758, 758, 758, 758, 976, 694, 604, - 425, 604, 604, 372, 976, 605, 976, 606, 607, 608, - 608, 608, 608, 420, 420, 420, 420, 976, 976, 421, - 976, 372, 601, 602, 602, 602, 602, 976, 976, 976, - 696, 758, 758, 758, 758, 976, 976, 349, 611, 611, - 611, 611, 976, 976, 976, 427, 976, 976, 696, 604, - 425, 604, 604, 976, 976, 605, 976, 606, 607, 608, - - 608, 608, 608, 427, 440, 365, 440, 440, 976, 976, - 441, 976, 442, 443, 619, 619, 619, 619, 976, 976, - 976, 620, 760, 760, 760, 760, 766, 766, 766, 766, - 766, 766, 766, 766, 768, 768, 768, 768, 976, 620, - 440, 365, 440, 440, 976, 976, 441, 706, 707, 443, - 708, 708, 708, 708, 369, 370, 369, 369, 976, 976, - 371, 976, 253, 254, 621, 621, 621, 621, 976, 976, - 976, 622, 768, 768, 768, 768, 976, 393, 394, 393, - 393, 976, 976, 395, 776, 776, 776, 776, 976, 622, - 251, 153, 251, 251, 396, 976, 252, 709, 710, 254, - - 711, 711, 711, 711, 365, 365, 365, 365, 976, 976, - 366, 976, 396, 976, 623, 623, 623, 623, 976, 976, - 976, 624, 781, 781, 781, 781, 976, 976, 718, 719, - 719, 719, 719, 976, 976, 976, 861, 976, 976, 624, - 455, 370, 455, 455, 976, 976, 456, 976, 457, 458, - 625, 625, 625, 625, 861, 976, 976, 626, 781, 781, - 781, 781, 976, 402, 403, 402, 402, 976, 976, 404, - 789, 789, 789, 789, 976, 626, 455, 370, 455, 455, - 405, 976, 456, 714, 715, 458, 716, 716, 716, 716, - 628, 628, 628, 628, 976, 976, 629, 976, 405, 976, - - 627, 627, 627, 627, 976, 976, 976, 630, 794, 795, - 795, 795, 795, 878, 878, 878, 878, 880, 880, 880, - 880, 803, 803, 803, 803, 630, 628, 628, 628, 628, - 976, 976, 629, 976, 717, 718, 719, 719, 719, 719, - 721, 628, 721, 721, 976, 976, 722, 976, 723, 724, - 725, 725, 725, 725, 632, 633, 632, 632, 976, 976, - 634, 976, 473, 474, 631, 631, 631, 631, 976, 976, - 976, 635, 808, 809, 809, 809, 809, 884, 884, 884, - 884, 886, 886, 886, 886, 818, 818, 818, 818, 635, - 632, 633, 632, 632, 976, 976, 634, 976, 728, 729, - - 730, 730, 730, 730, 633, 633, 633, 633, 976, 976, - 642, 976, 731, 732, 733, 733, 733, 733, 735, 633, - 735, 735, 976, 976, 736, 976, 737, 738, 739, 739, - 739, 739, 471, 376, 471, 471, 976, 976, 472, 740, - 741, 474, 742, 742, 742, 742, 637, 638, 637, 637, - 976, 976, 639, 976, 277, 278, 636, 636, 636, 636, - 976, 976, 976, 640, 818, 818, 818, 818, 824, 825, - 825, 825, 825, 890, 890, 890, 890, 892, 892, 892, - 892, 640, 637, 638, 637, 637, 976, 976, 639, 976, - 743, 744, 745, 745, 745, 745, 638, 638, 638, 638, - - 976, 976, 746, 976, 747, 748, 749, 749, 749, 749, - 751, 638, 751, 751, 976, 976, 752, 976, 753, 754, - 755, 755, 755, 755, 275, 169, 275, 275, 976, 976, - 276, 756, 757, 278, 758, 758, 758, 758, 633, 633, - 633, 633, 976, 976, 642, 976, 976, 976, 641, 641, - 641, 641, 976, 976, 976, 643, 834, 834, 834, 834, - 834, 834, 834, 834, 836, 836, 836, 836, 842, 842, - 842, 842, 976, 643, 735, 633, 735, 735, 976, 976, - 736, 976, 737, 738, 739, 739, 739, 739, 645, 638, - 645, 645, 976, 976, 646, 976, 488, 489, 644, 644, - - 644, 644, 976, 976, 976, 647, 842, 842, 842, 842, - 844, 844, 844, 844, 844, 844, 844, 844, 852, 852, - 852, 852, 976, 647, 645, 638, 645, 645, 976, 976, - 646, 976, 761, 762, 763, 763, 763, 763, 751, 638, - 751, 751, 976, 976, 752, 976, 753, 754, 755, 755, - 755, 755, 486, 381, 486, 486, 976, 976, 487, 764, - 765, 489, 766, 766, 766, 766, 503, 389, 503, 503, - 976, 976, 504, 976, 505, 506, 650, 650, 650, 650, - 976, 899, 899, 651, 900, 900, 900, 900, 907, 907, - 976, 908, 908, 908, 908, 560, 882, 882, 882, 882, - - 976, 651, 503, 389, 503, 503, 976, 976, 504, 769, - 770, 506, 771, 771, 771, 771, 393, 394, 393, 393, - 976, 976, 395, 976, 301, 302, 652, 652, 652, 652, - 976, 915, 915, 653, 916, 916, 916, 916, 976, 424, - 425, 424, 424, 923, 923, 426, 924, 924, 924, 924, - 976, 653, 299, 189, 299, 299, 427, 976, 300, 772, - 773, 302, 774, 774, 774, 774, 389, 389, 389, 389, - 976, 976, 390, 976, 427, 976, 654, 654, 654, 654, - 976, 925, 926, 655, 927, 927, 927, 927, 976, 976, - 474, 742, 742, 742, 742, 976, 976, 976, 635, 976, - - 976, 655, 518, 394, 518, 518, 976, 976, 519, 976, - 520, 521, 656, 656, 656, 656, 635, 928, 929, 657, - 930, 930, 930, 930, 976, 884, 884, 884, 884, 931, - 931, 976, 932, 932, 932, 932, 976, 657, 518, 394, - 518, 518, 976, 976, 519, 777, 778, 521, 779, 779, - 779, 779, 530, 398, 530, 530, 976, 976, 531, 976, - 532, 533, 660, 660, 660, 660, 976, 933, 934, 661, - 935, 935, 935, 935, 327, 888, 888, 888, 888, 936, - 937, 976, 938, 938, 938, 938, 976, 661, 530, 398, - 530, 530, 976, 976, 531, 782, 783, 533, 784, 784, - - 784, 784, 402, 403, 402, 402, 976, 976, 404, 976, - 312, 313, 662, 662, 662, 662, 976, 976, 976, 663, - 976, 890, 890, 890, 890, 939, 939, 976, 940, 940, - 940, 940, 575, 894, 894, 894, 894, 663, 310, 195, - 310, 310, 976, 976, 311, 785, 786, 313, 787, 787, - 787, 787, 398, 398, 398, 398, 976, 976, 399, 976, - 976, 976, 664, 664, 664, 664, 976, 941, 942, 665, - 943, 943, 943, 943, 976, 976, 278, 758, 758, 758, - 758, 976, 976, 976, 383, 976, 976, 665, 545, 403, - 545, 545, 976, 976, 546, 976, 547, 548, 666, 666, - - 666, 666, 383, 944, 945, 667, 946, 946, 946, 946, - 900, 900, 900, 900, 900, 900, 900, 900, 908, 908, - 908, 908, 976, 667, 545, 403, 545, 545, 976, 976, - 546, 790, 791, 548, 792, 792, 792, 792, 669, 669, - 669, 669, 976, 976, 670, 976, 976, 976, 668, 668, - 668, 668, 976, 976, 976, 671, 860, 860, 860, 860, - 976, 976, 976, 861, 916, 916, 916, 916, 924, 924, - 924, 924, 976, 671, 669, 669, 669, 669, 976, 976, - 670, 861, 793, 794, 795, 795, 795, 795, 797, 669, - 797, 797, 976, 976, 798, 976, 799, 800, 801, 801, - - 801, 801, 673, 674, 673, 673, 976, 976, 675, 976, - 559, 560, 672, 672, 672, 672, 976, 976, 976, 676, - 878, 878, 878, 878, 976, 976, 976, 879, 924, 924, - 924, 924, 927, 927, 927, 927, 976, 676, 673, 674, - 673, 673, 976, 976, 675, 879, 804, 805, 806, 806, - 806, 806, 674, 674, 674, 674, 976, 976, 683, 976, - 807, 808, 809, 809, 809, 809, 811, 674, 811, 811, - 976, 976, 812, 976, 813, 814, 815, 815, 815, 815, - 557, 407, 557, 557, 976, 976, 558, 816, 817, 560, - 818, 818, 818, 818, 678, 679, 678, 678, 976, 976, - - 680, 976, 326, 327, 677, 677, 677, 677, 976, 976, - 976, 681, 880, 880, 880, 880, 976, 976, 976, 881, - 927, 927, 927, 927, 930, 930, 930, 930, 976, 681, - 678, 679, 678, 678, 976, 976, 680, 881, 819, 820, - 821, 821, 821, 821, 679, 679, 679, 679, 976, 976, - 822, 976, 823, 824, 825, 825, 825, 825, 827, 679, - 827, 827, 976, 976, 828, 976, 829, 830, 831, 831, - 831, 831, 324, 208, 324, 324, 976, 976, 325, 832, - 833, 327, 834, 834, 834, 834, 674, 674, 674, 674, - 976, 976, 683, 976, 976, 976, 682, 682, 682, 682, - - 976, 976, 976, 684, 886, 886, 886, 886, 976, 976, - 976, 887, 930, 930, 930, 930, 932, 932, 932, 932, - 976, 684, 811, 674, 811, 811, 976, 976, 812, 887, - 813, 814, 815, 815, 815, 815, 686, 679, 686, 686, - 976, 976, 687, 976, 574, 575, 685, 685, 685, 685, - 976, 976, 976, 688, 892, 892, 892, 892, 976, 976, - 976, 893, 935, 935, 935, 935, 935, 935, 935, 935, - 976, 688, 686, 679, 686, 686, 976, 976, 687, 893, - 837, 838, 839, 839, 839, 839, 827, 679, 827, 827, - 976, 976, 828, 976, 829, 830, 831, 831, 831, 831, - - 572, 412, 572, 572, 976, 976, 573, 840, 841, 575, - 842, 842, 842, 842, 589, 420, 589, 589, 976, 976, - 590, 976, 591, 592, 691, 691, 691, 691, 976, 976, - 976, 692, 938, 938, 938, 938, 938, 938, 938, 938, - 940, 940, 940, 940, 940, 940, 940, 940, 976, 692, - 589, 420, 589, 589, 976, 976, 590, 845, 846, 592, - 847, 847, 847, 847, 424, 425, 424, 424, 976, 976, - 426, 976, 348, 349, 693, 693, 693, 693, 976, 976, - 976, 694, 943, 943, 943, 943, 943, 943, 943, 943, - 946, 946, 946, 946, 946, 946, 946, 946, 976, 694, - - 346, 224, 346, 346, 976, 976, 347, 848, 849, 349, - 850, 850, 850, 850, 420, 420, 420, 420, 976, 976, - 421, 976, 976, 976, 695, 695, 695, 695, 976, 976, - 962, 696, 963, 962, 976, 976, 964, 976, 489, 766, - 766, 766, 766, 976, 976, 976, 647, 976, 976, 696, - 604, 425, 604, 604, 976, 976, 605, 976, 606, 607, - 697, 697, 697, 697, 647, 976, 976, 698, 965, 966, - 967, 965, 976, 962, 968, 962, 962, 976, 962, 964, - 962, 962, 976, 976, 964, 698, 604, 425, 604, 604, - 976, 976, 605, 853, 854, 607, 855, 855, 855, 855, - - 440, 365, 440, 440, 976, 976, 441, 976, 442, 443, - 708, 708, 708, 708, 440, 365, 440, 440, 976, 976, - 441, 976, 442, 443, 708, 708, 708, 708, 251, 153, - 251, 251, 976, 976, 252, 976, 253, 254, 711, 711, - 711, 711, 251, 153, 251, 251, 976, 976, 252, 976, - 253, 254, 711, 711, 711, 711, 365, 365, 365, 365, - 976, 976, 366, 976, 976, 976, 713, 713, 713, 713, - 455, 370, 455, 455, 976, 976, 456, 976, 457, 458, - 716, 716, 716, 716, 455, 370, 455, 455, 976, 976, - 456, 976, 457, 458, 716, 716, 716, 716, 721, 628, - - 721, 721, 976, 976, 722, 976, 723, 724, 725, 725, - 725, 725, 721, 628, 721, 721, 976, 976, 722, 976, - 723, 724, 725, 725, 725, 725, 628, 628, 628, 628, - 976, 976, 629, 976, 976, 976, 727, 727, 727, 727, - 471, 376, 471, 471, 976, 976, 472, 976, 473, 729, - 730, 730, 730, 730, 471, 376, 471, 471, 976, 976, - 472, 976, 473, 474, 864, 864, 864, 864, 632, 633, - 632, 632, 976, 976, 634, 976, 976, 729, 730, 730, - 730, 730, 976, 976, 976, 865, 794, 795, 795, 795, - 795, 976, 976, 976, 879, 927, 927, 927, 927, 976, - - 976, 976, 881, 865, 628, 628, 628, 628, 976, 976, - 629, 976, 879, 732, 733, 733, 733, 733, 976, 976, - 881, 867, 935, 935, 935, 935, 976, 976, 970, 887, - 970, 970, 976, 976, 971, 976, 976, 976, 976, 867, - 735, 633, 735, 735, 976, 976, 736, 887, 737, 738, - 739, 739, 739, 739, 735, 633, 735, 735, 976, 976, - 736, 976, 737, 738, 739, 739, 739, 739, 275, 169, - 275, 275, 976, 976, 276, 976, 277, 744, 745, 745, - 745, 745, 275, 169, 275, 275, 976, 976, 276, 976, - 277, 278, 870, 870, 870, 870, 637, 638, 637, 637, - - 976, 976, 639, 976, 976, 744, 745, 745, 745, 745, - 976, 976, 976, 871, 943, 943, 943, 943, 976, 976, - 976, 893, 965, 959, 967, 965, 976, 976, 968, 976, - 976, 871, 751, 638, 751, 751, 976, 976, 752, 893, - 753, 754, 755, 755, 755, 755, 633, 633, 633, 633, - 976, 976, 642, 976, 976, 748, 749, 749, 749, 749, - 976, 976, 962, 873, 963, 962, 976, 976, 964, 965, - 966, 967, 965, 976, 970, 968, 970, 970, 976, 976, - 971, 873, 751, 638, 751, 751, 976, 976, 752, 976, - 753, 754, 755, 755, 755, 755, 633, 633, 633, 633, - - 976, 976, 642, 976, 976, 976, 760, 760, 760, 760, - 486, 381, 486, 486, 976, 976, 487, 976, 488, 762, - 763, 763, 763, 763, 486, 381, 486, 486, 976, 976, - 487, 976, 488, 489, 876, 876, 876, 876, 645, 638, - 645, 645, 976, 976, 646, 976, 976, 762, 763, 763, - 763, 763, 976, 976, 976, 877, 973, 959, 974, 973, - 976, 970, 975, 970, 970, 976, 970, 971, 970, 970, - 976, 976, 971, 877, 503, 389, 503, 503, 976, 976, - 504, 976, 505, 506, 771, 771, 771, 771, 503, 389, - 503, 503, 976, 976, 504, 976, 505, 506, 771, 771, - - 771, 771, 299, 189, 299, 299, 976, 976, 300, 976, - 301, 302, 774, 774, 774, 774, 299, 189, 299, 299, - 976, 976, 300, 976, 301, 302, 774, 774, 774, 774, - 389, 389, 389, 389, 976, 976, 390, 976, 976, 976, - 776, 776, 776, 776, 518, 394, 518, 518, 976, 976, - 519, 976, 520, 521, 779, 779, 779, 779, 518, 394, - 518, 518, 976, 976, 519, 976, 520, 521, 779, 779, - 779, 779, 530, 398, 530, 530, 976, 976, 531, 976, - 532, 533, 784, 784, 784, 784, 530, 398, 530, 530, - 976, 976, 531, 976, 532, 533, 784, 784, 784, 784, - - 310, 195, 310, 310, 976, 976, 311, 976, 312, 313, - 787, 787, 787, 787, 310, 195, 310, 310, 976, 976, - 311, 976, 312, 313, 787, 787, 787, 787, 398, 398, - 398, 398, 976, 976, 399, 976, 976, 976, 789, 789, - 789, 789, 545, 403, 545, 545, 976, 976, 546, 976, - 547, 548, 792, 792, 792, 792, 545, 403, 545, 545, - 976, 976, 546, 976, 547, 548, 792, 792, 792, 792, - 797, 669, 797, 797, 976, 976, 798, 976, 799, 800, - 801, 801, 801, 801, 797, 669, 797, 797, 976, 976, - 798, 976, 799, 800, 801, 801, 801, 801, 669, 669, - - 669, 669, 976, 976, 670, 976, 976, 976, 803, 803, - 803, 803, 557, 407, 557, 557, 976, 976, 558, 976, - 559, 805, 806, 806, 806, 806, 557, 407, 557, 557, - 976, 976, 558, 976, 559, 560, 882, 882, 882, 882, - 673, 674, 673, 673, 976, 976, 675, 976, 976, 805, - 806, 806, 806, 806, 976, 976, 976, 883, 560, 818, - 818, 818, 818, 976, 976, 976, 676, 973, 959, 974, - 973, 976, 976, 975, 976, 883, 669, 669, 669, 669, - 976, 976, 670, 976, 676, 808, 809, 809, 809, 809, - 976, 976, 976, 885, 973, 959, 974, 973, 976, 976, - - 975, 973, 966, 974, 973, 976, 976, 975, 976, 976, - 976, 885, 811, 674, 811, 811, 976, 976, 812, 976, - 813, 814, 815, 815, 815, 815, 811, 674, 811, 811, - 976, 976, 812, 976, 813, 814, 815, 815, 815, 815, - 324, 208, 324, 324, 976, 976, 325, 976, 326, 820, - 821, 821, 821, 821, 324, 208, 324, 324, 976, 976, - 325, 976, 326, 327, 888, 888, 888, 888, 678, 679, - 678, 678, 976, 976, 680, 976, 976, 820, 821, 821, - 821, 821, 976, 976, 976, 889, 973, 959, 974, 973, - 976, 976, 975, 976, 976, 976, 976, 976, 976, 976, - - 976, 976, 976, 889, 827, 679, 827, 827, 976, 976, - 828, 976, 829, 830, 831, 831, 831, 831, 674, 674, - 674, 674, 976, 976, 683, 976, 976, 824, 825, 825, - 825, 825, 976, 976, 976, 891, 976, 976, 976, 976, - 976, 976, 327, 834, 834, 834, 834, 976, 976, 976, - 414, 976, 976, 891, 827, 679, 827, 827, 976, 976, - 828, 976, 829, 830, 831, 831, 831, 831, 414, 674, - 674, 674, 674, 976, 976, 683, 976, 976, 976, 836, - 836, 836, 836, 572, 412, 572, 572, 976, 976, 573, - 976, 574, 838, 839, 839, 839, 839, 572, 412, 572, - - 572, 976, 976, 573, 976, 574, 575, 894, 894, 894, - 894, 686, 679, 686, 686, 976, 976, 687, 976, 976, - 838, 839, 839, 839, 839, 976, 976, 976, 895, 575, - 842, 842, 842, 842, 976, 976, 976, 688, 976, 976, - 976, 976, 976, 976, 976, 976, 895, 976, 976, 976, - 976, 976, 976, 976, 976, 688, 589, 420, 589, 589, - 976, 976, 590, 976, 591, 592, 847, 847, 847, 847, - 589, 420, 589, 589, 976, 976, 590, 976, 591, 592, - 847, 847, 847, 847, 346, 224, 346, 346, 976, 976, - 347, 976, 348, 349, 850, 850, 850, 850, 346, 224, - - 346, 346, 976, 976, 347, 976, 348, 349, 850, 850, - 850, 850, 420, 420, 420, 420, 976, 976, 421, 976, - 976, 976, 852, 852, 852, 852, 604, 425, 604, 604, - 976, 976, 605, 976, 606, 607, 855, 855, 855, 855, - 604, 425, 604, 604, 976, 976, 605, 976, 606, 607, - 855, 855, 855, 855, 721, 628, 721, 721, 976, 976, - 722, 976, 723, 724, 862, 862, 862, 862, 976, 976, - 976, 863, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 863, - 721, 628, 721, 721, 976, 976, 722, 901, 902, 724, - - 903, 903, 903, 903, 632, 633, 632, 632, 976, 976, - 634, 976, 473, 474, 864, 864, 864, 864, 976, 976, - 976, 865, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 865, - 471, 376, 471, 471, 976, 976, 472, 904, 905, 474, - 906, 906, 906, 906, 628, 628, 628, 628, 976, 976, - 629, 976, 976, 976, 866, 866, 866, 866, 976, 976, - 976, 867, 976, 976, 976, 976, 976, 976, 560, 930, - 930, 930, 930, 976, 976, 976, 676, 976, 976, 867, - 735, 633, 735, 735, 976, 976, 736, 976, 737, 738, - - 868, 868, 868, 868, 676, 976, 976, 869, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 869, 735, 633, 735, 735, - 976, 976, 736, 909, 910, 738, 911, 911, 911, 911, - 637, 638, 637, 637, 976, 976, 639, 976, 277, 278, - 870, 870, 870, 870, 976, 976, 976, 871, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 871, 275, 169, 275, 275, - 976, 976, 276, 912, 913, 278, 914, 914, 914, 914, - 633, 633, 633, 633, 976, 976, 642, 976, 976, 976, - - 872, 872, 872, 872, 976, 976, 976, 873, 976, 976, - 976, 976, 976, 976, 327, 938, 938, 938, 938, 976, - 976, 976, 414, 976, 976, 873, 751, 638, 751, 751, - 976, 976, 752, 976, 753, 754, 874, 874, 874, 874, - 414, 976, 976, 875, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 875, 751, 638, 751, 751, 976, 976, 752, 917, - 918, 754, 919, 919, 919, 919, 645, 638, 645, 645, - 976, 976, 646, 976, 488, 489, 876, 876, 876, 876, - 976, 976, 976, 877, 976, 976, 976, 976, 976, 976, - - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 877, 486, 381, 486, 486, 976, 976, 487, 920, - 921, 489, 922, 922, 922, 922, 632, 633, 632, 632, - 976, 976, 634, 470, 473, 976, 976, 976, 976, 976, - 976, 976, 976, 635, 575, 946, 946, 946, 946, 976, - 976, 976, 688, 976, 976, 976, 976, 976, 976, 976, - 976, 635, 628, 628, 628, 628, 976, 976, 629, 976, - 688, 976, 908, 908, 908, 908, 637, 638, 637, 637, - 976, 976, 639, 274, 277, 976, 976, 976, 976, 976, - 976, 976, 976, 383, 976, 976, 976, 976, 976, 976, - - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 383, 633, 633, 633, 633, 976, 976, 642, 976, - 976, 976, 916, 916, 916, 916, 645, 638, 645, 645, - 976, 976, 646, 485, 488, 976, 976, 976, 976, 976, - 976, 976, 976, 647, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 647, 669, 669, 669, 669, 976, 976, 670, 976, - 976, 976, 932, 932, 932, 932, 46, 46, 46, 46, - 46, 46, 46, 46, 81, 81, 81, 81, 81, 81, - 81, 81, 109, 109, 109, 109, 109, 109, 109, 109, - - 119, 119, 119, 119, 119, 119, 119, 119, 130, 130, - 976, 130, 130, 130, 130, 130, 131, 131, 976, 131, - 131, 131, 131, 131, 134, 976, 976, 134, 135, 976, - 976, 135, 172, 976, 976, 172, 976, 172, 172, 172, - 173, 173, 976, 173, 173, 173, 173, 173, 211, 976, - 976, 211, 976, 211, 211, 212, 212, 976, 212, 212, - 212, 212, 212, 227, 227, 976, 227, 976, 227, 227, - 227, 230, 230, 976, 230, 230, 230, 230, 230, 250, - 250, 250, 250, 250, 250, 250, 250, 263, 263, 263, - 263, 263, 263, 263, 263, 269, 269, 976, 976, 269, - - 269, 274, 274, 274, 274, 274, 274, 274, 274, 287, - 287, 287, 287, 287, 287, 287, 287, 298, 298, 298, - 298, 298, 298, 298, 298, 309, 309, 309, 309, 309, - 309, 309, 309, 323, 323, 323, 323, 323, 323, 323, - 323, 212, 212, 976, 212, 212, 212, 212, 212, 334, - 334, 334, 334, 334, 334, 334, 334, 345, 345, 345, - 345, 345, 345, 345, 345, 227, 227, 976, 227, 976, - 227, 227, 227, 230, 230, 976, 230, 230, 230, 230, - 230, 131, 131, 976, 131, 131, 131, 131, 131, 134, - 976, 976, 134, 250, 250, 250, 250, 250, 250, 250, - - 250, 263, 263, 263, 263, 263, 263, 263, 263, 269, - 269, 976, 976, 269, 269, 274, 274, 274, 274, 274, - 274, 274, 274, 439, 439, 439, 439, 439, 439, 439, - 439, 454, 454, 454, 454, 454, 454, 454, 454, 470, - 470, 470, 470, 470, 470, 470, 470, 485, 485, 485, - 485, 485, 485, 485, 485, 287, 287, 287, 287, 287, - 287, 287, 287, 502, 502, 502, 502, 502, 502, 502, - 502, 298, 298, 298, 298, 298, 298, 298, 298, 517, - 517, 517, 517, 517, 517, 517, 517, 529, 529, 529, - 529, 529, 529, 529, 529, 309, 309, 309, 309, 309, - - 309, 309, 309, 544, 544, 544, 544, 544, 544, 544, - 544, 556, 556, 556, 556, 556, 556, 556, 556, 323, - 323, 323, 323, 323, 323, 323, 323, 571, 571, 571, - 571, 571, 571, 571, 571, 334, 334, 334, 334, 334, - 334, 334, 334, 588, 588, 588, 588, 588, 588, 588, - 588, 345, 345, 345, 345, 345, 345, 345, 345, 603, - 603, 603, 603, 603, 603, 603, 603, 131, 131, 976, - 131, 131, 131, 131, 131, 134, 976, 976, 134, 439, - 439, 439, 439, 439, 439, 439, 439, 250, 250, 250, - 250, 250, 250, 250, 250, 454, 454, 454, 454, 454, - - 454, 454, 454, 470, 470, 470, 470, 470, 470, 470, - 470, 274, 274, 274, 274, 274, 274, 274, 274, 485, - 485, 485, 485, 485, 485, 485, 485, 287, 287, 287, - 287, 287, 287, 287, 287, 502, 502, 502, 502, 502, - 502, 502, 502, 298, 298, 298, 298, 298, 298, 298, - 298, 517, 517, 517, 517, 517, 517, 517, 517, 529, - 529, 529, 529, 529, 529, 529, 529, 309, 309, 309, - 309, 309, 309, 309, 309, 544, 544, 544, 544, 544, - 544, 544, 544, 556, 556, 556, 556, 556, 556, 556, - 556, 323, 323, 323, 323, 323, 323, 323, 323, 571, - - 571, 571, 571, 571, 571, 571, 571, 334, 334, 334, - 334, 334, 334, 334, 334, 588, 588, 588, 588, 588, - 588, 588, 588, 345, 345, 345, 345, 345, 345, 345, - 345, 603, 603, 603, 603, 603, 603, 603, 603, 131, - 131, 976, 131, 131, 131, 131, 131, 134, 976, 976, - 134, 439, 439, 439, 439, 439, 439, 439, 439, 250, - 250, 250, 250, 250, 250, 250, 250, 454, 454, 454, - 454, 454, 454, 454, 454, 720, 720, 720, 720, 720, - 720, 720, 720, 470, 470, 470, 470, 470, 470, 470, - 470, 734, 734, 734, 734, 734, 734, 734, 734, 274, - - 274, 274, 274, 274, 274, 274, 274, 750, 750, 750, - 750, 750, 750, 750, 750, 485, 485, 485, 485, 485, - 485, 485, 485, 502, 502, 502, 502, 502, 502, 502, - 502, 298, 298, 298, 298, 298, 298, 298, 298, 517, - 517, 517, 517, 517, 517, 517, 517, 529, 529, 529, - 529, 529, 529, 529, 529, 309, 309, 309, 309, 309, - 309, 309, 309, 544, 544, 544, 544, 544, 544, 544, - 544, 796, 796, 796, 796, 796, 796, 796, 796, 556, - 556, 556, 556, 556, 556, 556, 556, 810, 810, 810, - 810, 810, 810, 810, 810, 323, 323, 323, 323, 323, - - 323, 323, 323, 826, 826, 826, 826, 826, 826, 826, - 826, 571, 571, 571, 571, 571, 571, 571, 571, 588, - 588, 588, 588, 588, 588, 588, 588, 345, 345, 345, - 345, 345, 345, 345, 345, 603, 603, 603, 603, 603, - 603, 603, 603, 131, 131, 976, 131, 131, 131, 131, - 131, 134, 976, 976, 134, 439, 439, 439, 439, 439, - 439, 439, 439, 250, 250, 250, 250, 250, 250, 250, - 250, 454, 454, 454, 454, 454, 454, 454, 454, 720, - 720, 720, 720, 720, 720, 720, 720, 470, 470, 470, - 470, 470, 470, 470, 470, 734, 734, 734, 734, 734, - - 734, 734, 734, 274, 274, 274, 274, 274, 274, 274, - 274, 750, 750, 750, 750, 750, 750, 750, 750, 485, - 485, 485, 485, 485, 485, 485, 485, 502, 502, 502, - 502, 502, 502, 502, 502, 298, 298, 298, 298, 298, - 298, 298, 298, 517, 517, 517, 517, 517, 517, 517, - 517, 529, 529, 529, 529, 529, 529, 529, 529, 309, - 309, 309, 309, 309, 309, 309, 309, 544, 544, 544, - 544, 544, 544, 544, 544, 796, 796, 796, 796, 796, - 796, 796, 796, 556, 556, 556, 556, 556, 556, 556, - 556, 810, 810, 810, 810, 810, 810, 810, 810, 323, - - 323, 323, 323, 323, 323, 323, 323, 826, 826, 826, - 826, 826, 826, 826, 826, 571, 571, 571, 571, 571, - 571, 571, 571, 588, 588, 588, 588, 588, 588, 588, - 588, 345, 345, 345, 345, 345, 345, 345, 345, 603, - 603, 603, 603, 603, 603, 603, 603, 131, 131, 976, - 131, 131, 131, 131, 131, 134, 976, 976, 134, 720, - 720, 720, 720, 720, 720, 720, 720, 470, 470, 470, - 470, 470, 470, 470, 470, 734, 734, 734, 734, 734, - 734, 734, 734, 274, 274, 274, 274, 274, 274, 274, - 274, 750, 750, 750, 750, 750, 750, 750, 750, 485, - - 485, 485, 485, 485, 485, 485, 485, 958, 958, 958, - 958, 958, 958, 958, 958, 969, 969, 976, 969, 969, - 969, 969, 969, 972, 972, 972, 972, 972, 972, 972, - 972, 45, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976 - } ; - -static yyconst flex_int16_t yy_chk[8681] = - { 0, - 0, 1, 1, 1, 1, 0, 1039, 1, 2, 2, - 2, 2, 122, 122, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 5, 5, 5, 5, 61, 61, 5, - 9, 9, 9, 9, 9, 9, 66, 66, 66, 66, - 66, 5, 5, 10, 10, 10, 10, 10, 10, 1017, - 5, 6, 6, 6, 6, 229, 229, 6, 11, 11, - - 11, 11, 11, 11, 67, 67, 67, 67, 74, 6, - 6, 12, 12, 12, 12, 12, 12, 1014, 6, 7, - 7, 7, 7, 428, 74, 7, 428, 7, 7, 7, - 7, 7, 7, 69, 69, 69, 69, 69, 7, 13, - 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, - 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, - 16, 16, 16, 17, 17, 17, 17, 354, 17, 17, - 18, 18, 18, 18, 1012, 18, 18, 70, 70, 70, - 70, 354, 17, 19, 19, 19, 19, 19, 19, 18, - 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, - - 21, 21, 22, 22, 22, 22, 22, 22, 23, 23, - 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, - 25, 25, 25, 25, 25, 25, 267, 39, 39, 39, - 39, 25, 39, 39, 40, 40, 40, 40, 49, 40, - 40, 133, 267, 25, 1006, 25, 26, 26, 26, 26, - 26, 26, 47, 856, 47, 47, 856, 26, 47, 39, - 133, 49, 41, 41, 41, 41, 40, 41, 41, 26, - 950, 26, 27, 27, 27, 27, 27, 27, 235, 42, - 42, 42, 42, 27, 42, 42, 230, 230, 71, 71, - 71, 71, 71, 235, 41, 27, 71, 27, 28, 28, - - 28, 28, 28, 28, 72, 72, 72, 72, 950, 28, - 999, 42, 231, 231, 71, 75, 75, 75, 75, 947, - 465, 28, 947, 28, 29, 29, 29, 29, 29, 29, - 77, 77, 77, 77, 994, 29, 465, 43, 43, 43, - 43, 43, 43, 79, 79, 79, 79, 29, 43, 29, - 30, 30, 30, 30, 30, 30, 78, 78, 78, 78, - 78, 30, 952, 44, 44, 44, 44, 44, 44, 86, - 86, 86, 86, 30, 44, 30, 31, 31, 31, 31, - 31, 31, 85, 85, 85, 85, 85, 31, 76, 76, - 76, 76, 83, 949, 83, 83, 432, 83, 83, 31, - - 432, 31, 32, 32, 32, 32, 32, 32, 76, 89, - 89, 89, 89, 32, 87, 87, 87, 87, 87, 948, - 699, 898, 87, 612, 76, 32, 699, 32, 33, 33, - 33, 33, 897, 33, 33, 88, 88, 88, 88, 88, - 87, 91, 91, 91, 91, 91, 612, 33, 92, 92, - 92, 92, 94, 94, 94, 94, 94, 901, 901, 33, - 292, 33, 34, 34, 34, 34, 859, 34, 34, 95, - 95, 95, 95, 100, 100, 100, 100, 100, 292, 902, - 902, 34, 101, 101, 101, 101, 102, 102, 102, 102, - 102, 904, 904, 34, 102, 34, 35, 35, 35, 35, - - 35, 35, 103, 103, 103, 103, 857, 35, 104, 104, - 104, 104, 102, 105, 105, 105, 105, 905, 905, 35, - 703, 35, 36, 36, 36, 36, 36, 36, 104, 107, - 107, 107, 107, 36, 106, 106, 106, 106, 106, 113, - 113, 113, 113, 113, 104, 36, 702, 36, 37, 37, - 37, 37, 37, 37, 339, 111, 700, 111, 111, 37, - 111, 111, 114, 114, 114, 114, 116, 116, 116, 116, - 116, 37, 339, 37, 38, 38, 38, 38, 38, 38, - 117, 117, 117, 117, 616, 38, 111, 120, 111, 120, - 120, 466, 128, 120, 128, 128, 444, 38, 128, 38, - - 68, 68, 68, 68, 459, 615, 68, 466, 953, 68, - 68, 68, 68, 68, 444, 909, 909, 68, 125, 125, - 125, 125, 459, 126, 126, 126, 126, 127, 127, 127, - 127, 150, 150, 150, 150, 68, 73, 73, 73, 73, - 896, 614, 73, 126, 896, 953, 73, 73, 73, 73, - 152, 152, 152, 152, 152, 910, 910, 155, 155, 126, - 155, 155, 155, 155, 912, 912, 73, 156, 156, 156, - 156, 157, 157, 157, 157, 157, 913, 913, 613, 157, - 498, 507, 73, 80, 80, 80, 80, 522, 433, 80, - 917, 917, 80, 80, 80, 80, 80, 157, 498, 507, - - 80, 158, 158, 158, 158, 522, 159, 159, 158, 159, - 159, 159, 159, 164, 164, 164, 164, 429, 80, 90, - 90, 90, 90, 918, 918, 90, 158, 534, 90, 90, - 90, 90, 90, 955, 549, 161, 90, 161, 161, 161, - 161, 163, 163, 163, 163, 534, 362, 163, 166, 166, - 166, 166, 549, 584, 90, 93, 93, 93, 93, 920, - 920, 93, 593, 955, 93, 93, 93, 93, 93, 921, - 921, 584, 93, 168, 168, 168, 168, 168, 171, 171, - 593, 171, 171, 171, 171, 176, 176, 176, 176, 956, - 93, 96, 96, 96, 96, 361, 956, 96, 360, 359, - - 96, 96, 96, 96, 96, 358, 357, 173, 96, 173, - 173, 355, 173, 173, 174, 246, 174, 174, 245, 174, - 174, 180, 180, 180, 180, 608, 96, 108, 108, 108, - 108, 244, 708, 108, 716, 243, 108, 108, 108, 108, - 108, 725, 739, 608, 108, 177, 177, 177, 177, 177, - 708, 242, 716, 177, 178, 178, 178, 178, 240, 725, - 739, 178, 108, 115, 115, 115, 115, 239, 238, 115, - 237, 177, 115, 115, 115, 115, 115, 149, 147, 178, - 115, 179, 179, 146, 179, 179, 179, 179, 182, 182, - 182, 182, 182, 186, 186, 186, 186, 145, 115, 118, - - 118, 118, 118, 144, 143, 118, 141, 140, 118, 118, - 118, 118, 118, 139, 185, 185, 118, 185, 185, 185, - 185, 188, 188, 188, 188, 188, 191, 191, 137, 191, - 191, 191, 191, 136, 118, 153, 153, 153, 153, 132, - 131, 153, 129, 153, 153, 153, 153, 153, 153, 154, - 154, 154, 154, 123, 755, 154, 112, 154, 154, 154, - 154, 154, 154, 162, 162, 162, 162, 97, 84, 162, - 65, 162, 755, 162, 162, 162, 162, 169, 169, 169, - 169, 64, 63, 169, 62, 169, 169, 169, 169, 169, - 169, 170, 170, 170, 170, 60, 59, 170, 58, 170, - - 170, 170, 170, 170, 170, 183, 183, 183, 183, 57, - 56, 183, 55, 183, 183, 183, 183, 183, 183, 184, - 184, 184, 184, 54, 53, 184, 51, 184, 184, 184, - 184, 184, 184, 189, 189, 189, 189, 45, 0, 189, - 0, 189, 189, 189, 189, 189, 189, 190, 190, 190, - 190, 0, 0, 190, 0, 190, 190, 190, 190, 190, - 190, 192, 192, 192, 192, 194, 194, 194, 194, 194, - 195, 195, 195, 195, 0, 0, 195, 0, 195, 195, - 195, 195, 195, 195, 196, 196, 196, 196, 0, 0, - 196, 0, 196, 196, 196, 196, 196, 196, 197, 197, - - 0, 197, 197, 197, 197, 199, 199, 199, 199, 200, - 200, 200, 200, 200, 0, 0, 771, 200, 201, 201, - 201, 201, 779, 202, 202, 201, 202, 202, 202, 202, - 203, 203, 203, 203, 771, 200, 205, 205, 205, 205, - 779, 0, 0, 201, 207, 207, 207, 207, 207, 208, - 208, 208, 208, 0, 0, 208, 0, 208, 208, 208, - 208, 208, 208, 209, 209, 209, 209, 784, 0, 209, - 792, 209, 209, 209, 209, 209, 209, 210, 210, 0, - 210, 210, 210, 210, 212, 784, 212, 212, 792, 212, - 212, 213, 0, 213, 213, 0, 213, 213, 215, 215, - - 215, 215, 217, 217, 217, 217, 217, 220, 220, 0, - 220, 220, 220, 220, 801, 212, 0, 212, 221, 221, - 221, 221, 213, 815, 213, 216, 216, 216, 216, 0, - 0, 216, 801, 0, 216, 216, 216, 216, 216, 0, - 0, 815, 216, 223, 223, 223, 223, 223, 226, 226, - 831, 226, 226, 226, 226, 233, 233, 233, 233, 0, - 216, 218, 218, 218, 218, 0, 0, 218, 831, 218, - 218, 218, 218, 218, 218, 219, 219, 219, 219, 847, - 0, 219, 0, 219, 219, 219, 219, 219, 219, 222, - 222, 222, 222, 0, 0, 222, 0, 847, 222, 222, - - 222, 222, 222, 855, 0, 228, 222, 228, 228, 0, - 0, 228, 247, 247, 247, 247, 247, 248, 248, 248, - 248, 855, 0, 0, 222, 224, 224, 224, 224, 0, - 0, 224, 0, 224, 224, 224, 224, 224, 224, 225, - 225, 225, 225, 0, 0, 225, 0, 225, 225, 225, - 225, 225, 225, 249, 249, 249, 249, 0, 0, 249, - 0, 0, 249, 249, 249, 249, 249, 0, 0, 0, - 249, 254, 254, 254, 254, 256, 256, 256, 256, 258, - 258, 258, 258, 259, 259, 259, 259, 0, 249, 250, - 250, 250, 250, 0, 0, 250, 0, 250, 250, 250, - - 250, 250, 250, 251, 251, 251, 251, 0, 0, 251, - 0, 251, 251, 251, 251, 251, 251, 255, 255, 255, - 255, 0, 0, 255, 260, 260, 260, 260, 262, 262, - 262, 262, 0, 0, 255, 0, 0, 261, 261, 261, - 261, 269, 269, 269, 269, 0, 0, 269, 272, 272, - 272, 272, 255, 257, 257, 257, 257, 261, 0, 257, - 0, 0, 0, 257, 257, 257, 257, 271, 271, 271, - 271, 271, 0, 261, 263, 263, 263, 263, 957, 957, - 263, 0, 263, 957, 263, 263, 263, 263, 264, 264, - 264, 264, 958, 958, 264, 0, 264, 958, 264, 264, - - 264, 264, 273, 273, 273, 273, 0, 0, 273, 0, - 0, 273, 273, 273, 273, 273, 0, 0, 0, 273, - 278, 278, 278, 278, 280, 280, 280, 280, 282, 282, - 282, 282, 283, 283, 283, 283, 0, 273, 274, 274, - 274, 274, 0, 0, 274, 0, 274, 274, 274, 274, - 274, 274, 275, 275, 275, 275, 0, 0, 275, 0, - 275, 275, 275, 275, 275, 275, 279, 279, 279, 279, - 0, 0, 279, 284, 284, 284, 284, 284, 285, 285, - 285, 285, 0, 279, 286, 286, 286, 286, 286, 0, - 0, 0, 286, 291, 291, 291, 291, 293, 293, 293, - - 293, 279, 281, 281, 281, 281, 961, 961, 281, 0, - 286, 961, 281, 281, 281, 281, 287, 287, 287, 287, - 0, 0, 287, 0, 287, 287, 287, 287, 287, 287, - 294, 294, 294, 294, 0, 0, 294, 0, 0, 0, - 294, 294, 294, 294, 295, 295, 295, 295, 295, 296, - 296, 296, 296, 297, 297, 297, 297, 0, 0, 297, - 0, 0, 297, 297, 297, 297, 297, 0, 0, 0, - 297, 302, 302, 302, 302, 0, 303, 303, 303, 303, - 0, 0, 303, 304, 304, 304, 304, 0, 297, 298, - 298, 298, 298, 303, 0, 298, 0, 298, 298, 298, - - 298, 298, 298, 306, 306, 306, 306, 306, 0, 903, - 903, 303, 305, 305, 305, 305, 0, 0, 305, 903, - 0, 0, 305, 305, 305, 305, 307, 307, 307, 307, - 308, 308, 308, 308, 0, 0, 308, 903, 0, 308, - 308, 308, 308, 308, 0, 0, 0, 308, 313, 313, - 313, 313, 0, 314, 314, 314, 314, 0, 0, 314, - 315, 315, 315, 315, 0, 308, 309, 309, 309, 309, - 314, 0, 309, 0, 309, 309, 309, 309, 309, 309, - 317, 317, 317, 317, 318, 318, 318, 318, 314, 316, - 316, 316, 316, 0, 0, 316, 0, 0, 0, 316, - - 316, 316, 316, 320, 320, 320, 320, 320, 321, 321, - 321, 321, 322, 322, 322, 322, 0, 0, 322, 0, - 0, 322, 322, 322, 322, 322, 0, 0, 0, 322, - 327, 327, 327, 327, 0, 328, 328, 328, 328, 0, - 0, 328, 329, 329, 329, 329, 0, 322, 323, 323, - 323, 323, 328, 0, 323, 0, 323, 323, 323, 323, - 323, 323, 331, 331, 331, 331, 331, 0, 911, 911, - 328, 330, 330, 330, 330, 0, 0, 330, 911, 0, - 0, 330, 330, 330, 330, 332, 332, 332, 332, 333, - 333, 333, 333, 333, 0, 0, 911, 333, 338, 338, - - 338, 338, 340, 340, 340, 340, 342, 342, 342, 342, - 342, 343, 343, 343, 343, 333, 334, 334, 334, 334, - 0, 0, 334, 0, 334, 334, 334, 334, 334, 334, - 341, 341, 341, 341, 0, 0, 341, 0, 919, 919, - 341, 341, 341, 341, 344, 344, 344, 344, 919, 0, - 344, 0, 0, 344, 344, 344, 344, 344, 0, 0, - 0, 344, 349, 349, 349, 349, 919, 350, 350, 350, - 350, 0, 0, 350, 351, 351, 351, 351, 0, 344, - 345, 345, 345, 345, 350, 0, 345, 0, 345, 345, - 345, 345, 345, 345, 364, 364, 364, 364, 364, 0, - - 0, 0, 350, 352, 352, 352, 352, 0, 0, 352, - 0, 0, 0, 352, 352, 352, 352, 365, 365, 365, - 365, 0, 0, 365, 0, 365, 365, 365, 365, 365, - 365, 366, 366, 366, 366, 0, 0, 366, 0, 366, - 366, 366, 366, 366, 366, 367, 367, 0, 367, 367, - 367, 367, 368, 368, 368, 368, 0, 0, 368, 0, - 0, 0, 368, 368, 368, 368, 0, 372, 372, 368, - 372, 372, 372, 372, 375, 375, 375, 375, 375, 378, - 378, 0, 378, 378, 378, 378, 0, 368, 369, 369, - 369, 369, 369, 369, 0, 0, 0, 369, 384, 384, - - 384, 384, 0, 385, 385, 384, 385, 385, 385, 385, - 436, 436, 436, 436, 436, 369, 370, 370, 370, 370, - 0, 0, 370, 384, 370, 370, 370, 370, 370, 370, - 371, 371, 371, 371, 0, 0, 371, 0, 371, 371, - 371, 371, 371, 371, 374, 374, 374, 374, 374, 374, - 374, 374, 374, 391, 391, 0, 391, 391, 391, 391, - 400, 400, 0, 400, 400, 400, 400, 0, 374, 374, - 374, 376, 376, 376, 376, 0, 0, 376, 0, 376, - 376, 376, 376, 376, 376, 377, 377, 377, 377, 0, - 0, 377, 0, 377, 377, 377, 377, 377, 377, 379, - - 379, 379, 379, 0, 0, 379, 0, 0, 0, 379, - 379, 379, 379, 0, 409, 409, 379, 409, 409, 409, - 409, 415, 415, 415, 415, 0, 416, 416, 415, 416, - 416, 416, 416, 0, 379, 380, 380, 380, 380, 380, - 380, 0, 0, 0, 380, 0, 415, 422, 422, 0, - 422, 422, 422, 422, 437, 437, 437, 437, 443, 443, - 443, 443, 380, 381, 381, 381, 381, 0, 0, 381, - 0, 381, 381, 381, 381, 381, 381, 382, 382, 382, - 382, 0, 0, 382, 0, 382, 382, 382, 382, 382, - 382, 383, 383, 383, 383, 0, 0, 383, 383, 383, - - 0, 383, 383, 383, 383, 0, 0, 0, 383, 445, - 445, 445, 445, 0, 0, 438, 438, 438, 438, 438, - 0, 0, 0, 438, 0, 0, 383, 386, 386, 386, - 386, 0, 0, 386, 0, 386, 386, 386, 386, 386, - 386, 438, 0, 0, 386, 451, 451, 451, 451, 451, - 452, 452, 452, 452, 458, 458, 458, 458, 460, 460, - 460, 460, 386, 387, 387, 387, 387, 0, 0, 387, - 387, 387, 387, 387, 387, 387, 387, 388, 388, 388, - 388, 0, 0, 388, 0, 0, 0, 388, 388, 388, - 388, 0, 0, 0, 388, 461, 461, 461, 461, 467, - - 467, 467, 467, 467, 468, 468, 468, 468, 474, 474, - 474, 474, 388, 389, 389, 389, 389, 0, 0, 389, - 0, 389, 389, 389, 389, 389, 389, 390, 390, 390, - 390, 0, 0, 390, 0, 390, 390, 390, 390, 390, - 390, 392, 392, 392, 392, 0, 0, 392, 0, 392, - 392, 392, 392, 392, 392, 0, 0, 0, 392, 476, - 476, 476, 476, 482, 482, 482, 482, 482, 483, 483, - 483, 483, 489, 489, 489, 489, 392, 393, 393, 393, - 393, 0, 0, 393, 0, 393, 393, 393, 393, 393, - 393, 394, 394, 394, 394, 0, 0, 394, 0, 394, - - 394, 394, 394, 394, 394, 395, 395, 395, 395, 0, - 0, 395, 0, 395, 395, 395, 395, 395, 395, 396, - 396, 396, 396, 0, 0, 396, 396, 396, 396, 396, - 396, 396, 396, 397, 397, 397, 397, 0, 0, 397, - 0, 0, 0, 397, 397, 397, 397, 0, 0, 0, - 397, 491, 491, 491, 491, 492, 492, 492, 492, 494, - 494, 494, 494, 495, 495, 495, 495, 0, 397, 398, - 398, 398, 398, 0, 0, 398, 0, 398, 398, 398, - 398, 398, 398, 399, 399, 399, 399, 0, 0, 399, - 0, 399, 399, 399, 399, 399, 399, 401, 401, 401, - - 401, 0, 0, 401, 0, 401, 401, 401, 401, 401, - 401, 0, 0, 0, 401, 499, 499, 499, 499, 499, - 500, 500, 500, 500, 506, 506, 506, 506, 508, 508, - 508, 508, 401, 402, 402, 402, 402, 0, 0, 402, - 0, 402, 402, 402, 402, 402, 402, 403, 403, 403, - 403, 0, 0, 403, 0, 403, 403, 403, 403, 403, - 403, 404, 404, 404, 404, 0, 0, 404, 0, 404, - 404, 404, 404, 404, 404, 405, 405, 405, 405, 0, - 0, 405, 405, 405, 405, 405, 405, 405, 405, 406, - 406, 406, 406, 0, 0, 406, 0, 0, 0, 406, - - 406, 406, 406, 0, 0, 0, 406, 514, 514, 514, - 514, 514, 515, 515, 515, 515, 521, 521, 521, 521, - 523, 523, 523, 523, 406, 407, 407, 407, 407, 0, - 0, 407, 0, 407, 407, 407, 407, 407, 407, 408, - 408, 408, 408, 0, 0, 408, 0, 408, 408, 408, - 408, 408, 408, 410, 410, 410, 410, 0, 0, 410, - 0, 410, 410, 410, 410, 410, 410, 0, 0, 0, - 410, 524, 524, 524, 524, 526, 526, 526, 526, 526, - 527, 527, 527, 527, 533, 533, 533, 533, 410, 411, - 411, 411, 411, 0, 0, 411, 0, 411, 411, 411, - - 411, 411, 411, 412, 412, 412, 412, 0, 0, 412, - 0, 412, 412, 412, 412, 412, 412, 413, 413, 413, - 413, 0, 0, 413, 0, 413, 413, 413, 413, 413, - 413, 414, 414, 414, 414, 0, 0, 414, 414, 414, - 414, 414, 414, 414, 414, 417, 417, 417, 417, 0, - 0, 417, 0, 417, 417, 417, 417, 417, 417, 0, - 0, 0, 417, 535, 535, 535, 535, 0, 475, 475, - 475, 475, 0, 0, 475, 541, 541, 541, 541, 541, - 417, 418, 418, 418, 418, 475, 0, 418, 418, 418, - 418, 418, 418, 418, 418, 419, 419, 419, 419, 0, - - 0, 419, 0, 475, 0, 419, 419, 419, 419, 0, - 0, 0, 419, 542, 542, 542, 542, 548, 548, 548, - 548, 550, 550, 550, 550, 551, 551, 551, 551, 0, - 419, 420, 420, 420, 420, 0, 0, 420, 0, 420, - 420, 420, 420, 420, 420, 421, 421, 421, 421, 0, - 0, 421, 0, 421, 421, 421, 421, 421, 421, 423, - 423, 423, 423, 0, 0, 423, 0, 423, 423, 423, - 423, 423, 423, 0, 0, 0, 423, 553, 553, 553, - 553, 553, 554, 554, 554, 554, 560, 560, 560, 560, - 562, 562, 562, 562, 423, 424, 424, 424, 424, 0, - - 0, 424, 0, 424, 424, 424, 424, 424, 424, 425, - 425, 425, 425, 0, 0, 425, 0, 425, 425, 425, - 425, 425, 425, 426, 426, 426, 426, 0, 0, 426, - 0, 426, 426, 426, 426, 426, 426, 427, 427, 427, - 427, 0, 0, 427, 427, 427, 427, 427, 427, 427, - 427, 439, 439, 439, 439, 0, 0, 439, 0, 439, - 439, 439, 439, 439, 439, 440, 440, 440, 440, 0, - 0, 440, 0, 440, 440, 440, 440, 440, 440, 446, - 446, 446, 446, 0, 0, 446, 0, 0, 0, 446, - 446, 446, 446, 447, 447, 447, 447, 0, 0, 447, - - 0, 447, 447, 447, 447, 447, 447, 448, 448, 448, - 448, 0, 0, 448, 0, 448, 448, 448, 448, 448, - 448, 449, 449, 449, 449, 0, 0, 449, 0, 0, - 449, 449, 449, 449, 449, 0, 0, 0, 449, 568, - 568, 568, 568, 568, 490, 490, 490, 490, 0, 0, - 490, 569, 569, 569, 569, 0, 449, 450, 450, 450, - 450, 490, 0, 450, 0, 450, 450, 450, 450, 450, - 450, 453, 453, 453, 453, 0, 0, 453, 0, 490, - 453, 453, 453, 453, 453, 0, 0, 0, 453, 575, - 575, 575, 575, 0, 0, 462, 462, 462, 462, 462, - - 0, 0, 0, 462, 0, 0, 453, 454, 454, 454, - 454, 0, 0, 454, 0, 454, 454, 454, 454, 454, - 454, 462, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 464, 464, 464, 464, 464, 464, 464, 464, 464, 464, - 469, 469, 469, 469, 0, 0, 469, 0, 0, 469, - 469, 469, 469, 469, 0, 0, 0, 469, 577, 577, - 577, 577, 578, 578, 578, 578, 580, 580, 580, 580, - - 581, 581, 581, 581, 0, 469, 470, 470, 470, 470, - 0, 0, 470, 0, 470, 470, 470, 470, 470, 470, - 471, 471, 471, 471, 0, 0, 471, 0, 471, 471, - 471, 471, 471, 471, 477, 477, 477, 477, 0, 0, - 477, 0, 0, 0, 477, 477, 477, 477, 478, 478, - 478, 478, 0, 0, 478, 0, 478, 478, 478, 478, - 478, 478, 479, 479, 479, 479, 0, 0, 479, 0, - 479, 479, 479, 479, 479, 479, 480, 480, 480, 480, - 0, 0, 480, 0, 0, 480, 480, 480, 480, 480, - 0, 0, 0, 480, 585, 585, 585, 585, 585, 561, - - 561, 561, 561, 0, 0, 561, 586, 586, 586, 586, - 0, 480, 481, 481, 481, 481, 561, 0, 481, 0, - 481, 481, 481, 481, 481, 481, 484, 484, 484, 484, - 0, 0, 484, 0, 561, 484, 484, 484, 484, 484, - 0, 0, 0, 484, 592, 592, 592, 592, 0, 576, - 576, 576, 576, 0, 0, 576, 594, 594, 594, 594, - 0, 484, 485, 485, 485, 485, 576, 0, 485, 0, - 485, 485, 485, 485, 485, 485, 493, 493, 493, 493, - 0, 0, 493, 0, 576, 0, 493, 493, 493, 493, - 0, 0, 0, 493, 600, 600, 600, 600, 600, 601, - - 601, 601, 601, 607, 607, 607, 607, 609, 609, 609, - 609, 493, 496, 496, 496, 496, 0, 0, 496, 0, - 496, 496, 496, 496, 496, 496, 497, 497, 497, 497, - 0, 0, 497, 0, 497, 497, 497, 497, 497, 497, - 501, 501, 501, 501, 501, 0, 0, 0, 501, 610, - 610, 610, 610, 618, 618, 0, 618, 618, 618, 618, - 704, 704, 704, 704, 0, 0, 501, 502, 502, 502, - 502, 0, 0, 502, 0, 502, 502, 502, 502, 502, - 502, 503, 503, 503, 503, 0, 0, 503, 0, 503, - 503, 503, 503, 503, 503, 509, 509, 509, 509, 0, - - 0, 509, 0, 0, 0, 509, 509, 509, 509, 510, - 510, 510, 510, 0, 0, 510, 0, 510, 510, 510, - 510, 510, 510, 511, 511, 511, 511, 0, 0, 511, - 0, 511, 511, 511, 511, 511, 511, 512, 512, 512, - 512, 0, 0, 512, 0, 0, 512, 512, 512, 512, - 512, 0, 0, 0, 512, 617, 617, 617, 617, 0, - 624, 624, 617, 624, 624, 624, 624, 705, 705, 705, - 705, 0, 512, 513, 513, 513, 513, 0, 0, 513, - 617, 513, 513, 513, 513, 513, 513, 516, 516, 516, - 516, 0, 0, 516, 0, 0, 516, 516, 516, 516, - - 516, 0, 630, 630, 516, 630, 630, 630, 630, 0, - 0, 525, 525, 525, 525, 525, 0, 0, 0, 525, - 0, 0, 516, 517, 517, 517, 517, 0, 0, 517, - 0, 517, 517, 517, 517, 517, 517, 525, 528, 528, - 528, 528, 528, 0, 643, 643, 528, 643, 643, 643, - 643, 649, 649, 0, 649, 649, 649, 649, 712, 712, - 712, 712, 0, 0, 528, 529, 529, 529, 529, 0, - 0, 529, 0, 529, 529, 529, 529, 529, 529, 530, - 530, 530, 530, 0, 0, 530, 0, 530, 530, 530, - 530, 530, 530, 536, 536, 536, 536, 0, 0, 536, - - 0, 0, 0, 536, 536, 536, 536, 537, 537, 537, - 537, 0, 0, 537, 0, 537, 537, 537, 537, 537, - 537, 538, 538, 538, 538, 0, 0, 538, 0, 538, - 538, 538, 538, 538, 538, 539, 539, 539, 539, 0, - 0, 539, 0, 0, 539, 539, 539, 539, 539, 0, - 0, 0, 539, 648, 648, 648, 648, 0, 655, 655, - 648, 655, 655, 655, 655, 717, 717, 717, 717, 717, - 539, 540, 540, 540, 540, 0, 0, 540, 648, 540, - 540, 540, 540, 540, 540, 543, 543, 543, 543, 0, - 0, 543, 0, 0, 543, 543, 543, 543, 543, 0, - - 659, 659, 543, 659, 659, 659, 659, 0, 0, 552, - 552, 552, 552, 552, 0, 0, 0, 552, 0, 0, - 543, 544, 544, 544, 544, 0, 0, 544, 0, 544, - 544, 544, 544, 544, 544, 552, 555, 555, 555, 555, - 0, 0, 555, 0, 0, 555, 555, 555, 555, 555, - 0, 0, 0, 555, 658, 658, 658, 658, 0, 665, - 665, 658, 665, 665, 665, 665, 718, 718, 718, 718, - 0, 555, 556, 556, 556, 556, 0, 0, 556, 658, - 556, 556, 556, 556, 556, 556, 557, 557, 557, 557, - 0, 0, 557, 0, 557, 557, 557, 557, 557, 557, - - 563, 563, 563, 563, 0, 0, 563, 0, 0, 0, - 563, 563, 563, 563, 564, 564, 564, 564, 0, 0, - 564, 0, 564, 564, 564, 564, 564, 564, 565, 565, - 565, 565, 0, 0, 565, 0, 565, 565, 565, 565, - 565, 565, 566, 566, 566, 566, 0, 0, 566, 0, - 0, 566, 566, 566, 566, 566, 0, 671, 671, 566, - 671, 671, 671, 671, 684, 684, 0, 684, 684, 684, - 684, 724, 724, 724, 724, 0, 0, 566, 567, 567, - 567, 567, 0, 0, 567, 0, 567, 567, 567, 567, - 567, 567, 570, 570, 570, 570, 0, 0, 570, 0, - - 0, 570, 570, 570, 570, 570, 0, 0, 0, 570, - 689, 689, 689, 689, 0, 690, 690, 689, 690, 690, - 690, 690, 726, 726, 726, 726, 0, 570, 571, 571, - 571, 571, 0, 0, 571, 689, 571, 571, 571, 571, - 571, 571, 579, 579, 579, 579, 0, 0, 579, 0, - 0, 0, 579, 579, 579, 579, 0, 696, 696, 579, - 696, 696, 696, 696, 731, 731, 731, 731, 731, 732, - 732, 732, 732, 738, 738, 738, 738, 579, 582, 582, - 582, 582, 0, 0, 582, 0, 582, 582, 582, 582, - 582, 582, 583, 583, 583, 583, 0, 0, 583, 0, - - 583, 583, 583, 583, 583, 583, 587, 587, 587, 587, - 587, 0, 0, 0, 587, 740, 740, 740, 740, 741, - 741, 741, 741, 747, 747, 747, 747, 747, 748, 748, - 748, 748, 587, 588, 588, 588, 588, 0, 0, 588, - 0, 588, 588, 588, 588, 588, 588, 589, 589, 589, - 589, 0, 0, 589, 0, 589, 589, 589, 589, 589, - 589, 595, 595, 595, 595, 0, 0, 595, 0, 0, - 0, 595, 595, 595, 595, 596, 596, 596, 596, 0, - 0, 596, 0, 596, 596, 596, 596, 596, 596, 597, - 597, 597, 597, 0, 0, 597, 0, 597, 597, 597, - - 597, 597, 597, 598, 598, 598, 598, 0, 0, 598, - 0, 0, 598, 598, 598, 598, 598, 0, 0, 0, - 598, 754, 754, 754, 754, 0, 711, 711, 711, 711, - 0, 0, 711, 756, 756, 756, 756, 0, 598, 599, - 599, 599, 599, 711, 0, 599, 0, 599, 599, 599, - 599, 599, 599, 602, 602, 602, 602, 0, 0, 602, - 0, 711, 602, 602, 602, 602, 602, 0, 0, 0, - 602, 757, 757, 757, 757, 0, 0, 611, 611, 611, - 611, 611, 0, 0, 0, 611, 0, 0, 602, 603, - 603, 603, 603, 0, 0, 603, 0, 603, 603, 603, - - 603, 603, 603, 611, 619, 619, 619, 619, 0, 0, - 619, 0, 619, 619, 619, 619, 619, 619, 0, 0, - 0, 619, 759, 759, 759, 759, 764, 764, 764, 764, - 765, 765, 765, 765, 767, 767, 767, 767, 0, 619, - 620, 620, 620, 620, 0, 0, 620, 620, 620, 620, - 620, 620, 620, 620, 621, 621, 621, 621, 0, 0, - 621, 0, 621, 621, 621, 621, 621, 621, 0, 0, - 0, 621, 768, 768, 768, 768, 0, 774, 774, 774, - 774, 0, 0, 774, 775, 775, 775, 775, 0, 621, - 622, 622, 622, 622, 774, 0, 622, 622, 622, 622, - - 622, 622, 622, 622, 623, 623, 623, 623, 0, 0, - 623, 0, 774, 0, 623, 623, 623, 623, 0, 0, - 0, 623, 780, 780, 780, 780, 0, 0, 719, 719, - 719, 719, 719, 0, 0, 0, 719, 0, 0, 623, - 625, 625, 625, 625, 0, 0, 625, 0, 625, 625, - 625, 625, 625, 625, 719, 0, 0, 625, 781, 781, - 781, 781, 0, 787, 787, 787, 787, 0, 0, 787, - 788, 788, 788, 788, 0, 625, 626, 626, 626, 626, - 787, 0, 626, 626, 626, 626, 626, 626, 626, 626, - 627, 627, 627, 627, 0, 0, 627, 0, 787, 0, - - 627, 627, 627, 627, 0, 0, 0, 627, 793, 793, - 793, 793, 793, 794, 794, 794, 794, 800, 800, 800, - 800, 802, 802, 802, 802, 627, 628, 628, 628, 628, - 0, 0, 628, 0, 628, 628, 628, 628, 628, 628, - 629, 629, 629, 629, 0, 0, 629, 0, 629, 629, - 629, 629, 629, 629, 631, 631, 631, 631, 0, 0, - 631, 0, 631, 631, 631, 631, 631, 631, 0, 0, - 0, 631, 807, 807, 807, 807, 807, 808, 808, 808, - 808, 814, 814, 814, 814, 816, 816, 816, 816, 631, - 632, 632, 632, 632, 0, 0, 632, 0, 632, 632, - - 632, 632, 632, 632, 633, 633, 633, 633, 0, 0, - 633, 0, 633, 633, 633, 633, 633, 633, 634, 634, - 634, 634, 0, 0, 634, 0, 634, 634, 634, 634, - 634, 634, 635, 635, 635, 635, 0, 0, 635, 635, - 635, 635, 635, 635, 635, 635, 636, 636, 636, 636, - 0, 0, 636, 0, 636, 636, 636, 636, 636, 636, - 0, 0, 0, 636, 817, 817, 817, 817, 823, 823, - 823, 823, 823, 824, 824, 824, 824, 830, 830, 830, - 830, 636, 637, 637, 637, 637, 0, 0, 637, 0, - 637, 637, 637, 637, 637, 637, 638, 638, 638, 638, - - 0, 0, 638, 0, 638, 638, 638, 638, 638, 638, - 639, 639, 639, 639, 0, 0, 639, 0, 639, 639, - 639, 639, 639, 639, 640, 640, 640, 640, 0, 0, - 640, 640, 640, 640, 640, 640, 640, 640, 641, 641, - 641, 641, 0, 0, 641, 0, 0, 0, 641, 641, - 641, 641, 0, 0, 0, 641, 832, 832, 832, 832, - 833, 833, 833, 833, 835, 835, 835, 835, 840, 840, - 840, 840, 0, 641, 642, 642, 642, 642, 0, 0, - 642, 0, 642, 642, 642, 642, 642, 642, 644, 644, - 644, 644, 0, 0, 644, 0, 644, 644, 644, 644, - - 644, 644, 0, 0, 0, 644, 841, 841, 841, 841, - 843, 843, 843, 843, 844, 844, 844, 844, 851, 851, - 851, 851, 0, 644, 645, 645, 645, 645, 0, 0, - 645, 0, 645, 645, 645, 645, 645, 645, 646, 646, - 646, 646, 0, 0, 646, 0, 646, 646, 646, 646, - 646, 646, 647, 647, 647, 647, 0, 0, 647, 647, - 647, 647, 647, 647, 647, 647, 650, 650, 650, 650, - 0, 0, 650, 0, 650, 650, 650, 650, 650, 650, - 0, 861, 861, 650, 861, 861, 861, 861, 867, 867, - 0, 867, 867, 867, 867, 882, 882, 882, 882, 882, - - 0, 650, 651, 651, 651, 651, 0, 0, 651, 651, - 651, 651, 651, 651, 651, 651, 652, 652, 652, 652, - 0, 0, 652, 0, 652, 652, 652, 652, 652, 652, - 0, 873, 873, 652, 873, 873, 873, 873, 0, 850, - 850, 850, 850, 879, 879, 850, 879, 879, 879, 879, - 0, 652, 653, 653, 653, 653, 850, 0, 653, 653, - 653, 653, 653, 653, 653, 653, 654, 654, 654, 654, - 0, 0, 654, 0, 850, 0, 654, 654, 654, 654, - 0, 881, 881, 654, 881, 881, 881, 881, 0, 0, - 742, 742, 742, 742, 742, 0, 0, 0, 742, 0, - - 0, 654, 656, 656, 656, 656, 0, 0, 656, 0, - 656, 656, 656, 656, 656, 656, 742, 883, 883, 656, - 883, 883, 883, 883, 884, 884, 884, 884, 884, 885, - 885, 0, 885, 885, 885, 885, 0, 656, 657, 657, - 657, 657, 0, 0, 657, 657, 657, 657, 657, 657, - 657, 657, 660, 660, 660, 660, 0, 0, 660, 0, - 660, 660, 660, 660, 660, 660, 0, 887, 887, 660, - 887, 887, 887, 887, 888, 888, 888, 888, 888, 889, - 889, 0, 889, 889, 889, 889, 0, 660, 661, 661, - 661, 661, 0, 0, 661, 661, 661, 661, 661, 661, - - 661, 661, 662, 662, 662, 662, 0, 0, 662, 0, - 662, 662, 662, 662, 662, 662, 0, 0, 0, 662, - 890, 890, 890, 890, 890, 891, 891, 0, 891, 891, - 891, 891, 894, 894, 894, 894, 894, 662, 663, 663, - 663, 663, 0, 0, 663, 663, 663, 663, 663, 663, - 663, 663, 664, 664, 664, 664, 0, 0, 664, 0, - 0, 0, 664, 664, 664, 664, 0, 893, 893, 664, - 893, 893, 893, 893, 0, 0, 758, 758, 758, 758, - 758, 0, 0, 0, 758, 0, 0, 664, 666, 666, - 666, 666, 0, 0, 666, 0, 666, 666, 666, 666, - - 666, 666, 758, 895, 895, 666, 895, 895, 895, 895, - 899, 899, 899, 899, 900, 900, 900, 900, 907, 907, - 907, 907, 0, 666, 667, 667, 667, 667, 0, 0, - 667, 667, 667, 667, 667, 667, 667, 667, 668, 668, - 668, 668, 0, 0, 668, 0, 0, 0, 668, 668, - 668, 668, 0, 0, 0, 668, 860, 860, 860, 860, - 0, 0, 0, 860, 915, 915, 915, 915, 923, 923, - 923, 923, 0, 668, 669, 669, 669, 669, 0, 0, - 669, 860, 669, 669, 669, 669, 669, 669, 670, 670, - 670, 670, 0, 0, 670, 0, 670, 670, 670, 670, - - 670, 670, 672, 672, 672, 672, 0, 0, 672, 0, - 672, 672, 672, 672, 672, 672, 0, 0, 0, 672, - 878, 878, 878, 878, 0, 0, 0, 878, 924, 924, - 924, 924, 925, 925, 925, 925, 0, 672, 673, 673, - 673, 673, 0, 0, 673, 878, 673, 673, 673, 673, - 673, 673, 674, 674, 674, 674, 0, 0, 674, 0, - 674, 674, 674, 674, 674, 674, 675, 675, 675, 675, - 0, 0, 675, 0, 675, 675, 675, 675, 675, 675, - 676, 676, 676, 676, 0, 0, 676, 676, 676, 676, - 676, 676, 676, 676, 677, 677, 677, 677, 0, 0, - - 677, 0, 677, 677, 677, 677, 677, 677, 0, 0, - 0, 677, 880, 880, 880, 880, 0, 0, 0, 880, - 926, 926, 926, 926, 928, 928, 928, 928, 0, 677, - 678, 678, 678, 678, 0, 0, 678, 880, 678, 678, - 678, 678, 678, 678, 679, 679, 679, 679, 0, 0, - 679, 0, 679, 679, 679, 679, 679, 679, 680, 680, - 680, 680, 0, 0, 680, 0, 680, 680, 680, 680, - 680, 680, 681, 681, 681, 681, 0, 0, 681, 681, - 681, 681, 681, 681, 681, 681, 682, 682, 682, 682, - 0, 0, 682, 0, 0, 0, 682, 682, 682, 682, - - 0, 0, 0, 682, 886, 886, 886, 886, 0, 0, - 0, 886, 929, 929, 929, 929, 931, 931, 931, 931, - 0, 682, 683, 683, 683, 683, 0, 0, 683, 886, - 683, 683, 683, 683, 683, 683, 685, 685, 685, 685, - 0, 0, 685, 0, 685, 685, 685, 685, 685, 685, - 0, 0, 0, 685, 892, 892, 892, 892, 0, 0, - 0, 892, 933, 933, 933, 933, 934, 934, 934, 934, - 0, 685, 686, 686, 686, 686, 0, 0, 686, 892, - 686, 686, 686, 686, 686, 686, 687, 687, 687, 687, - 0, 0, 687, 0, 687, 687, 687, 687, 687, 687, - - 688, 688, 688, 688, 0, 0, 688, 688, 688, 688, - 688, 688, 688, 688, 691, 691, 691, 691, 0, 0, - 691, 0, 691, 691, 691, 691, 691, 691, 0, 0, - 0, 691, 936, 936, 936, 936, 937, 937, 937, 937, - 939, 939, 939, 939, 940, 940, 940, 940, 0, 691, - 692, 692, 692, 692, 0, 0, 692, 692, 692, 692, - 692, 692, 692, 692, 693, 693, 693, 693, 0, 0, - 693, 0, 693, 693, 693, 693, 693, 693, 0, 0, - 0, 693, 941, 941, 941, 941, 942, 942, 942, 942, - 944, 944, 944, 944, 945, 945, 945, 945, 0, 693, - - 694, 694, 694, 694, 0, 0, 694, 694, 694, 694, - 694, 694, 694, 694, 695, 695, 695, 695, 0, 0, - 695, 0, 0, 0, 695, 695, 695, 695, 0, 0, - 959, 695, 959, 959, 0, 0, 959, 0, 766, 766, - 766, 766, 766, 0, 0, 0, 766, 0, 0, 695, - 697, 697, 697, 697, 0, 0, 697, 0, 697, 697, - 697, 697, 697, 697, 766, 0, 0, 697, 960, 960, - 960, 960, 0, 962, 960, 962, 962, 0, 963, 962, - 963, 963, 0, 0, 963, 697, 698, 698, 698, 698, - 0, 0, 698, 698, 698, 698, 698, 698, 698, 698, - - 706, 706, 706, 706, 0, 0, 706, 0, 706, 706, - 706, 706, 706, 706, 707, 707, 707, 707, 0, 0, - 707, 0, 707, 707, 707, 707, 707, 707, 709, 709, - 709, 709, 0, 0, 709, 0, 709, 709, 709, 709, - 709, 709, 710, 710, 710, 710, 0, 0, 710, 0, - 710, 710, 710, 710, 710, 710, 713, 713, 713, 713, - 0, 0, 713, 0, 0, 0, 713, 713, 713, 713, - 714, 714, 714, 714, 0, 0, 714, 0, 714, 714, - 714, 714, 714, 714, 715, 715, 715, 715, 0, 0, - 715, 0, 715, 715, 715, 715, 715, 715, 720, 720, - - 720, 720, 0, 0, 720, 0, 720, 720, 720, 720, - 720, 720, 721, 721, 721, 721, 0, 0, 721, 0, - 721, 721, 721, 721, 721, 721, 727, 727, 727, 727, - 0, 0, 727, 0, 0, 0, 727, 727, 727, 727, - 728, 728, 728, 728, 0, 0, 728, 0, 728, 728, - 728, 728, 728, 728, 729, 729, 729, 729, 0, 0, - 729, 0, 729, 729, 729, 729, 729, 729, 730, 730, - 730, 730, 0, 0, 730, 0, 0, 730, 730, 730, - 730, 730, 0, 0, 0, 730, 795, 795, 795, 795, - 795, 0, 0, 0, 795, 927, 927, 927, 927, 0, - - 0, 0, 927, 730, 733, 733, 733, 733, 0, 0, - 733, 0, 795, 733, 733, 733, 733, 733, 0, 0, - 927, 733, 935, 935, 935, 935, 0, 0, 964, 935, - 964, 964, 0, 0, 964, 0, 0, 0, 0, 733, - 734, 734, 734, 734, 0, 0, 734, 935, 734, 734, - 734, 734, 734, 734, 735, 735, 735, 735, 0, 0, - 735, 0, 735, 735, 735, 735, 735, 735, 743, 743, - 743, 743, 0, 0, 743, 0, 743, 743, 743, 743, - 743, 743, 744, 744, 744, 744, 0, 0, 744, 0, - 744, 744, 744, 744, 744, 744, 745, 745, 745, 745, - - 0, 0, 745, 0, 0, 745, 745, 745, 745, 745, - 0, 0, 0, 745, 943, 943, 943, 943, 0, 0, - 0, 943, 965, 965, 965, 965, 0, 0, 965, 0, - 0, 745, 746, 746, 746, 746, 0, 0, 746, 943, - 746, 746, 746, 746, 746, 746, 749, 749, 749, 749, - 0, 0, 749, 0, 0, 749, 749, 749, 749, 749, - 0, 0, 966, 749, 966, 966, 0, 0, 966, 967, - 967, 967, 967, 0, 969, 967, 969, 969, 0, 0, - 969, 749, 750, 750, 750, 750, 0, 0, 750, 0, - 750, 750, 750, 750, 750, 750, 760, 760, 760, 760, - - 0, 0, 760, 0, 0, 0, 760, 760, 760, 760, - 761, 761, 761, 761, 0, 0, 761, 0, 761, 761, - 761, 761, 761, 761, 762, 762, 762, 762, 0, 0, - 762, 0, 762, 762, 762, 762, 762, 762, 763, 763, - 763, 763, 0, 0, 763, 0, 0, 763, 763, 763, - 763, 763, 0, 0, 0, 763, 968, 968, 968, 968, - 0, 970, 968, 970, 970, 0, 971, 970, 971, 971, - 0, 0, 971, 763, 769, 769, 769, 769, 0, 0, - 769, 0, 769, 769, 769, 769, 769, 769, 770, 770, - 770, 770, 0, 0, 770, 0, 770, 770, 770, 770, - - 770, 770, 772, 772, 772, 772, 0, 0, 772, 0, - 772, 772, 772, 772, 772, 772, 773, 773, 773, 773, - 0, 0, 773, 0, 773, 773, 773, 773, 773, 773, - 776, 776, 776, 776, 0, 0, 776, 0, 0, 0, - 776, 776, 776, 776, 777, 777, 777, 777, 0, 0, - 777, 0, 777, 777, 777, 777, 777, 777, 778, 778, - 778, 778, 0, 0, 778, 0, 778, 778, 778, 778, - 778, 778, 782, 782, 782, 782, 0, 0, 782, 0, - 782, 782, 782, 782, 782, 782, 783, 783, 783, 783, - 0, 0, 783, 0, 783, 783, 783, 783, 783, 783, - - 785, 785, 785, 785, 0, 0, 785, 0, 785, 785, - 785, 785, 785, 785, 786, 786, 786, 786, 0, 0, - 786, 0, 786, 786, 786, 786, 786, 786, 789, 789, - 789, 789, 0, 0, 789, 0, 0, 0, 789, 789, - 789, 789, 790, 790, 790, 790, 0, 0, 790, 0, - 790, 790, 790, 790, 790, 790, 791, 791, 791, 791, - 0, 0, 791, 0, 791, 791, 791, 791, 791, 791, - 796, 796, 796, 796, 0, 0, 796, 0, 796, 796, - 796, 796, 796, 796, 797, 797, 797, 797, 0, 0, - 797, 0, 797, 797, 797, 797, 797, 797, 803, 803, - - 803, 803, 0, 0, 803, 0, 0, 0, 803, 803, - 803, 803, 804, 804, 804, 804, 0, 0, 804, 0, - 804, 804, 804, 804, 804, 804, 805, 805, 805, 805, - 0, 0, 805, 0, 805, 805, 805, 805, 805, 805, - 806, 806, 806, 806, 0, 0, 806, 0, 0, 806, - 806, 806, 806, 806, 0, 0, 0, 806, 818, 818, - 818, 818, 818, 0, 0, 0, 818, 972, 972, 972, - 972, 0, 0, 972, 0, 806, 809, 809, 809, 809, - 0, 0, 809, 0, 818, 809, 809, 809, 809, 809, - 0, 0, 0, 809, 973, 973, 973, 973, 0, 0, - - 973, 974, 974, 974, 974, 0, 0, 974, 0, 0, - 0, 809, 810, 810, 810, 810, 0, 0, 810, 0, - 810, 810, 810, 810, 810, 810, 811, 811, 811, 811, - 0, 0, 811, 0, 811, 811, 811, 811, 811, 811, - 819, 819, 819, 819, 0, 0, 819, 0, 819, 819, - 819, 819, 819, 819, 820, 820, 820, 820, 0, 0, - 820, 0, 820, 820, 820, 820, 820, 820, 821, 821, - 821, 821, 0, 0, 821, 0, 0, 821, 821, 821, - 821, 821, 0, 0, 0, 821, 975, 975, 975, 975, - 0, 0, 975, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 821, 822, 822, 822, 822, 0, 0, - 822, 0, 822, 822, 822, 822, 822, 822, 825, 825, - 825, 825, 0, 0, 825, 0, 0, 825, 825, 825, - 825, 825, 0, 0, 0, 825, 0, 0, 0, 0, - 0, 0, 834, 834, 834, 834, 834, 0, 0, 0, - 834, 0, 0, 825, 826, 826, 826, 826, 0, 0, - 826, 0, 826, 826, 826, 826, 826, 826, 834, 836, - 836, 836, 836, 0, 0, 836, 0, 0, 0, 836, - 836, 836, 836, 837, 837, 837, 837, 0, 0, 837, - 0, 837, 837, 837, 837, 837, 837, 838, 838, 838, - - 838, 0, 0, 838, 0, 838, 838, 838, 838, 838, - 838, 839, 839, 839, 839, 0, 0, 839, 0, 0, - 839, 839, 839, 839, 839, 0, 0, 0, 839, 842, - 842, 842, 842, 842, 0, 0, 0, 842, 0, 0, - 0, 0, 0, 0, 0, 0, 839, 0, 0, 0, - 0, 0, 0, 0, 0, 842, 845, 845, 845, 845, - 0, 0, 845, 0, 845, 845, 845, 845, 845, 845, - 846, 846, 846, 846, 0, 0, 846, 0, 846, 846, - 846, 846, 846, 846, 848, 848, 848, 848, 0, 0, - 848, 0, 848, 848, 848, 848, 848, 848, 849, 849, - - 849, 849, 0, 0, 849, 0, 849, 849, 849, 849, - 849, 849, 852, 852, 852, 852, 0, 0, 852, 0, - 0, 0, 852, 852, 852, 852, 853, 853, 853, 853, - 0, 0, 853, 0, 853, 853, 853, 853, 853, 853, - 854, 854, 854, 854, 0, 0, 854, 0, 854, 854, - 854, 854, 854, 854, 862, 862, 862, 862, 0, 0, - 862, 0, 862, 862, 862, 862, 862, 862, 0, 0, - 0, 862, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 862, - 863, 863, 863, 863, 0, 0, 863, 863, 863, 863, - - 863, 863, 863, 863, 864, 864, 864, 864, 0, 0, - 864, 0, 864, 864, 864, 864, 864, 864, 0, 0, - 0, 864, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 864, - 865, 865, 865, 865, 0, 0, 865, 865, 865, 865, - 865, 865, 865, 865, 866, 866, 866, 866, 0, 0, - 866, 0, 0, 0, 866, 866, 866, 866, 0, 0, - 0, 866, 0, 0, 0, 0, 0, 0, 930, 930, - 930, 930, 930, 0, 0, 0, 930, 0, 0, 866, - 868, 868, 868, 868, 0, 0, 868, 0, 868, 868, - - 868, 868, 868, 868, 930, 0, 0, 868, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 868, 869, 869, 869, 869, - 0, 0, 869, 869, 869, 869, 869, 869, 869, 869, - 870, 870, 870, 870, 0, 0, 870, 0, 870, 870, - 870, 870, 870, 870, 0, 0, 0, 870, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 870, 871, 871, 871, 871, - 0, 0, 871, 871, 871, 871, 871, 871, 871, 871, - 872, 872, 872, 872, 0, 0, 872, 0, 0, 0, - - 872, 872, 872, 872, 0, 0, 0, 872, 0, 0, - 0, 0, 0, 0, 938, 938, 938, 938, 938, 0, - 0, 0, 938, 0, 0, 872, 874, 874, 874, 874, - 0, 0, 874, 0, 874, 874, 874, 874, 874, 874, - 938, 0, 0, 874, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 874, 875, 875, 875, 875, 0, 0, 875, 875, - 875, 875, 875, 875, 875, 875, 876, 876, 876, 876, - 0, 0, 876, 0, 876, 876, 876, 876, 876, 876, - 0, 0, 0, 876, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 876, 877, 877, 877, 877, 0, 0, 877, 877, - 877, 877, 877, 877, 877, 877, 906, 906, 906, 906, - 0, 0, 906, 906, 906, 0, 0, 0, 0, 0, - 0, 0, 0, 906, 946, 946, 946, 946, 946, 0, - 0, 0, 946, 0, 0, 0, 0, 0, 0, 0, - 0, 906, 908, 908, 908, 908, 0, 0, 908, 0, - 946, 0, 908, 908, 908, 908, 914, 914, 914, 914, - 0, 0, 914, 914, 914, 0, 0, 0, 0, 0, - 0, 0, 0, 914, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 914, 916, 916, 916, 916, 0, 0, 916, 0, - 0, 0, 916, 916, 916, 916, 922, 922, 922, 922, - 0, 0, 922, 922, 922, 0, 0, 0, 0, 0, - 0, 0, 0, 922, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 922, 932, 932, 932, 932, 0, 0, 932, 0, - 0, 0, 932, 932, 932, 932, 977, 977, 977, 977, - 977, 977, 977, 977, 978, 978, 978, 978, 978, 978, - 978, 978, 979, 979, 979, 979, 979, 979, 979, 979, - - 980, 980, 980, 980, 980, 980, 980, 980, 981, 981, - 0, 981, 981, 981, 981, 981, 982, 982, 0, 982, - 982, 982, 982, 982, 983, 0, 0, 983, 984, 0, - 0, 984, 985, 0, 0, 985, 0, 985, 985, 985, - 986, 986, 0, 986, 986, 986, 986, 986, 987, 0, - 0, 987, 0, 987, 987, 988, 988, 0, 988, 988, - 988, 988, 988, 989, 989, 0, 989, 0, 989, 989, - 989, 990, 990, 0, 990, 990, 990, 990, 990, 991, - 991, 991, 991, 991, 991, 991, 991, 992, 992, 992, - 992, 992, 992, 992, 992, 993, 993, 0, 0, 993, - - 993, 995, 995, 995, 995, 995, 995, 995, 995, 996, - 996, 996, 996, 996, 996, 996, 996, 997, 997, 997, - 997, 997, 997, 997, 997, 998, 998, 998, 998, 998, - 998, 998, 998, 1000, 1000, 1000, 1000, 1000, 1000, 1000, - 1000, 1001, 1001, 0, 1001, 1001, 1001, 1001, 1001, 1002, - 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1003, 1003, 1003, - 1003, 1003, 1003, 1003, 1003, 1004, 1004, 0, 1004, 0, - 1004, 1004, 1004, 1005, 1005, 0, 1005, 1005, 1005, 1005, - 1005, 1007, 1007, 0, 1007, 1007, 1007, 1007, 1007, 1008, - 0, 0, 1008, 1009, 1009, 1009, 1009, 1009, 1009, 1009, - - 1009, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1010, 1011, - 1011, 0, 0, 1011, 1011, 1013, 1013, 1013, 1013, 1013, - 1013, 1013, 1013, 1015, 1015, 1015, 1015, 1015, 1015, 1015, - 1015, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1018, - 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1019, 1019, 1019, - 1019, 1019, 1019, 1019, 1019, 1020, 1020, 1020, 1020, 1020, - 1020, 1020, 1020, 1021, 1021, 1021, 1021, 1021, 1021, 1021, - 1021, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1023, - 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1024, 1024, 1024, - 1024, 1024, 1024, 1024, 1024, 1025, 1025, 1025, 1025, 1025, - - 1025, 1025, 1025, 1026, 1026, 1026, 1026, 1026, 1026, 1026, - 1026, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1028, - 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1029, 1029, 1029, - 1029, 1029, 1029, 1029, 1029, 1030, 1030, 1030, 1030, 1030, - 1030, 1030, 1030, 1031, 1031, 1031, 1031, 1031, 1031, 1031, - 1031, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1033, - 1033, 1033, 1033, 1033, 1033, 1033, 1033, 1034, 1034, 0, - 1034, 1034, 1034, 1034, 1034, 1035, 0, 0, 1035, 1036, - 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1037, 1037, 1037, - 1037, 1037, 1037, 1037, 1037, 1038, 1038, 1038, 1038, 1038, - - 1038, 1038, 1038, 1040, 1040, 1040, 1040, 1040, 1040, 1040, - 1040, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1042, - 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1043, 1043, 1043, - 1043, 1043, 1043, 1043, 1043, 1044, 1044, 1044, 1044, 1044, - 1044, 1044, 1044, 1045, 1045, 1045, 1045, 1045, 1045, 1045, - 1045, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1047, - 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1048, 1048, 1048, - 1048, 1048, 1048, 1048, 1048, 1049, 1049, 1049, 1049, 1049, - 1049, 1049, 1049, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1052, - - 1052, 1052, 1052, 1052, 1052, 1052, 1052, 1053, 1053, 1053, - 1053, 1053, 1053, 1053, 1053, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1055, 1055, 1055, 1055, 1055, 1055, 1055, - 1055, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1057, - 1057, 0, 1057, 1057, 1057, 1057, 1057, 1058, 0, 0, - 1058, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1059, 1060, - 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1061, 1061, 1061, - 1061, 1061, 1061, 1061, 1061, 1062, 1062, 1062, 1062, 1062, - 1062, 1062, 1062, 1063, 1063, 1063, 1063, 1063, 1063, 1063, - 1063, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1065, - - 1065, 1065, 1065, 1065, 1065, 1065, 1065, 1066, 1066, 1066, - 1066, 1066, 1066, 1066, 1066, 1067, 1067, 1067, 1067, 1067, - 1067, 1067, 1067, 1068, 1068, 1068, 1068, 1068, 1068, 1068, - 1068, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1070, - 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1071, 1071, 1071, - 1071, 1071, 1071, 1071, 1071, 1072, 1072, 1072, 1072, 1072, - 1072, 1072, 1072, 1073, 1073, 1073, 1073, 1073, 1073, 1073, - 1073, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1075, - 1075, 1075, 1075, 1075, 1075, 1075, 1075, 1076, 1076, 1076, - 1076, 1076, 1076, 1076, 1076, 1077, 1077, 1077, 1077, 1077, - - 1077, 1077, 1077, 1078, 1078, 1078, 1078, 1078, 1078, 1078, - 1078, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1080, - 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1081, 1081, 1081, - 1081, 1081, 1081, 1081, 1081, 1082, 1082, 1082, 1082, 1082, - 1082, 1082, 1082, 1083, 1083, 0, 1083, 1083, 1083, 1083, - 1083, 1084, 0, 0, 1084, 1085, 1085, 1085, 1085, 1085, - 1085, 1085, 1085, 1086, 1086, 1086, 1086, 1086, 1086, 1086, - 1086, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1088, - 1088, 1088, 1088, 1088, 1088, 1088, 1088, 1089, 1089, 1089, - 1089, 1089, 1089, 1089, 1089, 1090, 1090, 1090, 1090, 1090, - - 1090, 1090, 1090, 1091, 1091, 1091, 1091, 1091, 1091, 1091, - 1091, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1092, 1093, - 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1094, 1094, 1094, - 1094, 1094, 1094, 1094, 1094, 1095, 1095, 1095, 1095, 1095, - 1095, 1095, 1095, 1096, 1096, 1096, 1096, 1096, 1096, 1096, - 1096, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1097, 1098, - 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1099, 1099, 1099, - 1099, 1099, 1099, 1099, 1099, 1100, 1100, 1100, 1100, 1100, - 1100, 1100, 1100, 1101, 1101, 1101, 1101, 1101, 1101, 1101, - 1101, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1103, - - 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1104, 1104, 1104, - 1104, 1104, 1104, 1104, 1104, 1105, 1105, 1105, 1105, 1105, - 1105, 1105, 1105, 1106, 1106, 1106, 1106, 1106, 1106, 1106, - 1106, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1107, 1108, - 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1109, 1109, 0, - 1109, 1109, 1109, 1109, 1109, 1110, 0, 0, 1110, 1111, - 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1112, 1112, 1112, - 1112, 1112, 1112, 1112, 1112, 1113, 1113, 1113, 1113, 1113, - 1113, 1113, 1113, 1114, 1114, 1114, 1114, 1114, 1114, 1114, - 1114, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1115, 1116, - - 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1117, 1117, 1117, - 1117, 1117, 1117, 1117, 1117, 1118, 1118, 0, 1118, 1118, - 1118, 1118, 1118, 1119, 1119, 1119, 1119, 1119, 1119, 1119, - 1119, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976, - 976, 976, 976, 976, 976, 976, 976, 976, 976, 976 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -extern int vrmlyy_flex_debug; -int vrmlyy_flex_debug = 0; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *vrmlyytext; -#line 1 "vrmlLexer.lxx" -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlLexer.lxx - * @author drose - * @date 2004-10-01 - */ -/************************************************** - * VRML 2.0 Parser - * Copyright (C) 1996 Silicon Graphics, Inc. - * - * Author(s) : Gavin Bell - * Daniel Woods (first port) - ************************************************** - */ -#line 26 "vrmlLexer.lxx" -#include "pandatoolbase.h" - -#include "vrmlNode.h" -#include "vrmlParser.h" -#include "pnotify.h" -#include "pstrtod.h" - -static int yyinput(void); // declared by flex. -extern "C" int vrmlyywrap(); - -//////////////////////////////////////////////////////////////////// -// Static variables -//////////////////////////////////////////////////////////////////// - -// We'll increment line_number as we parse the file, so -// that we can report the position of an error. -static int line_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 std::istream *input_p = nullptr; - -// This is the name of the vrml file we're parsing. We keep it so we -// can print it out for error messages. -static std::string vrml_filename; - -extern void vrmlyyerror(const std::string &); - - /* The YACC parser sets this to a token to direct the lexer */ - /* in cases where just syntax isn't enough: */ -int expectToken = 0; - - /* True when parsing a multiple-valued field: */ -static int parsing_mf = 0; - - /* These are used when parsing SFImage fields: */ -static int sfImageIntsParsed = 0; -static int sfImageIntsExpected = 0; - -// This is used while scanning a quoted string. -static std::string quoted_string; - -// And this keeps track of the currently-parsing array. -static MFArray *mfarray; - -void -vrml_init_lexer(std::istream &in, const std::string &filename) { - input_p = ∈ - vrml_filename = filename; - line_number = 0; - error_count = 0; - warning_count = 0; -} - -//////////////////////////////////////////////////////////////////// -// Internal support functions. -//////////////////////////////////////////////////////////////////// - -int -vrmlyywrap(void) { - return 1; -} - -void -vrmlyyerror(const std::string &msg) { - using std::cerr; - - cerr << "\nError"; - if (!vrml_filename.empty()) { - cerr << " in " << vrml_filename; - } - cerr - << " at line " << line_number << ":\n" - << current_line << "\n"; - - error_count++; -} - -void -vrmlyywarning(const std::string &msg) { - using std::cerr; - - cerr << "\nWarning"; - if (!vrml_filename.empty()) { - cerr << " in " << vrml_filename; - } - cerr - << " at line " << line_number << ":\n" - << current_line << "\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(input_p != NULL); - if (*input_p) { - input_p->read(buffer, max_size); - result = input_p->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, vrmlyytext, max_error_width); - current_line[max_error_width] = '\0'; - line_number++; - - // 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 this macro carefully, since different flex versions call it -// with a different type for result. -#define YY_INPUT(buffer, result, max_size) { \ - int int_result = 0; \ - input_chars((buffer), int_result, (max_size)); \ - (result) = int_result; \ -} - -int extract_int() { - return strtol(vrmlyytext, NULL, 0); -} - -double extract_float() { - return patof(vrmlyytext); -} - -void extract_vec(double vec[], int num_elements) { - char *p = vrmlyytext; - for (int i = 0; i < num_elements; i++) { - vec[i] = pstrtod(p, &p); - } -} - -/* Normal state: parsing nodes. The initial start state is used */ -/* only to recognize the VRML header. */ - -/* Start tokens for all of the field types, */ -/* except for MFNode and SFNode, which are almost completely handled */ -/* by the parser: */ - - - -/* Big hairy expression for floating point numbers: */ -/* Ints are decimal or hex (0x##): */ -/* Whitespace. Using this pattern can screw up currentLineNumber, */ -/* so it is only used wherever it is really convenient and it is */ -/* extremely unlikely that the user will put in a carriage return */ -/* (example: between the floats in an SFVec3f) */ -/* And the same pattern without the newline */ -/* Here's a pattern that matches a single newline character. */ -/* Legal characters to start an identifier */ -/* Legal other characters in an identifier */ -/*idRestChar ([^\x00-\x20\x22\x23\x27\x2b-\x2e\x5b-\x5d\x7b\x7d])*/ -/* Allow hyphen (0x2d) in identifiers. */ -#line 2927 "lex.yy.c" - -#define INITIAL 0 -#define NODE 1 -#define SFB 2 -#define SFC 3 -#define SFF 4 -#define SFIMG 5 -#define SFI 6 -#define SFR 7 -#define SFS 8 -#define SFT 9 -#define SFV2 10 -#define SFV3 11 -#define MFC 12 -#define MFF 13 -#define MFI 14 -#define MFR 15 -#define MFS 16 -#define MFV2 17 -#define MFV3 18 -#define IN_SFS 19 -#define IN_MFS 20 -#define IN_SFIMG 21 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int vrmlyylex_destroy (void ); - -int vrmlyyget_debug (void ); - -void vrmlyyset_debug (int debug_flag ); - -YY_EXTRA_TYPE vrmlyyget_extra (void ); - -void vrmlyyset_extra (YY_EXTRA_TYPE user_defined ); - -FILE *vrmlyyget_in (void ); - -void vrmlyyset_in (FILE * in_str ); - -FILE *vrmlyyget_out (void ); - -void vrmlyyset_out (FILE * out_str ); - -int vrmlyyget_leng (void ); - -char *vrmlyyget_text (void ); - -int vrmlyyget_lineno (void ); - -void vrmlyyset_lineno (int line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int vrmlyywrap (void ); -#else -extern int vrmlyywrap (void ); -#endif -#endif - - static void yyunput (int c,char *buf_ptr ); - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (void ); -#else -static int input (void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#define YY_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO fwrite( vrmlyytext, vrmlyyleng, 1, vrmlyyout ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - int n; \ - for ( n = 0; n < max_size && \ - (c = getc( vrmlyyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( vrmlyyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, vrmlyyin))==0 && ferror(vrmlyyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(vrmlyyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int vrmlyylex (void); - -#define YY_DECL int vrmlyylex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after vrmlyytext and vrmlyyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 217 "vrmlLexer.lxx" - - - - /* Switch into a new start state if the parser */ - /* just told us that we've read a field name */ - /* and should expect a field value (or IS) */ - if (expectToken != 0) { - - /* - * Annoying. This big switch is necessary because - * LEX wants to assign particular numbers to start - * tokens, and YACC wants to define all the tokens - * used, too. Sigh. - */ - switch(expectToken) { - case SFBOOL: BEGIN SFB; break; - case SFCOLOR: BEGIN SFC; break; - case SFFLOAT: BEGIN SFF; break; - case SFIMAGE: BEGIN SFIMG; break; - case SFINT32: BEGIN SFI; break; - case SFROTATION: BEGIN SFR; break; - case SFSTRING: BEGIN SFS; break; - case SFTIME: BEGIN SFT; break; - case SFVEC2F: BEGIN SFV2; break; - case SFVEC3F: BEGIN SFV3; break; - case MFCOLOR: BEGIN MFC; break; - case MFFLOAT: BEGIN MFF; break; - case MFINT32: BEGIN MFI; break; - case MFROTATION: BEGIN MFR; break; - case MFSTRING: BEGIN MFS; break; - case MFVEC2F: BEGIN MFV2; break; - case MFVEC3F: BEGIN MFV3; break; - - /* SFNode and MFNode are special. Here the lexer just returns */ - /* "marker tokens" so the parser knows what type of field is */ - /* being parsed; unlike the other fields, parsing of SFNode/MFNode */ - /* field happens in the parser. */ - case MFNODE: expectToken = 0; return MFNODE; - case SFNODE: expectToken = 0; return SFNODE; - - default: vrmlyyerror("ACK: Bad expectToken"); break; - } - } - - - /* This is more complicated than they really need to be because */ - /* I was ambitious and made the whitespace-matching rule aggressive */ -#line 3178 "lex.yy.c" - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! vrmlyyin ) - vrmlyyin = stdin; - - if ( ! vrmlyyout ) - vrmlyyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - vrmlyyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - vrmlyy_create_buffer(vrmlyyin,YY_BUF_SIZE ); - } - - vrmlyy_load_buffer_state( ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = (yy_c_buf_p); - - /* Support of vrmlyytext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 977 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 8632 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - goto yy_find_action; - -case 1: -/* rule 1 can match eol */ -YY_RULE_SETUP -#line 264 "vrmlLexer.lxx" -{ - BEGIN NODE; -} - YY_BREAK -/* The lexer is in the NODE state when parsing nodes, either */ -/* top-level nodes in the .wrl file, in a prototype implementation, */ -/* or when parsing the contents of SFNode or MFNode fields. */ -case 2: -YY_RULE_SETUP -#line 271 "vrmlLexer.lxx" -{ return PROTO; } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 272 "vrmlLexer.lxx" -{ return EXTERNPROTO; } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 273 "vrmlLexer.lxx" -{ return DEF; } - YY_BREAK -case 5: -YY_RULE_SETUP -#line 274 "vrmlLexer.lxx" -{ return USE; } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 275 "vrmlLexer.lxx" -{ return TO; } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 276 "vrmlLexer.lxx" -{ return IS; } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 277 "vrmlLexer.lxx" -{ return ROUTE; } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 278 "vrmlLexer.lxx" -{ return SFN_NULL; } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 279 "vrmlLexer.lxx" -{ return EVENTIN; } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 280 "vrmlLexer.lxx" -{ return EVENTOUT; } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 281 "vrmlLexer.lxx" -{ return FIELD; } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 282 "vrmlLexer.lxx" -{ return EXPOSEDFIELD; } - YY_BREAK -/* Legal identifiers: */ -case 14: -YY_RULE_SETUP -#line 285 "vrmlLexer.lxx" -{ - vrmlyylval.string = strdup(vrmlyytext); - return IDENTIFIER; -} - YY_BREAK -/* This hopefully won't bitch things too much. It's not legal for - an identifier to begin with a digit, but Form-Z writes out VRML - files that do. So we'll allow it. Hopefully the start states - will keep them sorted out. */ -case 15: -YY_RULE_SETUP -#line 293 "vrmlLexer.lxx" -{ - vrmlyylval.string = strdup(vrmlyytext); - return IDENTIFIER; -} - YY_BREAK -/* All fields may have an IS declaration: */ -case 16: -YY_RULE_SETUP -#line 299 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - yyless(0); -} - YY_BREAK -case 17: -YY_RULE_SETUP -#line 305 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - yyless(0); /* put back the IS */ -} - YY_BREAK -/* All MF field types other than MFNode are completely parsed here */ -/* in the lexer, and one token is returned to the parser. They all */ -/* share the same rules for open and closing brackets: */ -case 18: -YY_RULE_SETUP -#line 314 "vrmlLexer.lxx" -{ - if (parsing_mf) vrmlyyerror("Double ["); - parsing_mf = 1; - mfarray = new MFArray; -} - YY_BREAK -case 19: -YY_RULE_SETUP -#line 320 "vrmlLexer.lxx" -{ - if (!parsing_mf) vrmlyyerror("Unmatched ]"); - int fieldType = expectToken; - BEGIN NODE; - parsing_mf = 0; - expectToken = 0; - vrmlyylval.fv._mf = mfarray; - return fieldType; -} - YY_BREAK -case 20: -YY_RULE_SETUP -#line 330 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfbool = true; - return SFBOOL; -} - YY_BREAK -case 21: -YY_RULE_SETUP -#line 337 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfbool = false; - return SFBOOL; -} - YY_BREAK -case 22: -YY_RULE_SETUP -#line 344 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfint32 = extract_int(); - return SFINT32; -} - YY_BREAK -case 23: -YY_RULE_SETUP -#line 351 "vrmlLexer.lxx" -{ - VrmlFieldValue v; - v._sfint32 = extract_int(); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFINT32; - } -} - YY_BREAK -/* All the floating-point types are pretty similar: */ -case 24: -YY_RULE_SETUP -#line 366 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sffloat = extract_float(); - return SFFLOAT; -} - YY_BREAK -case 25: -YY_RULE_SETUP -#line 373 "vrmlLexer.lxx" -{ - VrmlFieldValue v; - v._sffloat = extract_float(); - if (parsing_mf) { - /* Add to array... */ - mfarray->push_back(v); - } else { - /* No open bracket means a single value: */ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFFLOAT; - } -} - YY_BREAK -case 26: -/* rule 26 can match eol */ -YY_RULE_SETUP -#line 389 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 2); - return SFVEC2F; -} - YY_BREAK -case 27: -/* rule 27 can match eol */ -YY_RULE_SETUP -#line 396 "vrmlLexer.lxx" -{ - VrmlFieldValue v; - extract_vec(v._sfvec, 2); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFVEC2F; - } -} - YY_BREAK -case 28: -/* rule 28 can match eol */ -YY_RULE_SETUP -#line 410 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 3); - return SFVEC3F; -} - YY_BREAK -case 29: -/* rule 29 can match eol */ -YY_RULE_SETUP -#line 417 "vrmlLexer.lxx" -{ - VrmlFieldValue v; - extract_vec(v._sfvec, 3); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFVEC3F; - } -} - YY_BREAK -case 30: -/* rule 30 can match eol */ -YY_RULE_SETUP -#line 431 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 4); - return SFROTATION; -} - YY_BREAK -case 31: -/* rule 31 can match eol */ -YY_RULE_SETUP -#line 438 "vrmlLexer.lxx" -{ - VrmlFieldValue v; - extract_vec(v._sfvec, 4); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFROTATION; - } -} - YY_BREAK -case 32: -/* rule 32 can match eol */ -YY_RULE_SETUP -#line 452 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 3); - return SFCOLOR; -} - YY_BREAK -case 33: -/* rule 33 can match eol */ -YY_RULE_SETUP -#line 459 "vrmlLexer.lxx" -{ - VrmlFieldValue v; - extract_vec(v._sfvec, 3); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFCOLOR; - } -} - YY_BREAK -case 34: -YY_RULE_SETUP -#line 473 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sffloat = extract_float(); - return SFTIME; -} - YY_BREAK -/* SFString/MFString */ -case 35: -YY_RULE_SETUP -#line 481 "vrmlLexer.lxx" -{ - BEGIN IN_SFS; - quoted_string = ""; -} - YY_BREAK -case 36: -YY_RULE_SETUP -#line 486 "vrmlLexer.lxx" -{ - BEGIN IN_MFS; - quoted_string = ""; -} - YY_BREAK -/* Anything besides open-quote (or whitespace) is an error: */ -case 37: -YY_RULE_SETUP -#line 492 "vrmlLexer.lxx" -{ - vrmlyyerror("String missing open-quote"); - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfstring = strdup(""); - return SFSTRING; -} - YY_BREAK -/* Expect open-quote, open-bracket, or whitespace: */ -case 38: -YY_RULE_SETUP -#line 501 "vrmlLexer.lxx" -{ - vrmlyyerror("String missing open-quote"); - BEGIN NODE; - expectToken = 0; - return MFSTRING; -} - YY_BREAK -/* Backslashed-quotes are OK: */ -case 39: -YY_RULE_SETUP -#line 509 "vrmlLexer.lxx" -{ - quoted_string += '"'; -} - YY_BREAK -/* Gobble up anything besides quotes and newlines. */ -/* Newlines are legal in strings, but we exclude them here so */ -/* that line number are counted correctly by the catch-all newline */ -/* rule that applies to everything. */ -case 40: -YY_RULE_SETUP -#line 517 "vrmlLexer.lxx" -{ - quoted_string += vrmlyytext; -} - YY_BREAK -/* Quote ends the string: */ -case 41: -YY_RULE_SETUP -#line 522 "vrmlLexer.lxx" -{ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfstring = strdup(quoted_string.c_str()); - return SFSTRING; -} - YY_BREAK -case 42: -YY_RULE_SETUP -#line 529 "vrmlLexer.lxx" -{ - VrmlFieldValue v; - v._sfstring = strdup(quoted_string.c_str()); - if (parsing_mf) { - BEGIN MFS; - mfarray->push_back(v); - quoted_string = ""; - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFSTRING; - } -} - YY_BREAK -/* SFImage: width height numComponents then width*height integers: */ -case 43: -/* rule 43 can match eol */ -YY_RULE_SETUP -#line 546 "vrmlLexer.lxx" -{ int w, h; - sscanf(vrmlyytext, "%d %d", &w, &h); - sfImageIntsExpected = 1+w*h; - sfImageIntsParsed = 0; - BEGIN IN_SFIMG; - } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 552 "vrmlLexer.lxx" -{ ++sfImageIntsParsed; - if (sfImageIntsParsed == sfImageIntsExpected) { - BEGIN NODE; expectToken = 0; return SFIMAGE; - } - } - YY_BREAK -/* Whitespace and catch-all rules apply to all start states: */ -case 45: -YY_RULE_SETUP -#line 559 "vrmlLexer.lxx" -; - YY_BREAK -/* A newline is also whitespace, but we'll keep track of line number */ -/* to report in errors: */ -case 46: -/* rule 46 can match eol */ -YY_RULE_SETUP -#line 563 "vrmlLexer.lxx" -{ - // 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, vrmlyytext+1, max_error_width); - current_line[max_error_width] = '\0'; - line_number++; - - // Return the whole line to the lexer, except the newline character, - // which we eat. - yyless(1); -} - YY_BREAK -/* This catch-all rule catches anything not covered by any of */ -/* the above: */ -case 47: -YY_RULE_SETUP -#line 577 "vrmlLexer.lxx" -{ - return vrmlyytext[0]; -} - YY_BREAK -case 48: -YY_RULE_SETUP -#line 581 "vrmlLexer.lxx" -ECHO; - YY_BREAK -#line 3748 "lex.yy.c" -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(NODE): -case YY_STATE_EOF(SFB): -case YY_STATE_EOF(SFC): -case YY_STATE_EOF(SFF): -case YY_STATE_EOF(SFIMG): -case YY_STATE_EOF(SFI): -case YY_STATE_EOF(SFR): -case YY_STATE_EOF(SFS): -case YY_STATE_EOF(SFT): -case YY_STATE_EOF(SFV2): -case YY_STATE_EOF(SFV3): -case YY_STATE_EOF(MFC): -case YY_STATE_EOF(MFF): -case YY_STATE_EOF(MFI): -case YY_STATE_EOF(MFR): -case YY_STATE_EOF(MFS): -case YY_STATE_EOF(MFV2): -case YY_STATE_EOF(MFV3): -case YY_STATE_EOF(IN_SFS): -case YY_STATE_EOF(IN_MFS): -case YY_STATE_EOF(IN_SFIMG): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed vrmlyyin at a new source and called - * vrmlyylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = vrmlyyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( vrmlyywrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * vrmlyytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of vrmlyylex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); - register int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - vrmlyyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - vrmlyyrestart(vrmlyyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) vrmlyyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = (yy_start); - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 977 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - register int yy_is_jam; - register char *yy_cp = (yy_c_buf_p); - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 977 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 976); - - return yy_is_jam ? 0 : yy_current_state; -} - - static void yyunput (int c, register char * yy_bp ) -{ - register char *yy_cp; - - yy_cp = (yy_c_buf_p); - - /* undo effects of setting up vrmlyytext */ - *yy_cp = (yy_hold_char); - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - register char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - vrmlyyrestart(vrmlyyin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( vrmlyywrap( ) ) - return EOF; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve vrmlyytext */ - (yy_hold_char) = *++(yy_c_buf_p); - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void vrmlyyrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - vrmlyyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - vrmlyy_create_buffer(vrmlyyin,YY_BUF_SIZE ); - } - - vrmlyy_init_buffer(YY_CURRENT_BUFFER,input_file ); - vrmlyy_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void vrmlyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * vrmlyypop_buffer_state(); - * vrmlyypush_buffer_state(new_buffer); - */ - vrmlyyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - vrmlyy_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (vrmlyywrap()) processing, but the only time this flag - * is looked at is after vrmlyywrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void vrmlyy_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - vrmlyyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE vrmlyy_create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) vrmlyyalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in vrmlyy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) vrmlyyalloc(b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in vrmlyy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - vrmlyy_init_buffer(b,file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with vrmlyy_create_buffer() - * - */ - void vrmlyy_delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - vrmlyyfree((void *) b->yy_ch_buf ); - - vrmlyyfree((void *) b ); -} - -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a vrmlyyrestart() or at EOF. - */ - static void vrmlyy_init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - vrmlyy_flush_buffer(b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then vrmlyy_init_buffer was _probably_ - * called from vrmlyyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void vrmlyy_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - vrmlyy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void vrmlyypush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - vrmlyyensure_buffer_stack(); - - /* This block is copied from vrmlyy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from vrmlyy_switch_to_buffer. */ - vrmlyy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void vrmlyypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - vrmlyy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - vrmlyy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void vrmlyyensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)vrmlyyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in vrmlyyensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)vrmlyyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in vrmlyyensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE vrmlyy_scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) vrmlyyalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in vrmlyy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - vrmlyy_switch_to_buffer(b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to vrmlyylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * vrmlyy_scan_bytes() instead. - */ -YY_BUFFER_STATE vrmlyy_scan_string (yyconst char * yystr ) -{ - - return vrmlyy_scan_bytes(yystr,strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to vrmlyylex() will - * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE vrmlyy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) vrmlyyalloc(n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in vrmlyy_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = vrmlyy_scan_buffer(buf,n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in vrmlyy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up vrmlyytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - vrmlyytext[vrmlyyleng] = (yy_hold_char); \ - (yy_c_buf_p) = vrmlyytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - vrmlyyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int vrmlyyget_lineno (void) -{ - - return vrmlyylineno; -} - -/** Get the input stream. - * - */ -FILE *vrmlyyget_in (void) -{ - return vrmlyyin; -} - -/** Get the output stream. - * - */ -FILE *vrmlyyget_out (void) -{ - return vrmlyyout; -} - -/** Get the length of the current token. - * - */ -int vrmlyyget_leng (void) -{ - return vrmlyyleng; -} - -/** Get the current token. - * - */ - -char *vrmlyyget_text (void) -{ - return vrmlyytext; -} - -/** Set the current line number. - * @param line_number - * - */ -void vrmlyyset_lineno (int line_number ) -{ - - vrmlyylineno = line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see vrmlyy_switch_to_buffer - */ -void vrmlyyset_in (FILE * in_str ) -{ - vrmlyyin = in_str ; -} - -void vrmlyyset_out (FILE * out_str ) -{ - vrmlyyout = out_str ; -} - -int vrmlyyget_debug (void) -{ - return vrmlyy_flex_debug; -} - -void vrmlyyset_debug (int bdebug ) -{ - vrmlyy_flex_debug = bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from vrmlyylex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - vrmlyyin = stdin; - vrmlyyout = stdout; -#else - vrmlyyin = (FILE *) 0; - vrmlyyout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * vrmlyylex_init() - */ - return 0; -} - -/* vrmlyylex_destroy is for both reentrant and non-reentrant scanners. */ -int vrmlyylex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - vrmlyy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - vrmlyypop_buffer_state(); - } - - /* Destroy the stack itself. */ - vrmlyyfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * vrmlyylex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *vrmlyyalloc (yy_size_t size ) -{ - return (void *) malloc( size ); -} - -void *vrmlyyrealloc (void * ptr, yy_size_t size ) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} - -void vrmlyyfree (void * ptr ) -{ - free( (char *) ptr ); /* see vrmlyyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 581 "vrmlLexer.lxx" diff --git a/pandatool/src/vrml/vrmlLexer.lxx b/pandatool/src/vrml/vrmlLexer.lxx deleted file mode 100644 index 6b03b798..00000000 --- a/pandatool/src/vrml/vrmlLexer.lxx +++ /dev/null @@ -1,581 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlLexer.lxx - * @author drose - * @date 2004-10-01 - */ - -/************************************************** - * VRML 2.0 Parser - * Copyright (C) 1996 Silicon Graphics, Inc. - * - * Author(s) : Gavin Bell - * Daniel Woods (first port) - ************************************************** - */ -%{ -#include "pandatoolbase.h" - -#include "vrmlNode.h" -#include "vrmlParser.h" -#include "pnotify.h" -#include "pstrtod.h" - -static int yyinput(void); // declared by flex. -extern "C" int vrmlyywrap(); - -//////////////////////////////////////////////////////////////////// -// Static variables -//////////////////////////////////////////////////////////////////// - -// We'll increment line_number as we parse the file, so -// that we can report the position of an error. -static int line_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 std::istream *input_p = nullptr; - -// This is the name of the vrml file we're parsing. We keep it so we -// can print it out for error messages. -static std::string vrml_filename; - -extern void vrmlyyerror(const std::string &); - - /* The YACC parser sets this to a token to direct the lexer */ - /* in cases where just syntax isn't enough: */ -int expectToken = 0; - - /* True when parsing a multiple-valued field: */ -static int parsing_mf = 0; - - /* These are used when parsing SFImage fields: */ -static int sfImageIntsParsed = 0; -static int sfImageIntsExpected = 0; - -// This is used while scanning a quoted string. -static std::string quoted_string; - -// And this keeps track of the currently-parsing array. -static MFArray *mfarray; - -void -vrml_init_lexer(std::istream &in, const std::string &filename) { - input_p = ∈ - vrml_filename = filename; - line_number = 0; - error_count = 0; - warning_count = 0; -} - -//////////////////////////////////////////////////////////////////// -// Internal support functions. -//////////////////////////////////////////////////////////////////// - -int -vrmlyywrap(void) { - return 1; -} - -void -vrmlyyerror(const std::string &msg) { - using std::cerr; - - cerr << "\nError"; - if (!vrml_filename.empty()) { - cerr << " in " << vrml_filename; - } - cerr - << " at line " << line_number << ":\n" - << current_line << "\n"; - - error_count++; -} - -void -vrmlyywarning(const std::string &msg) { - using std::cerr; - - cerr << "\nWarning"; - if (!vrml_filename.empty()) { - cerr << " in " << vrml_filename; - } - cerr - << " at line " << line_number << ":\n" - << current_line << "\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(input_p != nullptr); - if (*input_p) { - input_p->read(buffer, max_size); - result = input_p->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, vrmlyytext, max_error_width); - current_line[max_error_width] = '\0'; - line_number++; - - // Truncate it at the newline. - char *end = strchr(current_line, '\n'); - if (end != nullptr) { - *end = '\0'; - } - } - - } else { - // End of file or I/O error. - result = 0; - } -} -#undef YY_INPUT - -// Define this macro carefully, since different flex versions call it -// with a different type for result. -#define YY_INPUT(buffer, result, max_size) { \ - int int_result = 0; \ - input_chars((buffer), int_result, (max_size)); \ - (result) = int_result; \ -} - -int extract_int() { - return strtol(yytext, nullptr, 0); -} - -double extract_float() { - return patof(yytext); -} - -void extract_vec(double vec[], int num_elements) { - char *p = yytext; - for (int i = 0; i < num_elements; i++) { - vec[i] = pstrtod(p, &p); - } -} - -%} - - /* Normal state: parsing nodes. The initial start state is used */ - /* only to recognize the VRML header. */ -%x NODE - - /* Start tokens for all of the field types, */ - /* except for MFNode and SFNode, which are almost completely handled */ - /* by the parser: */ -%x SFB SFC SFF SFIMG SFI SFR SFS SFT SFV2 SFV3 -%x MFC MFF MFI MFR MFS MFV2 MFV3 -%x IN_SFS IN_MFS IN_SFIMG - - /* Big hairy expression for floating point numbers: */ -float (-?((([0-9]+)|([0-9]*\.[0-9]+))([eE][+\-]?[0-9]+)?)) - - /* Ints are decimal or hex (0x##): */ -int (-?([0-9]+)|(0[xX][0-9a-fA-F]*)) - - /* Whitespace. Using this pattern can screw up currentLineNumber, */ - /* so it is only used wherever it is really convenient and it is */ - /* extremely unlikely that the user will put in a carriage return */ - /* (example: between the floats in an SFVec3f) */ -ws ([ \t\r\n,]|(#.*))+ - /* And the same pattern without the newline */ -wsnnl ([ \t\r,]|(#.*)) - /* Here's a pattern that matches a single newline character. */ -nl ((\n)|(\n\r)|(\r\n)|(\r)) - - /* Legal characters to start an identifier */ -idStartChar ([^\x30-\x39\x00-\x20\x22\x23\x27\x2b-\x2e\x5b-\x5d\x7b\x7d]) - /* Legal other characters in an identifier */ - /*idRestChar ([^\x00-\x20\x22\x23\x27\x2b-\x2e\x5b-\x5d\x7b\x7d])*/ - - /* Allow hyphen (0x2d) in identifiers. */ -idRestChar ([^\x00-\x20\x22\x23\x27\x2b-\x2c\x2e\x5b-\x5d\x7b\x7d]) -%% - -%{ - /* Switch into a new start state if the parser */ - /* just told us that we've read a field name */ - /* and should expect a field value (or IS) */ - if (expectToken != 0) { - - /* - * Annoying. This big switch is necessary because - * LEX wants to assign particular numbers to start - * tokens, and YACC wants to define all the tokens - * used, too. Sigh. - */ - switch(expectToken) { - case SFBOOL: BEGIN SFB; break; - case SFCOLOR: BEGIN SFC; break; - case SFFLOAT: BEGIN SFF; break; - case SFIMAGE: BEGIN SFIMG; break; - case SFINT32: BEGIN SFI; break; - case SFROTATION: BEGIN SFR; break; - case SFSTRING: BEGIN SFS; break; - case SFTIME: BEGIN SFT; break; - case SFVEC2F: BEGIN SFV2; break; - case SFVEC3F: BEGIN SFV3; break; - case MFCOLOR: BEGIN MFC; break; - case MFFLOAT: BEGIN MFF; break; - case MFINT32: BEGIN MFI; break; - case MFROTATION: BEGIN MFR; break; - case MFSTRING: BEGIN MFS; break; - case MFVEC2F: BEGIN MFV2; break; - case MFVEC3F: BEGIN MFV3; break; - - /* SFNode and MFNode are special. Here the lexer just returns */ - /* "marker tokens" so the parser knows what type of field is */ - /* being parsed; unlike the other fields, parsing of SFNode/MFNode */ - /* field happens in the parser. */ - case MFNODE: expectToken = 0; return MFNODE; - case SFNODE: expectToken = 0; return SFNODE; - - default: vrmlyyerror("ACK: Bad expectToken"); break; - } - } -%} - - /* This is more complicated than they really need to be because */ - /* I was ambitious and made the whitespace-matching rule aggressive */ -"#VRML V2.0 utf8".*{nl}{wsnnl}* { - BEGIN NODE; -} - - /* The lexer is in the NODE state when parsing nodes, either */ - /* top-level nodes in the .wrl file, in a prototype implementation, */ - /* or when parsing the contents of SFNode or MFNode fields. */ -PROTO { return PROTO; } -EXTERNPROTO { return EXTERNPROTO; } -DEF { return DEF; } -USE { return USE; } -TO { return TO; } -IS { return IS; } -ROUTE { return ROUTE; } -nullptr { return SFN_NULL; } -eventIn { return EVENTIN; } -eventOut { return EVENTOUT; } -field { return FIELD; } -exposedField { return EXPOSEDFIELD; } - - /* Legal identifiers: */ -{idStartChar}{idRestChar}* { - vrmlyylval.string = strdup(yytext); - return IDENTIFIER; -} - /* This hopefully won't bitch things too much. It's not legal for - an identifier to begin with a digit, but Form-Z writes out VRML - files that do. So we'll allow it. Hopefully the start states - will keep them sorted out. */ -[0-9]{idRestChar}* { - vrmlyylval.string = strdup(yytext); - return IDENTIFIER; -} - - /* All fields may have an IS declaration: */ -IS { - BEGIN NODE; - expectToken = 0; - yyless(0); -} - -IS { - BEGIN NODE; - expectToken = 0; - yyless(0); /* put back the IS */ -} - - /* All MF field types other than MFNode are completely parsed here */ - /* in the lexer, and one token is returned to the parser. They all */ - /* share the same rules for open and closing brackets: */ -\[ { - if (parsing_mf) vrmlyyerror("Double ["); - parsing_mf = 1; - mfarray = new MFArray; -} - -\] { - if (!parsing_mf) vrmlyyerror("Unmatched ]"); - int fieldType = expectToken; - BEGIN NODE; - parsing_mf = 0; - expectToken = 0; - vrmlyylval.fv._mf = mfarray; - return fieldType; -} - -TRUE { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfbool = true; - return SFBOOL; -} - -FALSE { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfbool = false; - return SFBOOL; -} - -{int} { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfint32 = extract_int(); - return SFINT32; -} - -{int} { - VrmlFieldValue v; - v._sfint32 = extract_int(); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFINT32; - } -} - - /* All the floating-point types are pretty similar: */ -{float} { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sffloat = extract_float(); - return SFFLOAT; -} - -{float} { - VrmlFieldValue v; - v._sffloat = extract_float(); - if (parsing_mf) { - /* Add to array... */ - mfarray->push_back(v); - } else { - /* No open bracket means a single value: */ - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFFLOAT; - } -} - -{float}{ws}{float} { - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 2); - return SFVEC2F; -} - -{float}{ws}{float} { - VrmlFieldValue v; - extract_vec(v._sfvec, 2); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFVEC2F; - } -} - -({float}{ws}){2}{float} { - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 3); - return SFVEC3F; -} - -({float}{ws}){2}{float} { - VrmlFieldValue v; - extract_vec(v._sfvec, 3); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFVEC3F; - } -} - -({float}{ws}){3}{float} { - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 4); - return SFROTATION; -} - -({float}{ws}){3}{float} { - VrmlFieldValue v; - extract_vec(v._sfvec, 4); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFROTATION; - } -} - -({float}{ws}){2}{float} { - BEGIN NODE; - expectToken = 0; - extract_vec(vrmlyylval.fv._sfvec, 3); - return SFCOLOR; -} - -({float}{ws}){2}{float} { - VrmlFieldValue v; - extract_vec(v._sfvec, 3); - if (parsing_mf) { - mfarray->push_back(v); - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFCOLOR; - } -} - -{float} { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sffloat = extract_float(); - return SFTIME; -} - - /* SFString/MFString */ -\" { - BEGIN IN_SFS; - quoted_string = ""; -} - -\" { - BEGIN IN_MFS; - quoted_string = ""; -} - - /* Anything besides open-quote (or whitespace) is an error: */ -[^ \"\t\r\,\n]+ { - vrmlyyerror("String missing open-quote"); - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfstring = strdup(""); - return SFSTRING; -} - - /* Expect open-quote, open-bracket, or whitespace: */ -[^ \[\]\"\t\r\,\n]+ { - vrmlyyerror("String missing open-quote"); - BEGIN NODE; - expectToken = 0; - return MFSTRING; -} - - /* Backslashed-quotes are OK: */ -\\\" { - quoted_string += '"'; -} - - /* Gobble up anything besides quotes and newlines. */ - /* Newlines are legal in strings, but we exclude them here so */ - /* that line number are counted correctly by the catch-all newline */ - /* rule that applies to everything. */ -[^\"\n]+ { - quoted_string += yytext; -} - - /* Quote ends the string: */ -\" { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._sfstring = strdup(quoted_string.c_str()); - return SFSTRING; -} - -\" { - VrmlFieldValue v; - v._sfstring = strdup(quoted_string.c_str()); - if (parsing_mf) { - BEGIN MFS; - mfarray->push_back(v); - quoted_string = ""; - } else { - BEGIN NODE; - expectToken = 0; - vrmlyylval.fv._mf = new MFArray; - vrmlyylval.fv._mf->push_back(v); - return MFSTRING; - } -} - - /* SFImage: width height numComponents then width*height integers: */ -{int}{ws}{int} { int w, h; - sscanf(yytext, "%d %d", &w, &h); - sfImageIntsExpected = 1+w*h; - sfImageIntsParsed = 0; - BEGIN IN_SFIMG; - } -{int} { ++sfImageIntsParsed; - if (sfImageIntsParsed == sfImageIntsExpected) { - BEGIN NODE; expectToken = 0; return SFIMAGE; - } - } - - /* Whitespace and catch-all rules apply to all start states: */ -<*>{wsnnl}+ ; - - /* A newline is also whitespace, but we'll keep track of line number */ - /* to report in errors: */ -<*>\n.* { - // 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, yytext+1, max_error_width); - current_line[max_error_width] = '\0'; - line_number++; - - // Return the whole line to the lexer, except the newline character, - // which we eat. - yyless(1); -} - - /* This catch-all rule catches anything not covered by any of */ - /* the above: */ -<*>. { - return yytext[0]; -} - diff --git a/pandatool/src/vrml/vrmlLexerDefs.h b/pandatool/src/vrml/vrmlLexerDefs.h deleted file mode 100644 index 5cbdc81b..00000000 --- a/pandatool/src/vrml/vrmlLexerDefs.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlLexerDefs.h - * @author drose - * @date 2004-09-30 - */ - -#ifndef VRMLLEXERDEFS_H -#define VRMLLEXERDEFS_H - -#include "pandatoolbase.h" - -void vrml_init_lexer(std::istream &in, const std::string &filename); -int vrml_error_count(); -int vrml_warning_count(); - -void vrmlyyerror(const std::string &msg); -void vrmlyywarning(const std::string &msg); - -int vrmlyylex(); - -#endif diff --git a/pandatool/src/vrml/vrmlNode.cxx b/pandatool/src/vrml/vrmlNode.cxx deleted file mode 100644 index c48ce35e..00000000 --- a/pandatool/src/vrml/vrmlNode.cxx +++ /dev/null @@ -1,80 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlNode.cxx - * @author drose - * @date 1999-06-23 - */ - -#include "vrmlNode.h" -#include "vrmlParser.h" - -#include "indent.h" -#include "pnotify.h" - -VrmlNode:: -VrmlNode(const VrmlNodeType *type) { - _type = type; - _use_count = 0; -} - -VrmlNode:: -~VrmlNode() { -} - - -const VrmlFieldValue &VrmlNode:: -get_value(const char *field_name) const { - Fields::const_iterator fi; - for (fi = _fields.begin(); fi != _fields.end(); ++fi) { - if (strcmp((*fi)._type->name, field_name) == 0) { - return ((*fi)._value); - } - } - - // That field was not defined. Get the default value. - const VrmlNodeType::NameTypeRec *field = _type->hasField(field_name); - if (field != nullptr) { - return field->dflt; - } - - std::cerr << "No such field defined for type " << _type->getName() << ": " - << field_name << "\n"; - exit(1); - // Just to make the compiler happy. - static VrmlFieldValue zero; - return zero; -} - -void VrmlNode:: -output(std::ostream &out, int indent_level) const { - out << _type->getName() << " {\n"; - Fields::const_iterator fi; - for (fi = _fields.begin(); fi != _fields.end(); ++fi) { - indent(out, indent_level + 2) << (*fi)._type->name << " "; - output_value(out, (*fi)._value, (*fi)._type->type, indent_level + 2) << "\n"; - } - indent(out, indent_level) << "}"; -} - - -void Declaration:: -output(std::ostream &out, int indent) const { - VrmlFieldValue v; - v._sfnode = _node; - output_value(out, v, SFNODE, indent); -} - -std::ostream &operator << (std::ostream &out, const VrmlScene &scene) { - VrmlScene::const_iterator si; - for (si = scene.begin(); si != scene.end(); ++si) { - out << (*si) << "\n"; - } - - return out; -} diff --git a/pandatool/src/vrml/vrmlNode.h b/pandatool/src/vrml/vrmlNode.h deleted file mode 100644 index 648f477c..00000000 --- a/pandatool/src/vrml/vrmlNode.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlNode.h - * @author drose - * @date 1999-06-23 - */ - -#ifndef VRMLNODE_H -#define VRMLNODE_H - -#include "pandatoolbase.h" - -#include "vrmlNodeType.h" -#include "pvector.h" -#include "pmap.h" - -class VrmlNode { -public: - VrmlNode(const VrmlNodeType *type); - ~VrmlNode(); - - const VrmlFieldValue &get_value(const char *field_name) const; - - void output(std::ostream &out, int indent) const; - - class Field { - public: - Field() { } - Field(const VrmlNodeType::NameTypeRec *type, const VrmlFieldValue &value) : - _type(type), _value(value) { } - const VrmlNodeType::NameTypeRec *_type; - VrmlFieldValue _value; - }; - - typedef std::vector Fields; - Fields _fields; - - int _use_count; - - const VrmlNodeType *_type; -}; - -inline std::ostream &operator << (std::ostream &out, const VrmlNode &node) { - node.output(out, 0); - return out; -} - -class Declaration { -public: - SFNodeRef _node; - - void output(std::ostream &out, int indent) const; -}; - -inline std::ostream &operator << (std::ostream &out, const Declaration &dec) { - dec.output(out, 0); - return out; -} - -typedef pvector VrmlScene; - -std::ostream &operator << (std::ostream &out, const VrmlScene &scene); - -#endif diff --git a/pandatool/src/vrml/vrmlNodeType.cxx b/pandatool/src/vrml/vrmlNodeType.cxx deleted file mode 100644 index 56652507..00000000 --- a/pandatool/src/vrml/vrmlNodeType.cxx +++ /dev/null @@ -1,338 +0,0 @@ -/************************************************** - * VRML 2.0 Parser - * Copyright (C) 1996 Silicon Graphics, Inc. - * - * Author(s) : Gavin Bell - * Daniel Woods (first port) - ************************************************** - */ - -// -// The VrmlNodeType class is responsible for storing information about node -// or prototype types. -// - -#include "vrmlNodeType.h" -#include "vrmlNode.h" -#include "vrmlParser.h" -#include "pnotify.h" -#include "indent.h" - -#include // for sprintf() - -using std::ostream; - - -// -// Static list of node types. -// -plist VrmlNodeType::typeList; - -static ostream & -output_array(ostream &out, const MFArray *mf, - int type, int indent_level, int items_per_row) { - if (mf->empty()) { - out << "[ ]"; - } else { - out << "["; - MFArray::const_iterator mi; - int col = 0; - for (mi = mf->begin(); mi != mf->end(); ++mi) { - if (col == 0) { - out << "\n"; - indent(out, indent_level + 2); - } - output_value(out, (*mi), type, indent_level + 2); - if (++col >= items_per_row) { - col = 0; - } else { - out << " "; - } - } - out << "\n"; - indent(out, indent_level) << "]"; - } - return out; -} - -ostream & -output_value(ostream &out, const VrmlFieldValue &value, int type, - int indent) { - switch (type) { - case SFBOOL: - return out << (value._sfbool ? "TRUE" : "FALSE"); - - case SFFLOAT: - case SFTIME: - return out << value._sffloat; - - case SFINT32: - return out << value._sfint32; - - case SFSTRING: - { - out << '"'; - for (const char *p = value._sfstring; *p != '\0'; p++) { - if (*p == '"') { - out << "\\\""; - } else { - out << *p; - } - } - return out << '"'; - } - - case SFVEC2F: - return out << value._sfvec[0] << " " << value._sfvec[1]; - - case SFCOLOR: - case SFVEC3F: - return out << value._sfvec[0] << " " << value._sfvec[1] << " " - << value._sfvec[2]; - - case SFROTATION: - return out << value._sfvec[0] << " " << value._sfvec[1] << " " - << value._sfvec[2] << " " << value._sfvec[3]; - - case SFNODE: - switch (value._sfnode._type) { - case SFNodeRef::T_null: - return out << "NULL"; - - case SFNodeRef::T_unnamed: - nassertr(value._sfnode._p != nullptr, out); - value._sfnode._p->output(out, indent); - return out; - - case SFNodeRef::T_def: - out << "DEF " << value._sfnode._name << " "; - value._sfnode._p->output(out, indent); - return out; - - case SFNodeRef::T_use: - return out << "USE " << value._sfnode._name; - } - return out << "(invalid)"; - - case SFIMAGE: - return out << "(image)"; - - case MFCOLOR: - return output_array(out, value._mf, SFCOLOR, indent, 1); - - case MFFLOAT: - return output_array(out, value._mf, SFFLOAT, indent, 5); - - case MFINT32: - return output_array(out, value._mf, SFINT32, indent, 10); - - case MFROTATION: - return output_array(out, value._mf, SFROTATION, indent, 1); - - case MFSTRING: - return output_array(out, value._mf, SFSTRING, indent, 1); - - case MFVEC2F: - return output_array(out, value._mf, SFVEC2F, indent, 1); - - case MFVEC3F: - return output_array(out, value._mf, SFVEC3F, indent, 1); - - case MFNODE: - return output_array(out, value._mf, SFNODE, indent, 1); - } - - return out << "(unknown)"; -} - -VrmlNodeType::VrmlNodeType(const char *nm) -{ - nassertv(nm != nullptr); - name = strdup(nm); -} - -VrmlNodeType::~VrmlNodeType() -{ - free(name); - - // Free strings duplicated when fields/eventIns/eventOuts added: - plist::iterator i; - - for (i = eventIns.begin(); i != eventIns.end(); i++) { - NameTypeRec *r = *i; - free(r->name); - delete r; - } - for (i = eventOuts.begin(); i != eventOuts.end(); i++) { - NameTypeRec *r = *i; - free(r->name); - delete r; - } - for (i = fields.begin(); i != fields.end(); i++) { - NameTypeRec *r = *i; - free(r->name); - delete r; - } -} - -void -VrmlNodeType::addToNameSpace(VrmlNodeType *_type) -{ - if (find(_type->getName()) != nullptr) { - std::cerr << "PROTO " << _type->getName() << " already defined\n"; - return; - } - typeList.push_front(_type); -} - -// -// One list is used to store all the node types. Nested namespaces are -// separated by NULL elements. -// This isn't terribly efficient, but it is nice and simple. -// -void -VrmlNodeType::pushNameSpace() -{ - typeList.push_front(nullptr); -} - -void -VrmlNodeType::popNameSpace() -{ - // Remove everything up to and including the next NULL marker: - plist::iterator i; - for (i = typeList.begin(); i != typeList.end();) { - VrmlNodeType *nodeType = *i; - ++i; - typeList.pop_front(); - - if (nodeType == nullptr) { - break; - } - else { - // NOTE: Instead of just deleting the VrmlNodeTypes, you will - // probably want to reference count or garbage collect them, since - // any nodes created as part of the PROTO implementation will - // probably point back to their VrmlNodeType structure. - delete nodeType; - } - } -} - -const VrmlNodeType * -VrmlNodeType::find(const char *_name) -{ - // Look through the type stack: - plist::iterator i; - for (i = typeList.begin(); i != typeList.end(); i++) { - const VrmlNodeType *nt = *i; - if (nt != nullptr && strcmp(nt->getName(),_name) == 0) { - return nt; - } - } - return nullptr; -} - -void -VrmlNodeType::addEventIn(const char *name, int type, - const VrmlFieldValue *dflt) -{ - add(eventIns, name, type, dflt); -}; -void -VrmlNodeType::addEventOut(const char *name, int type, - const VrmlFieldValue *dflt) -{ - add(eventOuts, name, type, dflt); -}; -void -VrmlNodeType::addField(const char *name, int type, - const VrmlFieldValue *dflt) -{ - add(fields, name, type, dflt); -}; -void -VrmlNodeType::addExposedField(const char *name, int type, - const VrmlFieldValue *dflt) -{ - char tmp[1000]; - add(fields, name, type, dflt); - sprintf(tmp, "set_%s", name); - add(eventIns, tmp, type, dflt); - sprintf(tmp, "%s_changed", name); - add(eventOuts, tmp, type, dflt); -}; - -void -VrmlNodeType::add(plist &recs, const char *name, int type, - const VrmlFieldValue *dflt) -{ - NameTypeRec *r = new NameTypeRec; - r->name = strdup(name); - r->type = type; - if (dflt != nullptr) { - r->dflt = *dflt; - } else { - memset(&r->dflt, 0, sizeof(r->dflt)); - } - recs.push_front(r); -} - -const VrmlNodeType::NameTypeRec * -VrmlNodeType::hasEventIn(const char *name) const -{ - return has(eventIns, name); -} - -const VrmlNodeType::NameTypeRec * -VrmlNodeType::hasEventOut(const char *name) const -{ - return has(eventOuts, name); -} - -const VrmlNodeType::NameTypeRec * -VrmlNodeType::hasField(const char *name) const -{ - return has(fields, name); -} - -const VrmlNodeType::NameTypeRec * -VrmlNodeType::hasExposedField(const char *name) const -{ - // Must have field "name", eventIn "set_name", and eventOut - // "name_changed", all with same type: - char tmp[1000]; - const NameTypeRec *base, *set_name, *name_changed; - - base = has(fields, name); - - sprintf(tmp, "set_%s\n", name); - nassertr(strlen(tmp) < 1000, nullptr); - set_name = has(eventIns, tmp); - - sprintf(tmp, "%s_changed\n", name); - nassertr(strlen(tmp) < 1000, nullptr); - name_changed = has(eventOuts, tmp); - - if (base == nullptr || set_name == nullptr || name_changed == nullptr) { - return nullptr; - } - - if (base->type != set_name->type || base->type != name_changed->type) { - return nullptr; - } - - return base; -} - -const VrmlNodeType::NameTypeRec * -VrmlNodeType::has(const plist &recs, const char *name) const -{ - plist::const_iterator i; - for (i = recs.begin(); i != recs.end(); i++) { - if (strcmp((*i)->name, name) == 0) - return (*i); - } - return nullptr; -} - diff --git a/pandatool/src/vrml/vrmlNodeType.h b/pandatool/src/vrml/vrmlNodeType.h deleted file mode 100644 index 1852429a..00000000 --- a/pandatool/src/vrml/vrmlNodeType.h +++ /dev/null @@ -1,108 +0,0 @@ -/************************************************** - * VRML 2.0 Parser - * Copyright (C) 1996 Silicon Graphics, Inc. - * - * Author(s) : Gavin Bell - * Daniel Woods (first port) - ************************************************** - */ - -#ifndef VRMLNODETYPE_H -#define VRMLNODETYPE_H - -// -// The VrmlNodeType class is responsible for storing information about node -// or prototype types. -// - - -#include "pandatoolbase.h" - -#include "plist.h" -#include "pvector.h" - -class VrmlNode; - -struct SFNodeRef { - VrmlNode *_p; - enum { T_null, T_unnamed, T_def, T_use } _type; - char *_name; -}; - -union VrmlFieldValue { - bool _sfbool; - double _sffloat; - long _sfint32; - char *_sfstring; - double _sfvec[4]; - SFNodeRef _sfnode; - pvector *_mf; -}; - -typedef pvector MFArray; - - -std::ostream &output_value(std::ostream &out, const VrmlFieldValue &value, int type, - int indent = 0); - - -class VrmlNodeType { -public: - // Constructor. Takes name of new type (e.g. "Transform" or "Box") - // Copies the string given as name. - VrmlNodeType(const char *nm); - - // Destructor exists mainly to deallocate storage for name - ~VrmlNodeType(); - - // Namespace management functions. PROTO definitions add node types - // to the namespace. PROTO implementations are a separate node - // namespace, and require that any nested PROTOs NOT be available - // outside the PROTO implementation. - // addToNameSpace will print an error to stderr if the given type - // is already defined. - static void addToNameSpace(VrmlNodeType *); - static void pushNameSpace(); - static void popNameSpace(); - - // Find a node type, given its name. Returns NULL if type is not defined. - static const VrmlNodeType *find(const char *nm); - - // Routines for adding/getting eventIns/Outs/fields - void addEventIn(const char *name, int type, - const VrmlFieldValue *dflt = nullptr); - void addEventOut(const char *name, int type, - const VrmlFieldValue *dflt = nullptr); - void addField(const char *name, int type, - const VrmlFieldValue *dflt = nullptr); - void addExposedField(const char *name, int type, - const VrmlFieldValue *dflt = nullptr); - - typedef struct { - char *name; - int type; - VrmlFieldValue dflt; - } NameTypeRec; - - const NameTypeRec *hasEventIn(const char *name) const; - const NameTypeRec *hasEventOut(const char *name) const; - const NameTypeRec *hasField(const char *name) const; - const NameTypeRec *hasExposedField(const char *name) const; - - const char *getName() const { return name; } - -private: - void add(plist &,const char *,int, const VrmlFieldValue *dflt); - const NameTypeRec *has(const plist &,const char *) const; - - char *name; - - // Node types are stored in this data structure: - static plist typeList; - - plist eventIns; - plist eventOuts; - plist fields; -}; - -#endif diff --git a/pandatool/src/vrml/vrmlParser.cxx.prebuilt b/pandatool/src/vrml/vrmlParser.cxx.prebuilt deleted file mode 100644 index b94bc8d5..00000000 --- a/pandatool/src/vrml/vrmlParser.cxx.prebuilt +++ /dev/null @@ -1,2387 +0,0 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "2.4.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - -/* Using locations. */ -#define YYLSP_NEEDED 0 - -/* Substitute the variable and function names. */ -#define yyparse vrmlyyparse -#define yylex vrmlyylex -#define yyerror vrmlyyerror -#define yylval vrmlyylval -#define yychar vrmlyychar -#define yydebug vrmlyydebug -#define yynerrs vrmlyynerrs - - -/* Copy the first part of user declarations. */ - -/* Line 189 of yacc.c */ -#line 23 "vrmlParser.yxx" - - -// -// Parser for VRML 2.0 files. -// This is a minimal parser that does NOT generate an in-memory scene graph. -// - -// The original parser was developed on a Windows 95 PC with -// Borland's C++ 5.0 development tools. This was then ported -// to a Windows 95 PC with Microsoft's MSDEV C++ 4.0 development -// tools. The port introduced the ifdef's for -// USING_BORLAND_CPP_5 : since this provides a "std namespace", -// TWO_ARGUMENTS_FOR_STL_STACK : STL is a moving target. The stack template -// class takes either one or two arguments. - -#include "pandatoolbase.h" -#include "vrmlLexerDefs.h" -#include "vrmlNodeType.h" -#include "vrmlNode.h" -#include "pnotify.h" -#include "plist.h" - -#include -#include // for sprintf() - -//#define YYDEBUG 1 - -// Currently-being-define proto. Prototypes may be nested, so a stack -// is needed: - -std::stack > currentProtoStack; - -// This is used to keep track of which field in which type of node is being -// parsed. Field are nested (nodes are contained inside MFNode/SFNode fields) -// so a stack of these is needed: -typedef struct { - const VrmlNodeType *nodeType; - const char *fieldName; - const VrmlNodeType::NameTypeRec *typeRec; -} FieldRec; - -std::stack > currentField; - -// Similarly for the node entries (which contain the actual values for -// the fields as they are encountered): - -std::stack > currentNode; - -// This is used when the parser knows what kind of token it expects -// to get next-- used when parsing field values (whose types are declared -// and read by the parser) and at certain other places: -extern int expectToken; - -// This is where we store the parsed scene. -VrmlScene *parsed_scene = NULL; - -// Some helper routines defined below: -static void beginProto(const char *); -static void endProto(); -int addField(const char *type, const char *name, const VrmlFieldValue *dflt = NULL); -int addEventIn(const char *type, const char *name, const VrmlFieldValue *dflt = NULL); -int addEventOut(const char *type, const char *name, const VrmlFieldValue *dflt = NULL); -int addExposedField(const char *type, const char *name, const VrmlFieldValue *dflt = NULL); -int add(void (VrmlNodeType::*func)(const char *, int, const VrmlFieldValue *), - const char *typeString, const char *name, - const VrmlFieldValue *dflt); -int fieldType(const char *type); -void enterNode(const char *); -VrmlNode *exitNode(); -void inScript(); -void enterField(const char *); -void storeField(const VrmlFieldValue &value); -void exitField(); -void expect(int type); - -extern void vrmlyyerror(const std::string &); - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the parser. -//////////////////////////////////////////////////////////////////// - -void -vrml_init_parser(std::istream &in, const std::string &filename) { - //yydebug = 0; - vrml_init_lexer(in, filename); -} - -void -vrml_cleanup_parser() { -} - - - -/* Line 189 of yacc.c */ -#line 174 "y.tab.c" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - IDENTIFIER = 258, - DEF = 259, - USE = 260, - PROTO = 261, - EXTERNPROTO = 262, - TO = 263, - IS = 264, - ROUTE = 265, - SFN_NULL = 266, - EVENTIN = 267, - EVENTOUT = 268, - FIELD = 269, - EXPOSEDFIELD = 270, - SFBOOL = 271, - SFCOLOR = 272, - SFFLOAT = 273, - SFIMAGE = 274, - SFINT32 = 275, - SFNODE = 276, - SFROTATION = 277, - SFSTRING = 278, - SFTIME = 279, - SFVEC2F = 280, - SFVEC3F = 281, - MFCOLOR = 282, - MFFLOAT = 283, - MFINT32 = 284, - MFROTATION = 285, - MFSTRING = 286, - MFVEC2F = 287, - MFVEC3F = 288, - MFNODE = 289 - }; -#endif -/* Tokens. */ -#define IDENTIFIER 258 -#define DEF 259 -#define USE 260 -#define PROTO 261 -#define EXTERNPROTO 262 -#define TO 263 -#define IS 264 -#define ROUTE 265 -#define SFN_NULL 266 -#define EVENTIN 267 -#define EVENTOUT 268 -#define FIELD 269 -#define EXPOSEDFIELD 270 -#define SFBOOL 271 -#define SFCOLOR 272 -#define SFFLOAT 273 -#define SFIMAGE 274 -#define SFINT32 275 -#define SFNODE 276 -#define SFROTATION 277 -#define SFSTRING 278 -#define SFTIME 279 -#define SFVEC2F 280 -#define SFVEC3F 281 -#define MFCOLOR 282 -#define MFFLOAT 283 -#define MFINT32 284 -#define MFROTATION 285 -#define MFSTRING 286 -#define MFVEC2F 287 -#define MFVEC3F 288 -#define MFNODE 289 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -{ - -/* Line 214 of yacc.c */ -#line 116 "vrmlParser.yxx" - - char *string; - VrmlFieldValue fv; - VrmlNode *node; - MFArray *mfarray; - SFNodeRef nodeRef; - VrmlScene *scene; - - - -/* Line 214 of yacc.c */ -#line 289 "y.tab.c" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - - -/* Copy the second part of user declarations. */ - - -/* Line 264 of yacc.c */ -#line 301 "y.tab.c" - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; -#else -typedef short int yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef YY_ -# define YY_(msgid) msgid -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) -#else -# define YYUSE(e) /* empty */ -#endif - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; -#endif -{ - return yyi; -} -#endif - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined _STDLIB_H \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 3 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 126 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 40 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 26 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 70 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 125 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 289 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 39, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 35, 2, 36, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 37, 2, 38, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 -}; - -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint8 yyprhs[] = -{ - 0, 0, 3, 5, 6, 9, 12, 15, 17, 21, - 24, 26, 28, 29, 39, 40, 41, 50, 51, 54, - 58, 62, 63, 69, 70, 76, 77, 80, 84, 88, - 92, 96, 105, 106, 112, 113, 116, 117, 121, 123, - 125, 129, 133, 134, 140, 146, 152, 154, 156, 158, - 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, - 180, 182, 184, 186, 189, 192, 195, 198, 202, 204, - 205 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 41, 0, -1, 42, -1, -1, 42, 43, -1, 42, - 44, -1, 42, 56, -1, 57, -1, 4, 3, 57, - -1, 5, 3, -1, 45, -1, 47, -1, -1, 6, - 3, 46, 35, 50, 36, 37, 42, 38, -1, -1, - -1, 7, 3, 48, 35, 54, 36, 49, 63, -1, - -1, 50, 51, -1, 12, 3, 3, -1, 13, 3, - 3, -1, -1, 14, 3, 3, 52, 63, -1, -1, - 15, 3, 3, 53, 63, -1, -1, 54, 55, -1, - 12, 3, 3, -1, 13, 3, 3, -1, 14, 3, - 3, -1, 15, 3, 3, -1, 10, 3, 39, 3, - 8, 3, 39, 3, -1, -1, 3, 58, 37, 59, - 38, -1, -1, 59, 60, -1, -1, 3, 61, 63, - -1, 56, -1, 44, -1, 12, 3, 3, -1, 13, - 3, 3, -1, -1, 14, 3, 3, 62, 63, -1, - 12, 3, 3, 9, 3, -1, 13, 3, 3, 9, - 3, -1, 16, -1, 17, -1, 27, -1, 18, -1, - 28, -1, 19, -1, 20, -1, 29, -1, 22, -1, - 30, -1, 23, -1, 31, -1, 24, -1, 25, -1, - 32, -1, 26, -1, 33, -1, 21, 43, -1, 21, - 11, -1, 34, 64, -1, 9, 3, -1, 35, 65, - 36, -1, 43, -1, -1, 65, 43, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 147, 147, 155, 158, 165, 166, 170, 176, 182, - 191, 192, 196, 196, 202, 204, 202, 207, 209, 213, - 215, 218, 217, 229, 228, 241, 243, 247, 249, 251, - 253, 258, 263, 263, 267, 269, 273, 273, 280, 281, - 284, 285, 286, 286, 290, 292, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, - 311, 312, 313, 315, 316, 322, 323, 327, 331, 342, - 345 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "IDENTIFIER", "DEF", "USE", "PROTO", - "EXTERNPROTO", "TO", "IS", "ROUTE", "SFN_NULL", "EVENTIN", "EVENTOUT", - "FIELD", "EXPOSEDFIELD", "SFBOOL", "SFCOLOR", "SFFLOAT", "SFIMAGE", - "SFINT32", "SFNODE", "SFROTATION", "SFSTRING", "SFTIME", "SFVEC2F", - "SFVEC3F", "MFCOLOR", "MFFLOAT", "MFINT32", "MFROTATION", "MFSTRING", - "MFVEC2F", "MFVEC3F", "MFNODE", "'['", "']'", "'{'", "'}'", "'.'", - "$accept", "vrmlscene", "declarations", "nodeDeclaration", - "protoDeclaration", "proto", "$@1", "externproto", "$@2", "$@3", - "interfaceDeclarations", "interfaceDeclaration", "$@4", "$@5", - "externInterfaceDeclarations", "externInterfaceDeclaration", - "routeDeclaration", "node", "$@6", "nodeGuts", "nodeGut", "$@7", "$@8", - "fieldValue", "mfnodeValue", "nodes", 0 -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 91, 93, 123, 125, 46 -}; -# endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 40, 41, 42, 42, 42, 42, 43, 43, 43, - 44, 44, 46, 45, 48, 49, 47, 50, 50, 51, - 51, 52, 51, 53, 51, 54, 54, 55, 55, 55, - 55, 56, 58, 57, 59, 59, 61, 60, 60, 60, - 60, 60, 62, 60, 60, 60, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 64, 64, 65, - 65 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 1, 0, 2, 2, 2, 1, 3, 2, - 1, 1, 0, 9, 0, 0, 8, 0, 2, 3, - 3, 0, 5, 0, 5, 0, 2, 3, 3, 3, - 3, 8, 0, 5, 0, 2, 0, 3, 1, 1, - 3, 3, 0, 5, 5, 5, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 2, 2, 3, 1, 0, - 2 -}; - -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 3, 0, 2, 1, 32, 0, 0, 0, 0, 0, - 4, 5, 10, 11, 6, 7, 0, 0, 9, 12, - 14, 0, 34, 8, 0, 0, 0, 0, 17, 25, - 0, 36, 0, 0, 0, 33, 39, 38, 35, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 18, 0, 0, 0, 0, 15, 26, 0, 0, - 46, 47, 49, 51, 52, 0, 54, 56, 58, 59, - 61, 48, 50, 53, 55, 57, 60, 62, 0, 37, - 40, 41, 42, 0, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 66, 64, 63, 69, 68, 65, - 0, 0, 0, 19, 20, 21, 23, 0, 27, 28, - 29, 30, 16, 31, 0, 44, 45, 43, 0, 0, - 13, 67, 70, 22, 24 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int8 yydefgoto[] = -{ - -1, 1, 2, 10, 11, 12, 24, 13, 25, 92, - 39, 51, 118, 119, 40, 57, 14, 15, 16, 27, - 38, 42, 102, 79, 99, 114 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -73 -static const yytype_int8 yypact[] = -{ - -73, 2, 79, -73, -73, 0, 3, 4, 6, 11, - -73, -73, -73, -73, -73, -73, -16, 26, -73, -73, - -73, -4, -73, -73, 5, 7, 38, -2, -73, -73, - 35, -73, 41, 45, 48, -73, -73, -73, -73, 19, - 66, 50, 43, 51, 54, 84, 85, 87, 88, 89, - 56, -73, 91, 92, 93, 94, -73, -73, 59, 96, - -73, -73, -73, -73, -73, 34, -73, -73, -73, -73, - -73, -73, -73, -73, -73, -73, -73, -73, 23, -73, - 95, 97, -73, 98, 100, 102, 104, -73, 105, 106, - 107, 108, 43, 109, -73, -73, -73, -73, -73, -73, - 110, 111, 43, -73, -73, -73, -73, 12, -73, -73, - -73, -73, -73, -73, 20, -73, -73, -73, 43, 43, - -73, -73, -73, -73, -73 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = -{ - -73, -73, 13, -65, 90, -73, -73, -73, -73, -73, - -73, -73, -73, -73, -73, -73, 99, 101, -73, -73, - -73, -73, -73, -72, -73, -73 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -1 -static const yytype_uint8 yytable[] = -{ - 96, 31, 3, 17, 7, 8, 18, 19, 9, 20, - 32, 33, 34, 98, 21, 4, 5, 6, 7, 8, - 112, 22, 9, 4, 5, 6, 4, 5, 6, 4, - 117, 46, 47, 48, 49, 26, 35, 4, 5, 6, - 28, 30, 29, 41, 43, 95, 123, 124, 44, 122, - 120, 45, 59, 58, 80, 50, 121, 81, 97, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 52, 53, - 54, 55, 4, 5, 6, 7, 8, 82, 83, 9, - 84, 85, 86, 87, 88, 89, 90, 91, 93, 94, - 107, 103, 56, 104, 100, 105, 101, 106, 108, 109, - 110, 111, 113, 115, 116, 0, 0, 36, 23, 0, - 0, 0, 0, 0, 0, 0, 37 -}; - -static const yytype_int8 yycheck[] = -{ - 65, 3, 0, 3, 6, 7, 3, 3, 10, 3, - 12, 13, 14, 78, 3, 3, 4, 5, 6, 7, - 92, 37, 10, 3, 4, 5, 3, 4, 5, 3, - 102, 12, 13, 14, 15, 39, 38, 3, 4, 5, - 35, 3, 35, 8, 3, 11, 118, 119, 3, 114, - 38, 3, 9, 3, 3, 36, 36, 3, 35, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 12, 13, - 14, 15, 3, 4, 5, 6, 7, 3, 3, 10, - 3, 3, 3, 37, 3, 3, 3, 3, 39, 3, - 87, 3, 36, 3, 9, 3, 9, 3, 3, 3, - 3, 3, 3, 3, 3, -1, -1, 27, 17, -1, - -1, -1, -1, -1, -1, -1, 27 -}; - -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 41, 42, 0, 3, 4, 5, 6, 7, 10, - 43, 44, 45, 47, 56, 57, 58, 3, 3, 3, - 3, 3, 37, 57, 46, 48, 39, 59, 35, 35, - 3, 3, 12, 13, 14, 38, 44, 56, 60, 50, - 54, 8, 61, 3, 3, 3, 12, 13, 14, 15, - 36, 51, 12, 13, 14, 15, 36, 55, 3, 9, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 63, - 3, 3, 3, 3, 3, 3, 3, 37, 3, 3, - 3, 3, 49, 39, 3, 11, 43, 35, 43, 64, - 9, 9, 62, 3, 3, 3, 3, 42, 3, 3, - 3, 3, 63, 3, 65, 3, 3, 63, 52, 53, - 38, 36, 43, 63, 63 -}; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ - -#define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) - - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) -#else -# define YYLEX yylex () -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) - { - default: - break; - } -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif -{ - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } -} -#endif /* YYERROR_VERBOSE */ - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else -static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif -{ - YYUSE (yyvaluep); - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - - default: - break; - } -} - -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ - -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else -int -yyparse () - -#endif -#endif -{ - - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - *++yyvsp = yylval; - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: - -/* Line 1464 of yacc.c */ -#line 148 "vrmlParser.yxx" - { - parsed_scene = (yyvsp[(1) - (1)].scene); -} - break; - - case 3: - -/* Line 1464 of yacc.c */ -#line 155 "vrmlParser.yxx" - { - (yyval.scene) = new VrmlScene; -} - break; - - case 4: - -/* Line 1464 of yacc.c */ -#line 159 "vrmlParser.yxx" - { - Declaration d; - d._node = (yyvsp[(2) - (2)].nodeRef); - (yyvsp[(1) - (2)].scene)->push_back(d); - (yyval.scene) = (yyvsp[(1) - (2)].scene); -} - break; - - case 7: - -/* Line 1464 of yacc.c */ -#line 171 "vrmlParser.yxx" - { - (yyval.nodeRef)._p = (yyvsp[(1) - (1)].node); - (yyval.nodeRef)._type = SFNodeRef::T_unnamed; - (yyval.nodeRef)._name = NULL; -} - break; - - case 8: - -/* Line 1464 of yacc.c */ -#line 177 "vrmlParser.yxx" - { - (yyval.nodeRef)._p = (yyvsp[(3) - (3)].node); - (yyval.nodeRef)._type = SFNodeRef::T_def; - (yyval.nodeRef)._name = (yyvsp[(2) - (3)].string); -} - break; - - case 9: - -/* Line 1464 of yacc.c */ -#line 183 "vrmlParser.yxx" - { - (yyval.nodeRef)._p = NULL; - (yyval.nodeRef)._type = SFNodeRef::T_use; - (yyval.nodeRef)._name = (yyvsp[(2) - (2)].string); -} - break; - - case 12: - -/* Line 1464 of yacc.c */ -#line 196 "vrmlParser.yxx" - { beginProto((yyvsp[(2) - (2)].string)); } - break; - - case 13: - -/* Line 1464 of yacc.c */ -#line 198 "vrmlParser.yxx" - { endProto(); free((yyvsp[(2) - (9)].string));} - break; - - case 14: - -/* Line 1464 of yacc.c */ -#line 202 "vrmlParser.yxx" - { beginProto((yyvsp[(2) - (2)].string)); } - break; - - case 15: - -/* Line 1464 of yacc.c */ -#line 204 "vrmlParser.yxx" - { expect(MFSTRING); } - break; - - case 16: - -/* Line 1464 of yacc.c */ -#line 205 "vrmlParser.yxx" - { endProto(); free((yyvsp[(2) - (8)].string)); } - break; - - case 19: - -/* Line 1464 of yacc.c */ -#line 213 "vrmlParser.yxx" - { addEventIn((yyvsp[(2) - (3)].string), (yyvsp[(3) - (3)].string)); - free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 20: - -/* Line 1464 of yacc.c */ -#line 215 "vrmlParser.yxx" - { addEventOut((yyvsp[(2) - (3)].string), (yyvsp[(3) - (3)].string)); - free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 21: - -/* Line 1464 of yacc.c */ -#line 218 "vrmlParser.yxx" - { - int type = fieldType((yyvsp[(2) - (3)].string)); - expect(type); -} - break; - - case 22: - -/* Line 1464 of yacc.c */ -#line 223 "vrmlParser.yxx" - { - addField((yyvsp[(2) - (5)].string), (yyvsp[(3) - (5)].string), &((yyvsp[(5) - (5)].fv))); - free((yyvsp[(2) - (5)].string)); - free((yyvsp[(3) - (5)].string)); -} - break; - - case 23: - -/* Line 1464 of yacc.c */ -#line 229 "vrmlParser.yxx" - { - int type = fieldType((yyvsp[(2) - (3)].string)); - expect(type); -} - break; - - case 24: - -/* Line 1464 of yacc.c */ -#line 234 "vrmlParser.yxx" - { - addExposedField((yyvsp[(2) - (5)].string), (yyvsp[(3) - (5)].string), &((yyvsp[(5) - (5)].fv))); - free((yyvsp[(2) - (5)].string)); - free((yyvsp[(3) - (5)].string)); -} - break; - - case 27: - -/* Line 1464 of yacc.c */ -#line 247 "vrmlParser.yxx" - { addEventIn((yyvsp[(2) - (3)].string), (yyvsp[(3) - (3)].string)); - free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 28: - -/* Line 1464 of yacc.c */ -#line 249 "vrmlParser.yxx" - { addEventOut((yyvsp[(2) - (3)].string), (yyvsp[(3) - (3)].string)); - free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 29: - -/* Line 1464 of yacc.c */ -#line 251 "vrmlParser.yxx" - { addField((yyvsp[(2) - (3)].string), (yyvsp[(3) - (3)].string)); - free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 30: - -/* Line 1464 of yacc.c */ -#line 253 "vrmlParser.yxx" - { addExposedField((yyvsp[(2) - (3)].string), (yyvsp[(3) - (3)].string)); - free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 31: - -/* Line 1464 of yacc.c */ -#line 259 "vrmlParser.yxx" - { free((yyvsp[(2) - (8)].string)); free((yyvsp[(4) - (8)].string)); free((yyvsp[(6) - (8)].string)); free((yyvsp[(8) - (8)].string)); } - break; - - case 32: - -/* Line 1464 of yacc.c */ -#line 263 "vrmlParser.yxx" - { enterNode((yyvsp[(1) - (1)].string)); } - break; - - case 33: - -/* Line 1464 of yacc.c */ -#line 264 "vrmlParser.yxx" - { (yyval.node) = exitNode(); free((yyvsp[(1) - (5)].string));} - break; - - case 36: - -/* Line 1464 of yacc.c */ -#line 273 "vrmlParser.yxx" - { enterField((yyvsp[(1) - (1)].string)); } - break; - - case 37: - -/* Line 1464 of yacc.c */ -#line 275 "vrmlParser.yxx" - { - storeField((yyvsp[(3) - (3)].fv)); - exitField(); - free((yyvsp[(1) - (3)].string)); -} - break; - - case 40: - -/* Line 1464 of yacc.c */ -#line 284 "vrmlParser.yxx" - { inScript(); free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 41: - -/* Line 1464 of yacc.c */ -#line 285 "vrmlParser.yxx" - { inScript(); free((yyvsp[(2) - (3)].string)); free((yyvsp[(3) - (3)].string)); } - break; - - case 42: - -/* Line 1464 of yacc.c */ -#line 286 "vrmlParser.yxx" - { inScript(); - int type = fieldType((yyvsp[(2) - (3)].string)); - expect(type); } - break; - - case 43: - -/* Line 1464 of yacc.c */ -#line 289 "vrmlParser.yxx" - { free((yyvsp[(2) - (5)].string)); free((yyvsp[(3) - (5)].string)); } - break; - - case 44: - -/* Line 1464 of yacc.c */ -#line 291 "vrmlParser.yxx" - { inScript(); free((yyvsp[(2) - (5)].string)); free((yyvsp[(3) - (5)].string)); free((yyvsp[(5) - (5)].string)); } - break; - - case 45: - -/* Line 1464 of yacc.c */ -#line 293 "vrmlParser.yxx" - { inScript(); free((yyvsp[(2) - (5)].string)); free((yyvsp[(3) - (5)].string)); free((yyvsp[(5) - (5)].string)); } - break; - - case 63: - -/* Line 1464 of yacc.c */ -#line 315 "vrmlParser.yxx" - { (yyval.fv)._sfnode = (yyvsp[(2) - (2)].nodeRef); } - break; - - case 64: - -/* Line 1464 of yacc.c */ -#line 317 "vrmlParser.yxx" - { - (yyval.fv)._sfnode._p = NULL; - (yyval.fv)._sfnode._type = SFNodeRef::T_null; - (yyval.fv)._sfnode._name = NULL; -} - break; - - case 65: - -/* Line 1464 of yacc.c */ -#line 322 "vrmlParser.yxx" - { (yyval.fv)._mf = (yyvsp[(2) - (2)].mfarray); } - break; - - case 66: - -/* Line 1464 of yacc.c */ -#line 323 "vrmlParser.yxx" - { free((yyvsp[(2) - (2)].string)); } - break; - - case 67: - -/* Line 1464 of yacc.c */ -#line 328 "vrmlParser.yxx" - { - (yyval.mfarray) = (yyvsp[(2) - (3)].mfarray); -} - break; - - case 68: - -/* Line 1464 of yacc.c */ -#line 332 "vrmlParser.yxx" - { - (yyval.mfarray) = new MFArray; - VrmlFieldValue v; - v._sfnode = (yyvsp[(1) - (1)].nodeRef); - (yyval.mfarray)->push_back(v); -} - break; - - case 69: - -/* Line 1464 of yacc.c */ -#line 342 "vrmlParser.yxx" - { - (yyval.mfarray) = new MFArray; -} - break; - - case 70: - -/* Line 1464 of yacc.c */ -#line 346 "vrmlParser.yxx" - { - VrmlFieldValue v; - v._sfnode = (yyvsp[(2) - (2)].nodeRef); - (yyvsp[(1) - (2)].mfarray)->push_back(v); - (yyval.mfarray) = (yyvsp[(1) - (2)].mfarray); -} - break; - - - -/* Line 1464 of yacc.c */ -#line 1960 "y.tab.c" - default: break; - } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - *++yyvsp = yylval; - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined(yyoverflow) || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} - - - -/* Line 1684 of yacc.c */ -#line 354 "vrmlParser.yxx" - - -static void -beginProto(const char *protoName) -{ - // Any protos in the implementation are in a local namespace: - VrmlNodeType::pushNameSpace(); - - VrmlNodeType *t = new VrmlNodeType(protoName); - currentProtoStack.push(t); -} - -static void -endProto() -{ - // Make any protos defined in implementation unavailable: - VrmlNodeType::popNameSpace(); - - // Add this proto definition: - if (currentProtoStack.empty()) { - std::cerr << "Error: Empty PROTO stack!\n"; - } - else { - VrmlNodeType *t = currentProtoStack.top(); - currentProtoStack.pop(); - VrmlNodeType::addToNameSpace(t); - } -} - -int -addField(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addField, type, name, dflt); -} - -int -addEventIn(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addEventIn, type, name, dflt); -} -int -addEventOut(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addEventOut, type, name, dflt); -} -int -addExposedField(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addExposedField, type, name, dflt); -} - -int -add(void (VrmlNodeType::*func)(const char *, int, const VrmlFieldValue *), - const char *typeString, const char *name, - const VrmlFieldValue *dflt) -{ - int type = fieldType(typeString); - - if (type == 0) { - std::cerr << "Error: invalid field type: " << type << "\n"; - } - - // Need to add support for Script nodes: - // if (inScript) ... ??? - - if (currentProtoStack.empty()) { - std::cerr << "Error: declaration outside of prototype\n"; - return 0; - } - VrmlNodeType *t = currentProtoStack.top(); - (t->*func)(name, type, dflt); - - return type; -} - -int -fieldType(const char *type) -{ - if (strcmp(type, "SFBool") == 0) return SFBOOL; - if (strcmp(type, "SFColor") == 0) return SFCOLOR; - if (strcmp(type, "SFFloat") == 0) return SFFLOAT; - if (strcmp(type, "SFImage") == 0) return SFIMAGE; - if (strcmp(type, "SFInt32") == 0) return SFINT32; - if (strcmp(type, "SFNode") == 0) return SFNODE; - if (strcmp(type, "SFRotation") == 0) return SFROTATION; - if (strcmp(type, "SFString") == 0) return SFSTRING; - if (strcmp(type, "SFTime") == 0) return SFTIME; - if (strcmp(type, "SFVec2f") == 0) return SFVEC2F; - if (strcmp(type, "SFVec3f") == 0) return SFVEC3F; - if (strcmp(type, "MFColor") == 0) return MFCOLOR; - if (strcmp(type, "MFFloat") == 0) return MFFLOAT; - if (strcmp(type, "MFInt32") == 0) return MFINT32; - if (strcmp(type, "MFNode") == 0) return MFNODE; - if (strcmp(type, "MFRotation") == 0) return MFROTATION; - if (strcmp(type, "MFString") == 0) return MFSTRING; - if (strcmp(type, "MFVec2f") == 0) return MFVEC2F; - if (strcmp(type, "MFVec3f") == 0) return MFVEC3F; - - std::cerr << "Illegal field type: " << type << "\n"; - - return 0; -} - -void -enterNode(const char *nodeType) -{ - const VrmlNodeType *t = VrmlNodeType::find(nodeType); - if (t == NULL) { - char tmp[1000]; - sprintf(tmp, "Unknown node type '%s'", nodeType); - vrmlyyerror(tmp); - } - FieldRec *fr = new FieldRec; - fr->nodeType = t; - fr->fieldName = NULL; - fr->typeRec = NULL; - currentField.push(fr); - - VrmlNode *node = new VrmlNode(t); - currentNode.push(node); -} - -VrmlNode * -exitNode() -{ - FieldRec *fr = currentField.top(); - nassertr(fr != NULL, NULL); - currentField.pop(); - - VrmlNode *node = currentNode.top(); - nassertr(node != NULL, NULL); - currentNode.pop(); - - // std::cerr << "Just defined node:\n" << *node << "\n\n"; - - delete fr; - return node; -} - -void -inScript() -{ - FieldRec *fr = currentField.top(); - if (fr->nodeType == NULL || - strcmp(fr->nodeType->getName(), "Script") != 0) { - vrmlyyerror("interface declaration outside of Script or prototype"); - } -} - -void -enterField(const char *fieldName) -{ - FieldRec *fr = currentField.top(); - nassertv(fr != NULL); - - fr->fieldName = fieldName; - fr->typeRec = NULL; - if (fr->nodeType != NULL) { - // enterField is called when parsing eventIn and eventOut IS - // declarations, in which case we don't need to do anything special-- - // the IS IDENTIFIER will be returned from the lexer normally. - if (fr->nodeType->hasEventIn(fieldName) || - fr->nodeType->hasEventOut(fieldName)) - return; - - const VrmlNodeType::NameTypeRec *typeRec = - fr->nodeType->hasField(fieldName); - if (typeRec != NULL) { - fr->typeRec = typeRec; - // Let the lexer know what field type to expect: - expect(typeRec->type); - } - else { - std::cerr << "Error: Nodes of type " << fr->nodeType->getName() << - " do not have fields/eventIn/eventOut named " << - fieldName << "\n"; - // expect(ANY_FIELD); - } - } - // else expect(ANY_FIELD); -} - -void -storeField(const VrmlFieldValue &value) { - FieldRec *fr = currentField.top(); - nassertv(fr != NULL); - - VrmlNode *node = currentNode.top(); - nassertv(node != NULL); - - if (fr->typeRec != NULL) { - node->_fields.push_back(VrmlNode::Field(fr->typeRec, value)); - } -} - -void -exitField() -{ - FieldRec *fr = currentField.top(); - nassertv(fr != NULL); - - fr->fieldName = NULL; - fr->typeRec = NULL; -} - -void -expect(int type) -{ - expectToken = type; -} - - diff --git a/pandatool/src/vrml/vrmlParser.h.prebuilt b/pandatool/src/vrml/vrmlParser.h.prebuilt deleted file mode 100644 index d7f8a483..00000000 --- a/pandatool/src/vrml/vrmlParser.h.prebuilt +++ /dev/null @@ -1,138 +0,0 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ - -/* Skeleton interface for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - IDENTIFIER = 258, - DEF = 259, - USE = 260, - PROTO = 261, - EXTERNPROTO = 262, - TO = 263, - IS = 264, - ROUTE = 265, - SFN_NULL = 266, - EVENTIN = 267, - EVENTOUT = 268, - FIELD = 269, - EXPOSEDFIELD = 270, - SFBOOL = 271, - SFCOLOR = 272, - SFFLOAT = 273, - SFIMAGE = 274, - SFINT32 = 275, - SFNODE = 276, - SFROTATION = 277, - SFSTRING = 278, - SFTIME = 279, - SFVEC2F = 280, - SFVEC3F = 281, - MFCOLOR = 282, - MFFLOAT = 283, - MFINT32 = 284, - MFROTATION = 285, - MFSTRING = 286, - MFVEC2F = 287, - MFVEC3F = 288, - MFNODE = 289 - }; -#endif -/* Tokens. */ -#define IDENTIFIER 258 -#define DEF 259 -#define USE 260 -#define PROTO 261 -#define EXTERNPROTO 262 -#define TO 263 -#define IS 264 -#define ROUTE 265 -#define SFN_NULL 266 -#define EVENTIN 267 -#define EVENTOUT 268 -#define FIELD 269 -#define EXPOSEDFIELD 270 -#define SFBOOL 271 -#define SFCOLOR 272 -#define SFFLOAT 273 -#define SFIMAGE 274 -#define SFINT32 275 -#define SFNODE 276 -#define SFROTATION 277 -#define SFSTRING 278 -#define SFTIME 279 -#define SFVEC2F 280 -#define SFVEC3F 281 -#define MFCOLOR 282 -#define MFFLOAT 283 -#define MFINT32 284 -#define MFROTATION 285 -#define MFSTRING 286 -#define MFVEC2F 287 -#define MFVEC3F 288 -#define MFNODE 289 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef union YYSTYPE -{ - -/* Line 1685 of yacc.c */ -#line 116 "vrmlParser.yxx" - - char *string; - VrmlFieldValue fv; - VrmlNode *node; - MFArray *mfarray; - SFNodeRef nodeRef; - VrmlScene *scene; - - - -/* Line 1685 of yacc.c */ -#line 130 "y.tab.h" -} YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - -extern YYSTYPE vrmlyylval; - - diff --git a/pandatool/src/vrml/vrmlParser.yxx b/pandatool/src/vrml/vrmlParser.yxx deleted file mode 100644 index 9bbdda7b..00000000 --- a/pandatool/src/vrml/vrmlParser.yxx +++ /dev/null @@ -1,567 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlParser.yxx - * @author drose - * @date 2004-10-01 - */ - -// ******************************************************* -// VRML 2.0 Parser -// Copyright (C) 1996 Silicon Graphics, Inc. -// -// Author(s) : Gavin Bell -// Daniel Woods (first port, minor fixes) -// ******************************************************* -// -%{ - -// -// Parser for VRML 2.0 files. -// This is a minimal parser that does NOT generate an in-memory scene graph. -// - -// The original parser was developed on a Windows 95 PC with -// Borland's C++ 5.0 development tools. This was then ported -// to a Windows 95 PC with Microsoft's MSDEV C++ 4.0 development -// tools. The port introduced the ifdef's for -// USING_BORLAND_CPP_5 : since this provides a "std namespace", -// TWO_ARGUMENTS_FOR_STL_STACK : STL is a moving target. The stack template -// class takes either one or two arguments. - -#include "pandatoolbase.h" -#include "vrmlLexerDefs.h" -#include "vrmlNodeType.h" -#include "vrmlNode.h" -#include "pnotify.h" -#include "plist.h" - -#include -#include // for sprintf() - -//#define YYDEBUG 1 - -// Currently-being-define proto. Prototypes may be nested, so a stack -// is needed: - -std::stack > currentProtoStack; - -// This is used to keep track of which field in which type of node is being -// parsed. Field are nested (nodes are contained inside MFNode/SFNode fields) -// so a stack of these is needed: -typedef struct { - const VrmlNodeType *nodeType; - const char *fieldName; - const VrmlNodeType::NameTypeRec *typeRec; -} FieldRec; - -std::stack > currentField; - -// Similarly for the node entries (which contain the actual values for -// the fields as they are encountered): - -std::stack > currentNode; - -// This is used when the parser knows what kind of token it expects -// to get next-- used when parsing field values (whose types are declared -// and read by the parser) and at certain other places: -extern int expectToken; - -// This is where we store the parsed scene. -VrmlScene *parsed_scene = nullptr; - -// Some helper routines defined below: -static void beginProto(const char *); -static void endProto(); -int addField(const char *type, const char *name, const VrmlFieldValue *dflt = nullptr); -int addEventIn(const char *type, const char *name, const VrmlFieldValue *dflt = nullptr); -int addEventOut(const char *type, const char *name, const VrmlFieldValue *dflt = nullptr); -int addExposedField(const char *type, const char *name, const VrmlFieldValue *dflt = nullptr); -int add(void (VrmlNodeType::*func)(const char *, int, const VrmlFieldValue *), - const char *typeString, const char *name, - const VrmlFieldValue *dflt); -int fieldType(const char *type); -void enterNode(const char *); -VrmlNode *exitNode(); -void inScript(); -void enterField(const char *); -void storeField(const VrmlFieldValue &value); -void exitField(); -void expect(int type); - -extern void vrmlyyerror(const std::string &); - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the parser. -//////////////////////////////////////////////////////////////////// - -void -vrml_init_parser(std::istream &in, const std::string &filename) { - //yydebug = 0; - vrml_init_lexer(in, filename); -} - -void -vrml_cleanup_parser() { -} - -%} - -%union { - char *string; - VrmlFieldValue fv; - VrmlNode *node; - MFArray *mfarray; - SFNodeRef nodeRef; - VrmlScene *scene; -}; - -%type fieldValue -%type node -%type nodeDeclaration -%type mfnodeValue nodes -%type declarations - -/* - * And types that will be needed by a true VRML implementation: - * %type vrmlscene declarations - */ - -%token IDENTIFIER -%token DEF USE PROTO EXTERNPROTO TO IS ROUTE SFN_NULL -%token EVENTIN EVENTOUT FIELD EXPOSEDFIELD - -%token SFBOOL SFCOLOR SFFLOAT SFIMAGE SFINT32 SFNODE SFROTATION -%token SFSTRING SFTIME SFVEC2F SFVEC3F -%token MFCOLOR MFFLOAT MFINT32 MFROTATION MFSTRING MFVEC2F MFVEC3F -%token MFNODE - -%% - -vrmlscene: declarations -{ - parsed_scene = $1; -} - ; - -declarations: - /* Empty is OK */ -{ - $$ = new VrmlScene; -} - | declarations nodeDeclaration -{ - Declaration d; - d._node = $2; - $1->push_back(d); - $$ = $1; -} - | declarations protoDeclaration - | declarations routeDeclaration - ; - -nodeDeclaration: - node -{ - $$._p = $1; - $$._type = SFNodeRef::T_unnamed; - $$._name = nullptr; -} - | DEF IDENTIFIER node -{ - $$._p = $3; - $$._type = SFNodeRef::T_def; - $$._name = $2; -} - | USE IDENTIFIER -{ - $$._p = nullptr; - $$._type = SFNodeRef::T_use; - $$._name = $2; -} - ; - -protoDeclaration: - proto - | externproto - ; - -proto: - PROTO IDENTIFIER { beginProto($2); } - '[' interfaceDeclarations ']' - '{' declarations '}' { endProto(); free($2);} - ; - -externproto: - EXTERNPROTO IDENTIFIER { beginProto($2); } - '[' externInterfaceDeclarations ']' - { expect(MFSTRING); } - fieldValue { endProto(); free($2); } - ; -interfaceDeclarations: - /* Empty is OK */ - | interfaceDeclarations interfaceDeclaration - ; - -interfaceDeclaration: - EVENTIN IDENTIFIER IDENTIFIER { addEventIn($2, $3); - free($2); free($3); } - | EVENTOUT IDENTIFIER IDENTIFIER { addEventOut($2, $3); - free($2); free($3); } - | FIELD IDENTIFIER IDENTIFIER -{ - int type = fieldType($2); - expect(type); -} - fieldValue -{ - addField($2, $3, &($5)); - free($2); - free($3); -} - | EXPOSEDFIELD IDENTIFIER IDENTIFIER -{ - int type = fieldType($2); - expect(type); -} - fieldValue -{ - addExposedField($2, $3, &($5)); - free($2); - free($3); -} - ; - -externInterfaceDeclarations: - /* Empty is OK */ - | externInterfaceDeclarations externInterfaceDeclaration - ; - -externInterfaceDeclaration: - EVENTIN IDENTIFIER IDENTIFIER { addEventIn($2, $3); - free($2); free($3); } - | EVENTOUT IDENTIFIER IDENTIFIER { addEventOut($2, $3); - free($2); free($3); } - | FIELD IDENTIFIER IDENTIFIER { addField($2, $3); - free($2); free($3); } - | EXPOSEDFIELD IDENTIFIER IDENTIFIER { addExposedField($2, $3); - free($2); free($3); } - ; - -routeDeclaration: - ROUTE IDENTIFIER '.' IDENTIFIER TO IDENTIFIER '.' IDENTIFIER - { free($2); free($4); free($6); free($8); } - ; - -node: - IDENTIFIER { enterNode($1); } - '{' nodeGuts '}' { $$ = exitNode(); free($1);} - ; - -nodeGuts: - /* Empty is OK */ - | nodeGuts nodeGut - ; - -nodeGut: - IDENTIFIER { enterField($1); } - fieldValue -{ - storeField($3); - exitField(); - free($1); -} - | routeDeclaration - | protoDeclaration - - /* The following are only valid for Script nodes: */ - | EVENTIN IDENTIFIER IDENTIFIER { inScript(); free($2); free($3); } - | EVENTOUT IDENTIFIER IDENTIFIER { inScript(); free($2); free($3); } - | FIELD IDENTIFIER IDENTIFIER { inScript(); - int type = fieldType($2); - expect(type); } - fieldValue { free($2); free($3); } - | EVENTIN IDENTIFIER IDENTIFIER IS IDENTIFIER - { inScript(); free($2); free($3); free($5); } - | EVENTOUT IDENTIFIER IDENTIFIER IS IDENTIFIER - { inScript(); free($2); free($3); free($5); } - ; - -fieldValue: - SFBOOL - | SFCOLOR - | MFCOLOR - | SFFLOAT - | MFFLOAT - | SFIMAGE - | SFINT32 - | MFINT32 - | SFROTATION - | MFROTATION - | SFSTRING - | MFSTRING - | SFTIME - | SFVEC2F - | MFVEC2F - | SFVEC3F - | MFVEC3F - - | SFNODE nodeDeclaration { $$._sfnode = $2; } - | SFNODE SFN_NULL -{ - $$._sfnode._p = nullptr; - $$._sfnode._type = SFNodeRef::T_null; - $$._sfnode._name = nullptr; -} - | MFNODE mfnodeValue { $$._mf = $2; } - | IS IDENTIFIER { free($2); } - ; - -mfnodeValue: - '[' nodes ']' -{ - $$ = $2; -} - | nodeDeclaration -{ - $$ = new MFArray; - VrmlFieldValue v; - v._sfnode = $1; - $$->push_back(v); -} - ; - -nodes: - /* Empty is OK */ -{ - $$ = new MFArray; -} - | nodes nodeDeclaration -{ - VrmlFieldValue v; - v._sfnode = $2; - $1->push_back(v); - $$ = $1; -} - ; - -%% - -static void -beginProto(const char *protoName) -{ - // Any protos in the implementation are in a local namespace: - VrmlNodeType::pushNameSpace(); - - VrmlNodeType *t = new VrmlNodeType(protoName); - currentProtoStack.push(t); -} - -static void -endProto() -{ - // Make any protos defined in implementation unavailable: - VrmlNodeType::popNameSpace(); - - // Add this proto definition: - if (currentProtoStack.empty()) { - std::cerr << "Error: Empty PROTO stack!\n"; - } - else { - VrmlNodeType *t = currentProtoStack.top(); - currentProtoStack.pop(); - VrmlNodeType::addToNameSpace(t); - } -} - -int -addField(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addField, type, name, dflt); -} - -int -addEventIn(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addEventIn, type, name, dflt); -} -int -addEventOut(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addEventOut, type, name, dflt); -} -int -addExposedField(const char *type, const char *name, - const VrmlFieldValue *dflt) -{ - return add(&VrmlNodeType::addExposedField, type, name, dflt); -} - -int -add(void (VrmlNodeType::*func)(const char *, int, const VrmlFieldValue *), - const char *typeString, const char *name, - const VrmlFieldValue *dflt) -{ - int type = fieldType(typeString); - - if (type == 0) { - std::cerr << "Error: invalid field type: " << type << "\n"; - } - - // Need to add support for Script nodes: - // if (inScript) ... ??? - - if (currentProtoStack.empty()) { - std::cerr << "Error: declaration outside of prototype\n"; - return 0; - } - VrmlNodeType *t = currentProtoStack.top(); - (t->*func)(name, type, dflt); - - return type; -} - -int -fieldType(const char *type) -{ - if (strcmp(type, "SFBool") == 0) return SFBOOL; - if (strcmp(type, "SFColor") == 0) return SFCOLOR; - if (strcmp(type, "SFFloat") == 0) return SFFLOAT; - if (strcmp(type, "SFImage") == 0) return SFIMAGE; - if (strcmp(type, "SFInt32") == 0) return SFINT32; - if (strcmp(type, "SFNode") == 0) return SFNODE; - if (strcmp(type, "SFRotation") == 0) return SFROTATION; - if (strcmp(type, "SFString") == 0) return SFSTRING; - if (strcmp(type, "SFTime") == 0) return SFTIME; - if (strcmp(type, "SFVec2f") == 0) return SFVEC2F; - if (strcmp(type, "SFVec3f") == 0) return SFVEC3F; - if (strcmp(type, "MFColor") == 0) return MFCOLOR; - if (strcmp(type, "MFFloat") == 0) return MFFLOAT; - if (strcmp(type, "MFInt32") == 0) return MFINT32; - if (strcmp(type, "MFNode") == 0) return MFNODE; - if (strcmp(type, "MFRotation") == 0) return MFROTATION; - if (strcmp(type, "MFString") == 0) return MFSTRING; - if (strcmp(type, "MFVec2f") == 0) return MFVEC2F; - if (strcmp(type, "MFVec3f") == 0) return MFVEC3F; - - std::cerr << "Illegal field type: " << type << "\n"; - - return 0; -} - -void -enterNode(const char *nodeType) -{ - const VrmlNodeType *t = VrmlNodeType::find(nodeType); - if (t == nullptr) { - char tmp[1000]; - sprintf(tmp, "Unknown node type '%s'", nodeType); - vrmlyyerror(tmp); - } - FieldRec *fr = new FieldRec; - fr->nodeType = t; - fr->fieldName = nullptr; - fr->typeRec = nullptr; - currentField.push(fr); - - VrmlNode *node = new VrmlNode(t); - currentNode.push(node); -} - -VrmlNode * -exitNode() -{ - FieldRec *fr = currentField.top(); - nassertr(fr != nullptr, nullptr); - currentField.pop(); - - VrmlNode *node = currentNode.top(); - nassertr(node != nullptr, nullptr); - currentNode.pop(); - - // std::cerr << "Just defined node:\n" << *node << "\n\n"; - - delete fr; - return node; -} - -void -inScript() -{ - FieldRec *fr = currentField.top(); - if (fr->nodeType == nullptr || - strcmp(fr->nodeType->getName(), "Script") != 0) { - vrmlyyerror("interface declaration outside of Script or prototype"); - } -} - -void -enterField(const char *fieldName) -{ - FieldRec *fr = currentField.top(); - nassertv(fr != nullptr); - - fr->fieldName = fieldName; - fr->typeRec = nullptr; - if (fr->nodeType != nullptr) { - // enterField is called when parsing eventIn and eventOut IS - // declarations, in which case we don't need to do anything special-- - // the IS IDENTIFIER will be returned from the lexer normally. - if (fr->nodeType->hasEventIn(fieldName) || - fr->nodeType->hasEventOut(fieldName)) - return; - - const VrmlNodeType::NameTypeRec *typeRec = - fr->nodeType->hasField(fieldName); - if (typeRec != nullptr) { - fr->typeRec = typeRec; - // Let the lexer know what field type to expect: - expect(typeRec->type); - } - else { - std::cerr << "Error: Nodes of type " << fr->nodeType->getName() << - " do not have fields/eventIn/eventOut named " << - fieldName << "\n"; - // expect(ANY_FIELD); - } - } - // else expect(ANY_FIELD); -} - -void -storeField(const VrmlFieldValue &value) { - FieldRec *fr = currentField.top(); - nassertv(fr != nullptr); - - VrmlNode *node = currentNode.top(); - nassertv(node != nullptr); - - if (fr->typeRec != nullptr) { - node->_fields.push_back(VrmlNode::Field(fr->typeRec, value)); - } -} - -void -exitField() -{ - FieldRec *fr = currentField.top(); - nassertv(fr != nullptr); - - fr->fieldName = nullptr; - fr->typeRec = nullptr; -} - -void -expect(int type) -{ - expectToken = type; -} - diff --git a/pandatool/src/vrml/vrmlParserDefs.h b/pandatool/src/vrml/vrmlParserDefs.h deleted file mode 100644 index cad0d5b2..00000000 --- a/pandatool/src/vrml/vrmlParserDefs.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlParserDefs.h - * @author drose - * @date 2004-09-30 - */ - -#ifndef VRMLPARSERDEFS_H -#define VRMLPARSERDEFS_H - -#include "pandatoolbase.h" - -void vrml_init_parser(std::istream &in, const std::string &filename); -void vrml_cleanup_parser(); -int vrmlyyparse(); - -#endif diff --git a/pandatool/src/vrmlegg/CMakeLists.txt b/pandatool/src/vrmlegg/CMakeLists.txt deleted file mode 100644 index b2a38c84..00000000 --- a/pandatool/src/vrmlegg/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3VRMLEGG_HEADERS - indexedFaceSet.h - vrmlAppearance.h - vrmlToEggConverter.h -) - -set(P3VRMLEGG_SOURCES - indexedFaceSet.cxx - vrmlAppearance.cxx - vrmlToEggConverter.cxx -) - -composite_sources(p3vrmlegg P3VRMLEGG_SOURCES) -add_library(p3vrmlegg STATIC ${P3VRMLEGG_HEADERS} ${P3VRMLEGG_SOURCES}) -target_link_libraries(p3vrmlegg p3vrml p3eggbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/vrmlegg/indexedFaceSet.cxx b/pandatool/src/vrmlegg/indexedFaceSet.cxx deleted file mode 100644 index 0f0dce8e..00000000 --- a/pandatool/src/vrmlegg/indexedFaceSet.cxx +++ /dev/null @@ -1,549 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file indexedFaceSet.cxx - * @author drose - * @date 1999-06-24 - */ - -#include "indexedFaceSet.h" -#include "vrmlAppearance.h" -#include "vrmlNodeType.h" -#include "vrmlNode.h" -#include "pnotify.h" - -#include "eggGroup.h" -#include "eggVertex.h" -#include "eggVertexPool.h" -#include "eggPolygon.h" - -using std::cerr; - -/** - * - */ -IndexedFaceSet:: -IndexedFaceSet(const VrmlNode *geometry, const VRMLAppearance &appearance) : - _geometry(geometry), _appearance(appearance) -{ - get_coord_values(); - get_polys(); - get_colors(); - _has_normals = get_normals(); - if (!_per_vertex_normals.empty()) { - assign_per_vertex_normals(); - } - get_uvs(); - if (!_per_vertex_uvs.empty()) { - assign_per_vertex_uvs(); - } -} - - -/** - * - */ -void IndexedFaceSet:: -convert_to_egg(EggGroup *group, const LMatrix4d &net_transform) { - EggVertexPool *vpool = new EggVertexPool(group->get_name()); - group->add_child(vpool); - - make_polys(vpool, group, net_transform); - if (!_has_normals && _appearance._has_material) { - compute_normals(group); - } -} - - -/** - * - */ -void IndexedFaceSet:: -get_coord_values() { - const VrmlNode *coord = _geometry->get_value("coord")._sfnode._p; - - if (coord != nullptr) { - const MFArray *point = coord->get_value("point")._mf; - MFArray::const_iterator ci; - for (ci = point->begin(); ci != point->end(); ++ci) { - const double *p = (*ci)._sfvec; - _coord_values.push_back(LVertexd(p[0], p[1], p[2])); - } - } -} - - -/** - * - */ -void IndexedFaceSet:: -get_polys() { - const MFArray *coordIndex = _geometry->get_value("coordIndex")._mf; - VrmlPolygon poly; - - MFArray::const_iterator ci; - for (ci = coordIndex->begin(); ci != coordIndex->end(); ++ci) { - if ((*ci)._sfint32 < 0) { - _polys.push_back(poly); - poly._verts.clear(); - } else { - const LVertexd &p = _coord_values[(*ci)._sfint32]; - VrmlVertex vert; - vert._index = (*ci)._sfint32; - vert._pos = p; - poly._verts.push_back(vert); - } - } -} - -/** - * Builds up a vector of LColor pointers corresponding to the VRML color node. - */ -void IndexedFaceSet:: -get_vrml_colors(const VrmlNode *color_node, double transparency, - pvector &color_list) { - const MFArray *color = color_node->get_value("color")._mf; - MFArray::const_iterator ci; - for (ci = color->begin(); ci != color->end(); ++ci) { - const double *p = (*ci)._sfvec; - LColor color(p[0], p[1], p[2], 1.0 - transparency); - color_list.push_back(color); - } -} - -/** - * Builds up a vector of double array pointers corresponding to the VRML - * normal node. - */ -void IndexedFaceSet:: -get_vrml_normals(const VrmlNode *normal_node, - pvector &normal_list) { - const MFArray *point = normal_node->get_value("vector")._mf; - MFArray::const_iterator ci; - for (ci = point->begin(); ci != point->end(); ++ci) { - const double *p = (*ci)._sfvec; - LNormald normal(p[0], p[1], p[2]); - normal_list.push_back(normal); - } -} - -/** - * Builds up a vector of double array pointers corresponding to the VRML - * texCoord node. - */ -void IndexedFaceSet:: -get_vrml_uvs(const VrmlNode *texCoord_node, - pvector &uv_list) { - const MFArray *point = texCoord_node->get_value("point")._mf; - MFArray::const_iterator ci; - for (ci = point->begin(); ci != point->end(); ++ci) { - const double *p = (*ci)._sfvec; - LTexCoordd uv(p[0], p[1]); - uv_list.push_back(uv); - } -} - - -/** - * - */ -bool IndexedFaceSet:: -get_colors() { - const VrmlNode *color = _geometry->get_value("color")._sfnode._p; - if (color != nullptr) { - // Vertex or face colors. - pvector color_list; - get_vrml_colors(color, _appearance._transparency, color_list); - - bool colorPerVertex = _geometry->get_value("colorPerVertex")._sfbool; - MFArray *colorIndex = _geometry->get_value("colorIndex")._mf; - if (colorPerVertex) { - MFArray::const_iterator ci; - size_t pi = 0; - size_t pv = 0; - for (ci = colorIndex->begin(); ci != colorIndex->end(); ++ci) { - if ((*ci)._sfint32 < 0) { - // End of poly. - if (pv != _polys[pi]._verts.size()) { - cerr << "Color indices don't match up!\n"; - return false; - } - pi++; - pv = 0; - } else { - if (pi >= _polys.size() || pv >= _polys[pi]._verts.size()) { - cerr << "Color indices don't match up!\n"; - return false; - } - _polys[pi]._verts[pv]._attrib.set_color(color_list[(*ci)._sfint32]); - pv++; - } - } - if (pi != _polys.size()) { - cerr << "Not enough color indices!\n"; - return false; - } - } else { - if (!colorIndex->empty()) { - MFArray::const_iterator ci; - size_t pi = 0; - if (colorIndex->size() != _polys.size()) { - cerr << "Wrong number of color indices!\n"; - return false; - } - for (ci = colorIndex->begin(); ci != colorIndex->end(); ++ci) { - if ((*ci)._sfint32 < 0 || (*ci)._sfint32 >= (int)color_list.size()) { - cerr << "Invalid color index!\n"; - return false; - } - _polys[pi]._attrib.set_color(color_list[(*ci)._sfint32]); - pi++; - } - } else { - if (color_list.size() != _polys.size()) { - cerr << "Wrong number of colors!\n"; - return false; - } - for (size_t pi = 0; pi < color_list.size(); pi++) { - _polys[pi]._attrib.set_color(color_list[pi]); - } - } - } - return true; - } - return false; -} - -/** - * - */ -bool IndexedFaceSet:: -get_normals() { - const VrmlNode *normal = _geometry->get_value("normal")._sfnode._p; - if (normal != nullptr) { - // Vertex or face normals. - pvector normal_list; - get_vrml_normals(normal, normal_list); - - bool normalPerVertex = _geometry->get_value("normalPerVertex")._sfbool; - MFArray *normalIndex = _geometry->get_value("normalIndex")._mf; - MFArray::const_iterator ci; - - if (normalPerVertex && - normal_list.size() == _polys.size() && - normalIndex->empty()) { - // Here's an interesting formZ bug. We end up with a VRML file that - // claims to have normals per vertex, yet there is no normal index list, - // and there are exactly enough normals in the list to indicate one - // normal per face. Silly formZ. - normalPerVertex = false; - } - - if (normalPerVertex) { - - if (normalIndex->empty()) { - // If we have *no* normal index array, but we do have per-vertex - // normals, assume the VRML writer meant to imply a one-to-one - // mapping. This works around a broken formZ VRML file writer. - for (size_t i = 0; i < normal_list.size(); i++) { - VrmlFieldValue fv; - fv._sfint32 = i; - (*normalIndex).push_back(fv); - } - } - - // It's possible that this .wrl file indexes normals directly into the - // vertex array, instead of into the polygon list. Check for this - // possibility. This can only happen if the number of normal indices - // exactly matches the number of vertices, and none of the indices is - // -1. - bool linear_list = (normalIndex->size() == _coord_values.size()); - for (ci = normalIndex->begin(); - ci != normalIndex->end() && linear_list; - ++ci) { - linear_list = ((*ci)._sfint32 >= 0); - } - - if (linear_list) { - // Ok, we do have such a list. This .wrl file seems to store its - // texture coordinates one per vertex, instead of one per polygon - // vertex. - _per_vertex_normals.reserve(_coord_values.size()); - - for (ci = normalIndex->begin(); ci != normalIndex->end(); ++ci) { - size_t vi = (*ci)._sfint32; - nassertr(vi >= 0, false); - if (vi >= normal_list.size()) { - cerr << "Invalid normal index: " << vi << "\n"; - return false; - } - _per_vertex_normals.push_back(normal_list[vi]); - } - nassertr(_per_vertex_normals.size() == _coord_values.size(), false); - - } else { - // This is a "correct" .wrl file that stores its texture coordinates - // one per polygon vertex. This allows a shared vertex to contain two - // different normal values in differing polygons (meaning it's not - // actually shared). - - MFArray::const_iterator ci; - size_t pi = 0; - size_t pv = 0; - for (ci = normalIndex->begin(); ci != normalIndex->end(); ++ci) { - if ((*ci)._sfint32 < 0) { - // End of poly. - if (pv != _polys[pi]._verts.size()) { - cerr << "Normal indices don't match up!\n"; - return false; - } - pi++; - pv = 0; - } else { - if (pi >= _polys.size() || pv >= _polys[pi]._verts.size()) { - cerr << "Normal indices don't match up!\n"; - return false; - } - const LNormald &d = normal_list[(*ci)._sfint32]; - _polys[pi]._verts[pv]._attrib.set_normal(d); - pv++; - } - } - if (pi != _polys.size()) { - cerr << "Not enough normal indices!\n"; - return false; - } - } - } else { - if (!normalIndex->empty()) { - size_t pi = 0; - if (normalIndex->size() != _polys.size()) { - cerr << "Wrong number of normal indices!\n"; - return false; - } - for (ci = normalIndex->begin(); ci != normalIndex->end(); ++ci) { - if ((*ci)._sfint32 < 0 || (*ci)._sfint32 >= (int)normal_list.size()) { - cerr << "Invalid normal index!\n"; - return false; - } - const LNormald &d = normal_list[(*ci)._sfint32]; - _polys[pi]._attrib.set_normal(d); - pi++; - } - } else { - if (normal_list.size() != _polys.size()) { - cerr << "Wrong number of normals!\n"; - return false; - } - for (size_t pi = 0; pi < normal_list.size(); pi++) { - const LNormald &d = normal_list[pi]; - _polys[pi]._attrib.set_normal(d); - } - } - } - return true; - } - return false; -} - -/** - * Once the array of _per_vertex_normals has been filled (by a broken .wrl - * file that indexes the normal's directly into the vertex array instead of - * per polygon vertex), go back through the polygons and assign the normals by - * index number. - */ -void IndexedFaceSet:: -assign_per_vertex_normals() { - for (size_t pi = 0; pi < _polys.size(); pi++) { - for (size_t pv = 0; pv < _polys[pi]._verts.size(); pv++) { - VrmlVertex &vv = _polys[pi]._verts[pv]; - if (vv._index >= 0 && vv._index < (int)_per_vertex_normals.size()) { - const LNormald &d = _per_vertex_normals[vv._index]; - vv._attrib.set_normal(d); - } - } - } -} - - -/** - * - */ -bool IndexedFaceSet:: -get_uvs() { - const VrmlNode *texCoord = _geometry->get_value("texCoord")._sfnode._p; - if (texCoord != nullptr) { - // Vertex or face texCoords. - pvector uv_list; - get_vrml_uvs(texCoord, uv_list); - - MFArray *texCoordIndex = _geometry->get_value("texCoordIndex")._mf; - MFArray::const_iterator ci; - - if (texCoordIndex->empty()) { - // If we have *no* texture coordinate index array, but we do have - // texture coordinates, assume the VRML writer meant to imply a one-to- - // one mapping. This works around a broken formZ VRML file writer. - for (size_t i = 0; i < uv_list.size(); i++) { - VrmlFieldValue fv; - fv._sfint32 = i; - (*texCoordIndex).push_back(fv); - } - } - - // It's possible that this .wrl file indexes texture coordinates directly - // into the vertex array, instead of into the polygon list. Check for - // this possibility. This can only happen if the number of texture - // coordinate indices exactly matches the number of vertices, and none of - // the indices is -1. - bool linear_list = (texCoordIndex->size() == _coord_values.size()); - for (ci = texCoordIndex->begin(); - ci != texCoordIndex->end() && linear_list; - ++ci) { - linear_list = ((*ci)._sfint32 >= 0); - } - - if (linear_list) { - // Ok, we do have such a list. This .wrl file seems to store its - // texture coordinates one per vertex, instead of one per polygon - // vertex. - _per_vertex_uvs.reserve(_coord_values.size()); - - for (ci = texCoordIndex->begin(); ci != texCoordIndex->end(); ++ci) { - size_t vi = (*ci)._sfint32; - nassertr(vi >= 0, false); - if (vi >= uv_list.size()) { - cerr << "Invalid texCoord index: " << vi << "\n"; - return false; - } - _per_vertex_uvs.push_back(uv_list[vi]); - } - nassertr(_per_vertex_uvs.size() == _coord_values.size(), false); - - } else { - // This is a "correct" .wrl file that stores its texture coordinates one - // per polygon vertex. This allows a shared vertex to contain two - // different texture coordinate values in differing polygons (meaning - // it's not actually shared). - - size_t pi = 0; - size_t pv = 0; - for (ci = texCoordIndex->begin(); ci != texCoordIndex->end(); ++ci) { - if ((*ci)._sfint32 < 0) { - // End of poly. - if (pv != _polys[pi]._verts.size()) { - cerr << "texCoord indices don't match up!\n"; - return false; - } - pi++; - pv = 0; - } else { - if (pi >= _polys.size() || pv >= _polys[pi]._verts.size()) { - cerr << "texCoord indices don't match up!\n"; - return false; - } - _polys[pi]._verts[pv]._attrib.set_uv(uv_list[(*ci)._sfint32]); - pv++; - } - } - if (pi != _polys.size()) { - cerr << "Not enough texCoord indices!\n"; - return false; - } - } - return true; - } - return false; -} - -/** - * Once the array of _per_vertex_uvs has been filled (by a broken .wrl file - * that indexes the uv's directly into the vertex array instead of per polygon - * vertex), go back through the polygons and assign the UV's by index number. - */ -void IndexedFaceSet:: -assign_per_vertex_uvs() { - for (size_t pi = 0; pi < _polys.size(); pi++) { - for (size_t pv = 0; pv < _polys[pi]._verts.size(); pv++) { - VrmlVertex &vv = _polys[pi]._verts[pv]; - if (vv._index >= 0 && vv._index < (int)_per_vertex_uvs.size()) { - const LTexCoordd &d = _per_vertex_uvs[vv._index]; - vv._attrib.set_uv(d); - } - } - } -} - - -/** - * - */ -void IndexedFaceSet:: -make_polys(EggVertexPool *vpool, EggGroup *group, - const LMatrix4d &net_transform) { - bool ccw = _geometry->get_value("ccw")._sfbool; - bool solid = _geometry->get_value("solid")._sfbool; - - for (size_t pi = 0; pi < _polys.size(); pi++) { - EggPolygon *poly = new EggPolygon; - group->add_child(poly); - poly->copy_attributes(_polys[pi]._attrib); - - if (!poly->has_color() && _appearance._has_material) { - poly->set_color(_appearance._color); - } - - if (_appearance._tex != nullptr) { - poly->set_texture(_appearance._tex); - } - - if (!solid) { - poly->set_bface_flag(true); - } - - if (ccw) { - // The vertices are counterclockwise, same as Egg. - for (int pv = 0; pv < (int)_polys[pi]._verts.size(); pv++) { - EggVertex vert(_polys[pi]._verts[pv]._attrib); - LVertexd pos = - _polys[pi]._verts[pv]._pos * net_transform; - vert.set_pos(pos); - - poly->add_vertex(vpool->create_unique_vertex(vert)); - } - } else { - // The vertices are clockwise, so add 'em in reverse order. - for (int pv = (int)_polys[pi]._verts.size() - 1; pv >= 0; pv--) { - EggVertex vert(_polys[pi]._verts[pv]._attrib); - LVertexd pos = - _polys[pi]._verts[pv]._pos * net_transform; - vert.set_pos(pos); - - poly->add_vertex(vpool->create_unique_vertex(vert)); - } - } - } -} - - -/** - * - */ -void IndexedFaceSet:: -compute_normals(EggGroup *group) { - const VrmlNode *normal = _geometry->get_value("normal")._sfnode._p; - if (normal == nullptr) { - // Compute normals. - double creaseAngle = _geometry->get_value("creaseAngle")._sffloat; - if (creaseAngle == 0.0) { - group->recompute_polygon_normals(); - } else { - group->recompute_vertex_normals(rad_2_deg(creaseAngle)); - } - } -} diff --git a/pandatool/src/vrmlegg/indexedFaceSet.h b/pandatool/src/vrmlegg/indexedFaceSet.h deleted file mode 100644 index 48e63ae8..00000000 --- a/pandatool/src/vrmlegg/indexedFaceSet.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file indexedFaceSet.h - * @author drose - * @date 1999-06-24 - */ - -#ifndef INDEXEDFACESET_H -#define INDEXEDFACESET_H - -#include "pandatoolbase.h" -#include "pvector.h" -#include "epvector.h" -#include "pset.h" -#include "eggPolygon.h" -#include "eggVertex.h" -#include "eggAttributes.h" - -class VrmlNode; -class EggData; -class EggGroup; -class EggVertexPool; -class VRMLAppearance; -class LMatrix4d; - -/** - * Decodes the vertices and faces in a VRML indexed face set, and creates the - * corresponding egg geometry. - */ -class IndexedFaceSet { -public: - IndexedFaceSet(const VrmlNode *geometry, const VRMLAppearance &appearance); - - void convert_to_egg(EggGroup *group, const LMatrix4d &net_transform); - -private: - void get_coord_values(); - void get_polys(); - void get_vrml_colors(const VrmlNode *color_node, double transparency, - pvector &color_list); - void get_vrml_normals(const VrmlNode *normal_node, - pvector &normal_list); - void get_vrml_uvs(const VrmlNode *texCoord_node, - pvector &uv_list); - - bool get_colors(); - bool get_normals(); - void assign_per_vertex_normals(); - bool get_uvs(); - void assign_per_vertex_uvs(); - void make_polys(EggVertexPool *vpool, EggGroup *group, - const LMatrix4d &net_transform); - void compute_normals(EggGroup *group); - - class VrmlVertex { - public: - int _index; - LVertexd _pos; - EggVertex _attrib; - }; - class VrmlPolygon { - public: - EggPolygon _attrib; - epvector _verts; - }; - pvector _coord_values; - epvector _polys; - pvector _per_vertex_uvs; - pvector _per_vertex_normals; - - bool _has_normals; - - const VrmlNode *_geometry; - const VRMLAppearance &_appearance; -}; - -#endif diff --git a/pandatool/src/vrmlegg/vrmlAppearance.cxx b/pandatool/src/vrmlegg/vrmlAppearance.cxx deleted file mode 100644 index 06f9186c..00000000 --- a/pandatool/src/vrmlegg/vrmlAppearance.cxx +++ /dev/null @@ -1,67 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlAppearance.cxx - * @author drose - * @date 1999-06-24 - */ - -#include "vrmlAppearance.h" -#include "vrmlNode.h" -#include "deg_2_rad.h" - -VRMLAppearance:: -VRMLAppearance(const VrmlNode *appearance) { - _has_material = false; - _transparency = 0.0; - _color.set(1.0f, 1.0f, 1.0f, 1.0f); - _has_tex_transform = false; - - if (appearance != nullptr) { - const VrmlNode *material = appearance->get_value("material")._sfnode._p; - if (material != nullptr) { - _has_material = true; - const double *c = material->get_value("diffuseColor")._sfvec; - _transparency = material->get_value("transparency")._sffloat; - _color.set(c[0], c[1], c[2], 1.0 - _transparency); - } - - const VrmlNode *tex_transform = appearance->get_value("textureTransform")._sfnode._p; - if (tex_transform != nullptr) { - if (strcmp(tex_transform->_type->getName(), "TextureTransform") == 0) { - _has_tex_transform = true; - const double *c = tex_transform->get_value("center")._sfvec; - _tex_center.set(c[0], c[1]); - _tex_rotation = tex_transform->get_value("rotation")._sffloat; - const double *s = tex_transform->get_value("scale")._sfvec; - _tex_scale.set(s[0], s[1]); - const double *t = tex_transform->get_value("translation")._sfvec; - _tex_translation.set(t[0], t[1]); - } - } - - const VrmlNode *texture = appearance->get_value("texture")._sfnode._p; - if (texture != nullptr) { - if (strcmp(texture->_type->getName(), "ImageTexture") == 0) { - MFArray *url = texture->get_value("url")._mf; - if (!url->empty()) { - const char *filename = (*url->begin())._sfstring; - _tex = new EggTexture("tref", filename); - - if (_has_tex_transform) { - _tex->add_translate2d(-_tex_center); - _tex->add_scale2d(_tex_scale); - _tex->add_rotate2d(rad_2_deg(_tex_rotation)); - _tex->add_translate2d(_tex_center); - _tex->add_translate2d(_tex_translation); - } - } - } - } - } -} diff --git a/pandatool/src/vrmlegg/vrmlAppearance.h b/pandatool/src/vrmlegg/vrmlAppearance.h deleted file mode 100644 index 791d5fb6..00000000 --- a/pandatool/src/vrmlegg/vrmlAppearance.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlAppearance.h - * @author drose - * @date 1999-06-24 - */ - -#ifndef VRMLAPPEARANCE_H -#define VRMLAPPEARANCE_H - -#include "pandatoolbase.h" -#include "eggTexture.h" -#include "pt_EggTexture.h" - -class VrmlNode; - -class VRMLAppearance { -public: - VRMLAppearance(const VrmlNode *vrmlAppearance); - - bool _has_material; - LColor _color; - double _transparency; - PT_EggTexture _tex; - - bool _has_tex_transform; - LVecBase2d _tex_center; - double _tex_rotation; - LVecBase2d _tex_scale; - LVecBase2d _tex_translation; -}; - -#endif diff --git a/pandatool/src/vrmlegg/vrmlToEggConverter.cxx b/pandatool/src/vrmlegg/vrmlToEggConverter.cxx deleted file mode 100644 index d308e347..00000000 --- a/pandatool/src/vrmlegg/vrmlToEggConverter.cxx +++ /dev/null @@ -1,382 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlToEggConverter.cxx - * @author drose - * @date 2004-10-01 - */ - -#include "vrmlToEggConverter.h" -#include "vrmlAppearance.h" -#include "indexedFaceSet.h" -#include "vrmlNodeType.h" -#include "parse_vrml.h" -#include "vrmlParser.h" -#include "eggGroupNode.h" -#include "eggGroup.h" -#include "eggData.h" -#include "deg_2_rad.h" - -/** - * - */ -VRMLToEggConverter:: -VRMLToEggConverter() { -} - -/** - * - */ -VRMLToEggConverter:: -VRMLToEggConverter(const VRMLToEggConverter ©) : - SomethingToEggConverter(copy) -{ -} - -/** - * - */ -VRMLToEggConverter:: -~VRMLToEggConverter() { -} - -/** - * Allocates and returns a new copy of the converter. - */ -SomethingToEggConverter *VRMLToEggConverter:: -make_copy() { - return new VRMLToEggConverter(*this); -} - - -/** - * Returns the English name of the file type this converter supports. - */ -std::string VRMLToEggConverter:: -get_name() const { - return "VRML"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -std::string VRMLToEggConverter:: -get_extension() const { - return "wrl"; -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. - */ -bool VRMLToEggConverter:: -supports_compressed() const { - return true; -} - -/** - * Handles the reading of the input file and converting it to egg. Returns - * true if successful, false otherwise. - */ -bool VRMLToEggConverter:: -convert_file(const Filename &filename) { - clear_error(); - - VrmlScene *scene = parse_vrml(filename); - if (scene == nullptr) { - return false; - } - - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_yup_right); - } - - // First, resolve all the DEFUSE references, and count the number of times - // each node is USEd. - Nodes nodes; - VrmlScene::iterator si; - for (si = scene->begin(); si != scene->end(); ++si) { - get_all_defs((*si)._node, nodes); - } - - // Now go through the hierarchy again, and this time actually build the egg - // structure. - VrmlScene::const_iterator csi; - for (csi = scene->begin(); csi != scene->end(); ++csi) { - vrml_node((*csi)._node, get_egg_data(), LMatrix4d::ident_mat()); - } - - return !had_error(); -} - -/** - * Makes a first pass through the VRML hierarchy, identifying all nodes marked - * with a DEF code, and also counting the times each one is referenced by USE. - * Later, we'll need this information: if a node is referenced at least once, - * we need to define it as an instance node. - */ -void VRMLToEggConverter:: -get_all_defs(SFNodeRef &vrml, VRMLToEggConverter::Nodes &nodes) { - Nodes::iterator ni; - - switch (vrml._type) { - case SFNodeRef::T_def: - // If this is a node definition, add it to the map. - nassertv(vrml._name != nullptr); - nassertv(vrml._p != nullptr); - /* - This happens too often to bother yelling about it. - ni = nodes.find(vrml._name); - if (ni != nodes.end()) { - cerr << "Warning: node name " << vrml._name - << " appears multiple times.\n"; - } - */ - nodes[vrml._name] = vrml._p; - break; - - case SFNodeRef::T_use: - // If it's a reference, resolve it. - nassertv(vrml._name != nullptr); - ni = nodes.find(vrml._name); - if (ni == nodes.end()) { - std::cerr << "Unknown node reference: " << vrml._name << "\n"; - } else { - // Increment the use count of the node. - (*ni).second->_use_count++; - - // Store the pointer itself in the reference, so we don't have to do - // this again later. - vrml._p = (*ni).second; - } - return; - - default: - break; - } - - VrmlNode *node = vrml._p; - if (node != nullptr) { - VrmlNode::Fields::iterator fi; - for (fi = node->_fields.begin(); fi != node->_fields.end(); ++fi) { - if ((*fi)._type->type == SFNODE) { - get_all_defs((*fi)._value._sfnode, nodes); - } else if ((*fi)._type->type == MFNODE) { - MFArray *children = (*fi)._value._mf; - MFArray::iterator ci; - for (ci = children->begin(); ci != children->end(); ++ci) { - get_all_defs((*ci)._sfnode, nodes); - } - } - } - } -} - -/** - * Processes a single VRML node, converting it to egg and adding it to the egg - * file, if appropriate, or doing whatever else should be done. - */ -void VRMLToEggConverter:: -vrml_node(const SFNodeRef &vrml, EggGroupNode *egg, - const LMatrix4d &net_transform) { - const VrmlNode *node = vrml._p; - if (node != nullptr) { - // Now add it to the egg file at this point. - if (strcmp(node->_type->getName(), "Group") == 0) { - vrml_grouping_node(vrml, egg, net_transform, - &VRMLToEggConverter::vrml_group); - } else if (strcmp(node->_type->getName(), "Transform") == 0) { - vrml_grouping_node(vrml, egg, net_transform, - &VRMLToEggConverter::vrml_transform); - } else if (strcmp(node->_type->getName(), "Shape") == 0) { - vrml_grouping_node(vrml, egg, net_transform, - &VRMLToEggConverter::vrml_shape); - } - } -} - -/** - * Begins initial processing of a grouping-type node; that is, any node (like - * Group, Transform, or Shape) that maps to a or in egg. - * This create the group and does any instance-munging necessary, then calls - * the indicated method with the new parameters. - */ -void VRMLToEggConverter:: -vrml_grouping_node(const SFNodeRef &vrml, EggGroupNode *egg, - const LMatrix4d &net_transform, - void (VRMLToEggConverter::*process_func) - (const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform)) { - const VrmlNode *node = vrml._p; - nassertv(node != nullptr); - std::string name; - if (vrml._name != nullptr) { - name = vrml._name; - } - - /* - The following code fragment was used in the old DWD-style egg - library. Currently, the Panda egg library doesn't support - instance references, so we deal with VRML instances by copying. - - if (vrml._type == SFNodeRef::T_use) { - // If this is an instancing reference, just add the reference and return; - // no need for further processing on the node. - Instances::const_iterator fi = _instances.find(node); - assert(fi != _instances.end()); - EggInstance *inst = _data.CreateInstance(egg); - inst->AddGroupRef((*fi).second); - return; - } - */ - - PT(EggGroup) group = new EggGroup(name); - egg->add_child(group); - - LMatrix4d next_transform = net_transform; - - if (node->_use_count > 0) { - // If this node is referenced one or more times later in the file, we must - // make it an instance node. - group->set_group_type(EggGroup::GT_instance); - next_transform = LMatrix4d::ident_mat(); - - // And define the instance for future references. _instances[node] = - // group; - } - - (this->*process_func)(node, group, next_transform); -} - - -/** - * Creates an Egg group corresponding to the VRML group. - */ -void VRMLToEggConverter:: -vrml_group(const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform) { - const MFArray *children = node->get_value("children")._mf; - MFArray::const_iterator ci; - for (ci = children->begin(); ci != children->end(); ++ci) { - vrml_node((*ci)._sfnode, group, net_transform); - } -} - -/** - * Creates an Egg group with a transform corresponding to the VRML group. - */ -void VRMLToEggConverter:: -vrml_transform(const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform) { - const double *scale = node->get_value("scale")._sfvec; - const double *rotation = node->get_value("rotation")._sfvec; - const double *translation = node->get_value("translation")._sfvec; - - const double *center = node->get_value("center")._sfvec; - const double *o = node->get_value("scaleOrientation")._sfvec; - - LMatrix4d local_transform = LMatrix4d::ident_mat(); - - bool any_transform = false; - - if (scale[0] != 1.0 || scale[1] != 1.0 || scale[2] != 1.0) { - any_transform = true; - if (center[0] != 0.0 || center[1] != 0.0 || center[2] != 0.0) { - local_transform *= - LMatrix4d::translate_mat(-center[0], -center[1], -center[2]); - - if (o[3] != 0.0) { - local_transform *= - LMatrix4d::rotate_mat(rad_2_deg(-o[3]), LVector3d(o[0], o[1], o[2])); - local_transform *= - LMatrix4d::scale_mat(scale[0], scale[1], scale[2]); - local_transform *= - LMatrix4d::rotate_mat(rad_2_deg(o[3]), LVector3d(o[0], o[1], o[2])); - - } else { - local_transform *= - LMatrix4d::scale_mat(scale[0], scale[1], scale[2]); - } - local_transform *= - LMatrix4d::translate_mat(center[0], center[1], center[2]); - - } else { - if (o[3] != 0.0) { - local_transform *= - LMatrix4d::rotate_mat(rad_2_deg(-o[3]), LVector3d(o[0], o[1], o[2])); - local_transform *= - LMatrix4d::scale_mat(scale[0], scale[1], scale[2]); - local_transform *= - LMatrix4d::rotate_mat(rad_2_deg(o[3]), LVector3d(o[0], o[1], o[2])); - - } else { - local_transform *= - LMatrix4d::scale_mat(scale[0], scale[1], scale[2]); - } - } - } - - if (rotation[3] != 0.0) { - any_transform = true; - if (center[0] != 0.0 || center[1] != 0.0 || center[2] != 0.0) { - local_transform *= - LMatrix4d::translate_mat(-center[0], -center[1], -center[2]); - local_transform *= - LMatrix4d::rotate_mat(rad_2_deg(rotation[3]), - LVector3d(rotation[0], rotation[1], rotation[2])); - local_transform *= - LMatrix4d::translate_mat(center[0], center[1], center[2]); - - } else { - local_transform *= - LMatrix4d::rotate_mat(rad_2_deg(rotation[3]), - LVector3d(rotation[0], rotation[1], rotation[2])); - } - } - - if (translation[0] != 0.0 || - translation[1] != 0.0 || - translation[2] != 0.0) { - any_transform = true; - local_transform *= - LMatrix4d::translate_mat(translation[0], translation[1], translation[2]); - } - - if (any_transform) { - group->set_transform3d(local_transform); - } - - LMatrix4d next_transform = local_transform * net_transform; - - const MFArray *children = node->get_value("children")._mf; - MFArray::const_iterator ci; - for (ci = children->begin(); ci != children->end(); ++ci) { - vrml_node((*ci)._sfnode, group, next_transform); - } -} - -/** - * Creates an Egg group corresponding a VRML shape. This will probably - * contain a vertex pool and a number of polygons. - */ -void VRMLToEggConverter:: -vrml_shape(const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform) { - const VrmlNode *geometry = node->get_value("geometry")._sfnode._p; - - if (geometry != nullptr) { - VRMLAppearance appearance(node->get_value("appearance")._sfnode._p); - - if (strcmp(geometry->_type->getName(), "IndexedFaceSet") == 0) { - IndexedFaceSet ifs(geometry, appearance); - ifs.convert_to_egg(group, net_transform); - } else { - std::cerr << "Ignoring " << geometry->_type->getName() << "\n"; - } - } -} diff --git a/pandatool/src/vrmlegg/vrmlToEggConverter.h b/pandatool/src/vrmlegg/vrmlToEggConverter.h deleted file mode 100644 index 34a9b684..00000000 --- a/pandatool/src/vrmlegg/vrmlToEggConverter.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlToEggConverter.h - * @author drose - * @date 2004-10-01 - */ - -#ifndef VRMLTOEGGCONVERTER_H -#define VRMLTOEGGCONVERTER_H - -#include "pandatoolbase.h" - -#include "somethingToEggConverter.h" -#include "pmap.h" - -class VrmlNode; -struct SFNodeRef; -class EggGroupNode; -class EggGroup; -class LMatrix4d; - -/** - * This class supervises the construction of an EggData structure from a VRML - * file. - */ -class VRMLToEggConverter : public SomethingToEggConverter { -public: - VRMLToEggConverter(); - VRMLToEggConverter(const VRMLToEggConverter ©); - ~VRMLToEggConverter(); - - virtual SomethingToEggConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual bool supports_compressed() const; - - virtual bool convert_file(const Filename &filename); - -private: - typedef pmap Nodes; - - void get_all_defs(SFNodeRef &vrml, Nodes &nodes); - void vrml_node(const SFNodeRef &vrml, EggGroupNode *egg, - const LMatrix4d &net_transform); - - void vrml_grouping_node(const SFNodeRef &vrml, EggGroupNode *egg, - const LMatrix4d &net_transform, - void (VRMLToEggConverter::*process_func) - (const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform)); - void vrml_group(const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform); - void vrml_transform(const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform); - void vrml_shape(const VrmlNode *node, EggGroup *group, - const LMatrix4d &net_transform); -}; - -#endif diff --git a/pandatool/src/vrmlprogs/CMakeLists.txt b/pandatool/src/vrmlprogs/CMakeLists.txt deleted file mode 100644 index 9f92833c..00000000 --- a/pandatool/src/vrmlprogs/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(vrml-trans vrmlTrans.cxx vrmlTrans.h) -target_link_libraries(vrml-trans p3progbase p3vrml) -install(TARGETS vrml-trans EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -if(HAVE_EGG) - - add_executable(vrml2egg vrmlToEgg.cxx vrmlToEgg.h) - target_link_libraries(vrml2egg p3vrmlegg p3eggbase p3progbase) - install(TARGETS vrml2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -endif() diff --git a/pandatool/src/vrmlprogs/vrmlToEgg.cxx b/pandatool/src/vrmlprogs/vrmlToEgg.cxx deleted file mode 100644 index dee6b5eb..00000000 --- a/pandatool/src/vrmlprogs/vrmlToEgg.cxx +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlToEgg.cxx - * @author drose - * @date 2004-10-01 - */ - -#include "vrmlToEgg.h" - -#include "vrmlToEggConverter.h" - -/** - * - */ -VRMLToEgg:: -VRMLToEgg() : - SomethingToEgg("VRML", ".wrl") -{ - add_units_options(); - add_normals_options(); - add_transform_options(); - - set_program_brief("convert VRML 2.0 model files to .egg"); - set_program_description - ("This program converts VRML 2.0 model files to egg. Animated files, " - "and VRML 1.0 files, are not supported."); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. Normally, this is y-up."); - - _coordinate_system = CS_yup_right; -} - -/** - * - */ -void VRMLToEgg:: -run() { - nout << "Reading " << _input_filename << "\n"; - - _data->set_coordinate_system(_coordinate_system); - - VRMLToEggConverter converter; - converter.set_egg_data(_data); - converter._allow_errors = _allow_errors; - - apply_parameters(converter); - - if (!converter.convert_file(_input_filename)) { - nout << "Errors in conversion.\n"; - exit(1); - } - - write_egg_file(); - nout << "\n"; -} - - -int main(int argc, char *argv[]) { - VRMLToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/vrmlprogs/vrmlToEgg.h b/pandatool/src/vrmlprogs/vrmlToEgg.h deleted file mode 100644 index 90edb3b1..00000000 --- a/pandatool/src/vrmlprogs/vrmlToEgg.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlToEgg.h - * @author drose - * @date 2004-10-01 - */ - -#ifndef VRMLTOEGG_H -#define VRMLTOEGG_H - -#include "pandatoolbase.h" - -#include "somethingToEgg.h" -#include "vrmlToEggConverter.h" - -/** - * A program to read a VRML file and generate an egg file. - */ -class VRMLToEgg : public SomethingToEgg { -public: - VRMLToEgg(); - - void run(); -}; - -#endif diff --git a/pandatool/src/vrmlprogs/vrmlTrans.cxx b/pandatool/src/vrmlprogs/vrmlTrans.cxx deleted file mode 100644 index 48ed508b..00000000 --- a/pandatool/src/vrmlprogs/vrmlTrans.cxx +++ /dev/null @@ -1,94 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlTrans.cxx - * @author drose - * @date 2004-10-01 - */ - -#include "vrmlTrans.h" -#include "parse_vrml.h" - -/** - * - */ -VRMLTrans:: -VRMLTrans() : - WithOutputFile(true, true, false) -{ - // Indicate the extension name we expect the user to supply for output - // files. - _preferred_extension = ".wrl"; - - set_program_brief("reads and writes VRML 2.0 files"); - set_program_description - ("This program reads a VRML 2.0 file (.wrl) and writes an " - "essentially equivalent .wrl file. It is primarily useful for " - "debugging the VRML parser that is part of the Pandatool library."); - - clear_runlines(); - add_runline("[opts] input.wrl > output.wrl"); - add_runline("[opts] input.wrl output.wrl"); - add_runline("[opts] -o output.wrl input.wrl"); - - add_option - ("o", "filename", 0, - "Specify the filename to which the resulting .wrl file will be written. " - "If this option is omitted, the last parameter name is taken to be the " - "name of the output file.", - &VRMLTrans::dispatch_filename, &_got_output_filename, &_output_filename); -} - - -/** - * - */ -void VRMLTrans:: -run() { - nout << "Reading " << _input_filename << "\n"; - - VrmlScene *scene = parse_vrml(_input_filename); - if (scene == nullptr) { - nout << "Unable to read.\n"; - exit(1); - } - - get_output() << *scene << "\n"; -} - - -/** - * - */ -bool VRMLTrans:: -handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 1)) { - return false; - } - - if (args.empty()) { - nout << "You must specify the .wrl file to read on the command line.\n"; - return false; - - } else if (args.size() != 1) { - nout << "You must specify only one .wrl file to read on the command line.\n"; - return false; - } - - _input_filename = args[0]; - - return true; -} - - -int main(int argc, char *argv[]) { - VRMLTrans prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/vrmlprogs/vrmlTrans.h b/pandatool/src/vrmlprogs/vrmlTrans.h deleted file mode 100644 index 4ff49d24..00000000 --- a/pandatool/src/vrmlprogs/vrmlTrans.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file vrmlTrans.h - * @author drose - * @date 2004-10-01 - */ - -#ifndef VRMLTRANS_H -#define VRMLTRANS_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "withOutputFile.h" - -/** - * A program to read a VRML file and output an essentially similar VRML file. - * This is mainly useful to test the VRML parser used in Panda. - */ -class VRMLTrans : public ProgramBase, public WithOutputFile { -public: - VRMLTrans(); - - void run(); - -protected: - virtual bool handle_args(Args &args); - - Filename _input_filename; -}; - -#endif diff --git a/pandatool/src/win-stats/CMakeLists.txt b/pandatool/src/win-stats/CMakeLists.txt deleted file mode 100644 index 8c5a0a0f..00000000 --- a/pandatool/src/win-stats/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -if(NOT WIN32 OR NOT HAVE_NET) - return() -endif() - -set(WINSTATS_HEADERS - winStatsChartMenu.h - winStatsFlameGraph.h - winStatsGraph.h - winStats.h - winStatsLabel.h winStatsLabel.I - winStatsLabelStack.h - winStatsMenuId.h - winStatsMonitor.h winStatsMonitor.I - winStatsPianoRoll.h - winStatsServer.h - winStatsStripChart.h - winStatsTimeline.h -) - -set(WINSTATS_SOURCES - winStatsChartMenu.cxx - winStats.cxx - winStatsFlameGraph.cxx - winStatsGraph.cxx - winStatsLabel.cxx - winStatsLabelStack.cxx - winStatsMonitor.cxx - winStatsPianoRoll.cxx - winStatsServer.cxx - winStatsStripChart.cxx - winStatsTimeline.cxx -) - -composite_sources(win-stats WINSTATS_SOURCES) -add_executable(win-stats ${WINSTATS_HEADERS} ${WINSTATS_SOURCES}) -target_link_libraries(win-stats p3progbase p3pstatserver comctl32.lib uxtheme.lib) - -# This program is NOT actually called win-stats. It's just pstats.exe -set_target_properties(win-stats PROPERTIES OUTPUT_NAME "pstats") - -install(TARGETS win-stats EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/pandatool/src/win-stats/winStats.cxx b/pandatool/src/win-stats/winStats.cxx deleted file mode 100644 index a98d2063..00000000 --- a/pandatool/src/win-stats/winStats.cxx +++ /dev/null @@ -1,66 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStats.cxx - * @author drose - * @date 2003-12-02 - */ - -#include "pandatoolbase.h" - -#include "winStatsServer.h" -#include "config_pstatclient.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include -#include -#include - -// Enable common controls version 6, necessary for modern visual styles -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") - -int main(int argc, char *argv[]) { - // Initialize commctl32.dll. - INITCOMMONCONTROLSEX icc; - icc.dwICC = ICC_WIN95_CLASSES | ICC_STANDARD_CLASSES; - icc.dwSize = sizeof(INITCOMMONCONTROLSEX); - InitCommonControlsEx(&icc); - - // Signal DPI awareness. - SetProcessDPIAware(); - - // Create the server window. - WinStatsServer *server = new WinStatsServer; - if (server->parse_command_line(argc, argv, false) == ProgramBase::EC_failure) { - MessageBox(nullptr, "Failed to parse command-line options.", - "PStats Error", MB_OK | MB_ICONEXCLAMATION); - return 1; - } - - // Now get lost in the Windows message loop. - MSG msg; - int retval; - retval = GetMessage(&msg, nullptr, 0, 0); - while (retval != 0) { - if (retval == -1) { - nout << "Error processing message queue.\n"; - exit(1); - } - TranslateMessage(&msg); - DispatchMessage(&msg); - retval = GetMessage(&msg, nullptr, 0, 0); - } - - return 0; -} - -int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { - return main(__argc, __argv); -} diff --git a/pandatool/src/win-stats/winStats.h b/pandatool/src/win-stats/winStats.h deleted file mode 100644 index a1d9ed5e..00000000 --- a/pandatool/src/win-stats/winStats.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStats.h - * @author drose - * @date 2003-12-02 - */ - -#ifndef WINSTATS_H -#define WINSTATS_H - -#include "pStatServer.h" - -#endif diff --git a/pandatool/src/win-stats/winStatsChartMenu.cxx b/pandatool/src/win-stats/winStatsChartMenu.cxx deleted file mode 100644 index 3ee9faf6..00000000 --- a/pandatool/src/win-stats/winStatsChartMenu.cxx +++ /dev/null @@ -1,279 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsChartMenu.cxx - * @author drose - * @date 2004-01-08 - */ - -#include "winStatsChartMenu.h" -#include "winStatsMenuId.h" -#include "winStatsMonitor.h" - -/** - * - */ -WinStatsChartMenu:: -WinStatsChartMenu(WinStatsMonitor *monitor, int thread_index) : - _monitor(monitor), - _thread_index(thread_index) -{ - _menu = CreatePopupMenu(); - do_update(); -} - -/** - * - */ -WinStatsChartMenu:: -~WinStatsChartMenu() { - DestroyMenu(_menu); -} - -/** - * Returns the Windows menu handle for this particular menu. - */ -HMENU WinStatsChartMenu:: -get_menu_handle() { - return _menu; -} - -/** - * Adds the menu to the end of the indicated menu bar. - */ -void WinStatsChartMenu:: -add_to_menu_bar(HMENU menu_bar, int before_menu_id) { - const PStatClientData *client_data = _monitor->get_client_data(); - std::string thread_name; - if (_thread_index == 0) { - // A special case for the main thread. - thread_name = "Graphs"; - } else { - thread_name = client_data->get_thread_name(_thread_index); - } - - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = 1000 | _thread_index; - mii.hSubMenu = _menu; - mii.dwTypeData = (char *)thread_name.c_str(); - InsertMenuItem(menu_bar, before_menu_id, FALSE, &mii); -} - -/** - * - */ -void WinStatsChartMenu:: -remove_from_menu_bar(HMENU menu_bar) { - RemoveMenu(menu_bar, 1000 | _thread_index, MF_BYCOMMAND); -} - -/** - * Checks to see if the menu needs to be updated (e.g. because of new data - * from the client), and updates it if necessary. - */ -void WinStatsChartMenu:: -check_update() { - PStatView &view = _monitor->get_view(_thread_index); - if (view.get_level_index() != _last_level_index) { - do_update(); - } -} - -/** - * Unconditionally updates the menu with the latest data from the client. - */ -void WinStatsChartMenu:: -do_update() { - PStatView &view = _monitor->get_view(_thread_index); - _last_level_index = view.get_level_index(); - - // First, remove all of the old entries from the menu. - int num_items = GetMenuItemCount(_menu); - for (int i = num_items - 1; i >= 0; i--) { - DeleteMenu(_menu, i, MF_BYPOSITION); - } - - // Now rebuild the menu with the new set of entries. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - - if (_thread_index == 0) { - // Timeline goes first. - { - WinStatsMonitor::MenuDef menu_def(_thread_index, -1, WinStatsMonitor::CT_timeline, false); - int menu_id = _monitor->get_menu_id(menu_def); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = menu_id; - mii.dwTypeData = "Timeline"; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - } - - // And the piano roll (even though it's not very useful nowadays) - { - WinStatsMonitor::MenuDef menu_def(_thread_index, -1, WinStatsMonitor::CT_piano_roll, false); - int menu_id = _monitor->get_menu_id(menu_def); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = menu_id; - mii.dwTypeData = "Piano Roll"; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - } - - mii.fMask = MIIM_FTYPE; - mii.fType = MFT_SEPARATOR; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - } - - // The menu item(s) for the thread's frame time goes second. - add_view(_menu, view.get_top_level(), false); - - bool needs_separator = true; - - // And then the menu item(s) for each of the level values. - const PStatClientData *client_data = _monitor->get_client_data(); - int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); - for (int tc = 0; tc < num_toplevel_collectors; tc++) { - int collector = client_data->get_toplevel_collector(tc); - if (client_data->has_collector(collector) && - client_data->get_collector_has_level(collector, _thread_index)) { - - // We put a separator between the above frame collector and the first - // level collector. - if (needs_separator) { - mii.fMask = MIIM_FTYPE; - mii.fType = MFT_SEPARATOR; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - - needs_separator = false; - } - - PStatView &level_view = _monitor->get_level_view(collector, _thread_index); - add_view(_menu, level_view.get_top_level(), true); - } - } - - // For the main thread menu, also some options relating to all graph windows. - if (_thread_index == 0) { - mii.fMask = MIIM_FTYPE; - mii.fType = MFT_SEPARATOR; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = MI_graphs_close_all; - mii.dwTypeData = "Close All Graphs"; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = MI_graphs_reopen_default; - mii.dwTypeData = "Reopen Default Graphs"; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = MI_graphs_save_default; - mii.dwTypeData = "Save Current Layout as Default"; - InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); - } -} - -/** - * Adds a new entry or entries to the menu for the indicated view and its - * children. - */ -void WinStatsChartMenu:: -add_view(HMENU parent_menu, const PStatViewLevel *view_level, bool show_level) { - int collector = view_level->get_collector(); - - const PStatClientData *client_data = _monitor->get_client_data(); - std::string collector_name = client_data->get_collector_name(collector); - - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - - int num_children = view_level->get_num_children(); - if (show_level && num_children == 0) { - // For a level collector without children, no point in making a submenu. - WinStatsMonitor::MenuDef menu_def(_thread_index, collector, WinStatsMonitor::CT_strip_chart, show_level); - int menu_id = _monitor->get_menu_id(menu_def); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = menu_id; - mii.dwTypeData = (char *)collector_name.c_str(); - InsertMenuItem(parent_menu, GetMenuItemCount(parent_menu), TRUE, &mii); - return; - } - - HMENU menu; - if (!show_level && collector == 0 && num_children == 0) { - // Root collector without children, just add the options directly to the - // parent menu. - menu = parent_menu; - } - else { - // Create a submenu. - menu = CreatePopupMenu(); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; - mii.fType = MFT_STRING; - mii.hSubMenu = menu; - mii.dwTypeData = (char *)collector_name.c_str(); - InsertMenuItem(parent_menu, GetMenuItemCount(parent_menu), TRUE, &mii); - } - - { - WinStatsMonitor::MenuDef menu_def(_thread_index, collector, WinStatsMonitor::CT_strip_chart, show_level); - int menu_id = _monitor->get_menu_id(menu_def); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = menu_id; - mii.dwTypeData = "Open Strip Chart"; - InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &mii); - } - - if (!show_level) { - if (collector == 0 && num_children == 0) { - collector = -1; - } - - WinStatsMonitor::MenuDef menu_def(_thread_index, collector, WinStatsMonitor::CT_flame_graph); - int menu_id = _monitor->get_menu_id(menu_def); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = menu_id; - mii.dwTypeData = "Open Flame Graph"; - InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &mii); - } - - if (num_children > 0) { - mii.fMask = MIIM_FTYPE; - mii.fType = MFT_SEPARATOR; - InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &mii); - - // Reverse the order since the menus are listed from the top down; we want - // to be visually consistent with the graphs, which list these labels from - // the bottom up. - for (int c = num_children - 1; c >= 0; c--) { - add_view(menu, view_level->get_child(c), show_level); - } - } -} diff --git a/pandatool/src/win-stats/winStatsChartMenu.h b/pandatool/src/win-stats/winStatsChartMenu.h deleted file mode 100644 index c11553a1..00000000 --- a/pandatool/src/win-stats/winStatsChartMenu.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsChartMenu.h - * @author drose - * @date 2004-01-08 - */ - -#ifndef WINSTATSCHARTMENU_H -#define WINSTATSCHARTMENU_H - -#include "pandatoolbase.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class WinStatsMonitor; -class PStatView; -class PStatViewLevel; - -/** - * A pulldown menu of charts available for a particular thread. - */ -class WinStatsChartMenu { -public: - WinStatsChartMenu(WinStatsMonitor *monitor, int thread_index); - ~WinStatsChartMenu(); - - int get_thread_index() const { return _thread_index; } - - HMENU get_menu_handle(); - void add_to_menu_bar(HMENU menu_bar, int before_menu_id); - void remove_from_menu_bar(HMENU menu_bar); - - void check_update(); - void do_update(); - -private: - void add_view(HMENU parent_menu, const PStatViewLevel *view_level, - bool show_level); - - WinStatsMonitor *_monitor; - int _thread_index; - - int _last_level_index; - HMENU _menu; -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsFlameGraph.cxx b/pandatool/src/win-stats/winStatsFlameGraph.cxx deleted file mode 100644 index 9c4d2f67..00000000 --- a/pandatool/src/win-stats/winStatsFlameGraph.cxx +++ /dev/null @@ -1,868 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsFlameGraph.cxx - * @author rdb - * @date 2022-01-28 - */ - -#include "winStatsFlameGraph.h" -#include "winStatsLabel.h" -#include "winStatsMonitor.h" -#include "pStatCollectorDef.h" - -#include - -static const int default_flame_graph_width = 1085; -static const int default_flame_graph_height = 210; - -bool WinStatsFlameGraph::_window_class_registered = false; -const char * const WinStatsFlameGraph::_window_class_name = "flame"; - -/** - * - */ -WinStatsFlameGraph:: -WinStatsFlameGraph(WinStatsMonitor *monitor, int thread_index, - int collector_index, int frame_number) : - PStatFlameGraph(monitor, - thread_index, collector_index, frame_number, - monitor->get_pixel_scale() * default_flame_graph_width / 4, - monitor->get_pixel_scale() * default_flame_graph_height / 4), - WinStatsGraph(monitor) -{ - _left_margin = _pixel_scale * 2; - _right_margin = _pixel_scale * 2; - _top_margin = _pixel_scale * 6; - _bottom_margin = _pixel_scale * 2; - - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - _average_check_box = 0; - - create_window(); - force_redraw(); -} - -/** - * - */ -WinStatsFlameGraph:: -~WinStatsFlameGraph() { -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void WinStatsFlameGraph:: -new_data(int thread_index, int frame_number) { - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - SetWindowText(_window, window_title.c_str()); - } - } - - if (!_pause) { - update(); - - std::string text = format_number(get_horizontal_scale(), get_guide_bar_units(), get_guide_bar_unit_name()); - if (_net_value_text != text) { - _net_value_text = text; - RECT rect; - GetClientRect(_window, &rect); - rect.bottom = _top_margin; - InvalidateRect(_window, &rect, TRUE); - } - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void WinStatsFlameGraph:: -force_redraw() { - PStatFlameGraph::force_redraw(); -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void WinStatsFlameGraph:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatFlameGraph::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void WinStatsFlameGraph:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - RECT rect; - GetClientRect(_window, &rect); - rect.bottom = _top_margin; - InvalidateRect(_window, &rect, TRUE); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void WinStatsFlameGraph:: -on_click_label(int collector_index) { - if (collector_index != get_collector_index()) { - if (collector_index == -1) { - clear_history(); - set_collector_index(-1); - } else { - push_collector_index(collector_index); - } - - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - SetWindowText(_window, window_title.c_str()); - } - } - } -} - -/** - * Called when the user hovers the mouse over a label. - */ -void WinStatsFlameGraph:: -on_enter_label(int collector_index) { - if (collector_index != _highlighted_index) { - _highlighted_index = collector_index; - clear_graph_tooltip(); - - if (!get_average_mode()) { - PStatFlameGraph::force_redraw(); - } - } -} - -/** - * Called when the user's mouse cursor leaves a label. - */ -void WinStatsFlameGraph:: -on_leave_label(int collector_index) { - if (collector_index == _highlighted_index && collector_index != -1) { - _highlighted_index = -1; - - if (!get_average_mode()) { - PStatFlameGraph::force_redraw(); - } - } -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void WinStatsFlameGraph:: -normal_guide_bars() { - // We want vaguely 100 pixels between guide bars. - int num_bars = get_xsize() / (_pixel_scale * 25); - - _guide_bars.clear(); - - double dist = get_horizontal_scale() / num_bars; - - for (int i = 1; i < num_bars; ++i) { - _guide_bars.push_back(make_guide_bar(i * dist)); - } - - _guide_bars_changed = true; - - RECT rect; - GetClientRect(_window, &rect); - rect.bottom = _top_margin; - InvalidateRect(_window, &rect, TRUE); -} - -/** - * Erases the chart area. - */ -void WinStatsFlameGraph:: -clear_region() { - RECT rect = { 0, 0, get_xsize(), get_ysize() }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void WinStatsFlameGraph:: -begin_draw() { - clear_region(); - - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_bar(_bitmap_dc, get_guide_bar(i)); - } - - SelectObject(_bitmap_dc, WinStatsGraph::_monitor->get_font()); - SelectObject(_bitmap_dc, GetStockObject(NULL_PEN)); - SetBkMode(_bitmap_dc, TRANSPARENT); - SetTextAlign(_bitmap_dc, TA_LEFT | TA_TOP | TA_NOUPDATECP); -} - -/** - * Should be overridden by the user class. Should draw a single bar at the - * indicated location. - */ -void WinStatsFlameGraph:: -draw_bar(int depth, int from_x, int to_x, int collector_index, int parent_index) { - int bottom = get_ysize() - 1 - depth * _pixel_scale * 5; - int top = bottom - _pixel_scale * 5; - - bool is_highlighted = collector_index == _highlighted_index; - HBRUSH brush = get_collector_brush(collector_index, is_highlighted); - - if (to_x < from_x + 2) { - // It's just a tiny sliver. This is a more reliable way to draw it. - RECT rect = {from_x, top + 1, from_x + 1, bottom - 1}; - FillRect(_bitmap_dc, &rect, brush); - } - else { - SelectObject(_bitmap_dc, brush); - RoundRect(_bitmap_dc, - std::max(from_x, -_pixel_scale - 1), - top, - std::min(std::max(to_x, from_x + 1), get_xsize() + _pixel_scale), - bottom, - _pixel_scale, - _pixel_scale); - - int left = std::max(from_x, 0) + _pixel_scale / 2; - int right = std::min(to_x, get_xsize()) - _pixel_scale / 2; - - if ((to_x - from_x) >= _pixel_scale * 4) { - // Only bother drawing the text if we've got some space to draw on. - // Choose a suitable foreground color. - SetTextColor(_bitmap_dc, get_collector_text_color(collector_index, is_highlighted)); - - const PStatClientData *client_data = WinStatsGraph::_monitor->get_client_data(); - const PStatCollectorDef &def = client_data->get_collector_def(collector_index); - - SIZE size; - GetTextExtentPoint32(_bitmap_dc, def._name.data(), def._name.size(), &size); - - if (size.cx < right - left) { - // We have room for more. Show the collector's actual parent, if it's - // different than the block it's shown above. - if (def._parent_index > 0 && def._parent_index != parent_index) { - const PStatCollectorDef &parent_def = client_data->get_collector_def(def._parent_index); - std::string long_name = parent_def._name + ":" + def._name; - - SIZE long_size; - GetTextExtentPoint32(_bitmap_dc, long_name.data(), long_name.size(), &long_size); - if (long_size.cx < right - left) { - TextOut(_bitmap_dc, left, top + (bottom - top - long_size.cy) / 2, - long_name.data(), long_name.length()); - return; - } - } - TextOut(_bitmap_dc, left, top + (bottom - top - size.cy) / 2, - def._name.data(), def._name.length()); - } else { - // Let Windows figure out how to fit it, with ellipsis if necessary. - RECT rect = {left, top, right, bottom}; - DrawText(_bitmap_dc, def._name.data(), def._name.size(), - &rect, DT_LEFT | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER); - } - } - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void WinStatsFlameGraph:: -end_draw() { - InvalidateRect(_graph_window, nullptr, FALSE); -} - -/** - * Called at the end of the draw cycle. - */ -void WinStatsFlameGraph:: -idle() { -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool WinStatsFlameGraph:: -animate(double time, double dt) { - return PStatFlameGraph::animate(time, dt); -} - -/** - * Returns the current window dimensions. - */ -bool WinStatsFlameGraph:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - WinStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void WinStatsFlameGraph:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - WinStatsGraph::set_window_state(x, y, width, height, maximized, minimized); - - // Set the state of the checkbox. - SendMessage(_average_check_box, BM_SETCHECK, get_average_mode() ? BST_CHECKED : BST_UNCHECKED, 0); -} - -/** - * - */ -LONG WinStatsFlameGraph:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDOWN: - SetFocus(_window); - if (_potential_drag_mode == DM_new_guide_bar) { - set_drag_mode(DM_new_guide_bar); - SetCapture(_graph_window); - return 0; - } - break; - - case WM_COMMAND: - switch (LOWORD(wparam)) { - case BN_CLICKED: - if ((HWND)lparam == _average_check_box) { - int result = SendMessage(_average_check_box, BM_GETCHECK, 0, 0); - if (result == BST_CHECKED) { - set_average_mode(true); - start_animation(); - } else { - set_average_mode(false); - } - return 0; - } - break; - - case 101: - on_click_label(_popup_index); - return 0; - - case 102: - WinStatsGraph::_monitor->open_strip_chart(get_thread_index(), _popup_index, false); - return 0; - - case 103: - WinStatsGraph::_monitor->open_flame_graph(get_thread_index(), _popup_index); - return 0; - - case 104: - WinStatsGraph::_monitor->choose_collector_color(_popup_index); - return 0; - - case 105: - WinStatsGraph::_monitor->reset_collector_color(_popup_index); - return 0; - } - break; - - case WM_KEYDOWN: - { - bool changed = false; - switch (wparam) { - case VK_LEFT: - changed = prev_frame(); - break; - case VK_RIGHT: - changed = next_frame(); - break; - case VK_HOME: - changed = first_frame(); - break; - case VK_END: - changed = last_frame(); - break; - } - if (changed) { - std::string window_title = get_title_text(); - SetWindowText(_window, window_title.c_str()); - return 0; - } - } - break; - - case WM_SYSKEYDOWN: - if (((lparam >> 16) & KF_ALTDOWN) != 0 && wparam == VK_LEFT) { - if (pop_collector_index()) { - std::string window_title = get_title_text(); - SetWindowText(_window, window_title.c_str()); - } - return 0; - } - break; - - case WM_APPCOMMAND: - if (GET_APPCOMMAND_LPARAM(lparam) == APPCOMMAND_BROWSER_BACKWARD) { - if (pop_collector_index()) { - std::string window_title = get_title_text(); - SetWindowText(_window, window_title.c_str()); - } - return TRUE; - } - break; - - default: - break; - } - - return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam); -} - -/** - * - */ -LONG WinStatsFlameGraph:: -graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDOWN: - SetFocus(_window); - if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - int16_t x = LOWORD(lparam); - _drag_start_x = x; - SetCapture(_graph_window); - return 0; - } - break; - - case WM_MOUSEMOVE: - if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { - // When the mouse is over a color bar, highlight it. - int x = LOWORD(lparam); - int y = HIWORD(lparam); - - int collector_index = get_bar_collector(pixel_to_depth(y), x); - on_enter_label(collector_index); - - // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph - // window. - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - _graph_window, - 0 - }; - TrackMouseEvent(&tme); - } - else if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - int16_t x = LOWORD(lparam); - if (x >= 0 && x < get_xsize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(x)); - return 0; - } - } - else if (_drag_mode == DM_guide_bar) { - int16_t x = LOWORD(lparam); - move_user_guide_bar(_drag_guide_bar, pixel_to_height(x)); - return 0; - } - break; - - case WM_MOUSELEAVE: - // When the mouse leaves the graph, stop highlighting. - if (_highlighted_index != -1) { - on_leave_label(_highlighted_index); - } - break; - - case WM_LBUTTONUP: - if (_drag_mode == DM_guide_bar) { - int16_t x = LOWORD(lparam); - if (x < 0 || x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(x)); - } - set_drag_mode(DM_none); - ReleaseCapture(); - return 0; - } - break; - - case WM_LBUTTONDBLCLK: - { - // Double-clicking on a color bar in the graph will zoom the graph into - // that collector. - int16_t x = LOWORD(lparam); - int16_t y = HIWORD(lparam); - on_click_label(get_bar_collector(pixel_to_depth(y), x)); - return 0; - } - break; - - case WM_CONTEXTMENU: - { - POINT point; - if (GetCursorPos(&point)) { - POINT graph_point = point; - if (ScreenToClient(_graph_window, &graph_point)) { - int depth = pixel_to_depth(graph_point.y); - int collector_index = get_bar_collector(depth, graph_point.x); - if (collector_index >= 0) { - _popup_index = collector_index; - HMENU popup = CreatePopupMenu(); - - std::string label = get_bar_tooltip(depth, graph_point.x); - if (!label.empty()) { - AppendMenu(popup, MF_STRING | MF_DISABLED, 0, label.c_str()); - } - if (collector_index == get_collector_index()) { - AppendMenu(popup, MF_STRING | MF_DISABLED, 101, "Set as Focus"); - } else { - AppendMenu(popup, MF_STRING, 101, "Set as Focus"); - } - AppendMenu(popup, MF_STRING, 102, "Open Strip Chart"); - AppendMenu(popup, MF_STRING, 103, "Open Flame Graph"); - AppendMenu(popup, MF_STRING | MF_SEPARATOR, 0, nullptr); - AppendMenu(popup, MF_STRING, 104, "Change Color..."); - AppendMenu(popup, MF_STRING, 105, "Reset Color"); - TrackPopupMenu(popup, TPM_LEFTBUTTON, point.x, point.y, 0, _window, nullptr); - } - } - } - return 0; - } - break; - - case WM_MOUSEHWHEEL: - { - int delta = GET_WHEEL_DELTA_WPARAM(wparam); - if (delta != 0) { - if (delta > 0 ? next_frame() : prev_frame()) { - std::string window_title = get_title_text(); - SetWindowText(_window, window_title.c_str()); - } - } - return 0; - } - break; - - default: - break; - } - - return WinStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam); -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsFlameGraph:: -additional_window_paint(HDC hdc) { - // Draw in the labels for the guide bars. - SelectObject(hdc, WinStatsGraph::_monitor->get_font()); - SetTextAlign(hdc, TA_LEFT | TA_BOTTOM); - SetBkMode(hdc, TRANSPARENT); - - int y = _top_margin - _pixel_scale / 2; - - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; i++) { - draw_guide_label(hdc, y, get_guide_bar(i)); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; i++) { - draw_guide_label(hdc, y, get_user_guide_bar(i)); - } - - RECT rect; - GetClientRect(_window, &rect); - - // Now draw the "net value" label at the top. - SetTextAlign(hdc, TA_RIGHT | TA_BOTTOM); - SetTextColor(hdc, RGB(0, 0, 0)); - TextOut(hdc, rect.right - _right_margin, y, - _net_value_text.data(), _net_value_text.length()); -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsFlameGraph:: -additional_graph_window_paint(HDC hdc) { - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_bar(hdc, get_user_guide_bar(i)); - } -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsFlameGraph:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return get_bar_tooltip(pixel_to_depth(mouse_y), mouse_x); -} - -/** - * Based on the mouse position within the window's client area, look for - * draggable things the mouse might be hovering over and return the - * apprioprate DragMode enum or DM_none if nothing is indicated. - */ -WinStatsGraph::DragMode WinStatsFlameGraph:: -consider_drag_start(int mouse_x, int mouse_y, int width, int height) { - if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) { - if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) { - // See if the mouse is over a user-defined guide bar. - int x = mouse_x - _graph_left; - double from_height = pixel_to_height(x - 2); - double to_height = pixel_to_height(x + 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else if (mouse_x < _left_margin - 2 || - mouse_x > width - _right_margin + 2) { - // The mouse is left or right of the graph; maybe create a new guide - // bar. - return DM_new_guide_bar; - } - } - - // Don't upcall; there's no point resizing the margins. - return DM_none; -} - -/** - * Repositions the graph child window within the parent window according to - * the _margin variables. - */ -void WinStatsFlameGraph:: -move_graph_window(int graph_left, int graph_top, int graph_xsize, int graph_ysize) { - WinStatsGraph::move_graph_window(graph_left, graph_top, graph_xsize, graph_ysize); - if (_average_check_box != 0) { - SIZE size; - SendMessage(_average_check_box, BCM_GETIDEALSIZE, 0, (LPARAM)&size); - - SetWindowPos(_average_check_box, 0, - _left_margin, _top_margin - size.cy - _pixel_scale / 2, - size.cx, size.cy, - SWP_NOZORDER | SWP_SHOWWINDOW); - InvalidateRect(_average_check_box, nullptr, TRUE); - } -} - -/** - * Converts a pixel to a depth index. - */ -int WinStatsFlameGraph:: -pixel_to_depth(int y) const { - return (get_ysize() - 1 - y) / (_pixel_scale * 5); -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void WinStatsFlameGraph:: -draw_guide_bar(HDC hdc, const PStatGraph::GuideBar &bar) { - int x = height_to_pixel(bar._height); - - if (x > 0 && x < get_xsize() - 1) { - // Only draw it if it's not too close to either edge. - switch (bar._style) { - case GBS_target: - SelectObject(hdc, _light_pen); - break; - - case GBS_user: - SelectObject(hdc, _user_guide_bar_pen); - break; - - case GBS_normal: - SelectObject(hdc, _dark_pen); - break; - } - MoveToEx(hdc, x, 0, nullptr); - LineTo(hdc, x, get_ysize()); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void WinStatsFlameGraph:: -draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar) { - switch (bar._style) { - case GBS_target: - SetTextColor(hdc, _light_color); - break; - - case GBS_user: - SetTextColor(hdc, _user_guide_bar_color); - break; - - case GBS_normal: - SetTextColor(hdc, _dark_color); - break; - } - - int x = height_to_pixel(bar._height); - const std::string &label = bar._label; - SIZE size; - GetTextExtentPoint32(hdc, label.data(), label.length(), &size); - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(x - size.cx); - double to_height = pixel_to_height(x + size.cx); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - return; - } - } - - int this_x = _graph_left + x - size.cx / 2; - if (x >= 0 && x < get_xsize()) { - TextOut(hdc, this_x, y, - label.data(), label.length()); - } -} - -/** - * Creates the window for this strip chart. - */ -void WinStatsFlameGraph:: -create_window() { - if (_window) { - return; - } - - HINSTANCE application = GetModuleHandle(nullptr); - register_window_class(application); - - std::string window_title = get_title_text(); - POINT window_pos = WinStatsGraph::_monitor->get_new_window_pos(); - - RECT win_rect = { - 0, 0, - _left_margin + get_xsize() + _right_margin, - _top_margin + get_ysize() + _bottom_margin - }; - - // compute window size based on desired client area size - AdjustWindowRect(&win_rect, graph_window_style, FALSE); - - _window = - CreateWindowEx(WS_EX_DLGMODALFRAME, _window_class_name, - window_title.c_str(), graph_window_style, - window_pos.x, window_pos.y, - win_rect.right - win_rect.left, - win_rect.bottom - win_rect.top, - WinStatsGraph::_monitor->get_window(), - nullptr, application, 0); - if (!_window) { - nout << "Could not create FlameGraph window!\n"; - exit(1); - } - - SetWindowLongPtr(_window, 0, (LONG_PTR)this); - - _average_check_box = - CreateWindow(WC_BUTTON, "Average", WS_CHILD | BS_AUTOCHECKBOX, - 0, 0, 0, 0, - _window, nullptr, application, 0); - SendMessage(_average_check_box, WM_SETFONT, - (WPARAM)WinStatsGraph::_monitor->get_font(), TRUE); - - if (get_average_mode()) { - SendMessage(_average_check_box, BM_SETCHECK, BST_CHECKED, 0); - start_animation(); - } - - // Ensure that the window is on top of the stack. - SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - - SetFocus(_window); -} - -/** - * Registers the window class for the FlameGraph window, if it has not already - * been registered. - */ -void WinStatsFlameGraph:: -register_window_class(HINSTANCE application) { - if (_window_class_registered) { - return; - } - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(WNDCLASS)); - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = application; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszMenuName = nullptr; - wc.lpszClassName = _window_class_name; - - // Reserve space to associate the this pointer with the window. - wc.cbWndExtra = sizeof(WinStatsFlameGraph *); - - if (!RegisterClass(&wc)) { - nout << "Could not register FlameGraph window class!\n"; - exit(1); - } - - _window_class_registered = true; -} - -/** - * - */ -LONG WINAPI WinStatsFlameGraph:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - WinStatsFlameGraph *self = (WinStatsFlameGraph *)GetWindowLongPtr(hwnd, 0); - if (self != nullptr && self->_window == hwnd) { - return self->window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} diff --git a/pandatool/src/win-stats/winStatsFlameGraph.h b/pandatool/src/win-stats/winStatsFlameGraph.h deleted file mode 100644 index 6edae514..00000000 --- a/pandatool/src/win-stats/winStatsFlameGraph.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsFlameGraph.h - * @author rdb - * @date 2022-01-28 - */ - -#ifndef WINSTATSFLAMEGRAPH_H -#define WINSTATSFLAMEGRAPH_H - -#include "pandatoolbase.h" - -#include "winStatsGraph.h" -#include "pStatFlameGraph.h" - -class WinStatsLabel; - -/** - * A window that draws a flame chart, which shows the collectors explicitly - * stopping and starting, one frame at a time. - */ -class WinStatsFlameGraph : public PStatFlameGraph, public WinStatsGraph { -public: - WinStatsFlameGraph(WinStatsMonitor *monitor, int thread_index, - int collector_index=-1, int frame_number=-1); - virtual ~WinStatsFlameGraph(); - - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void on_click_label(int collector_index); - virtual void on_enter_label(int collector_index); - virtual void on_leave_label(int collector_index); - -protected: - virtual void normal_guide_bars(); - - void clear_region(); - virtual void begin_draw(); - virtual void draw_bar(int depth, int from_x, int to_x, - int collector_index, int parent_index); - virtual void end_draw(); - virtual void idle(); - - virtual bool animate(double time, double dt); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual LONG graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual void additional_window_paint(HDC hdc); - virtual void additional_graph_window_paint(HDC hdc); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int mouse_x, int mouse_y, - int width, int height); - virtual void move_graph_window(int graph_left, int graph_top, - int graph_xsize, int graph_ysize); - -private: - int pixel_to_depth(int y) const; - void draw_guide_bar(HDC hdc, const GuideBar &bar); - void draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar); - void create_window(); - static void register_window_class(HINSTANCE application); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - std::string _net_value_text; - HWND _average_check_box; - int _popup_index = -1; - - static bool _window_class_registered; - static const char * const _window_class_name; -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsGraph.cxx b/pandatool/src/win-stats/winStatsGraph.cxx deleted file mode 100644 index d8d41187..00000000 --- a/pandatool/src/win-stats/winStatsGraph.cxx +++ /dev/null @@ -1,831 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsGraph.cxx - * @author drose - * @date 2003-12-03 - */ - -#include "winStatsGraph.h" -#include "winStatsMonitor.h" -#include "winStatsLabelStack.h" -#include "winStatsServer.h" -#include "trueClock.h" -#include "convert_srgb.h" - -#include - -#define IDC_GRAPH 100 - -DWORD WinStatsGraph::graph_window_style = - WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_VISIBLE; - -/** - * - */ -WinStatsGraph:: -WinStatsGraph(WinStatsMonitor *monitor) : - _monitor(monitor) -{ - _window = 0; - _graph_window = 0; - _tooltip_window = 0; - _sizewe_cursor = LoadCursor(nullptr, IDC_SIZEWE); - _hand_cursor = LoadCursor(nullptr, IDC_HAND); - _bitmap = 0; - _bitmap_dc = 0; - - _graph_left = 0; - _graph_top = 0; - _bitmap_xsize = 0; - _bitmap_ysize = 0; - - _pixel_scale = monitor->get_pixel_scale(); - - // Default margins. - int margin = _pixel_scale * 2; - _left_margin = margin; - _right_margin = margin; - _top_margin = margin; - _bottom_margin = margin; - _top_label_stack_margin = margin; - - _dark_color = RGB(51, 51, 51); - _light_color = RGB(154, 154, 154); - _user_guide_bar_color = RGB(130, 150, 255); - _frame_guide_bar_color = RGB(255, 10, 10); - _dark_pen = CreatePen(PS_SOLID, 1, _dark_color); - _light_pen = CreatePen(PS_SOLID, 1, _light_color); - _user_guide_bar_pen = CreatePen(PS_DASH, 1, _user_guide_bar_color); - _frame_guide_bar_pen = CreatePen(PS_DASH, 1, _frame_guide_bar_color); - - _drag_mode = DM_none; - _potential_drag_mode = DM_none; - _drag_scale_start = 0.0f; - - _pause = false; -} - -/** - * - */ -WinStatsGraph:: -~WinStatsGraph() { - _monitor = nullptr; - release_bitmap(); - - DeleteObject(_dark_pen); - DeleteObject(_light_pen); - DeleteObject(_user_guide_bar_pen); - DeleteObject(_frame_guide_bar_pen); - - for (auto &item : _brushes) { - DeleteObject(item.second.first); - DeleteObject(item.second.second); - } - _brushes.clear(); - _text_colors.clear(); - - if (_graph_window) { - DestroyWindow(_graph_window); - _graph_window = 0; - } - - if (_window) { - DestroyWindow(_window); - _window = 0; - } - - if (_tooltip_window) { - DestroyWindow(_tooltip_window); - _tooltip_window = 0; - } -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void WinStatsGraph:: -new_collector(int new_collector) { -} - -/** - * Called whenever new data arrives. - */ -void WinStatsGraph:: -new_data(int thread_index, int frame_number) { -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void WinStatsGraph:: -changed_graph_size(int graph_xsize, int graph_ysize) { -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void WinStatsGraph:: -set_time_units(int unit_mask) { -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speed for the graph to the indicated value. - */ -void WinStatsGraph:: -set_scroll_speed(double scroll_speed) { -} - -/** - * Changes the pause flag for the graph. When this flag is true, the graph - * does not update in response to new data. - */ -void WinStatsGraph:: -set_pause(bool pause) { - _pause = pause; -} - -/** - * Called when the user guide bars have been changed. - */ -void WinStatsGraph:: -user_guide_bars_changed() { - InvalidateRect(_window, nullptr, TRUE); - InvalidateRect(_graph_window, nullptr, TRUE); -} - -/** - * Called when the user single-clicks on a label. - */ -void WinStatsGraph:: -on_click_label(int collector_index) { -} - -/** - * Called when a pop-up menu should be shown for the label. - */ -void WinStatsGraph:: -on_popup_label(int collector_index) { -} - -/** - * Called when the user hovers the mouse over a label. - */ -void WinStatsGraph:: -on_enter_label(int collector_index) { - if (collector_index != _highlighted_index) { - _highlighted_index = collector_index; - clear_graph_tooltip(); - force_redraw(); - } -} - -/** - * Called when the user's mouse cursor leaves a label. - */ -void WinStatsGraph:: -on_leave_label(int collector_index) { - if (collector_index == _highlighted_index && collector_index != -1) { - _highlighted_index = -1; - clear_graph_tooltip(); - force_redraw(); - } -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsGraph:: -get_label_tooltip(int collector_index) const { - return std::string(); -} - -/** - * Hides the graph tooltip. - */ -void WinStatsGraph:: -clear_graph_tooltip() { - if (_tooltip_window != 0) { - SendMessage(_tooltip_window, TTM_POP, 0, 0); - } -} - -/** - * Returns the window handle of the surrounding window. - */ -HWND WinStatsGraph:: -get_window() { - return _window; -} - -/** - * Should be called when the user closes the associated window. This tells - * the monitor to remove the graph. - */ -void WinStatsGraph:: -close() { - WinStatsMonitor *monitor = _monitor; - _monitor = nullptr; - if (monitor != nullptr) { - monitor->remove_graph(this); - } -} - -/** - * Sets up the label stack on the left edge of the frame. - */ -void WinStatsGraph:: -setup_label_stack() { - _label_stack.setup(_window); - move_label_stack(); -} - -/** - * Repositions the label stack if its coordinates or size have changed. - */ -void WinStatsGraph:: -move_label_stack() { - if (_label_stack.is_setup()) { - RECT rect; - GetClientRect(_window, &rect); - - rect.left += _pixel_scale * 2; - rect.right = _left_margin - _pixel_scale * 2; - - _label_stack.set_pos(rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, - _top_label_stack_margin, _bottom_margin); - } -} - -/** - * Turns on the animation timer, if it hasn't already been turned on. - */ -void WinStatsGraph:: -start_animation() { - if (!_timer_running) { - TrueClock *clock = TrueClock::get_global_ptr(); - _time = clock->get_short_time(); - SetTimer(_window, 0x100, 16, nullptr); - _timer_running = true; - } -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool WinStatsGraph:: -animate(double time, double dt) { - return false; -} - -/** - * Returns the current window dimensions. - */ -void WinStatsGraph:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - WinStatsServer *server = (WinStatsServer *)_monitor->get_server(); - POINT client_origin = server->get_client_origin(); - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(_window, &wp); - x = wp.rcNormalPosition.left - client_origin.x; - y = wp.rcNormalPosition.top - client_origin.y; - width = wp.rcNormalPosition.right - wp.rcNormalPosition.left; - height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; - maximized = (wp.showCmd == SW_SHOWMAXIMIZED || (wp.flags & WPF_RESTORETOMAXIMIZED) != 0); - minimized = (wp.showCmd == SW_SHOWMINIMIZED); -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void WinStatsGraph:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - WinStatsServer *server = (WinStatsServer *)_monitor->get_server(); - POINT client_origin = server->get_client_origin(); - WINDOWPLACEMENT wp; - wp.length = sizeof(WINDOWPLACEMENT); - wp.flags = maximized ? WPF_RESTORETOMAXIMIZED : 0; - wp.showCmd = minimized ? SW_SHOWMINIMIZED : (maximized ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL); - wp.ptMinPosition.x = -1; - wp.ptMinPosition.y = -1; - wp.ptMaxPosition.x = -1; - wp.ptMaxPosition.y = -1; - wp.rcNormalPosition.left = client_origin.x + x; - wp.rcNormalPosition.top = client_origin.y + y; - wp.rcNormalPosition.right = wp.rcNormalPosition.left + width; - wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + height; - - if (minimized) { - int x, y; - _monitor->calc_iconic_graph_window_pos(this, x, y); - wp.ptMinPosition.x = x; - wp.ptMinPosition.y = y; - wp.flags |= WPF_SETMINPOSITION; - } - - SetWindowPlacement(_window, &wp); -} - -/** - * Returns a brush suitable for drawing in the indicated collector's color. - */ -HBRUSH WinStatsGraph:: -get_collector_brush(int collector_index, bool highlight) { - Brushes::iterator bi; - bi = _brushes.find(collector_index); - if (bi != _brushes.end()) { - return highlight ? (*bi).second.second : (*bi).second.first; - } - - // Ask the monitor what color this guy should be. - LRGBColor rgb = _monitor->get_collector_color(collector_index); - int r = (int)encode_sRGB_uchar((float)rgb[0]); - int g = (int)encode_sRGB_uchar((float)rgb[1]); - int b = (int)encode_sRGB_uchar((float)rgb[2]); - HBRUSH brush = CreateSolidBrush(RGB(r, g, b)); - - int hr = (int)encode_sRGB_uchar((float)rgb[0] * 0.75f); - int hg = (int)encode_sRGB_uchar((float)rgb[1] * 0.75f); - int hb = (int)encode_sRGB_uchar((float)rgb[2] * 0.75f); - HBRUSH hbrush = CreateSolidBrush(RGB(hr, hg, hb)); - - _brushes[collector_index] = std::make_pair(brush, hbrush); - return highlight ? hbrush : brush; -} - -/** - * Returns a text color suitable for the given collector. - */ -COLORREF WinStatsGraph:: -get_collector_text_color(int collector_index, bool highlight) { - TextColors::iterator tci; - tci = _text_colors.find(collector_index); - if (tci != _text_colors.end()) { - return highlight ? (*tci).second.second : (*tci).second.first; - } - - LRGBColor rgb = _monitor->get_collector_color(collector_index); - double bright = - rgb[0] * 0.2126 + - rgb[1] * 0.7152 + - rgb[2] * 0.0722; - COLORREF color = bright >= 0.5 ? RGB(0, 0, 0) : RGB(255, 255, 255); - COLORREF hcolor = bright * 0.75 >= 0.5 ? RGB(0, 0, 0) : RGB(255, 255, 255); - - _text_colors[collector_index] = std::make_pair(color, hcolor); - return highlight ? hcolor : color; -} - -/** - * Called when the given collector has changed colors. - */ -void WinStatsGraph:: -reset_collector_color(int collector_index) { - _brushes.erase(collector_index); - _text_colors.erase(collector_index); - force_redraw(); - _label_stack.update_label_color(collector_index); -} - -/** - * This window_proc should be called up to by the derived classes for any - * messages that are not specifically handled by the derived class. - */ -LONG WinStatsGraph:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_DESTROY: - close(); - break; - - case WM_APPCOMMAND: - if (GET_APPCOMMAND_LPARAM(lparam) == APPCOMMAND_CLOSE) { - close(); - return TRUE; - } - break; - - case WM_GETMINMAXINFO: - { - WINDOWINFO winfo; - GetWindowInfo(hwnd, &winfo); - MINMAXINFO &minmax = *(MINMAXINFO *)lparam; - int vminheight = _bottom_margin + _top_margin; - if (_label_stack.get_num_labels() > 0) { - // If we have a label, make sure at least one can be shown. - vminheight = (std::max)(vminheight, _top_label_stack_margin + _label_stack.get_label_height(0) + _bottom_margin); - } - minmax.ptMinTrackSize.x = (winfo.rcClient.left - winfo.rcWindow.left) - + (winfo.rcWindow.right - winfo.rcClient.right) - + (_right_margin + _left_margin); - minmax.ptMinTrackSize.y = (winfo.rcClient.top - winfo.rcWindow.top) - + (winfo.rcWindow.bottom - winfo.rcClient.bottom) - + vminheight; - return 0; - } - - case WM_WINDOWPOSCHANGING: - { - WINDOWPOS &pos = *(WINDOWPOS *)lparam; - if ((pos.flags & (SWP_NOMOVE | SWP_NOSIZE)) == 0 && IsIconic(hwnd)) { - _monitor->calc_iconic_graph_window_pos(this, pos.x, pos.y); - } - } - break; - - case WM_SYSCOMMAND: - if (wparam == SC_MINIMIZE) { - WINDOWPLACEMENT wp; - if (GetWindowPlacement(hwnd, &wp)) { - int x, y; - _monitor->calc_iconic_graph_window_pos(this, x, y); - wp.showCmd = SW_SHOWMINIMIZED; - wp.flags |= WPF_SETMINPOSITION; - wp.ptMinPosition.x = x; - wp.ptMinPosition.y = y; - SetWindowPlacement(hwnd, &wp); - } - return 0; - } - break; - - case WM_SIZE: - move_label_stack(); - InvalidateRect(hwnd, nullptr, TRUE); - break; - - case WM_SIZING: - set_drag_mode(DM_sizing); - break; - - case WM_EXITSIZEMOVE: - set_drag_mode(DM_none); - break; - - case WM_SETCURSOR: - { - // Why is it so hard to ask for the cursor position within the window's - // client area? - POINT point; - GetCursorPos(&point); - WINDOWINFO winfo; - GetWindowInfo(hwnd, &winfo); - const RECT &rect = winfo.rcClient; - int x = point.x - rect.left; - int y = point.y - rect.top; - int width = rect.right - rect.left; - int height = rect.bottom - rect.top; - - _potential_drag_mode = consider_drag_start(x, y, width, height); - - switch (_potential_drag_mode) { - case DM_left_margin: - case DM_right_margin: - SetCursor(_sizewe_cursor); - return TRUE; - - case DM_guide_bar: - SetCursor(_hand_cursor); - return TRUE; - - default: - case DM_none: - break; - } - } - break; - - case WM_LBUTTONDOWN: - if (_potential_drag_mode != DM_none) { - set_drag_mode(_potential_drag_mode); - _drag_start_x = (int16_t)LOWORD(lparam); - _drag_start_y = (int16_t)HIWORD(lparam); - SetCapture(_window); - } - return 0; - - case WM_MOUSEMOVE: - if (_drag_mode == DM_left_margin) { - int16_t x = LOWORD(lparam); - int new_left_margin = _left_margin + (x - _drag_start_x); - _left_margin = std::max(new_left_margin, _pixel_scale * 2); - _drag_start_x = x - (new_left_margin - _left_margin); - InvalidateRect(hwnd, nullptr, TRUE); - move_label_stack(); - return 0; - - } else if (_drag_mode == DM_right_margin) { - int16_t x = LOWORD(lparam); - _right_margin += (_drag_start_x - x); - _drag_start_x = x; - InvalidateRect(hwnd, nullptr, TRUE); - return 0; - } - break; - - case WM_LBUTTONUP: - set_drag_mode(DM_none); - ReleaseCapture(); - break; - - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - - // First, draw a frame around the graph. - RECT rect; - GetClientRect(hwnd, &rect); - - rect.left += _left_margin; - rect.top += _top_margin; - rect.right -= _right_margin; - rect.bottom -= _bottom_margin; - - if (rect.right > rect.left && rect.bottom > rect.top) { - int graph_xsize = rect.right - rect.left; - int graph_ysize = rect.bottom - rect.top; - if (_bitmap_dc == 0 || - graph_xsize != _bitmap_xsize || - graph_ysize != _bitmap_ysize) { - // Oops, we need to change the bitmap (and graph) size. - changed_graph_size(graph_xsize, graph_ysize); - move_graph_window(rect.left, rect.top, graph_xsize, graph_ysize); - force_redraw(); - } - } - - additional_window_paint(hdc); - - EndPaint(hwnd, &ps); - return 0; - } - - case WM_DRAWITEM: - if (wparam == IDC_GRAPH) { - const DRAWITEMSTRUCT &dis = *(DRAWITEMSTRUCT *)lparam; - - // Repaint the graph by copying the backing pixmap in. - BitBlt(dis.hDC, 0, 0, - _bitmap_xsize, _bitmap_ysize, - _bitmap_dc, 0, 0, - SRCCOPY); - - additional_graph_window_paint(dis.hDC); - return 0; - } - break; - - case WM_TIMER: - { - TrueClock *clock = TrueClock::get_global_ptr(); - double new_time = clock->get_short_time(); - if (!animate(new_time, new_time - _time)) { - KillTimer(hwnd, 0x100); - _timer_running = false; - } - _time = new_time; - } - return 0; - - case WM_NOTIFY: - switch (((LPNMHDR)lparam)->code) { - case TTN_GETDISPINFO: - { - NMTTDISPINFO &info = *(NMTTDISPINFO *)lparam; - POINT point; - if (GetCursorPos(&point) && ScreenToClient(_graph_window, &point)) { - _tooltip_text = get_graph_tooltip(point.x, point.y); - info.lpszText = (char *)_tooltip_text.c_str(); - } - } - return 0; - } - break; - - default: - break; - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -/** - * - */ -LONG WinStatsGraph:: -graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_DISPLAYCHANGE: - setup_bitmap(_bitmap_xsize, _bitmap_ysize); - force_redraw(); - break; - - case WM_NCHITTEST: - // Necessary for mouse events to work; default returns HTTRANSPARENT - return HTCLIENT; - - case WM_LBUTTONDOWN: - // Vector any uncaught WM_LBUTTONDOWN into the main window, so we can drag - // margins, etc. - if (_potential_drag_mode != DM_none) { - int16_t x = LOWORD(lparam) + _graph_left; - int16_t y = HIWORD(lparam) + _graph_top; - return window_proc(_window, msg, wparam, MAKELPARAM(x, y)); - } - break; - - case WM_LBUTTONUP: - set_drag_mode(DM_none); - ReleaseCapture(); - break; - - default: - break; - } - - return DefSubclassProc(hwnd, msg, wparam, lparam); -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsGraph:: -additional_window_paint(HDC hdc) { -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the graph window. - */ -void WinStatsGraph:: -additional_graph_window_paint(HDC hdc) { -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsGraph:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return std::string(); -} - -/** - * Based on the mouse position within the window's client area, look for - * draggable things the mouse might be hovering over and return the - * appropriate DragMode enum or DM_none if nothing is indicated. - */ -WinStatsGraph::DragMode WinStatsGraph:: -consider_drag_start(int mouse_x, int mouse_y, int width, int height) { - if (mouse_x >= _left_margin - 2 && mouse_x <= _left_margin + 2) { - return DM_left_margin; - } else if (mouse_x >= width - _right_margin - 2 && mouse_x <= width - _right_margin + 2) { - return DM_right_margin; - } - - return DM_none; -} - -/** - * This should be called whenever the drag mode needs to change state. It - * provides hooks for a derived class to do something special. - */ -void WinStatsGraph:: -set_drag_mode(WinStatsGraph::DragMode drag_mode) { - _drag_mode = drag_mode; -} - -/** - * Repositions the graph child window within the parent window according to - * the _margin variables. - */ -void WinStatsGraph:: -move_graph_window(int graph_left, int graph_top, int graph_xsize, int graph_ysize) { - if (_graph_window == 0) { - create_graph_window(); - } - - _graph_left = graph_left; - _graph_top = graph_top; - - SetWindowPos(_graph_window, 0, - _graph_left, _graph_top, - graph_xsize, graph_ysize, - SWP_NOZORDER | SWP_SHOWWINDOW); - - if (graph_xsize != _bitmap_xsize || graph_ysize != _bitmap_ysize) { - setup_bitmap(graph_xsize, graph_ysize); - } -} - -/** - * Sets up a backing-store bitmap of the indicated size. - */ -void WinStatsGraph:: -setup_bitmap(int xsize, int ysize) { - release_bitmap(); - _bitmap_xsize = std::max(xsize, 0); - _bitmap_ysize = std::max(ysize, 0); - - HDC hdc = GetDC(_graph_window); - _bitmap_dc = CreateCompatibleDC(hdc); - _bitmap = CreateCompatibleBitmap(hdc, _bitmap_xsize, _bitmap_ysize); - SelectObject(_bitmap_dc, _bitmap); - - RECT rect = { 0, 0, _bitmap_xsize, _bitmap_ysize }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); - - ReleaseDC(_window, hdc); -} - -/** - * Frees the backing-store bitmap created by setup_bitmap(). - */ -void WinStatsGraph:: -release_bitmap() { - if (_bitmap) { - DeleteObject(_bitmap); - _bitmap = 0; - } - if (_bitmap_dc) { - DeleteDC(_bitmap_dc); - _bitmap_dc = 0; - } -} - -/** - * Creates the child window that actually holds the graph. - */ -void WinStatsGraph:: -create_graph_window() { - if (_graph_window) { - return; - } - - HINSTANCE application = GetModuleHandle(nullptr); - - DWORD window_style = WS_CHILD | WS_CLIPSIBLINGS | - SS_SUNKEN | SS_OWNERDRAW; - - _graph_window = - CreateWindow(WC_STATIC, "", window_style, 0, 0, 0, 0, - _window, (HMENU)IDC_GRAPH, application, 0); - if (!_graph_window) { - nout << "Could not create graph window!\n"; - exit(1); - } - - EnableWindow(_graph_window, TRUE); - - SetWindowSubclass(_graph_window, &static_graph_subclass_proc, 1234, (DWORD_PTR)this); - - // Create the tooltip window. This will cause a TTN_GETDISPINFO message to - // be sent to the window to acquire the tooltip text. - _tooltip_window = CreateWindow(TOOLTIPS_CLASS, nullptr, - WS_POPUP, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - _window, nullptr, - application, nullptr); - - if (_tooltip_window != 0) { - TOOLINFO info = { 0 }; - info.cbSize = sizeof(info); - info.uFlags = TTF_IDISHWND | TTF_SUBCLASS; - info.hwnd = _window; - info.uId = (UINT_PTR)_graph_window; - info.lpszText = LPSTR_TEXTCALLBACK; - SendMessage(_tooltip_window, TTM_ADDTOOL, 0, (LPARAM)&info); - } -} - -/** - * - */ -LRESULT WINAPI WinStatsGraph:: -static_graph_subclass_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT_PTR subclass, DWORD_PTR ref_data) { - WinStatsGraph *self = (WinStatsGraph *)ref_data; - if (self != nullptr && self->_graph_window == hwnd) { - return self->graph_window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} diff --git a/pandatool/src/win-stats/winStatsGraph.h b/pandatool/src/win-stats/winStatsGraph.h deleted file mode 100644 index e1a9f219..00000000 --- a/pandatool/src/win-stats/winStatsGraph.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsGraph.h - * @author drose - * @date 2003-12-03 - */ - -#ifndef WINSTATSGRAPH_H -#define WINSTATSGRAPH_H - -#include "pandatoolbase.h" -#include "winStatsLabelStack.h" -#include "pmap.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class PStatGraph; -class WinStatsMonitor; - -/** - * This is just an abstract base class to provide a common pointer type for - * the various kinds of graphs that may be created for a WinStatsMonitor. - */ -class WinStatsGraph { -public: - // What is the user adjusting by dragging the mouse in a window? - enum DragMode { - DM_none, - DM_scale, - DM_left_margin, - DM_right_margin, - DM_guide_bar, - DM_new_guide_bar, - DM_sizing, - DM_pan, - }; - -public: - WinStatsGraph(WinStatsMonitor *monitor); - virtual ~WinStatsGraph(); - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw()=0; - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void set_scroll_speed(double scroll_speed); - void set_pause(bool pause); - - void user_guide_bars_changed(); - virtual void on_click_label(int collector_index); - virtual void on_popup_label(int collector_index); - virtual void on_enter_label(int collector_index); - virtual void on_leave_label(int collector_index); - virtual std::string get_label_tooltip(int collector_index) const; - - void clear_graph_tooltip(); - - HWND get_window(); - - void reset_collector_color(int collector_index); - -protected: - void close(); - - void setup_label_stack(); - void move_label_stack(); - - void start_animation(); - virtual bool animate(double time, double dt); - - void get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - HBRUSH get_collector_brush(int collector_index, bool highlight = false); - COLORREF get_collector_text_color(int collector_index, bool highlight = false); - - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual LONG graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - virtual void additional_window_paint(HDC hdc); - virtual void additional_graph_window_paint(HDC hdc); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int mouse_x, int mouse_y, - int width, int height); - virtual void set_drag_mode(DragMode drag_mode); - - virtual void move_graph_window(int graph_left, int graph_top, - int graph_xsize, int graph_ysize); - -protected: - // Table of brushes for our various collectors. - typedef pmap > Brushes; - Brushes _brushes; - - typedef pmap > TextColors; - TextColors _text_colors; - - WinStatsMonitor *_monitor; - HWND _window; - HWND _graph_window; - HWND _tooltip_window; - WinStatsLabelStack _label_stack; - std::string _tooltip_text; - - HCURSOR _sizewe_cursor; - HCURSOR _hand_cursor; - - HBITMAP _bitmap; - HDC _bitmap_dc; - - int _graph_left, _graph_top; - int _bitmap_xsize, _bitmap_ysize; - int _left_margin, _right_margin; - int _top_margin, _bottom_margin; - int _top_label_stack_margin; - int _pixel_scale; - - COLORREF _dark_color; - COLORREF _light_color; - COLORREF _user_guide_bar_color; - COLORREF _frame_guide_bar_color; - HPEN _dark_pen; - HPEN _light_pen; - HPEN _user_guide_bar_pen; - HPEN _frame_guide_bar_pen; - - DragMode _drag_mode; - DragMode _potential_drag_mode; - int _drag_start_x, _drag_start_y; - double _drag_scale_start; - int _drag_guide_bar; - - int _highlighted_index = -1; - - bool _pause; - - bool _timer_running = false; - double _time; - -private: - void setup_bitmap(int xsize, int ysize); - void release_bitmap(); - void create_graph_window(); - - static LRESULT WINAPI static_graph_subclass_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT_PTR subclass, DWORD_PTR ref_data); - -protected: - static DWORD graph_window_style; -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsLabel.I b/pandatool/src/win-stats/winStatsLabel.I deleted file mode 100644 index a7cabe90..00000000 --- a/pandatool/src/win-stats/winStatsLabel.I +++ /dev/null @@ -1,68 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsLabel.I - * @author rdb - * @date 2022-01-29 - */ - -/** - * Returns the x position of the label on its parent. - */ -INLINE int WinStatsLabel:: -get_x() const { - return _x; -} - -/** - * Returns the y position of the label on its parent. - */ -INLINE int WinStatsLabel:: -get_y() const { - return _y; -} - -/** - * Returns the width of the label as we requested it. - */ -INLINE int WinStatsLabel:: -get_width() const { - return _width; -} - -/** - * Returns the height of the label as we requested it. - */ -INLINE int WinStatsLabel:: -get_height() const { - return _height; -} - -/** - * Returns the width the label would really prefer to be. - */ -INLINE int WinStatsLabel:: -get_ideal_width() const { - return _ideal_width; -} - -/** - * Returns the collector this label represents. - */ -INLINE int WinStatsLabel:: -get_collector_index() const { - return _collector_index; -} - -/** - * Returns true if the visual highlight for this label is enabled. - */ -INLINE bool WinStatsLabel:: -get_highlight() const { - return _highlight; -} diff --git a/pandatool/src/win-stats/winStatsLabel.cxx b/pandatool/src/win-stats/winStatsLabel.cxx deleted file mode 100644 index 007f7505..00000000 --- a/pandatool/src/win-stats/winStatsLabel.cxx +++ /dev/null @@ -1,390 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsLabel.cxx - * @author drose - * @date 2004-01-07 - */ - -#include "winStatsLabel.h" -#include "winStatsMonitor.h" -#include "winStatsGraph.h" -#include "convert_srgb.h" - -#include - -int WinStatsLabel::_left_margin = 2; -int WinStatsLabel::_right_margin = 2; -int WinStatsLabel::_top_margin = 2; -int WinStatsLabel::_bottom_margin = 2; - -bool WinStatsLabel::_window_class_registered = false; -const char * const WinStatsLabel::_window_class_name = "label"; - -/** - * - */ -WinStatsLabel:: -WinStatsLabel(WinStatsMonitor *monitor, WinStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname, - bool align_right) : - _monitor(monitor), - _graph(graph), - _thread_index(thread_index), - _collector_index(collector_index), - _align_right(align_right), - _window(0), - _tooltip_window(0) -{ - update_text(use_fullname); - update_color(); - - _x = 0; - _y = 0; - _width = 0; - _height = 0; - _ideal_width = 0; - _highlight = false; - _mouse_within = false; -} - -/** - * - */ -WinStatsLabel:: -~WinStatsLabel() { - if (_window) { - if (_tooltip_window) { - DestroyWindow(_tooltip_window); - _tooltip_window = 0; - } - DestroyWindow(_window); - _window = 0; - } - DeleteObject(_bg_brush); - DeleteObject(_highlight_bg_brush); -} - -/** - * Creates the actual window. - */ -void WinStatsLabel:: -setup(HWND parent_window) { - if (_window) { - DestroyWindow(_window); - _window = 0; - } - - create_window(parent_window); - - HDC hdc = GetDC(_window); - HFONT hfnt = _monitor->get_font(); - SelectObject(hdc, hfnt); - - SIZE size; - GetTextExtentPoint32(hdc, _text.data(), _text.length(), &size); - _height = size.cy + _top_margin + _bottom_margin; - _ideal_width = size.cx + _left_margin + _right_margin; - - ReleaseDC(_window, hdc); -} - -/** - * Sets the position of the label on its parent. The position describes the - * lower-left corner of the rectangle, not the upper-left. - */ -void WinStatsLabel:: -set_pos(int x, int y, int width) { - if (x != _x || y != _y || width != _width) { - _x = x; - _y = y; - _width = width; - SetWindowPos(_window, 0, x, y - _height, _width, _height, - SWP_NOZORDER | SWP_SHOWWINDOW); - } -} - -/** - * Changes the Y attribute without updating the window. - */ -void WinStatsLabel:: -set_y_noupdate(int y) { - _y = y; -} - -/** - * Enables or disables the visual highlight for this label. - */ -void WinStatsLabel:: -set_highlight(bool highlight) { - if (_highlight != highlight) { - _highlight = highlight; - InvalidateRect(_window, nullptr, TRUE); - } -} - -/** - * Updates the colors. - */ -void WinStatsLabel:: -update_color() { - if (_bg_brush != 0) { - DeleteObject(_bg_brush); - } - if (_highlight_bg_brush != 0) { - DeleteObject(_highlight_bg_brush); - } - - LRGBColor rgb = _monitor->get_collector_color(_collector_index); - int r = (int)encode_sRGB_uchar((float)rgb[0]); - int g = (int)encode_sRGB_uchar((float)rgb[1]); - int b = (int)encode_sRGB_uchar((float)rgb[2]); - _bg_brush = CreateSolidBrush(RGB(r, g, b)); - - // Calculate the color when it is highlighted. - int hr = (int)encode_sRGB_uchar((float)rgb[0] * 0.75f); - int hg = (int)encode_sRGB_uchar((float)rgb[1] * 0.75f); - int hb = (int)encode_sRGB_uchar((float)rgb[2] * 0.75f); - _highlight_bg_brush = CreateSolidBrush(RGB(hr, hg, hb)); - - // Should our foreground be black or white? - double bright = - rgb[0] * 0.2126 + - rgb[1] * 0.7152 + - rgb[2] * 0.0722; - - if (bright >= 0.5) { - _fg_color = RGB(0, 0, 0); - } else { - _fg_color = RGB(255, 255, 255); - } - if (bright * 0.75 >= 0.5) { - _highlight_fg_color = RGB(0, 0, 0); - } else { - _highlight_fg_color = RGB(255, 255, 255); - } - - if (_window) { - InvalidateRect(_window, nullptr, TRUE); - } -} - -/** - * Set to true if the full name of the collector should be shown. - */ -void WinStatsLabel:: -update_text(bool use_fullname) { - const PStatClientData *client_data = _monitor->get_client_data(); - _tooltip_text = client_data->get_collector_fullname(_collector_index); - if (use_fullname) { - _text = _tooltip_text; - } else { - _text = client_data->get_collector_name(_collector_index); - } - - // Recalculate the dimensions. - if (_window) { - HDC hdc = GetDC(_window); - HFONT hfnt = _monitor->get_font(); - SelectObject(hdc, hfnt); - - SIZE size; - GetTextExtentPoint32(hdc, _text.data(), _text.length(), &size); - _height = size.cy + _top_margin + _bottom_margin; - _ideal_width = size.cx + _left_margin + _right_margin; - } -} - -/** - * Used internally to indicate whether the mouse is within the label's window. - */ -void WinStatsLabel:: -set_mouse_within(bool mouse_within) { - if (_mouse_within != mouse_within) { - _mouse_within = mouse_within; - InvalidateRect(_window, nullptr, TRUE); - } -} - -/** - * Creates the window for this label. - */ -void WinStatsLabel:: -create_window(HWND parent_window) { - if (_window) { - return; - } - - HINSTANCE application = GetModuleHandle(nullptr); - register_window_class(application); - - _window = - CreateWindow(_window_class_name, _text.c_str(), WS_CHILD | WS_CLIPSIBLINGS, - 0, 0, 0, 0, - parent_window, nullptr, application, 0); - if (!_window) { - nout << "Could not create Label window!\n"; - exit(1); - } - - SetWindowLongPtr(_window, 0, (LONG_PTR)this); - - // Create the tooltip window. This will cause a TTN_GETDISPINFO message to - // be sent to the window to acquire the tooltip text. - _tooltip_window = CreateWindow(TOOLTIPS_CLASS, nullptr, - WS_POPUP, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - _window, nullptr, - application, nullptr); - - if (_tooltip_window != 0) { - TOOLINFO info = { 0 }; - info.cbSize = sizeof(info); - info.uFlags = TTF_IDISHWND | TTF_SUBCLASS; - info.hwnd = _window; - info.uId = (UINT_PTR)_window; - info.lpszText = LPSTR_TEXTCALLBACK; - SendMessage(_tooltip_window, TTM_ADDTOOL, 0, (LPARAM)&info); - } -} - -/** - * Registers the window class for the label window, if it has not already been - * registered. - */ -void WinStatsLabel:: -register_window_class(HINSTANCE application) { - if (_window_class_registered) { - return; - } - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(WNDCLASS)); - wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = application; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = nullptr; - wc.lpszMenuName = nullptr; - wc.lpszClassName = _window_class_name; - - // Reserve space to associate the this pointer with the window. - wc.cbWndExtra = sizeof(WinStatsLabel *); - - if (!RegisterClass(&wc)) { - nout << "Could not register Label window class!\n"; - exit(1); - } - - _window_class_registered = true; -} - -/** - * - */ -LONG WINAPI WinStatsLabel:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - WinStatsLabel *self = (WinStatsLabel *)GetWindowLongPtr(hwnd, 0); - if (self != nullptr && self->_window == hwnd) { - return self->window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} - -/** - * - */ -LONG WinStatsLabel:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDBLCLK: - _graph->on_click_label(_collector_index); - return 0; - - case WM_CONTEXTMENU: - _graph->on_popup_label(_collector_index); - return 0; - - case WM_MOUSEMOVE: - { - // When the mouse enters the label area, highlight the label. - if (!_mouse_within) { - set_mouse_within(true); - _graph->on_enter_label(_collector_index); - } - - // Now we want to get a WM_MOUSELEAVE when the mouse leaves the label. - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - _window, - 0 - }; - TrackMouseEvent(&tme); - } - break; - - case WM_MOUSELEAVE: - if (_mouse_within) { - set_mouse_within(false); - _graph->on_leave_label(_collector_index); - } - break; - - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - - RECT rect = { 0, 0, _width, _height }; - FillRect(hdc, &rect, (_highlight || _mouse_within) ? _highlight_bg_brush : _bg_brush); - - HFONT hfnt = _monitor->get_font(); - SelectObject(hdc, hfnt); - SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP); - - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, (_highlight || _mouse_within) ? _highlight_fg_color : _fg_color); - - if (_width > 8) { - UINT format = DT_END_ELLIPSIS | DT_SINGLELINE; - if (_align_right) { - format |= DT_RIGHT; - } else { - format |= DT_LEFT; - } - - RECT margins = { _left_margin, _top_margin, _width - _right_margin, _height - _bottom_margin }; - DrawText(hdc, _text.data(), _text.length(), &margins, format); - } - - EndPaint(hwnd, &ps); - return 0; - } - - case WM_NOTIFY: - switch (((LPNMHDR)lparam)->code) { - case TTN_GETDISPINFO: - { - NMTTDISPINFO &info = *(NMTTDISPINFO *)lparam; - _tooltip_text = _graph->get_label_tooltip(_collector_index); - info.lpszText = (char *)_tooltip_text.c_str(); - } - return 0; - } - break; - - default: - break; - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} diff --git a/pandatool/src/win-stats/winStatsLabel.h b/pandatool/src/win-stats/winStatsLabel.h deleted file mode 100644 index 3ad3b393..00000000 --- a/pandatool/src/win-stats/winStatsLabel.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsLabel.h - * @author drose - * @date 2004-01-07 - */ - -#ifndef WINSTATSLABEL_H -#define WINSTATSLABEL_H - -#include "pandatoolbase.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class WinStatsMonitor; -class WinStatsGraph; - -/** - * A text label that will draw in color appropriate for a particular - * collector. It also responds when the user double-clicks on it. This is - * handy for putting colored labels on strip charts. - */ -class WinStatsLabel { -public: - WinStatsLabel(WinStatsMonitor *monitor, WinStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname, - bool align_right = true); - ~WinStatsLabel(); - - void setup(HWND parent_window); - void set_pos(int x, int y, int width); - void set_y_noupdate(int y); - - INLINE int get_x() const; - INLINE int get_y() const; - INLINE int get_width() const; - INLINE int get_height() const; - INLINE int get_ideal_width() const; - - INLINE int get_collector_index() const; - - void set_highlight(bool highlight); - INLINE bool get_highlight() const; - - void update_color(); - void update_text(bool use_fullname); - -private: - void set_mouse_within(bool mouse_within); - - void create_window(HWND parent_window); - static void register_window_class(HINSTANCE application); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - WinStatsMonitor *_monitor; - WinStatsGraph *_graph; - int _thread_index; - int _collector_index; - std::string _text; - std::string _tooltip_text; - HWND _window; - HWND _tooltip_window; - COLORREF _fg_color; - COLORREF _highlight_fg_color; - HBRUSH _bg_brush = 0; - HBRUSH _highlight_bg_brush = 0; - - int _x; - int _y; - int _width; - int _height; - int _ideal_width; - bool _highlight; - bool _mouse_within; - bool _align_right; - - static int _left_margin, _right_margin; - static int _top_margin, _bottom_margin; - - static bool _window_class_registered; - static const char * const _window_class_name; -}; - -#include "winStatsLabel.I" - -#endif diff --git a/pandatool/src/win-stats/winStatsLabelStack.cxx b/pandatool/src/win-stats/winStatsLabelStack.cxx deleted file mode 100644 index be3a5971..00000000 --- a/pandatool/src/win-stats/winStatsLabelStack.cxx +++ /dev/null @@ -1,465 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsLabelStack.cxx - * @author drose - * @date 2004-01-07 - */ - -#include "winStatsLabelStack.h" -#include "winStatsLabel.h" -#include "pnotify.h" - -bool WinStatsLabelStack::_window_class_registered = false; -const char * const WinStatsLabelStack::_window_class_name = "stack"; - -/** - * - */ -WinStatsLabelStack:: -WinStatsLabelStack() { - _x = 0; - _y = 0; - _width = 0; - _height = 0; - _ideal_width = 0; - - _highlight_label = -1; -} - -/** - * - */ -WinStatsLabelStack:: -~WinStatsLabelStack() { - clear_labels(); - if (_window) { - DestroyWindow(_window); - _window = 0; - } -} - -/** - * Creates the actual window object. - */ -void WinStatsLabelStack:: -setup(HWND parent_window) { - if (_window) { - DestroyWindow(_window); - _window = 0; - } - - create_window(parent_window); - - _ideal_width = 0; - for (WinStatsLabel *label : _labels) { - label->setup(_window); - _ideal_width = std::max(_ideal_width, label->get_ideal_width()); - } -} - -/** - * Returns true if the label stack has been set up, false otherwise. - */ -bool WinStatsLabelStack:: -is_setup() const { - return (_window != 0); -} - -/** - * Sets the position and size of the label stack on its parent. - */ -void WinStatsLabelStack:: -set_pos(int x, int y, int width, int height, int top_margin, int bottom_margin) { - _x = x; - _y = y; - _width = width; - _height = height; - _top_margin = top_margin; - _bottom_margin = bottom_margin; - SetWindowPos(_window, 0, x, y, _width, _height, - SWP_NOZORDER | SWP_SHOWWINDOW); - - recalculate_label_positions(); -} - -/** - * Returns the x position of the stack on its parent. - */ -int WinStatsLabelStack:: -get_x() const { - return _x; -} - -/** - * Returns the y position of the stack on its parent. - */ -int WinStatsLabelStack:: -get_y() const { - return _y; -} - -/** - * Returns the width of the stack as we requested it. - */ -int WinStatsLabelStack:: -get_width() const { - return _width; -} - -/** - * Returns the height of the stack as we requested it. - */ -int WinStatsLabelStack:: -get_height() const { - return _height; -} - -/** - * Returns the width the stack would really prefer to be. - */ -int WinStatsLabelStack:: -get_ideal_width() const { - return _ideal_width; -} - -/** - * Returns the y position of the indicated label's bottom edge, relative to - * the label stack's parent window. - */ -int WinStatsLabelStack:: -get_label_y(int label_index) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0); - return _labels[label_index]->get_y() + get_y(); -} - -/** - * Returns the height of the indicated label. - */ -int WinStatsLabelStack:: -get_label_height(int label_index) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0); - return _labels[label_index]->get_height(); -} - -/** - * Returns the collector index associated with the indicated label. - */ -int WinStatsLabelStack:: -get_label_collector_index(int label_index) const { - nassertr(label_index >= 0 && label_index < (int)_labels.size(), -1); - return _labels[label_index]->get_collector_index(); -} - -/** - * Removes the set of labels and starts a new set. - */ -void WinStatsLabelStack:: -clear_labels() { - for (WinStatsLabel *label : _labels) { - delete label; - } - _labels.clear(); - _ideal_width = 0; - _scroll = 0; -} - -/** - * Adds a new label to the top of the stack; returns the new label index. - */ -int WinStatsLabelStack:: -add_label(WinStatsMonitor *monitor, WinStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname) { - int yp = _height; - if (!_labels.empty()) { - WinStatsLabel *top_label = _labels.back(); - yp = top_label->get_y() - top_label->get_height(); - } - WinStatsLabel *label = - new WinStatsLabel(monitor, graph, thread_index, collector_index, use_fullname); - if (_window) { - label->setup(_window); - label->set_pos(0, yp - _scroll, _width); - } - _ideal_width = std::max(_ideal_width, label->get_ideal_width()); - - int label_index = (int)_labels.size(); - _labels.push_back(label); - - recalculate_label_positions(); - - return label_index; -} - -/** - * Replaces the labels with the given collector indices. - */ -void WinStatsLabelStack:: -replace_labels(WinStatsMonitor *monitor, WinStatsGraph *graph, - int thread_index, const vector_int &collector_indices, - bool use_fullname) { - - _ideal_width = 0; - - // First skip the part of the stack that hasn't changed. - size_t li = 0; - size_t ci = 0; - while (ci < collector_indices.size() && li < _labels.size()) { - WinStatsLabel *label = _labels[li]; - if (collector_indices[ci] != label->get_collector_index()) { - // Mismatch. - break; - } - _ideal_width = std::max(_ideal_width, label->get_ideal_width()); - ++ci; - ++li; - } - - if (ci == collector_indices.size()) { - if (ci == _labels.size()) { - // Perfect, nothing changed. - return; - } - - // Simple case, just delete the rest. - while (li < _labels.size()) { - delete _labels[li++]; - } - _labels.resize(ci); - return; - } - - int yp = _height; - if (li > 0) { - WinStatsLabel *label = _labels[li - 1]; - yp = label->get_y() - label->get_height(); - } - - // Make a map of remaining labels. - std::map label_map; - for (size_t li2 = li; li2 < _labels.size(); ++li2) { - WinStatsLabel *label = _labels[li2]; - label_map[label->get_collector_index()] = label; - } - - _labels.resize(collector_indices.size()); - - while (ci < collector_indices.size()) { - int collector_index = collector_indices[ci++]; - - WinStatsLabel *label; - auto it = label_map.find(collector_index); - if (it == label_map.end()) { - // It's not in the map. Create a new label. - label = new WinStatsLabel(monitor, graph, thread_index, collector_index, use_fullname); - if (_window) { - label->setup(_window); - } - } else { - // Erase it from the map, so that it's not deleted. - label = it->second; - label_map.erase(it); - } - if (_window) { - label->set_pos(0, yp - _scroll, _width); - } - _ideal_width = std::max(_ideal_width, label->get_ideal_width()); - yp -= label->get_height(); - - _labels[li++] = label; - } - - // Anything that's remaining in the label map should be deleted. - for (auto it = label_map.begin(); it != label_map.end(); ++it) { - delete it->second; - } - - recalculate_label_positions(); -} - -/** - * Returns the number of labels in the stack. - */ -int WinStatsLabelStack:: -get_num_labels() const { - return _labels.size(); -} - -/** - * Draws a highlight around the label representing the indicated collector, - * and removes the highlight from any other label. Specify -1 to remove the - * highlight from all labels. - */ -void WinStatsLabelStack:: -highlight_label(int collector_index) { - if (_highlight_label != collector_index) { - _highlight_label = collector_index; - - for (WinStatsLabel *label : _labels) { - label->set_highlight(label->get_collector_index() == _highlight_label); - } - } -} - -/** - * Refreshes the color of the label with the given index. - */ -void WinStatsLabelStack:: -update_label_color(int collector_index) { - for (WinStatsLabel *label : _labels) { - if (label->get_collector_index() == collector_index) { - label->update_color(); - } - } -} - -/** - * Called to recalculate the positions of all labels in the stack. - */ -void WinStatsLabelStack:: -recalculate_label_positions() { - int total_height = 0; - for (WinStatsLabel *label : _labels) { - total_height += label->get_height(); - } - total_height += _bottom_margin + _top_margin; - int yp; - if (total_height <= _height) { - // Fits. Align to bottom and reset scroll. - yp = _height - _bottom_margin; - _scroll = 0; - } else { - // Doesn't fit. Align to top. - yp = total_height - _bottom_margin; - _scroll = (std::min)(_scroll, total_height - _height); - _scroll = (std::max)(_scroll, 0); - } - for (WinStatsLabel *label : _labels) { - label->set_pos(0, yp - _scroll, _width); - yp -= label->get_height(); - } -} - -/** - * Creates the window for this stack. - */ -void WinStatsLabelStack:: -create_window(HWND parent_window) { - if (_window) { - return; - } - - HINSTANCE application = GetModuleHandle(nullptr); - register_window_class(application); - - _window = - CreateWindow(_window_class_name, "label stack", WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, - 0, 0, 0, 0, - parent_window, nullptr, application, 0); - if (!_window) { - nout << "Could not create Label Stack window!\n"; - exit(1); - } - - SetWindowLongPtr(_window, 0, (LONG_PTR)this); -} - -/** - * Registers the window class for the label window, if it has not already been - * registered. - */ -void WinStatsLabelStack:: -register_window_class(HINSTANCE application) { - if (_window_class_registered) { - return; - } - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(WNDCLASS)); - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = application; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.lpszMenuName = nullptr; - wc.lpszClassName = _window_class_name; - - // Reserve space to associate the this pointer with the window. - wc.cbWndExtra = sizeof(WinStatsLabelStack *); - - if (!RegisterClass(&wc)) { - nout << "Could not register Label Stack window class!\n"; - exit(1); - } - - _window_class_registered = true; -} - -/** - * - */ -LONG WINAPI WinStatsLabelStack:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - WinStatsLabelStack *self = (WinStatsLabelStack *)GetWindowLongPtr(hwnd, 0); - if (self != nullptr && self->_window == hwnd) { - return self->window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} - -/** - * - */ -LONG WinStatsLabelStack:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - - RECT rect = { 0, 0, _width, _height }; - FillRect(hdc, &rect, (HBRUSH)COLOR_WINDOW); - EndPaint(hwnd, &ps); - return 0; - } - - case WM_MOUSEWHEEL: - { - int total_height = 0; - for (WinStatsLabel *label : _labels) { - total_height += label->get_height(); - } - total_height += _bottom_margin + _top_margin; - if ((total_height > _height || _scroll != 0) && !_labels.empty()) { - int delta = GET_WHEEL_DELTA_WPARAM(wparam); - delta = (delta * _labels[0]->get_height()) / 120; - int new_scroll = _scroll - delta; - new_scroll = (std::min)(new_scroll, total_height - _height); - new_scroll = (std::max)(new_scroll, 0); - delta = new_scroll - _scroll; - if (delta != 0) { - _scroll = new_scroll; - ScrollWindowEx(_window, 0, -delta, NULL, NULL, NULL, NULL, SW_INVALIDATE | SW_SCROLLCHILDREN); - int yp = yp = total_height - _bottom_margin; - for (WinStatsLabel *label : _labels) { - label->set_y_noupdate(yp - _scroll); - yp -= label->get_height(); - } - } - } - return 0; - } - - default: - break; - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} diff --git a/pandatool/src/win-stats/winStatsLabelStack.h b/pandatool/src/win-stats/winStatsLabelStack.h deleted file mode 100644 index 32239006..00000000 --- a/pandatool/src/win-stats/winStatsLabelStack.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsLabelStack.h - * @author drose - * @date 2004-01-07 - */ - -#ifndef WINSTATSLABELSTACK_H -#define WINSTATSLABELSTACK_H - -#include "pandatoolbase.h" -#include "pvector.h" -#include "vector_int.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class WinStatsLabel; -class WinStatsMonitor; -class WinStatsGraph; - -/** - * A window that contains a stack of labels from bottom to top. - */ -class WinStatsLabelStack { -public: - WinStatsLabelStack(); - ~WinStatsLabelStack(); - - void setup(HWND parent_window); - bool is_setup() const; - void set_pos(int x, int y, int width, int height, - int top_margin, int bottom_margin); - - int get_x() const; - int get_y() const; - int get_width() const; - int get_height() const; - int get_ideal_width() const; - - int get_label_y(int label_index) const; - int get_label_height(int label_index) const; - int get_label_collector_index(int label_index) const; - - void clear_labels(); - int add_label(WinStatsMonitor *monitor, WinStatsGraph *graph, - int thread_index, int collector_index, bool use_fullname); - void replace_labels(WinStatsMonitor *monitor, WinStatsGraph *graph, - int thread_index, const vector_int &collector_indices, - bool use_fullname); - int get_num_labels() const; - - void highlight_label(int collector_index); - void update_label_color(int collector_index); - -private: - void recalculate_label_positions(); - - void create_window(HWND parent_window); - static void register_window_class(HINSTANCE application); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - HWND _window; - int _x; - int _y; - int _width; - int _height; - int _ideal_width; - int _highlight_label; - int _top_margin = 0; - int _bottom_margin = 0; - int _scroll = 0; - - typedef pvector Labels; - Labels _labels; - - static bool _window_class_registered; - static const char * const _window_class_name; -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsMenuId.h b/pandatool/src/win-stats/winStatsMenuId.h deleted file mode 100644 index 9f73b50e..00000000 --- a/pandatool/src/win-stats/winStatsMenuId.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsMenuId.h - * @author drose - * @date 2004-01-11 - */ - -#ifndef WINSTATSMENUID_H -#define WINSTATSMENUID_H - -#include "pandatoolbase.h" - -/** - * The enumerated values here are used for menu ID's for the various pulldown - * menus in the application. - */ -enum WinStatsMenuId { - MI_none, - - MI_session_new, - MI_session_open, - MI_session_open_last, - MI_session_save, - MI_session_close, - MI_session_export_json, - MI_exit, - - MI_time_ms, - MI_time_hz, - MI_frame_rate_label, - MI_speed_1, - MI_speed_2, - MI_speed_3, - MI_speed_6, - MI_speed_12, - MI_pause, - - MI_graphs_close_all, - MI_graphs_reopen_default, - MI_graphs_save_default, - - // This one is last and represents the beginning of the range for the - // various "new chart" menu options. - MI_new_chart -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsMonitor.I b/pandatool/src/win-stats/winStatsMonitor.I deleted file mode 100644 index 6658a5ab..00000000 --- a/pandatool/src/win-stats/winStatsMonitor.I +++ /dev/null @@ -1,41 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsMonitor.I - * @author drose - * @date 2004-01-09 - */ - -/** - * - */ -INLINE WinStatsMonitor::MenuDef:: -MenuDef(int thread_index, int collector_index, ChartType chart_type, bool show_level) : - _thread_index(thread_index), - _collector_index(collector_index), - _chart_type(chart_type), - _show_level(show_level) -{ -} - -/** - * - */ -INLINE bool WinStatsMonitor::MenuDef:: -operator < (const MenuDef &other) const { - if (_thread_index != other._thread_index) { - return _thread_index < other._thread_index; - } - if (_collector_index != other._collector_index) { - return _collector_index < other._collector_index; - } - if (_chart_type != other._chart_type) { - return _chart_type < other._chart_type; - } - return (int)_show_level < (int)other._show_level; -} diff --git a/pandatool/src/win-stats/winStatsMonitor.cxx b/pandatool/src/win-stats/winStatsMonitor.cxx deleted file mode 100644 index 410d6388..00000000 --- a/pandatool/src/win-stats/winStatsMonitor.cxx +++ /dev/null @@ -1,952 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsMonitor.cxx - * @author drose - * @date 2003-12-02 - */ - -#include "winStatsMonitor.h" -#include "winStatsServer.h" -#include "winStatsStripChart.h" -#include "winStatsPianoRoll.h" -#include "winStatsFlameGraph.h" -#include "winStatsTimeline.h" -#include "winStatsChartMenu.h" -#include "winStatsMenuId.h" -#include "pStatFrameData.h" -#include "pStatGraph.h" -#include "pStatCollectorDef.h" - -#include "convert_srgb.h" - -#include - -#include -#include -#include - -/** - * - */ -WinStatsMonitor:: -WinStatsMonitor(WinStatsServer *server) : PStatMonitor(server) { - _window = server->get_window(); - _menu_bar = server->get_menu_bar(); - _status_bar = server->get_status_bar(); - - // These will be filled in later when the menu is created. - _scroll_speed = 0.0; - _pause = false; - - setup_speed_menu(); - setup_frame_rate_label(); -} - -/** - * - */ -WinStatsMonitor:: -~WinStatsMonitor() { - close(); -} - -/** - * Closes the client connection if it is active. - */ -void WinStatsMonitor:: -close() { - PStatMonitor::close(); - - remove_all_graphs(); - - RemoveMenu(_menu_bar, 2, MF_BYPOSITION); - RemoveMenu(_menu_bar, 2, MF_BYPOSITION); - - for (WinStatsChartMenu *chart_menu : _chart_menus) { - RemoveMenu(_menu_bar, 2, MF_BYPOSITION); - delete chart_menu; - } - _chart_menus.clear(); - - DrawMenuBar(_window); -} - -/** - * Should be redefined to return a descriptive name for the type of - * PStatsMonitor this is. - */ -std::string WinStatsMonitor:: -get_monitor_name() { - return "WinStats"; -} - -/** - * Called after the monitor has been fully set up. At this time, it will have - * a valid _client_data pointer, and things like is_alive() and close() will - * be meaningful. However, we may not yet know who we're connected to - * (is_client_known() may return false), and we may not know anything about - * the threads or collectors we're about to get data on. - */ -void WinStatsMonitor:: -initialized() { -} - -/** - * Called when the "hello" message has been received from the client. At this - * time, the client's hostname and program name will be known. - */ -void WinStatsMonitor:: -got_hello() { -} - -/** - * Like got_hello(), this is called when the "hello" message has been received - * from the client. At this time, the client's hostname and program name will - * be known. However, the client appears to be an incompatible version and - * the connection will be terminated; the monitor should issue a message to - * that effect. - */ -void WinStatsMonitor:: -got_bad_version(int client_major, int client_minor, - int server_major, int server_minor) { - std::ostringstream str; - str << "Unable to honor connection attempt from " - << get_client_progname() << " on " << get_client_hostname() - << ": unsupported PStats version " - << client_major << "." << client_minor; - - if (server_minor == 0) { - str << " (server understands version " << server_major - << "." << server_minor << " only)."; - } else { - str << " (server understands versions " << server_major - << ".0 through " << server_major << "." << server_minor << ")."; - } - - std::string message = str.str(); - MessageBox(nullptr, message.c_str(), "Bad version", - MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND); -} - -/** - * Called whenever a new Collector definition is received from the client. - * Generally, the client will send all of its collectors over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Collector definitions midstream. - */ -void WinStatsMonitor:: -new_collector(int collector_index) { - for (WinStatsGraph *graph : _graphs) { - graph->new_collector(collector_index); - } -} - -/** - * Called whenever a new Thread definition is received from the client. - * Generally, the client will send all of its threads over shortly after - * connecting, but there's no guarantee that they will all be received before - * the first frames are received. The monitor should be prepared to accept - * new Thread definitions midstream. - */ -void WinStatsMonitor:: -new_thread(int thread_index) { - WinStatsChartMenu *chart_menu = new WinStatsChartMenu(this, thread_index); - chart_menu->add_to_menu_bar(_menu_bar, MI_frame_rate_label); - _chart_menus.push_back(chart_menu); - DrawMenuBar(_window); - - if (thread_index == 0) { - update_status_bar(); - } -} - -/** - * Called when a thread should be removed from the list of threads. - */ -void WinStatsMonitor:: -remove_thread(int thread_index) { - for (ChartMenus::iterator it = _chart_menus.begin(); it != _chart_menus.end(); ++it) { - WinStatsChartMenu *chart_menu = *it; - if (chart_menu->get_thread_index() == thread_index) { - chart_menu->remove_from_menu_bar(_menu_bar); - delete chart_menu; - _chart_menus.erase(it); - return; - } - } -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void WinStatsMonitor:: -new_data(int thread_index, int frame_number) { - PStatMonitor::new_data(thread_index, frame_number); - - for (WinStatsGraph *graph : _graphs) { - graph->new_data(thread_index, frame_number); - } - - if (thread_index == 0) { - update_status_bar(); - } - - if (!_have_data) { - open_default_graphs(); - _have_data = true; - } -} - -/** - * Called whenever the connection to the client has been lost. This is a - * permanent state change. The monitor should update its display to represent - * this, and may choose to close down automatically. - */ -void WinStatsMonitor:: -lost_connection() { - nout << "Lost connection to " << get_client_hostname() << "\n"; -} - -/** - * If has_idle() returns true, this will be called periodically to allow the - * monitor to update its display or whatever it needs to do. - */ -void WinStatsMonitor:: -idle() { - // Check if any of our chart menus need updating. - for (WinStatsChartMenu *chart_menu : _chart_menus) { - chart_menu->check_update(); - } - - // Update the frame rate label from the main thread (thread 0). - const PStatThreadData *thread_data = get_client_data()->get_thread_data(0); - double frame_rate = thread_data->get_frame_rate(); - if (frame_rate != 0.0f) { - // The leading tab centers the text in the status bar. - char buffer[128]; - sprintf(buffer, "\t%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate); - - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; - mii.dwTypeData = buffer + 1; // chop off leading tab - SetMenuItemInfo(_menu_bar, MI_frame_rate_label, FALSE, &mii); - DrawMenuBar(_window); - - if (_status_bar) { - SendMessage(_status_bar, WM_SETTEXT, 0, (LPARAM)buffer); - } - } -} - -/** - * Should be redefined to return true if you want to redefine idle() and - * expect it to be called. - */ -bool WinStatsMonitor:: -has_idle() { - return true; -} - -/** - * Called when the user guide bars have been changed. - */ -void WinStatsMonitor:: -user_guide_bars_changed() { - for (WinStatsGraph *graph : _graphs) { - graph->user_guide_bars_changed(); - } -} - -/** - * Returns the window handle to the monitor's window. - */ -HWND WinStatsMonitor:: -get_window() const { - return _window; -} - -/** - * Returns the font that should be used for rendering text. - */ -HFONT WinStatsMonitor:: -get_font() const { - return ((WinStatsServer *)_server)->get_font(); -} - -/** - * Returns the system DPI scaling as a fraction where 4 = no scaling. - */ -int WinStatsMonitor:: -get_pixel_scale() const { - return ((WinStatsServer *)_server)->get_pixel_scale(); -} - -/** - * Returns an amount by which to offset the next window position. - */ -POINT WinStatsMonitor:: -get_new_window_pos() { - WinStatsServer *server = (WinStatsServer *)_server; - int offset = _graphs.size() * 10 * server->get_pixel_scale(); - POINT client_origin = server->get_client_origin(); - POINT pt; - pt.x = offset + client_origin.x; - pt.y = offset + client_origin.y; - return pt; -} - -/** - * Opens a new timeline. - */ -PStatGraph *WinStatsMonitor:: -open_timeline() { - WinStatsTimeline *graph = new WinStatsTimeline(this); - add_graph(graph); - return graph; -} - -/** - * Opens a new strip chart showing the indicated data. - */ -PStatGraph *WinStatsMonitor:: -open_strip_chart(int thread_index, int collector_index, bool show_level) { - WinStatsStripChart *graph = - new WinStatsStripChart(this, thread_index, collector_index, show_level); - add_graph(graph); - return graph; -} - -/** - * Opens a new flame graph showing the indicated data. - */ -PStatGraph *WinStatsMonitor:: -open_flame_graph(int thread_index, int collector_index, int frame_number) { - WinStatsFlameGraph *graph = new WinStatsFlameGraph(this, thread_index, collector_index, frame_number); - add_graph(graph); - return graph; -} - -/** - * Opens a new piano roll showing the indicated data. - */ -PStatGraph *WinStatsMonitor:: -open_piano_roll(int thread_index) { - WinStatsPianoRoll *graph = new WinStatsPianoRoll(this, thread_index); - add_graph(graph); - return graph; -} - -/** - * Opens a dialog to change the given collector color. - */ -void WinStatsMonitor:: -choose_collector_color(int collector_index) { - const LRGBColor ¤t = get_collector_color(collector_index); - static COLORREF custom_colors[16] = {0}; - - CHOOSECOLORA cc = { - sizeof(CHOOSECOLORA), - _window, - 0, - RGB(encode_sRGB_uchar((float)current[0]), - encode_sRGB_uchar((float)current[1]), - encode_sRGB_uchar((float)current[2])), - (LPDWORD)custom_colors, - CC_FULLOPEN | CC_RGBINIT, - 0, - nullptr, - nullptr, - }; - - if (ChooseColorA(&cc)) { - LRGBColor result( - decode_sRGB_float(GetRValue(cc.rgbResult)), - decode_sRGB_float(GetGValue(cc.rgbResult)), - decode_sRGB_float(GetBValue(cc.rgbResult))); - - set_collector_color(collector_index, result); - - for (WinStatsGraph *graph : _graphs) { - graph->reset_collector_color(collector_index); - } - } -} - -/** - * Resets the color of the given collector to the default. - */ -void WinStatsMonitor:: -reset_collector_color(int collector_index) { - clear_collector_color(collector_index); - - for (WinStatsGraph *graph : _graphs) { - graph->reset_collector_color(collector_index); - } -} - -/** - * Returns the MenuDef properties associated with the indicated menu ID. This - * specifies what we expect to do when the given menu has been selected. - */ -const WinStatsMonitor::MenuDef &WinStatsMonitor:: -lookup_menu(int menu_id) const { - static MenuDef invalid(0, 0, CT_strip_chart, false); - int menu_index = menu_id - MI_new_chart; - nassertr(menu_index >= 0 && menu_index < (int)_menu_by_id.size(), invalid); - return _menu_by_id[menu_index]; -} - -/** - * Returns the menu ID that is reserved for the indicated MenuDef properties. - * If this is the first time these particular properties have been requested, - * a new menu ID is returned; otherwise, the existing menu ID is returned. - */ -int WinStatsMonitor:: -get_menu_id(const MenuDef &menu_def) { - MenuByDef::iterator mi; - mi = _menu_by_def.find(menu_def); - if (mi != _menu_by_def.end()) { - return (*mi).second; - } - - // Slot a new id. - int menu_id = (int)_menu_by_id.size() + MI_new_chart; - _menu_by_id.push_back(menu_def); - _menu_by_def[menu_def] = menu_id; - - return menu_id; -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for all graphs to the indicated mask if - * it is a time-based graph. - */ -void WinStatsMonitor:: -set_time_units(int unit_mask) { - for (WinStatsGraph *graph : _graphs) { - graph->set_time_units(unit_mask); - } -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speeds for all graphs to the indicated value. - */ -void WinStatsMonitor:: -set_scroll_speed(double scroll_speed) { - _scroll_speed = scroll_speed; - - // First, change all of the open graphs appropriately. - for (WinStatsGraph *graph : _graphs) { - graph->set_scroll_speed(_scroll_speed); - } - - // Now change the checkmark on the pulldown menu. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - - mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 1.0, 0.1) ? - MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_speed_menu, MI_speed_1, FALSE, &mii); - - mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 2.0, 0.1) ? - MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_speed_menu, MI_speed_2, FALSE, &mii); - - mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 3.0, 0.1) ? - MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_speed_menu, MI_speed_3, FALSE, &mii); - - mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 6.0, 0.1) ? - MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_speed_menu, MI_speed_6, FALSE, &mii); - - mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 12.0, 0.1) ? - MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_speed_menu, MI_speed_12, FALSE, &mii); -} - -/** - * Called when the user selects a pause on or pause off option from the menu. - */ -void WinStatsMonitor:: -set_pause(bool pause) { - _pause = pause; - - // First, change all of the open graphs appropriately. - for (WinStatsGraph *graph : _graphs) { - graph->set_pause(_pause); - } - - // Now change the checkmark on the pulldown menu. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - - mii.fState = _pause ? MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_speed_menu, MI_pause, FALSE, &mii); -} - -/** - * Adds the newly-created graph to the list of managed graphs. - */ -void WinStatsMonitor:: -add_graph(WinStatsGraph *graph) { - _graphs.insert(graph); - - graph->set_time_units(((WinStatsServer *)_server)->get_time_units()); - graph->set_scroll_speed(_scroll_speed); - graph->set_pause(_pause); -} - -/** - * Deletes the indicated graph. - */ -void WinStatsMonitor:: -remove_graph(WinStatsGraph *graph) { - Graphs::iterator gi = _graphs.find(graph); - if (gi != _graphs.end()) { - _graphs.erase(gi); - delete graph; - } -} - -/** - * Deletes all open graphs. - */ -void WinStatsMonitor:: -remove_all_graphs() { - for (WinStatsGraph *graph : _graphs) { - delete graph; - } - _graphs.clear(); -} - -/** - * Creates the "Speed" pulldown menu. - */ -void WinStatsMonitor:: -setup_speed_menu() { - _speed_menu = CreatePopupMenu(); - - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; - mii.fType = MFT_STRING; - mii.hSubMenu = _speed_menu; - mii.dwTypeData = "Speed"; - InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii); - - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE; - mii.fType = MFT_STRING | MFT_RADIOCHECK; - mii.hbmpChecked = nullptr; - mii.hbmpUnchecked = nullptr; - mii.fState = MFS_UNCHECKED; - mii.wID = MI_speed_1; - mii.dwTypeData = "1"; - InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii); - - mii.wID = MI_speed_2; - mii.dwTypeData = "2"; - InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii); - - mii.wID = MI_speed_3; - mii.dwTypeData = "3"; - InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii); - - mii.wID = MI_speed_6; - mii.dwTypeData = "6"; - InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii); - - mii.wID = MI_speed_12; - mii.dwTypeData = "12"; - InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii); - - mii.fMask = MIIM_FTYPE; - mii.fType = MFT_SEPARATOR; - InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE; - mii.fType = MFT_STRING; - mii.wID = MI_pause; - mii.dwTypeData = "pause"; - InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii); - - set_scroll_speed(3); - set_pause(false); -} - -/** - * Creates the frame rate label on the right end of the menu bar. This is - * used as a text label to display the main thread's frame rate to the user, - * although it is implemented as a right-justified toplevel menu item that - * doesn't open to anything. - */ -void WinStatsMonitor:: -setup_frame_rate_label() { - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY; - mii.wID = MI_frame_rate_label; - mii.dwTypeData = ""; - InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii); -} - -/** - * Updates the status bar. - */ -void WinStatsMonitor:: -update_status_bar() { - const PStatClientData *client_data = get_client_data(); - if (client_data == nullptr) { - return; - } - - const PStatThreadData *thread_data = get_client_data()->get_thread_data(0); - if (thread_data == nullptr || thread_data->is_empty()) { - return; - } - int frame_number = thread_data->get_latest_frame_number(); - const PStatFrameData &frame_data = thread_data->get_latest_frame(); - - // Gather the top-level collector list. - pvector parts; - pvector collectors; - size_t total_chars = 0; - - int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); - for (int tc = 0; tc < num_toplevel_collectors; tc++) { - int collector = client_data->get_toplevel_collector(tc); - if (client_data->has_collector(collector) && - client_data->get_collector_has_level(collector, 0)) { - PStatView &view = get_level_view(collector, 0); - view.set_to_frame(frame_data); - double value = view.get_net_value(); - if (value == 0.0) { - // Don't include it unless we've included it before. - if (std::find(_status_bar_collectors.begin(), _status_bar_collectors.end(), collector) == _status_bar_collectors.end()) { - continue; - } - } - - // Add the value for other threads that have this collector. - for (int thread_index = 1; thread_index < client_data->get_num_threads(); ++thread_index) { - PStatView &view = get_level_view(collector, thread_index); - view.set_to_frame(frame_number); - value += view.get_net_value(); - } - - const PStatCollectorDef &def = client_data->get_collector_def(collector); - std::string text = "\t" + def._name; - text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units); - total_chars += text.size(); - parts.push_back(text); - collectors.push_back(collector); - } - } - - size_t cur_size = _status_bar_collectors.size(); - _status_bar_collectors = std::move(collectors); - - // Allocate an array for holding the right edge coordinates. - HLOCAL hloc = LocalAlloc(LHND, sizeof(int) * (parts.size() + 1)); - PINT sizes = (PINT)LocalLock(hloc); - - int pixel_scale = get_pixel_scale(); - - // Allocate the left-most slot for the framerate indicator. - double offset = 28.0 * pixel_scale; - sizes[0] = (int)(offset + 0.5); - - if (!parts.empty()) { - // Distribute the sizes roughly based on the number of characters. It's not - // as good as measuring the text, but it's good enough. - RECT rect; - double width_per_char = 0; - GetClientRect(_status_bar, &rect); - // Leave room for the grip. - rect.right -= pixel_scale * 4; - width_per_char = (rect.right - rect.left - offset) / (double)total_chars; - - // If we get below a minimum width, start chopping parts off. - while (!parts.empty() && width_per_char < pixel_scale * 1.5) { - total_chars -= parts.back().size(); - parts.pop_back(); - width_per_char = (rect.right - rect.left - offset) / (double)total_chars; - } - - if (!parts.empty()) { - for (size_t i = 0; i < parts.size(); ++i) { - offset += (parts[i].size()) * width_per_char; - sizes[i + 1] = (int)(offset + 0.5); - } - } else { - // No room for any collectors; the framerate can take up the whole width. - sizes[0] = rect.right - rect.left; - } - } - - SendMessage(_status_bar, SB_SETPARTS, (WPARAM)(parts.size() + 1), (LPARAM)sizes); - - LocalUnlock(hloc); - LocalFree(hloc); - - for (size_t i = 0; i < parts.size(); ++i) { - SendMessage(_status_bar, SB_SETTEXT, i + 1, (LPARAM)parts[i].c_str()); - } -} - -/** - * Called when someone right-clicks on a part of the status bar. - */ -void WinStatsMonitor:: -show_popup_menu(int collector) { - POINT point; - if (!GetCursorPos(&point)) { - return; - } - - const PStatClientData *client_data = get_client_data(); - if (client_data == nullptr) { - return; - } - - PStatView &level_view = get_level_view(collector, 0); - const PStatViewLevel *view_level = level_view.get_top_level(); - int num_children = view_level->get_num_children(); - if (num_children == 0) { - return; - } - - HMENU popup = CreatePopupMenu(); - - // Reverse the order since the menus are listed from the top down; we want - // to be visually consistent with the graphs, which list these labels from - // the bottom up. - for (int c = num_children - 1; c >= 0; c--) { - const PStatViewLevel *child_level = view_level->get_child(c); - - int child_collector = child_level->get_collector(); - MenuDef menu_def(0, child_collector, CT_strip_chart, true); - int menu_id = get_menu_id(menu_def); - - double value = child_level->get_net_value(); - - const PStatCollectorDef &def = client_data->get_collector_def(child_collector); - std::string text = def._name; - text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units); - AppendMenu(popup, MF_STRING, menu_id, text.c_str()); - } - - TrackPopupMenu(popup, TPM_LEFTBUTTON, point.x, point.y, 0, _window, nullptr); -} - -/** - * Called when a graph window is iconified or moved in the iconified state. - */ -void WinStatsMonitor:: -calc_iconic_graph_window_pos(WinStatsGraph *moved_graph, int &x, int &y) { - MINIMIZEDMETRICS metrics; - metrics.cbSize = sizeof(metrics); - SystemParametersInfoA(SPI_GETMINIMIZEDMETRICS, 0, &metrics, 0); - - int height = GetThemeSysSize(nullptr, SM_CYSIZE) + GetThemeSysSize(nullptr, SM_CXPADDEDBORDER) * 2; - - RECT client_rect; - GetClientRect(_window, &client_rect); - MapWindowPoints(_window, nullptr, (POINT *)&client_rect, 2); - - // Remove the status bar from the client rectangle. - RECT status_bar_rect; - GetWindowRect(_status_bar, &status_bar_rect); - client_rect.bottom -= (status_bar_rect.bottom - status_bar_rect.top); - - int iconic_offset = 0; - - for (WinStatsGraph *graph : _graphs) { - RECT child_rect; - HWND window = graph->get_window(); - if (graph == moved_graph) { - x = client_rect.left + iconic_offset; - y = client_rect.bottom - height; - iconic_offset += metrics.iWidth + metrics.iHorzGap; - } - else if (IsIconic(window) && GetWindowRect(window, &child_rect)) { - // Keep it glued to the bottom-left corner of the parent window. - child_rect.left = client_rect.left + iconic_offset; - child_rect.top = client_rect.bottom - height; - iconic_offset += metrics.iWidth + metrics.iHorzGap; - - SetWindowPos(window, 0, child_rect.left, child_rect.top, 0, 0, - SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); - } - } -} - -/** - * Called when the server window is moved. - */ -void WinStatsMonitor:: -handle_window_moved(const RECT &client_rect, int delta_x, int delta_y) { - if (_graphs.empty()) { - return; - } - - MINIMIZEDMETRICS metrics; - metrics.cbSize = sizeof(metrics); - SystemParametersInfoA(SPI_GETMINIMIZEDMETRICS, 0, &metrics, 0); - - int height = GetThemeSysSize(nullptr, SM_CYSIZE) + GetThemeSysSize(nullptr, SM_CXPADDEDBORDER) * 2; - - int iconic_offset = 0; - - for (WinStatsGraph *graph : _graphs) { - WINDOWPLACEMENT wp; - HWND window = graph->get_window(); - if (GetWindowPlacement(window, &wp)) { - if (wp.showCmd == SW_SHOWMINIMIZED) { - // Keep the minimized window title bar glued to the bottom-left - // corner of the parent window. - wp.flags |= WPF_SETMINPOSITION; - wp.ptMinPosition.x = client_rect.left + iconic_offset; - wp.ptMinPosition.y = client_rect.bottom - height; - iconic_offset += metrics.iWidth + metrics.iHorzGap; - } - - // Move the "restored" window (even when it's currently min/maximized). - wp.rcNormalPosition.left += delta_x; - wp.rcNormalPosition.top += delta_y; - wp.rcNormalPosition.right += delta_x; - wp.rcNormalPosition.bottom += delta_y; - SetWindowPlacement(window, &wp); - } - } -} - -/** - * Called when a menu item is clicked. - */ -void WinStatsMonitor:: -handle_menu_command(int menu_id) { - switch (menu_id) { - case MI_none: - break; - - case MI_speed_1: - set_scroll_speed(1); - break; - - case MI_speed_2: - set_scroll_speed(2); - break; - - case MI_speed_3: - set_scroll_speed(3); - break; - - case MI_speed_6: - set_scroll_speed(6); - break; - - case MI_speed_12: - set_scroll_speed(12); - break; - - case MI_pause: - set_pause(!_pause); - break; - - case MI_graphs_close_all: - remove_all_graphs(); - break; - - case MI_graphs_reopen_default: - remove_all_graphs(); - open_default_graphs(); - break; - - case MI_graphs_save_default: - save_default_graphs(); - break; - - default: - if (menu_id >= MI_new_chart) { - const MenuDef &menu_def = lookup_menu(menu_id); - switch (menu_def._chart_type) { - case CT_timeline: - open_timeline(); - break; - - case CT_strip_chart: - open_strip_chart(menu_def._thread_index, menu_def._collector_index, - menu_def._show_level); - break; - - case CT_flame_graph: - open_flame_graph(menu_def._thread_index, menu_def._collector_index); - break; - - case CT_piano_roll: - open_piano_roll(menu_def._thread_index); - break; - } - } - } -} - -/** - * Called when a status bar item is double-clicked. - */ -void WinStatsMonitor:: -handle_status_bar_click(int item) { - if (item == 0) { - open_strip_chart(0, 0, false); - } - else if (item >= 1 && item <= _status_bar_collectors.size()) { - int collector = _status_bar_collectors[item - 1]; - open_strip_chart(0, collector, true); - - // Also open a strip chart for other threads with data for this - // collector. - const PStatClientData *client_data = get_client_data(); - for (int thread_index = 1; thread_index < client_data->get_num_threads(); ++thread_index) { - PStatView &view = get_level_view(collector, thread_index); - if (view.get_net_value() > 0.0) { - open_strip_chart(thread_index, collector, true); - } - } - } -} - -/** - * Called when a status bar item is right-clicked. - */ -void WinStatsMonitor:: -handle_status_bar_popup(int item) { - if (item >= 1 && item <= _status_bar_collectors.size()) { - int collector = _status_bar_collectors[item - 1]; - show_popup_menu(collector); - } -} diff --git a/pandatool/src/win-stats/winStatsMonitor.h b/pandatool/src/win-stats/winStatsMonitor.h deleted file mode 100644 index 1fed3f9a..00000000 --- a/pandatool/src/win-stats/winStatsMonitor.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsMonitor.h - * @author drose - * @date 2003-12-02 - */ - -#ifndef WINSTATSMONITOR_H -#define WINSTATSMONITOR_H - -#include "pandatoolbase.h" - -#include "winStatsGraph.h" -#include "pStatMonitor.h" -#include "pointerTo.h" -#include "pset.h" -#include "pvector.h" -#include "pmap.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class WinStatsServer; -class WinStatsChartMenu; - -/** - * This class represents a connection to a PStatsClient and manages the data - * exchange with the client. - */ -class WinStatsMonitor : public PStatMonitor { -public: - enum ChartType { - CT_timeline, - CT_strip_chart, - CT_flame_graph, - CT_piano_roll, - }; - - class MenuDef { - public: - INLINE MenuDef(int thread_index, int collector_index, - ChartType chart_type, bool show_level = false); - INLINE bool operator < (const MenuDef &other) const; - - int _thread_index; - int _collector_index; - ChartType _chart_type; - bool _show_level; - }; - - WinStatsMonitor(WinStatsServer *server); - virtual ~WinStatsMonitor(); - - void close(); - - virtual std::string get_monitor_name(); - - virtual void initialized(); - virtual void got_hello(); - virtual void got_bad_version(int client_major, int client_minor, - int server_major, int server_minor); - virtual void new_collector(int collector_index); - virtual void new_thread(int thread_index); - virtual void new_data(int thread_index, int frame_number); - virtual void remove_thread(int thread_index); - virtual void lost_connection(); - virtual void idle(); - virtual bool has_idle(); - - virtual void user_guide_bars_changed(); - - HWND get_window() const; - HFONT get_font() const; - int get_pixel_scale() const; - POINT get_new_window_pos(); - - PStatGraph *open_timeline(); - PStatGraph *open_strip_chart(int thread_index, int collector_index, bool show_level); - PStatGraph *open_flame_graph(int thread_index, int collector_index = -1, int frame_number = -1); - PStatGraph *open_piano_roll(int thread_index); - - void choose_collector_color(int collector_index); - void reset_collector_color(int collector_index); - - const MenuDef &lookup_menu(int menu_id) const; - int get_menu_id(const MenuDef &menu_def); - - void set_time_units(int unit_mask); - void set_scroll_speed(double scroll_speed); - void set_pause(bool pause); - - void add_graph(WinStatsGraph *graph); - void remove_graph(WinStatsGraph *graph); - void remove_all_graphs(); - -private: - void setup_speed_menu(); - void setup_frame_rate_label(); - void update_status_bar(); - void show_popup_menu(int collector); - - void calc_iconic_graph_window_pos(WinStatsGraph *graph, int &x, int &y); - void handle_window_moved(const RECT &client_rect, int delta_x, int delta_y); - void handle_menu_command(int menu_id); - void handle_status_bar_click(int item); - void handle_status_bar_popup(int item); - - typedef pset Graphs; - Graphs _graphs; - - typedef pvector ChartMenus; - ChartMenus _chart_menus; - - typedef pvector MenuById; - typedef pmap MenuByDef; - MenuById _menu_by_id; - MenuByDef _menu_by_def; - - HWND _window; - HMENU _menu_bar; - HMENU _speed_menu; - HWND _status_bar; - pvector _status_bar_collectors; - std::string _window_title; - double _scroll_speed; - bool _pause; - bool _have_data = false; - - friend class WinStatsGraph; - friend class WinStatsServer; -}; - -#include "winStatsMonitor.I" - -#endif diff --git a/pandatool/src/win-stats/winStatsPianoRoll.cxx b/pandatool/src/win-stats/winStatsPianoRoll.cxx deleted file mode 100644 index 97cbbf88..00000000 --- a/pandatool/src/win-stats/winStatsPianoRoll.cxx +++ /dev/null @@ -1,699 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsPianoRoll.cxx - * @author drose - * @date 2003-12-03 - */ - -#include "winStatsPianoRoll.h" -#include "winStatsMonitor.h" -#include "numeric_types.h" - -static const int default_piano_roll_width = 800; -static const int default_piano_roll_height = 400; - -bool WinStatsPianoRoll::_window_class_registered = false; -const char * const WinStatsPianoRoll::_window_class_name = "piano"; - -/** - * - */ -WinStatsPianoRoll:: -WinStatsPianoRoll(WinStatsMonitor *monitor, int thread_index) : - PStatPianoRoll(monitor, thread_index, - monitor->get_pixel_scale() * default_piano_roll_width / 4, - monitor->get_pixel_scale() * default_piano_roll_height / 4), - WinStatsGraph(monitor) -{ - _left_margin = _pixel_scale * 32; - _right_margin = _pixel_scale * 2; - _top_margin = _pixel_scale * 5; - _bottom_margin = _pixel_scale * 2; - _top_label_stack_margin = _pixel_scale * 5; - - // Let's show the units on the guide bar labels. There's room. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - - create_window(); - force_redraw(); - idle(); -} - -/** - * - */ -WinStatsPianoRoll:: -~WinStatsPianoRoll() { -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void WinStatsPianoRoll:: -new_data(int thread_index, int frame_number) { - if (!_pause) { - update(); - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void WinStatsPianoRoll:: -force_redraw() { - PStatPianoRoll::force_redraw(); -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void WinStatsPianoRoll:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatPianoRoll::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void WinStatsPianoRoll:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - RECT rect; - GetClientRect(_window, &rect); - rect.left = _right_margin; - InvalidateRect(_window, &rect, TRUE); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void WinStatsPianoRoll:: -on_click_label(int collector_index) { - if (collector_index >= 0) { - WinStatsGraph::_monitor->open_strip_chart(_thread_index, collector_index, false); - } -} - -/** - * Called when the user right-clicks on a label. - */ -void WinStatsPianoRoll:: -on_popup_label(int collector_index) { - POINT point; - if (collector_index >= 0 && GetCursorPos(&point)) { - _popup_index = collector_index; - - HMENU popup = CreatePopupMenu(); - - std::string label = get_label_tooltip(collector_index); - if (!label.empty()) { - AppendMenu(popup, MF_STRING | MF_DISABLED, 0, label.c_str()); - } - AppendMenu(popup, MF_STRING, 102, "Open Strip Chart"); - AppendMenu(popup, MF_STRING, 103, "Open Flame Graph"); - AppendMenu(popup, MF_STRING | MF_SEPARATOR, 0, nullptr); - AppendMenu(popup, MF_STRING, 104, "Change Color..."); - AppendMenu(popup, MF_STRING, 105, "Reset Color"); - TrackPopupMenu(popup, TPM_LEFTBUTTON, point.x, point.y, 0, _window, nullptr); - } -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsPianoRoll:: -get_label_tooltip(int collector_index) const { - return PStatPianoRoll::get_label_tooltip(collector_index); -} - -/** - * Changes the amount of time the width of the horizontal axis represents. - * This may force a redraw. - */ -void WinStatsPianoRoll:: -set_horizontal_scale(double time_width) { - PStatPianoRoll::set_horizontal_scale(time_width); - - RECT rect; - GetClientRect(_window, &rect); - rect.bottom = _top_margin; - InvalidateRect(_window, &rect, TRUE); -} - -/** - * Calls update_guide_bars with parameters suitable to this kind of graph. - */ -void WinStatsPianoRoll:: -normal_guide_bars() { - // We want vaguely 100 pixels between guide bars. - update_guide_bars(get_xsize() / (_pixel_scale * 25), get_horizontal_scale()); -} - -/** - * Erases the chart area. - */ -void WinStatsPianoRoll:: -clear_region() { - RECT rect = { 0, 0, get_xsize(), get_ysize() }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void WinStatsPianoRoll:: -begin_draw() { - clear_region(); - - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_bar(_bitmap_dc, get_guide_bar(i)); - } - - SelectObject(_bitmap_dc, GetStockObject(NULL_PEN)); -} - -/** - * Should be overridden by the user class. This hook will be called before - * drawing any one row of bars. These bars correspond to the collector whose - * index is get_row_collector(row), and in the color get_row_color(row). - */ -void WinStatsPianoRoll:: -begin_row(int row) { - int collector_index = get_label_collector(row); - HBRUSH brush = get_collector_brush(collector_index, _highlighted_index == collector_index); - SelectObject(_bitmap_dc, brush); - SelectObject(_bitmap_dc, GetStockObject(NULL_PEN)); -} - -/** - * Draws a single bar on the chart. - */ -void WinStatsPianoRoll:: -draw_bar(int row, int from_x, int to_x) { - if (row >= 0 && row < _label_stack.get_num_labels()) { - int y = _label_stack.get_label_y(row) - _graph_top; - int height = _label_stack.get_label_height(row); - - RoundRect(_bitmap_dc, from_x, y - height + 2, to_x, y - 2, _pixel_scale, _pixel_scale); - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void WinStatsPianoRoll:: -end_draw() { - InvalidateRect(_graph_window, nullptr, FALSE); -} - -/** - * Called at the end of the draw cycle. - */ -void WinStatsPianoRoll:: -idle() { - if (_labels_changed) { - update_labels(); - } -} - -/** - * Returns the current window dimensions. - */ -bool WinStatsPianoRoll:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - WinStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void WinStatsPianoRoll:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - WinStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * - */ -LONG WinStatsPianoRoll:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDOWN: - if (_potential_drag_mode == DM_new_guide_bar) { - set_drag_mode(DM_new_guide_bar); - SetCapture(_graph_window); - return 0; - } - break; - - case WM_COMMAND: - switch (LOWORD(wparam)) { - case 102: - WinStatsGraph::_monitor->open_strip_chart(get_thread_index(), _popup_index, false); - return 0; - - case 103: - WinStatsGraph::_monitor->open_flame_graph(get_thread_index(), _popup_index); - return 0; - - case 104: - WinStatsGraph::_monitor->choose_collector_color(_popup_index); - return 0; - - case 105: - WinStatsGraph::_monitor->reset_collector_color(_popup_index); - return 0; - } - break; - - default: - break; - } - - return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam); -} - -/** - * - */ -LONG WinStatsPianoRoll:: -graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDOWN: - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - int16_t x = LOWORD(lparam); - _drag_scale_start = pixel_to_height(x); - SetCapture(_graph_window); - return 0; - - } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - int16_t x = LOWORD(lparam); - _drag_start_x = x; - SetCapture(_graph_window); - return 0; - } - break; - - case WM_MOUSEMOVE: - if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { - // When the mouse is over a color bar, highlight it. - int16_t x = LOWORD(lparam); - int16_t y = HIWORD(lparam); - - int collector_index = get_collector_under_pixel(x, y); - _label_stack.highlight_label(collector_index); - on_enter_label(collector_index); - - // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph - // window. - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - _graph_window, - 0 - }; - TrackMouseEvent(&tme); - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_scale) { - int16_t x = LOWORD(lparam); - double ratio = (double)x / (double)get_xsize(); - if (ratio > 0.0f) { - set_horizontal_scale(_drag_scale_start / ratio); - } - return 0; - - } else if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - int16_t x = LOWORD(lparam); - if (x >= 0 && x < get_xsize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(x)); - return 0; - } - - } else if (_drag_mode == DM_guide_bar) { - int16_t x = LOWORD(lparam); - move_user_guide_bar(_drag_guide_bar, pixel_to_height(x)); - return 0; - } - break; - - case WM_MOUSELEAVE: - // When the mouse leaves the graph, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - break; - - case WM_LBUTTONUP: - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - ReleaseCapture(); - return 0; - - } else if (_drag_mode == DM_guide_bar) { - int16_t x = LOWORD(lparam); - if (x < 0 || x >= get_xsize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(x)); - } - set_drag_mode(DM_none); - ReleaseCapture(); - return 0; - } - break; - - case WM_LBUTTONDBLCLK: - { - // Double-clicking on a color bar in the graph is the same as double- - // clicking on the corresponding label. - int16_t x = LOWORD(lparam); - int16_t y = HIWORD(lparam); - on_click_label(get_collector_under_pixel(x, y)); - return 0; - } - break; - - case WM_CONTEXTMENU: - { - POINT point; - if (GetCursorPos(&point) && ScreenToClient(_graph_window, &point)) { - int collector_index = get_collector_under_pixel(point.x, point.y); - if (collector_index >= 0) { - on_popup_label(collector_index); - } - } - return 0; - } - break; - - default: - break; - } - - return WinStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam); -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsPianoRoll:: -additional_window_paint(HDC hdc) { - // Draw in the labels for the guide bars. - SelectObject(hdc, WinStatsGraph::_monitor->get_font()); - SetTextAlign(hdc, TA_LEFT | TA_BOTTOM); - SetBkMode(hdc, TRANSPARENT); - - int y = _top_margin - 2; - - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; i++) { - draw_guide_label(hdc, y, get_guide_bar(i)); - } - - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; i++) { - draw_guide_label(hdc, y, get_user_guide_bar(i)); - } -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsPianoRoll:: -additional_graph_window_paint(HDC hdc) { - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_bar(hdc, get_user_guide_bar(i)); - } -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsPianoRoll:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - int collector_index = get_collector_under_pixel(mouse_x, mouse_y); - if (collector_index >= 0) { - return get_label_tooltip(collector_index); - } - return std::string(); -} - -/** - * Based on the mouse position within the window's client area, look for - * draggable things the mouse might be hovering over and return the - * apprioprate DragMode enum or DM_none if nothing is indicated. - */ -WinStatsGraph::DragMode WinStatsPianoRoll:: -consider_drag_start(int mouse_x, int mouse_y, int width, int height) { - if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) { - if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) { - // See if the mouse is over a user-defined guide bar. - int x = mouse_x - _graph_left; - double from_height = pixel_to_height(x - 2); - double to_height = pixel_to_height(x + 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else if (mouse_x < _left_margin - 2 || - mouse_x > width - _right_margin + 2) { - // The mouse is left or right of the graph; maybe create a new guide - // bar. - return DM_new_guide_bar; - } - } - - return WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height); -} - -/** - * Returns the collector index associated with the indicated vertical row, or - * -1. - */ -int WinStatsPianoRoll:: -get_collector_under_pixel(int xpoint, int ypoint) const { - if (_label_stack.get_num_labels() == 0) { - return -1; - } - - // Assume all of the labels are the same height. - int height = _label_stack.get_label_height(0); - int row = (get_ysize() - ypoint) / height; - if (row >= 0 && row < _label_stack.get_num_labels()) { - return _label_stack.get_label_collector_index(row); - } else { - return -1; - } -} - -/** - * Resets the list of labels. - */ -void WinStatsPianoRoll:: -update_labels() { - _label_stack.replace_labels(WinStatsGraph::_monitor, this, - _thread_index, _labels, true); - _labels_changed = false; -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void WinStatsPianoRoll:: -draw_guide_bar(HDC hdc, const PStatGraph::GuideBar &bar) { - int x = height_to_pixel(bar._height); - - if (x > 0 && x < get_xsize() - 1) { - // Only draw it if it's not too close to either edge. - switch (bar._style) { - case GBS_target: - SelectObject(hdc, _light_pen); - break; - - case GBS_user: - SelectObject(hdc, _user_guide_bar_pen); - break; - - case GBS_normal: - SelectObject(hdc, _dark_pen); - break; - } - MoveToEx(hdc, x, 0, nullptr); - LineTo(hdc, x, get_ysize()); - } -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void WinStatsPianoRoll:: -draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar) { - switch (bar._style) { - case GBS_target: - SetTextColor(hdc, _light_color); - break; - - case GBS_user: - SetTextColor(hdc, _user_guide_bar_color); - break; - - case GBS_normal: - SetTextColor(hdc, _dark_color); - break; - } - - int x = height_to_pixel(bar._height); - const std::string &label = bar._label; - SIZE size; - GetTextExtentPoint32(hdc, label.data(), label.length(), &size); - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(x - size.cx); - double to_height = pixel_to_height(x + size.cx); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - return; - } - } - - int this_x = _graph_left + x - size.cx / 2; - if (x >= 0 && x < get_xsize()) { - TextOut(hdc, this_x, y, - label.data(), label.length()); - } -} - -/** - * Creates the window for this strip chart. - */ -void WinStatsPianoRoll:: -create_window() { - if (_window) { - return; - } - - HINSTANCE application = GetModuleHandle(nullptr); - register_window_class(application); - - const PStatClientData *client_data = - WinStatsGraph::_monitor->get_client_data(); - std::string thread_name = client_data->get_thread_name(_thread_index); - std::string window_title = thread_name + " thread piano roll"; - POINT window_pos = WinStatsGraph::_monitor->get_new_window_pos(); - - RECT win_rect = { - 0, 0, - _left_margin + get_xsize() + _right_margin, - _top_margin + get_ysize() + _bottom_margin - }; - - // compute window size based on desired client area size - AdjustWindowRect(&win_rect, graph_window_style, FALSE); - - _window = - CreateWindowEx(WS_EX_DLGMODALFRAME, _window_class_name, - window_title.c_str(), graph_window_style, - window_pos.x, window_pos.y, - win_rect.right - win_rect.left, - win_rect.bottom - win_rect.top, - WinStatsGraph::_monitor->get_window(), - nullptr, application, 0); - if (!_window) { - nout << "Could not create PianoRoll window!\n"; - exit(1); - } - - SetWindowLongPtr(_window, 0, (LONG_PTR)this); - setup_label_stack(); - - // Ensure that the window is on top of the stack. - SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); -} - -/** - * Registers the window class for the pianoRoll window, if it has not already - * been registered. - */ -void WinStatsPianoRoll:: -register_window_class(HINSTANCE application) { - if (_window_class_registered) { - return; - } - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(WNDCLASS)); - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = application; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszMenuName = nullptr; - wc.lpszClassName = _window_class_name; - - // Reserve space to associate the this pointer with the window. - wc.cbWndExtra = sizeof(WinStatsPianoRoll *); - - if (!RegisterClass(&wc)) { - nout << "Could not register PianoRoll window class!\n"; - exit(1); - } - - _window_class_registered = true; -} - -/** - * - */ -LONG WINAPI WinStatsPianoRoll:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - WinStatsPianoRoll *self = (WinStatsPianoRoll *)GetWindowLongPtr(hwnd, 0); - if (self != nullptr && self->_window == hwnd) { - return self->window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} diff --git a/pandatool/src/win-stats/winStatsPianoRoll.h b/pandatool/src/win-stats/winStatsPianoRoll.h deleted file mode 100644 index ebf6cb4e..00000000 --- a/pandatool/src/win-stats/winStatsPianoRoll.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsPianoRoll.h - * @author drose - * @date 2004-01-12 - */ - -#ifndef WINSTATSPIANOROLL_H -#define WINSTATSPIANOROLL_H - -#include "pandatoolbase.h" - -#include "winStatsGraph.h" -#include "pStatPianoRoll.h" -#include "pointerTo.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class WinStatsMonitor; - -/** - * A window that draws a piano-roll style chart, which shows the collectors - * explicitly stopping and starting, one frame at a time. - */ -class WinStatsPianoRoll : public PStatPianoRoll, public WinStatsGraph { -public: - WinStatsPianoRoll(WinStatsMonitor *monitor, int thread_index); - virtual ~WinStatsPianoRoll(); - - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void on_click_label(int collector_index); - virtual void on_popup_label(int collector_index); - virtual std::string get_label_tooltip(int collector_index) const; - void set_horizontal_scale(double time_width); - -protected: - virtual void normal_guide_bars(); - void clear_region(); - virtual void begin_draw(); - virtual void begin_row(int row); - virtual void draw_bar(int row, int from_x, int to_x); - virtual void end_draw(); - virtual void idle(); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual LONG graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual void additional_window_paint(HDC hdc); - virtual void additional_graph_window_paint(HDC hdc); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int mouse_x, int mouse_y, - int width, int height); - -private: - int get_collector_under_pixel(int xpoint, int ypoint) const; - void update_labels(); - void draw_guide_bar(HDC hdc, const GuideBar &bar); - void draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar); - - void create_window(); - static void register_window_class(HINSTANCE application); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - int _popup_index = -1; - - static bool _window_class_registered; - static const char * const _window_class_name; -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsServer.cxx b/pandatool/src/win-stats/winStatsServer.cxx deleted file mode 100644 index dd77cfbf..00000000 --- a/pandatool/src/win-stats/winStatsServer.cxx +++ /dev/null @@ -1,941 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsServer.cxx - * @author drose - * @date 2003-12-02 - */ - -#include "winStatsServer.h" -#include "winStatsMenuId.h" -#include "winStatsMonitor.h" -#include "pandaVersion.h" -#include "pStatGraph.h" -#include "config_pstatclient.h" - -#include -#include - -bool WinStatsServer::_window_class_registered = false; -const char *const WinStatsServer::_window_class_name = "server"; - -/** - * - */ -WinStatsServer:: -WinStatsServer() : _port(pstats_port) { - set_program_brief("Windows PStats client"); - add_option("p", "port", 0, "", &ProgramBase::dispatch_int, nullptr, &_port); - - _last_session = Filename::expand_from( - "$USER_APPDATA/Panda3D-" PANDA_ABI_VERSION_STR "/last-session.pstats"); - _last_session.set_binary(); - - // Create the fonts used for rendering the UI. - NONCLIENTMETRICS metrics = {0}; - metrics.cbSize = sizeof(NONCLIENTMETRICS); - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0)) { - _font = CreateFontIndirect(&metrics.lfMenuFont); - } else { - _font = (HFONT)GetStockObject(ANSI_VAR_FONT); - } - - create_window(); -} - -/** - * Does something with the additional arguments on the command line (after all - * the -options have been parsed). Returns true if the arguments are good, - * false otherwise. - */ -bool WinStatsServer:: -handle_args(ProgramBase::Args &args) { - if (args.empty()) { - new_session(); - return true; - } - else if (args.size() == 1) { - Filename fn = Filename::from_os_specific(args[0]); - fn.set_binary(); - WinStatsMonitor *monitor = new WinStatsMonitor(this); - if (!monitor->read(fn)) { - delete monitor; - - std::ostringstream stream; - stream << "Failed to load session file: " << fn; - std::string str = stream.str(); - MessageBox(_window, str.c_str(), "PStats Error", - MB_OK | MB_ICONEXCLAMATION); - return true; - } - - // Enable the "New Session", "Save Session" and "Close Session" menu items. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_ENABLED; - SetMenuItemInfoA(_session_menu, MI_session_new, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_save, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_close, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_export_json, FALSE, &mii); - - _monitor = monitor; - return true; - } - else { - nout << "At most one filename may be specified on the command-line.\n"; - return false; - } -} - -/** - * - */ -PStatMonitor *WinStatsServer:: -make_monitor(const NetAddress &address) { - // Enable the "New Session", "Save Session" and "Close Session" menu items. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_ENABLED; - SetMenuItemInfoA(_session_menu, MI_session_new, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_save, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_close, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_export_json, FALSE, &mii); - - std::ostringstream strm; - strm << "PStats Server (connected to " << address << ")"; - std::string title = strm.str(); - SetWindowTextA(_window, title.c_str()); - - _monitor = new WinStatsMonitor(this); - return _monitor; -} - -/** - * Called when connection has been lost. - */ -void WinStatsServer:: -lost_connection(PStatMonitor *monitor) { - if (_monitor != nullptr && !_monitor->_have_data) { - // We didn't have any data yet. Just silently restart the session. - _monitor->close(); - _monitor = nullptr; - if (new_session()) { - return; - } - } else { - // Store a backup now, in case PStats crashes or something. - _last_session.make_dir(); - if (monitor->write(_last_session)) { - nout << "Wrote to " << _last_session << "\n"; - } else { - nout << "Failed to write to " << _last_session << "\n"; - } - } - - stop_listening(); - - SetWindowTextA(_window, "PStats Server (disconnected)"); -} - -/** - * Starts a new session. - */ -bool WinStatsServer:: -new_session() { - if (!close_session()) { - return false; - } - - if (listen(_port)) { - { - std::ostringstream strm; - strm << "PStats Server (listening on port " << _port << ")"; - std::string title = strm.str(); - SetWindowTextA(_window, title.c_str()); - } - { - std::ostringstream strm; - strm << "Waiting for client to connect on port " << _port << "..."; - std::string title = strm.str(); - int part = -1; - SendMessage(_status_bar, SB_SETPARTS, 1, (LPARAM)&part); - SendMessage(_status_bar, WM_SETTEXT, 0, (LPARAM)title.c_str()); - } - - // Disable the "New Session" menu item. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_DISABLED; - SetMenuItemInfoA(_session_menu, MI_session_new, FALSE, &mii); - - // Disable the "Save Session" menu item. - mii.fState = MFS_DISABLED; - SetMenuItemInfoA(_session_menu, MI_session_save, FALSE, &mii); - - // Enable the "Close Session" menu item. - mii.fState = MFS_ENABLED; - SetMenuItemInfoA(_session_menu, MI_session_close, FALSE, &mii); - - // Disable the "Export Session" menu item. - mii.fState = MFS_DISABLED; - SetMenuItemInfoA(_session_menu, MI_session_export_json, FALSE, &mii); - - return true; - } - - SetWindowTextA(_window, "PStats Server"); - - std::ostringstream stream; - stream - << "Unable to open port " << _port << ". Try specifying a different " - << "port number using pstats-port in your Config file or the -p option on " - << "the command-line."; - std::string str = stream.str(); - MessageBox(_window, str.c_str(), "PStats Error", - MB_OK | MB_ICONEXCLAMATION); - return false; -} - -/** - * Offers to open an existing session. - */ -bool WinStatsServer:: -open_session() { - if (!close_session()) { - return false; - } - - char buffer[4096]; - buffer[0] = '\0'; - - OPENFILENAMEA ofn = { - sizeof(OPENFILENAMEA), - _window, - nullptr, - "PStats Session Files (*.pstats)\0*.pstats\0All Files (*.*)\0*.*\0", - nullptr, - 0, - 0, - buffer, - sizeof(buffer), - nullptr, - 0, - nullptr, - "Open Session", - OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST, - 0, - }; - - if (GetOpenFileNameA(&ofn)) { - Filename fn = Filename::from_os_specific(buffer); - fn.set_binary(); - - WinStatsMonitor *monitor = new WinStatsMonitor(this); - if (!monitor->read(fn)) { - delete monitor; - - std::ostringstream stream; - stream << "Failed to load session file: " << fn; - std::string str = stream.str(); - MessageBox(_window, str.c_str(), "PStats Error", - MB_OK | MB_ICONEXCLAMATION); - return false; - } - _monitor = monitor; - - // Enable the "New Session", "Save Session" and "Close Session" menu items. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_ENABLED; - SetMenuItemInfoA(_session_menu, MI_session_new, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_save, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_close, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_export_json, FALSE, &mii); - - return true; - } - - return false; -} - -/** - * Opens the last session, if any. - */ -bool WinStatsServer:: -open_last_session() { - if (!close_session()) { - return false; - } - - Filename fn = _last_session; - WinStatsMonitor *monitor = new WinStatsMonitor(this); - if (!monitor->read(fn)) { - delete monitor; - - std::ostringstream stream; - stream << "Failed to load session file: " << fn; - std::string str = stream.str(); - MessageBox(_window, str.c_str(), "PStats Error", - MB_OK | MB_ICONEXCLAMATION); - return false; - } - _monitor = monitor; - - // Enable the "New Session", "Save Session" and "Close Session" menu items. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_ENABLED; - SetMenuItemInfoA(_session_menu, MI_session_new, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_save, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_close, FALSE, &mii); - SetMenuItemInfoA(_session_menu, MI_session_export_json, FALSE, &mii); - - // If the file contained no graphs, open the default graphs. - if (monitor->_graphs.empty()) { - monitor->open_default_graphs(); - } - - return true; -} - -/** - * Offers to save the current session. - */ -bool WinStatsServer:: -save_session() { - nassertr_always(_monitor != nullptr, true); - - char buffer[4096]; - buffer[0] = '\0'; - - OPENFILENAMEA ofn = { - sizeof(OPENFILENAMEA), - _window, - 0, - "PStats Session Files\0*.pstats\0", - nullptr, - 0, - 0, - buffer, - sizeof(buffer), - nullptr, - 0, - nullptr, - "Save Session", - OFN_OVERWRITEPROMPT, - 0, - 0, - "pstats", - 0, - }; - - if (GetSaveFileNameA(&ofn)) { - Filename fn = Filename::from_os_specific(buffer); - fn.set_binary(); - - if (!_monitor->write(fn)) { - std::ostringstream stream; - stream << "Failed to save session file: " << fn; - std::string str = stream.str(); - MessageBox(_window, str.c_str(), "PStats Error", - MB_OK | MB_ICONEXCLAMATION); - return false; - } - _monitor->get_client_data()->clear_dirty(); - return true; - } - - return false; -} - -/** - * Offers to export the current session as a JSON file. - */ -bool WinStatsServer:: -export_session() { - nassertr_always(_monitor != nullptr, true); - - char buffer[4096]; - buffer[0] = '\0'; - - OPENFILENAMEA ofn = { - sizeof(OPENFILENAMEA), - _window, - 0, - "JSON files\0*.json\0", - nullptr, - 0, - 0, - buffer, - sizeof(buffer), - nullptr, - 0, - nullptr, - "Export Session", - OFN_OVERWRITEPROMPT, - 0, - 0, - "json", - 0, - }; - - if (GetSaveFileNameA(&ofn)) { - Filename fn = Filename::from_os_specific(buffer); - fn.set_text(); - - std::ofstream stream; - if (!fn.open_write(stream)) { - std::ostringstream stream; - stream << "Failed to open file for export: " << fn; - std::string str = stream.str(); - MessageBox(_window, str.c_str(), "PStats Error", - MB_OK | MB_ICONEXCLAMATION); - return false; - } - - int pid = _monitor->get_client_pid(); - _monitor->get_client_data()->write_json(stream, std::max(0, pid)); - stream.close(); - return true; - } - - return false; -} - -/** - * Closes the current session. - */ -bool WinStatsServer:: -close_session() { - bool wrote_last_session = false; - - if (_monitor != nullptr) { - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data != nullptr && client_data->is_dirty()) { - if (!_monitor->has_read_filename()) { - _last_session.make_dir(); - if (_monitor->write(_last_session)) { - nout << "Wrote to " << _last_session << "\n"; - wrote_last_session = true; - } - else { - nout << "Failed to write to " << _last_session << "\n"; - } - } - - int result = MessageBox(_window, - "Would you like to save the currently open session?", - "Unsaved Data", MB_YESNOCANCEL | MB_ICONQUESTION); - if (result == IDCANCEL || (result == IDYES && !save_session())) { - return false; - } - } - - _monitor->close(); - _monitor = nullptr; - } - - stop_listening(); - - SetWindowTextA(_window, "PStats Server"); - - int part = -1; - SendMessage(_status_bar, SB_SETPARTS, 1, (LPARAM)&part); - SendMessage(_status_bar, WM_SETTEXT, 0, (LPARAM)""); - - // Enable the "New Session" menu item. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_ENABLED; - SetMenuItemInfoA(_session_menu, MI_session_new, FALSE, &mii); - - if (wrote_last_session) { - // And the "Open Last Session" menu item. - mii.fState = MFS_ENABLED; - SetMenuItemInfoA(_session_menu, MI_session_open_last, FALSE, &mii); - } - - // Disable the "Save Session" menu item. - mii.fState = MFS_DISABLED; - SetMenuItemInfoA(_session_menu, MI_session_save, FALSE, &mii); - - // Disable the "Close Session" menu item. - mii.fState = MFS_DISABLED; - SetMenuItemInfoA(_session_menu, MI_session_close, FALSE, &mii); - - // Disable the "Export Session" menu item. - mii.fState = MFS_DISABLED; - SetMenuItemInfoA(_session_menu, MI_session_export_json, FALSE, &mii); - - return true; -} - -/** - * Returns the window handle to the server's window. - */ -HWND WinStatsServer:: -get_window() const { - return _window; -} - -/** - * Returns the menu handle to the server's menu bar. - */ -HMENU WinStatsServer:: -get_menu_bar() const { - return _menu_bar; -} - -/** - * Returns the window handle to the server's status bar. - */ -HWND WinStatsServer:: -get_status_bar() const { - return _status_bar; -} - -/** - * Returns the font that should be used for rendering text. - */ -HFONT WinStatsServer:: -get_font() const { - return _font; -} - -/** - * Returns the system DPI scaling as a fraction where 4 = no scaling. - */ -int WinStatsServer:: -get_pixel_scale() const { - return _pixel_scale; -} - -/** - * Returns the origin of the window's client area. - */ -POINT WinStatsServer:: -get_client_origin() const { - return _client_origin; -} - -/** - * - */ -int WinStatsServer:: -get_time_units() const { - return _time_units; -} - - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for all graphs to the indicated mask if - * it is a time-based graph. - */ -void WinStatsServer:: -set_time_units(int unit_mask) { - _time_units = unit_mask; - - if (_monitor != nullptr) { - _monitor->set_time_units(unit_mask); - } - - // Now change the checkmark on the pulldown menu. - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - - mii.fState = ((_time_units & PStatGraph::GBU_ms) != 0) ? - MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_options_menu, MI_time_ms, FALSE, &mii); - - mii.fState = ((_time_units & PStatGraph::GBU_hz) != 0) ? - MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(_options_menu, MI_time_hz, FALSE, &mii); -} - -/** - * Creates the window for this server. - */ -void WinStatsServer:: -create_window() { - HINSTANCE application = GetModuleHandle(nullptr); - register_window_class(application); - - _menu_bar = CreateMenu(); - - setup_session_menu(); - setup_options_menu(); - - DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | - WS_CLIPSIBLINGS | WS_VISIBLE; - - _window = - CreateWindow(_window_class_name, "PStats Server", window_style, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - nullptr, _menu_bar, application, 0); - if (!_window) { - nout << "Could not create server window!\n"; - exit(1); - } - - SetWindowLongPtr(_window, 0, (LONG_PTR)this); - - create_status_bar(application); - - // For some reason, SW_SHOWNORMAL doesn't always work, but SW_RESTORE seems - // to. - ShowWindow(_window, SW_RESTORE); - SetForegroundWindow(_window); - - HDC dc = GetDC(_window); - _pixel_scale = 0; - if (dc) { - _pixel_scale = GetDeviceCaps(dc, LOGPIXELSX) / (96 / 4); - } - if (_pixel_scale <= 0) { - _pixel_scale = 4; - } - ReleaseDC(_window, dc); - - _client_origin.x = 0; - _client_origin.y = 0; - ClientToScreen(_window, &_client_origin); - - // Set up a timer to poll the pstats every so often. - SetTimer(_window, 1, 200, nullptr); -} - -/** - * Creates the "Session" pulldown menu. - */ -void WinStatsServer:: -setup_session_menu() { - _session_menu = CreatePopupMenu(); - - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; - mii.fType = MFT_STRING; - mii.hSubMenu = _session_menu; - - mii.dwTypeData = "&Session"; - InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii); - - AppendMenu(_session_menu, MF_STRING, MI_session_new, "&New Session\tCtrl+N"); - AppendMenu(_session_menu, MF_STRING, MI_session_open, "&Open Session...\tCtrl+O"); - - if (_last_session.exists()) { - AppendMenu(_session_menu, MF_STRING, MI_session_open_last, "Open &Last Session"); - } else { - AppendMenu(_session_menu, MF_STRING | MF_DISABLED, MI_session_open_last, "Open &Last Session"); - } - - AppendMenu(_session_menu, MF_STRING | MF_DISABLED, MI_session_save, "&Save Session...\tCtrl+S"); - AppendMenu(_session_menu, MF_STRING | MF_DISABLED, MI_session_close, "&Close Session\tCtrl+W"); - - AppendMenu(_session_menu, MF_SEPARATOR, 0, nullptr); - AppendMenu(_session_menu, MF_STRING | MF_DISABLED, MI_session_export_json, "&Export as JSON..."); - - AppendMenu(_session_menu, MF_SEPARATOR, 0, nullptr); - AppendMenu(_session_menu, MF_STRING, MI_exit, "E&xit"); -} - -/** - * Creates the "Options" pulldown menu. - */ -void WinStatsServer:: -setup_options_menu() { - _options_menu = CreatePopupMenu(); - - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; - mii.fType = MFT_STRING; - mii.hSubMenu = _options_menu; - - // One day, when there is more than one option here, we will actually - // present this to the user as the "Options" menu. For now, the only option - // we have is time units. mii.dwTypeData = "Options"; - mii.dwTypeData = "Units"; - InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii); - - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE; - mii.fType = MFT_STRING | MFT_RADIOCHECK; - mii.hbmpChecked = nullptr; - mii.hbmpUnchecked = nullptr; - mii.fState = MFS_UNCHECKED; - mii.wID = MI_time_ms; - mii.dwTypeData = "ms"; - InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii); - - mii.wID = MI_time_hz; - mii.dwTypeData = "Hz"; - InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii); - - set_time_units(PStatGraph::GBU_ms); -} - -/** - * Sets up a status bar at the bottom of the screen showing assorted level - * values. - */ -void WinStatsServer:: -create_status_bar(HINSTANCE application) { - _status_bar = CreateWindow(STATUSCLASSNAME, nullptr, - SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE, - 0, 0, 0, 0, - _window, (HMENU)0, application, nullptr); - - ShowWindow(_status_bar, SW_SHOW); - UpdateWindow(_status_bar); - - InvalidateRect(_status_bar, NULL, TRUE); -} - -/** - * Registers the window class for the server window, if it has not already - * been registered. - */ -void WinStatsServer:: -register_window_class(HINSTANCE application) { - if (_window_class_registered) { - return; - } - - HMODULE imageres = LoadLibraryExA("imageres.dll", 0, LOAD_LIBRARY_AS_DATAFILE); - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(WNDCLASS)); - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = application; - wc.hIcon = LoadIcon(imageres, MAKEINTRESOURCE(150)); - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszMenuName = nullptr; - wc.lpszClassName = _window_class_name; - - // Reserve space to associate the this pointer with the window. - wc.cbWndExtra = sizeof(WinStatsServer *); - - if (!RegisterClass(&wc)) { - nout << "Could not register server window class!\n"; - exit(1); - } - - _window_class_registered = true; -} - -/** - * - */ -LONG WINAPI WinStatsServer:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - WinStatsServer *self = (WinStatsServer *)GetWindowLongPtr(hwnd, 0); - if (self != nullptr && self->_window == hwnd) { - return self->window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} - -/** - * - */ -LONG WinStatsServer:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_TIMER: - poll(); - break; - - case WM_CLOSE: - if (!close_session()) { - return 0; - } - break; - - case WM_DESTROY: - PostQuitMessage(0); - break; - - case WM_WINDOWPOSCHANGED: - { - RECT client_rect; - GetClientRect(_window, &client_rect); - MapWindowPoints(_window, nullptr, (POINT *)&client_rect, 2); - - if (_monitor != nullptr) { - // Remove the status bar from the client rectangle. - RECT status_bar_rect; - GetWindowRect(_status_bar, &status_bar_rect); - client_rect.bottom -= (status_bar_rect.bottom - status_bar_rect.top); - - int delta_x = client_rect.left - _client_origin.x; - int delta_y = client_rect.top - _client_origin.y; - _client_origin.x = client_rect.left; - _client_origin.y = client_rect.top; - - _monitor->handle_window_moved(client_rect, delta_x, delta_y); - } - else { - _client_origin.x = client_rect.left; - _client_origin.y = client_rect.top; - } - } - break; - - case WM_SIZE: - if (_status_bar) { - SendMessage(_status_bar, WM_SIZE, 0, 0); - if (_monitor != nullptr) { - _monitor->update_status_bar(); - } - } - break; - - case WM_NOTIFY: - if (_monitor != nullptr) { - if (((LPNMHDR)lparam)->code == NM_DBLCLK) { - NMMOUSE &mouse = *(NMMOUSE *)lparam; - _monitor->handle_status_bar_click(mouse.dwItemSpec); - return TRUE; - } - else if (((LPNMHDR)lparam)->code == NM_RCLICK) { - NMMOUSE &mouse = *(NMMOUSE *)lparam; - _monitor->handle_status_bar_popup(mouse.dwItemSpec); - return TRUE; - } - } - break; - - case WM_KEYDOWN: - if ((lparam & 0x40000000) == 0 && GetKeyState(VK_CONTROL) < 0) { - switch (wparam) { - case 'N': - new_session(); - return 0; - - case 'O': - open_session(); - return 0; - - case 'S': - save_session(); - return 0; - - case 'W': - close_session(); - return 0; - - default: - break; - } - } - break; - - case WM_APPCOMMAND: - switch (GET_APPCOMMAND_LPARAM(lparam)) { - case APPCOMMAND_OPEN: - open_session(); - return TRUE; - - case APPCOMMAND_SAVE: - save_session(); - return TRUE; - } - break; - - case WM_COMMAND: - if (HIWORD(wparam) <= 1) { - int menu_id = LOWORD(wparam); - handle_menu_command(menu_id); - return 0; - } - break; - - default: - break; - } - - return DefWindowProc(hwnd, msg, wparam, lparam); -} - -/** - * - */ -void WinStatsServer:: -handle_menu_command(int menu_id) { - switch (menu_id) { - case MI_none: - break; - - case MI_session_new: - new_session(); - break; - - case MI_session_open: - open_session(); - break; - - case MI_session_open_last: - open_last_session(); - break; - - case MI_session_save: - save_session(); - break; - - case MI_session_close: - close_session(); - break; - - case MI_session_export_json: - export_session(); - break; - - case MI_exit: - if (close_session()) { - exit(0); - } - break; - - case MI_time_ms: - set_time_units(PStatGraph::GBU_ms); - break; - - case MI_time_hz: - set_time_units(PStatGraph::GBU_hz); - break; - - default: - if (_monitor != nullptr) { - _monitor->handle_menu_command(menu_id); - } - break; - } -} diff --git a/pandatool/src/win-stats/winStatsServer.h b/pandatool/src/win-stats/winStatsServer.h deleted file mode 100644 index 1c1e1341..00000000 --- a/pandatool/src/win-stats/winStatsServer.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsServer.h - * @author drose - * @date 2003-12-02 - */ - -#ifndef WINSTATSSERVER_H -#define WINSTATSSERVER_H - -#include "pandatoolbase.h" -#include "programBase.h" -#include "pStatServer.h" -#include "winStatsMonitor.h" - -/** - * The class that owns the main loop, waiting for client connections. - */ -class WinStatsServer : public PStatServer, public ProgramBase { -public: - WinStatsServer(); - - virtual bool handle_args(Args &args) override; - - virtual PStatMonitor *make_monitor(const NetAddress &address) override; - virtual void lost_connection(PStatMonitor *monitor) override; - - bool new_session(); - bool open_session(); - bool open_last_session(); - bool save_session(); - bool export_session(); - bool close_session(); - - HWND get_window() const; - HMENU get_menu_bar() const; - HWND get_status_bar() const; - HFONT get_font() const; - int get_pixel_scale() const; - POINT get_client_origin() const; - - int get_time_units() const; - void set_time_units(int unit_mask); - -private: - void create_window(); - void setup_session_menu(); - void setup_options_menu(); - void create_status_bar(HINSTANCE application); - static void register_window_class(HINSTANCE application); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - void handle_menu_command(int menu_id); - - PT(WinStatsMonitor) _monitor; - - Filename _last_session; - - int _port = -1; - HWND _window = 0; - HMENU _menu_bar = 0; - HMENU _session_menu = 0; - HMENU _options_menu = 0; - HWND _status_bar; - POINT _client_origin; - int _time_units = 0; - int _pixel_scale; - - HFONT _font; - - static bool _window_class_registered; - static const char * const _window_class_name; -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsStripChart.cxx b/pandatool/src/win-stats/winStatsStripChart.cxx deleted file mode 100644 index f6f894ea..00000000 --- a/pandatool/src/win-stats/winStatsStripChart.cxx +++ /dev/null @@ -1,900 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsStripChart.cxx - * @author drose - * @date 2003-12-03 - */ - -#include "winStatsStripChart.h" -#include "winStatsMonitor.h" -#include "pStatCollectorDef.h" -#include "numeric_types.h" - -#include - -static const int default_strip_chart_width = 400; -static const int default_strip_chart_height = 100; - -bool WinStatsStripChart::_window_class_registered = false; -const char * const WinStatsStripChart::_window_class_name = "strip"; - -/** - * - */ -WinStatsStripChart:: -WinStatsStripChart(WinStatsMonitor *monitor, int thread_index, - int collector_index, bool show_level) : - PStatStripChart(monitor, - thread_index, collector_index, show_level, - monitor->get_pixel_scale() * default_strip_chart_width / 4, - monitor->get_pixel_scale() * default_strip_chart_height / 4), - WinStatsGraph(monitor) -{ - _brush_origin = 0; - - _left_margin = _pixel_scale * 24; - _right_margin = _pixel_scale * 12; - _top_margin = _pixel_scale * 6; - _bottom_margin = _pixel_scale * 2; - - if (show_level) { - // If it's a level-type graph, show the appropriate units. - if (_unit_name.empty()) { - set_guide_bar_units(GBU_named); - } else { - set_guide_bar_units(GBU_named | GBU_show_units); - } - - } else { - // If it's a time-type graph, show the msHz units. - set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - } - - _smooth_check_box = 0; - - create_window(); - clear_region(); - - update(); -} - -/** - * - */ -WinStatsStripChart:: -~WinStatsStripChart() { -} - -/** - * Called whenever a new Collector definition is received from the client. - */ -void WinStatsStripChart:: -new_collector(int collector_index) { - WinStatsGraph::new_collector(collector_index); -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void WinStatsStripChart:: -new_data(int thread_index, int frame_number) { - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - SetWindowText(_window, window_title.c_str()); - } - } - - if (!_pause) { - update(); - - std::string text = get_total_text(); - if (_net_value_text != text) { - _net_value_text = text; - RECT rect; - GetClientRect(_window, &rect); - rect.bottom = _top_margin; - InvalidateRect(_window, &rect, TRUE); - } - } -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void WinStatsStripChart:: -force_redraw() { - PStatStripChart::force_redraw(); -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void WinStatsStripChart:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatStripChart::changed_size(graph_xsize, graph_ysize); -} - -/** - * Called when the user selects a new time units from the monitor pulldown - * menu, this should adjust the units for the graph to the indicated mask if - * it is a time-based graph. - */ -void WinStatsStripChart:: -set_time_units(int unit_mask) { - int old_unit_mask = get_guide_bar_units(); - if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { - unit_mask = unit_mask & (GBU_hz | GBU_ms); - unit_mask |= (old_unit_mask & GBU_show_units); - set_guide_bar_units(unit_mask); - - RECT rect; - GetClientRect(_window, &rect); - rect.left = _right_margin; - InvalidateRect(_window, &rect, TRUE); - - GetClientRect(_window, &rect); - rect.bottom = _top_margin; - InvalidateRect(_window, &rect, TRUE); - } -} - -/** - * Called when the user selects a new scroll speed from the monitor pulldown - * menu, this should adjust the speed for the graph to the indicated value. - */ -void WinStatsStripChart:: -set_scroll_speed(double scroll_speed) { - // The speed factor indicates chart widths per minute. - if (scroll_speed != 0.0f) { - set_horizontal_scale(60.0f / scroll_speed); - } -} - -/** - * Called when the user single-clicks on a label. - */ -void WinStatsStripChart:: -on_click_label(int collector_index) { - if (collector_index < 0) { - // Clicking on whitespace in the graph is the same as clicking on the top - // label. - collector_index = get_collector_index(); - } - - if (collector_index == get_collector_index() && collector_index != 0) { - // Clicking on the top label means to go up to the parent level. - const PStatClientData *client_data = - WinStatsGraph::_monitor->get_client_data(); - if (client_data->has_collector(collector_index)) { - const PStatCollectorDef &def = - client_data->get_collector_def(collector_index); - if (def._parent_index == 0 && get_view().get_show_level()) { - // Unless the parent is "Frame", and we're not a time collector. - } else { - set_collector_index(def._parent_index); - } - } - - } else { - // Clicking on any other label means to focus on that. - set_collector_index(collector_index); - } -} - -/** - * Called when the user right-clicks on a label. - */ -void WinStatsStripChart:: -on_popup_label(int collector_index) { - POINT point; - if (collector_index >= 0 && GetCursorPos(&point)) { - _popup_index = collector_index; - - HMENU popup = CreatePopupMenu(); - - std::string label = get_label_tooltip(collector_index); - if (!label.empty()) { - AppendMenu(popup, MF_STRING | MF_DISABLED, 0, label.c_str()); - } - if (collector_index == 0 && get_collector_index() == 0) { - AppendMenu(popup, MF_STRING | MF_DISABLED, 101, "Set as Focus"); - } else { - AppendMenu(popup, MF_STRING, 101, "Set as Focus"); - } - AppendMenu(popup, MF_STRING, 102, "Open Strip Chart"); - if (get_view().get_show_level()) { - AppendMenu(popup, MF_STRING | MF_DISABLED, 103, "Open Flame Graph"); - } else { - AppendMenu(popup, MF_STRING, 103, "Open Flame Graph"); - } - AppendMenu(popup, MF_STRING | MF_SEPARATOR, 0, nullptr); - AppendMenu(popup, MF_STRING, 104, "Change Color..."); - AppendMenu(popup, MF_STRING, 105, "Reset Color"); - TrackPopupMenu(popup, TPM_LEFTBUTTON, point.x, point.y, 0, _window, nullptr); - } -} - -/** - * Called when the mouse hovers over a label, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsStripChart:: -get_label_tooltip(int collector_index) const { - return PStatStripChart::get_label_tooltip(collector_index); -} - -/** - * Changes the collector represented by this strip chart. This may force a - * redraw. - */ -void WinStatsStripChart:: -set_collector_index(int collector_index) { - if (get_collector_index() != collector_index) { - PStatStripChart::set_collector_index(collector_index); - - if (is_title_unknown()) { - std::string window_title = get_title_text(); - if (!is_title_unknown()) { - SetWindowText(_window, window_title.c_str()); - } - } - - // Redraw the scale labels. - RECT rect; - GetClientRect(_window, &rect); - rect.left = _right_margin; - InvalidateRect(_window, &rect, TRUE); - } -} - -/** - * Changes the value the height of the vertical axis represents. This may - * force a redraw. - */ -void WinStatsStripChart:: -set_vertical_scale(double value_height) { - PStatStripChart::set_vertical_scale(value_height); - - RECT rect; - GetClientRect(_window, &rect); - rect.left = _right_margin; - InvalidateRect(_window, &rect, TRUE); -} - -/** - * Resets the list of labels. - */ -void WinStatsStripChart:: -update_labels() { - PStatStripChart::update_labels(); - - _label_stack.replace_labels(WinStatsGraph::_monitor, this, - _thread_index, _labels, false); - _labels_changed = false; -} - -/** - * Erases the chart area. - */ -void WinStatsStripChart:: -clear_region() { - RECT rect = { 0, 0, get_xsize(), get_ysize() }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); -} - -/** - * Should be overridden by the user class to copy a region of the chart from - * one part of the chart to another. This is used to implement scrolling. - */ -void WinStatsStripChart:: -copy_region(int start_x, int end_x, int dest_x) { - BitBlt(_bitmap_dc, dest_x, 0, - end_x - start_x, get_ysize(), - _bitmap_dc, start_x, 0, - SRCCOPY); - - // Also shift the brush origin over, so we still get proper dithering. - _brush_origin += (dest_x - start_x); - SetBrushOrgEx(_bitmap_dc, _brush_origin, 0, nullptr); - - RECT rect = { - dest_x, 0, dest_x + end_x - start_x, get_ysize() - }; - InvalidateRect(_graph_window, &rect, FALSE); -} - -/** - * Draws a single vertical slice of the strip chart, at the given pixel - * position, and corresponding to the indicated level data. - */ -void WinStatsStripChart:: -draw_slice(int x, int w, const PStatStripChart::FrameData &fdata) { - // Start by clearing the band first. - RECT rect = { x, 0, x + w, get_ysize() }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); - - double overall_time = 0.0; - int y = get_ysize(); - - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - overall_time += cd._net_value; - HBRUSH brush = get_collector_brush(cd._collector_index, cd._collector_index == _highlighted_index); - - if (overall_time > get_vertical_scale()) { - // Off the top. Go ahead and clamp it by hand, in case it's so far off - // the top we'd overflow the 16-bit pixel value. - rect.top = 0; - rect.bottom = y; - FillRect(_bitmap_dc, &rect, brush); - // And we can consider ourselves done now. - return; - } - - int top_y = height_to_pixel(overall_time); - rect.top = top_y; - rect.bottom = y; - FillRect(_bitmap_dc, &rect, brush); - y = top_y; - } -} - -/** - * Draws a single vertical slice of background color. - */ -void WinStatsStripChart:: -draw_empty(int x, int w) { - RECT rect = { x, 0, x + w, get_ysize() }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); -} - -/** - * Draws a single vertical slice of foreground color. - */ -void WinStatsStripChart:: -draw_cursor(int x) { - RECT rect = { x, 0, x + 1, get_ysize() }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH)); -} - -/** - * Should be overridden by the user class. This hook will be called after - * drawing a series of color bars in the strip chart; it gives the pixel range - * that was just redrawn. - */ -void WinStatsStripChart:: -end_draw(int from_x, int to_x) { - // Draw in the guide bars. - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - draw_guide_bar(_bitmap_dc, from_x, to_x, get_guide_bar(i)); - } - - RECT rect = { - from_x, 0, to_x + 1, get_ysize() - }; - InvalidateRect(_graph_window, &rect, FALSE); -} - -/** - * Returns the current window dimensions. - */ -bool WinStatsStripChart:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - WinStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void WinStatsStripChart:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - WinStatsGraph::set_window_state(x, y, width, height, maximized, minimized); - - // Set the state of the checkbox. - SendMessage(_smooth_check_box, BM_SETCHECK, get_average_mode() ? BST_CHECKED : BST_UNCHECKED, 0); -} - -/** - * - */ -LONG WinStatsStripChart:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDOWN: - if (_potential_drag_mode == DM_new_guide_bar) { - set_drag_mode(DM_new_guide_bar); - SetCapture(_graph_window); - return 0; - } - break; - - case WM_COMMAND: - switch (LOWORD(wparam)) { - case BN_CLICKED: - if ((HWND)lparam == _smooth_check_box) { - int result = SendMessage(_smooth_check_box, BM_GETCHECK, 0, 0); - set_average_mode(result == BST_CHECKED); - return 0; - } - break; - - case 101: - set_collector_index(_popup_index); - break; - - case 102: - WinStatsGraph::_monitor->open_strip_chart(get_thread_index(), _popup_index, - get_view().get_show_level()); - return 0; - - case 103: - WinStatsGraph::_monitor->open_flame_graph(get_thread_index(), _popup_index); - return 0; - - case 104: - WinStatsGraph::_monitor->choose_collector_color(_popup_index); - return 0; - - case 105: - WinStatsGraph::_monitor->reset_collector_color(_popup_index); - return 0; - } - break; - - default: - break; - } - - return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam); -} - -/** - * - */ -LONG WinStatsStripChart:: -graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDOWN: - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_scale); - int16_t y = HIWORD(lparam); - _drag_scale_start = pixel_to_height(y); - SetCapture(_graph_window); - return 0; - - } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) { - set_drag_mode(DM_guide_bar); - int16_t y = HIWORD(lparam); - _drag_start_y = y; - SetCapture(_graph_window); - return 0; - } - break; - - case WM_MOUSEMOVE: - if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { - // When the mouse is over a color bar, highlight it. - int16_t x = LOWORD(lparam); - int16_t y = HIWORD(lparam); - - int collector_index = get_collector_under_pixel(x, y); - _label_stack.highlight_label(collector_index); - on_enter_label(collector_index); - - // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph - // window. - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - _graph_window, - 0 - }; - TrackMouseEvent(&tme); - } - else { - // If the mouse is in some drag mode, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - } - - if (_drag_mode == DM_scale) { - int16_t y = HIWORD(lparam); - double ratio = 1.0 - ((double)y / (double)get_ysize()); - if (ratio > 0.0) { - double new_scale = _drag_scale_start / ratio; - if (!IS_NEARLY_EQUAL(get_vertical_scale(), new_scale)) { - // Disable smoothing while we do this expensive operation. - set_average_mode(false); - set_vertical_scale(_drag_scale_start / ratio); - } - } - return 0; - - } else if (_drag_mode == DM_new_guide_bar) { - // We haven't created the new guide bar yet; we won't until the mouse - // comes within the graph's region. - int16_t y = HIWORD(lparam); - if (y >= 0 && y < get_ysize()) { - set_drag_mode(DM_guide_bar); - _drag_guide_bar = add_user_guide_bar(pixel_to_height(y)); - return 0; - } - - } else if (_drag_mode == DM_guide_bar) { - int16_t y = HIWORD(lparam); - move_user_guide_bar(_drag_guide_bar, pixel_to_height(y)); - return 0; - } - break; - - case WM_MOUSELEAVE: - // When the mouse leaves the graph, stop highlighting. - _label_stack.highlight_label(-1); - on_leave_label(_highlighted_index); - break; - - case WM_LBUTTONUP: - if (_drag_mode == DM_scale) { - set_drag_mode(DM_none); - ReleaseCapture(); - return 0; - - } else if (_drag_mode == DM_guide_bar) { - int16_t y = HIWORD(lparam); - if (y < 0 || y >= get_ysize()) { - remove_user_guide_bar(_drag_guide_bar); - } else { - move_user_guide_bar(_drag_guide_bar, pixel_to_height(y)); - } - set_drag_mode(DM_none); - ReleaseCapture(); - return 0; - } - break; - - case WM_LBUTTONDBLCLK: - { - // Double-clicking on a color bar in the graph is the same as double- - // clicking on the corresponding label. - int16_t x = LOWORD(lparam); - int16_t y = HIWORD(lparam); - on_click_label(get_collector_under_pixel(x, y)); - return 0; - } - break; - - case WM_CONTEXTMENU: - { - POINT point; - if (GetCursorPos(&point) && ScreenToClient(_graph_window, &point)) { - int collector_index = get_collector_under_pixel(point.x, point.y); - if (collector_index >= 0) { - on_popup_label(collector_index); - } - } - return 0; - } - break; - - default: - break; - } - - return WinStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam); -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsStripChart:: -additional_window_paint(HDC hdc) { - // Draw in the labels for the guide bars. - SelectObject(hdc, WinStatsGraph::_monitor->get_font()); - SetTextAlign(hdc, TA_LEFT | TA_TOP); - SetBkMode(hdc, TRANSPARENT); - - RECT rect; - GetClientRect(_window, &rect); - int x = rect.right - _right_margin + _pixel_scale; - int last_y = -100; - - int i; - int num_guide_bars = get_num_guide_bars(); - for (i = 0; i < num_guide_bars; i++) { - last_y = draw_guide_label(hdc, x, get_guide_bar(i), last_y); - } - - GuideBar top_value = make_guide_bar(get_vertical_scale()); - draw_guide_label(hdc, x, top_value, last_y); - - last_y = -100; - int num_user_guide_bars = get_num_user_guide_bars(); - for (i = 0; i < num_user_guide_bars; i++) { - last_y = draw_guide_label(hdc, x, get_user_guide_bar(i), last_y); - } - - // Now draw the "net value" label at the top. - SetTextAlign(hdc, TA_RIGHT | TA_BOTTOM); - SetTextColor(hdc, RGB(0, 0, 0)); - TextOut(hdc, rect.right - _right_margin - _pixel_scale, _top_margin - _pixel_scale / 2, - _net_value_text.data(), _net_value_text.length()); -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsStripChart:: -additional_graph_window_paint(HDC hdc) { - int num_user_guide_bars = get_num_user_guide_bars(); - for (int i = 0; i < num_user_guide_bars; i++) { - draw_guide_bar(hdc, 0, get_xsize(), get_user_guide_bar(i)); - } -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsStripChart:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - if (_highlighted_index != -1) { - return get_label_tooltip(_highlighted_index); - } - return std::string(); -} - -/** - * Based on the mouse position within the window's client area, look for - * draggable things the mouse might be hovering over and return the - * apprioprate DragMode enum or DM_none if nothing is indicated. - */ -WinStatsGraph::DragMode WinStatsStripChart:: -consider_drag_start(int mouse_x, int mouse_y, int width, int height) { - if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) { - if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) { - // See if the mouse is over a user-defined guide bar. - int y = mouse_y - _graph_top; - double from_height = pixel_to_height(y + 2); - double to_height = pixel_to_height(y - 2); - _drag_guide_bar = find_user_guide_bar(from_height, to_height); - if (_drag_guide_bar >= 0) { - return DM_guide_bar; - } - - } else { - // The mouse is above or below the graph; maybe create a new guide bar. - return DM_new_guide_bar; - } - } - - return WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height); -} - -/** - * This should be called whenever the drag mode needs to change state. It - * provides hooks for a derived class to do something special. - */ -void WinStatsStripChart:: -set_drag_mode(WinStatsGraph::DragMode drag_mode) { - WinStatsGraph::set_drag_mode(drag_mode); - - if (_drag_mode == DM_none) { - // Restore smoothing according to the current setting of the check box. - int result = SendMessage(_smooth_check_box, BM_GETCHECK, 0, 0); - set_average_mode(result == BST_CHECKED); - } -} - -/** - * Repositions the graph child window within the parent window according to - * the _margin variables. - */ -void WinStatsStripChart:: -move_graph_window(int graph_left, int graph_top, int graph_xsize, int graph_ysize) { - WinStatsGraph::move_graph_window(graph_left, graph_top, graph_xsize, graph_ysize); - if (_smooth_check_box != 0) { - SIZE size; - SendMessage(_smooth_check_box, BCM_GETIDEALSIZE, 0, (LPARAM)&size); - - SetWindowPos(_smooth_check_box, 0, - _left_margin, _top_margin - size.cy - _pixel_scale / 2, - size.cx, size.cy, - SWP_NOZORDER | SWP_SHOWWINDOW); - InvalidateRect(_smooth_check_box, nullptr, TRUE); - } -} - -/** - * Draws the line for the indicated guide bar on the graph. - */ -void WinStatsStripChart:: -draw_guide_bar(HDC hdc, int from_x, int to_x, - const PStatGraph::GuideBar &bar) { - int y = height_to_pixel(bar._height); - - if (y > 0) { - // Only draw it if it's not too close to the top. - switch (bar._style) { - case GBS_target: - SelectObject(hdc, _light_pen); - break; - - case GBS_user: - SelectObject(hdc, _user_guide_bar_pen); - break; - - case GBS_normal: - SelectObject(hdc, _dark_pen); - break; - } - MoveToEx(hdc, from_x, y, nullptr); - LineTo(hdc, to_x + 1, y); - } -} - -/** - * Draws the text for the indicated guide bar label to the right of the graph, - * unless it would overlap with the indicated last label, whose top pixel - * value is given. Returns the top pixel value of the new label. - */ -int WinStatsStripChart:: -draw_guide_label(HDC hdc, int x, const PStatGraph::GuideBar &bar, int last_y) { - switch (bar._style) { - case GBS_target: - SetTextColor(hdc, _light_color); - break; - - case GBS_user: - SetTextColor(hdc, _user_guide_bar_color); - break; - - case GBS_normal: - SetTextColor(hdc, _dark_color); - break; - } - - int y = height_to_pixel(bar._height); - const std::string &label = bar._label; - SIZE size; - GetTextExtentPoint32(hdc, label.data(), label.length(), &size); - - if (bar._style != GBS_user) { - double from_height = pixel_to_height(y + size.cy); - double to_height = pixel_to_height(y - size.cy); - if (find_user_guide_bar(from_height, to_height) >= 0) { - // Omit the label: there's a user-defined guide bar in the same space. - return last_y; - } - } - - int this_y = _graph_top + y - size.cy / 2; - if (y >= 0 && y < get_ysize() && - (last_y < this_y || last_y > this_y + size.cy)) { - TextOut(hdc, x, this_y, - label.data(), label.length()); - last_y = this_y; - } - - return last_y; -} - - -/** - * Creates the window for this strip chart. - */ -void WinStatsStripChart:: -create_window() { - if (_window) { - return; - } - - HINSTANCE application = GetModuleHandle(nullptr); - register_window_class(application); - - std::string window_title = get_title_text(); - POINT window_pos = WinStatsGraph::_monitor->get_new_window_pos(); - - RECT win_rect = { - 0, 0, - _left_margin + get_xsize() + _right_margin, - _top_margin + get_ysize() + _bottom_margin - }; - - // compute window size based on desired client area size - AdjustWindowRect(&win_rect, graph_window_style, FALSE); - - _window = - CreateWindowEx(WS_EX_DLGMODALFRAME, _window_class_name, - window_title.c_str(), graph_window_style, - window_pos.x, window_pos.y, - win_rect.right - win_rect.left, - win_rect.bottom - win_rect.top, - WinStatsGraph::_monitor->get_window(), - nullptr, application, 0); - if (!_window) { - nout << "Could not create StripChart window!\n"; - exit(1); - } - - SetWindowLongPtr(_window, 0, (LONG_PTR)this); - setup_label_stack(); - - _smooth_check_box = - CreateWindow(WC_BUTTON, "Smooth", WS_CHILD | BS_AUTOCHECKBOX, - 0, 0, 0, 0, - _window, nullptr, application, 0); - SendMessage(_smooth_check_box, WM_SETFONT, - (WPARAM)WinStatsGraph::_monitor->get_font(), TRUE); - - if (get_average_mode()) { - SendMessage(_smooth_check_box, BM_SETCHECK, BST_CHECKED, 0); - } - - // Ensure that the window is on top of the stack. - SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); -} - -/** - * Registers the window class for the stripChart window, if it has not already - * been registered. - */ -void WinStatsStripChart:: -register_window_class(HINSTANCE application) { - if (_window_class_registered) { - return; - } - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(WNDCLASS)); - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = application; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszMenuName = nullptr; - wc.lpszClassName = _window_class_name; - - // Reserve space to associate the this pointer with the window. - wc.cbWndExtra = sizeof(WinStatsStripChart *); - - if (!RegisterClass(&wc)) { - nout << "Could not register StripChart window class!\n"; - exit(1); - } - - _window_class_registered = true; -} - -/** - * - */ -LONG WINAPI WinStatsStripChart:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - WinStatsStripChart *self = (WinStatsStripChart *)GetWindowLongPtr(hwnd, 0); - if (self != nullptr && self->_window == hwnd) { - return self->window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} diff --git a/pandatool/src/win-stats/winStatsStripChart.h b/pandatool/src/win-stats/winStatsStripChart.h deleted file mode 100644 index ac8728a1..00000000 --- a/pandatool/src/win-stats/winStatsStripChart.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsStripChart.h - * @author drose - * @date 2003-12-03 - */ - -#ifndef WINSTATSSTRIPCHART_H -#define WINSTATSSTRIPCHART_H - -#include "pandatoolbase.h" - -#include "winStatsGraph.h" -#include "pStatStripChart.h" -#include "pointerTo.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class WinStatsMonitor; - -/** - * A window that draws a strip chart, given a view. - */ -class WinStatsStripChart : public PStatStripChart, public WinStatsGraph { -public: - WinStatsStripChart(WinStatsMonitor *monitor, - int thread_index, int collector_index, bool show_level); - virtual ~WinStatsStripChart(); - - virtual void new_collector(int collector_index); - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - - virtual void set_time_units(int unit_mask); - virtual void set_scroll_speed(double scroll_speed); - virtual void on_click_label(int collector_index); - virtual void on_popup_label(int collector_index); - virtual std::string get_label_tooltip(int collector_index) const; - - void set_collector_index(int collector_index); - void set_vertical_scale(double value_height); - -protected: - virtual void update_labels(); - - virtual void clear_region(); - virtual void copy_region(int start_x, int end_x, int dest_x); - virtual void draw_slice(int x, int w, - const PStatStripChart::FrameData &fdata); - virtual void draw_empty(int x, int w); - virtual void draw_cursor(int x); - virtual void end_draw(int from_x, int to_x); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual LONG graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual void additional_window_paint(HDC hdc); - virtual void additional_graph_window_paint(HDC hdc); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int mouse_x, int mouse_y, - int width, int height); - virtual void set_drag_mode(DragMode drag_mode); - virtual void move_graph_window(int graph_left, int graph_top, - int graph_xsize, int graph_ysize); - -private: - void draw_guide_bar(HDC hdc, int from_x, int to_x, const GuideBar &bar); - int draw_guide_label(HDC hdc, int x, const GuideBar &bar, int last_y); - void create_window(); - static void register_window_class(HINSTANCE application); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - int _brush_origin; - std::string _net_value_text; - - HWND _smooth_check_box; - int _popup_index = -1; - - static bool _window_class_registered; - static const char * const _window_class_name; -}; - -#endif diff --git a/pandatool/src/win-stats/winStatsTimeline.cxx b/pandatool/src/win-stats/winStatsTimeline.cxx deleted file mode 100644 index a9c3f668..00000000 --- a/pandatool/src/win-stats/winStatsTimeline.cxx +++ /dev/null @@ -1,805 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsTimeline.cxx - * @author rdb - * @date 2022-02-11 - */ - -#include "winStatsTimeline.h" -#include "winStatsMonitor.h" -#include "numeric_types.h" - -static const int default_timeline_width = 1000; -static const int default_timeline_height = 500; - -bool WinStatsTimeline::_window_class_registered = false; -const char * const WinStatsTimeline::_window_class_name = "timeline"; - -/** - * - */ -WinStatsTimeline:: -WinStatsTimeline(WinStatsMonitor *monitor) : - PStatTimeline(monitor, - monitor->get_pixel_scale() * default_timeline_width / 4, - monitor->get_pixel_scale() * default_timeline_height / 4), - WinStatsGraph(monitor) -{ - _left_margin = _pixel_scale * 24; - _right_margin = _pixel_scale * 2; - _top_margin = _pixel_scale * 5; - _bottom_margin = _pixel_scale * 2; - - normal_guide_bars(); - - create_window(); - clear_region(); - - _grid_brush = CreateSolidBrush(RGB(0xdd, 0xdd, 0xdd)); -} - -/** - * - */ -WinStatsTimeline:: -~WinStatsTimeline() { -} - -/** - * Called as each frame's data is made available. There is no guarantee the - * frames will arrive in order, or that all of them will arrive at all. The - * monitor should be prepared to accept frames received out-of-order or - * missing. - */ -void WinStatsTimeline:: -new_data(int thread_index, int frame_number) { - PStatTimeline::new_data(thread_index, frame_number); -} - -/** - * Called when it is necessary to redraw the entire graph. - */ -void WinStatsTimeline:: -force_redraw() { - PStatTimeline::force_redraw(); -} - -/** - * Called when the user has resized the window, forcing a resize of the graph. - */ -void WinStatsTimeline:: -changed_graph_size(int graph_xsize, int graph_ysize) { - PStatTimeline::changed_size(graph_xsize, graph_ysize); -} - -/** - * Erases the chart area. - */ -void WinStatsTimeline:: -clear_region() { - RECT rect = { 0, 0, get_xsize(), get_ysize() }; - FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); -} - -/** - * Erases the chart area in preparation for drawing a bunch of bars. - */ -void WinStatsTimeline:: -begin_draw() { - SelectObject(_bitmap_dc, WinStatsGraph::_monitor->get_font()); - SelectObject(_bitmap_dc, GetStockObject(NULL_PEN)); - SetBkMode(_bitmap_dc, TRANSPARENT); - SetTextAlign(_bitmap_dc, TA_LEFT | TA_TOP | TA_NOUPDATECP); -} - -/** - * Draws a horizontal separator. - */ -void WinStatsTimeline:: -draw_separator(int row) { - int y = (row_to_pixel(row) + row_to_pixel(row + 1)) / 2; - RECT rect = {0, y, get_xsize(), y + _pixel_scale / 3}; - FillRect(_bitmap_dc, &rect, _grid_brush); -} - -/** - * Draws a vertical guide bar. If the row is -1, draws it in all rows. - */ -void WinStatsTimeline:: -draw_guide_bar(int x, GuideBarStyle style) { - int x1 = x - _pixel_scale / 6; - int x2 = x1 + _pixel_scale / 3; - if (style == GBS_frame) { - ++x2; - } - RECT rect = {x1, 0, x2, get_ysize()}; - FillRect(_bitmap_dc, &rect, _grid_brush); -} - -/** - * Draws a single bar in the chart for the indicated row, in the color for the - * given collector, for the indicated horizontal pixel range. - */ -void WinStatsTimeline:: -draw_bar(int row, int from_x, int to_x, int collector_index, - const std::string &collector_name) { - - int top = row_to_pixel(row); - int bottom = row_to_pixel(row + 1); - - bool is_highlighted = row == _highlighted_row && _highlighted_x >= from_x && _highlighted_x < to_x; - HBRUSH brush = get_collector_brush(collector_index, is_highlighted); - - if (to_x < from_x + 2) { - // It's just a tiny sliver. This is a more reliable way to draw it. - RECT rect = {from_x, top + 1, from_x + 1, bottom - 1}; - FillRect(_bitmap_dc, &rect, brush); - - //if (to_x <= from_x + 2) { - // // Draw an arrow pointing to it, if it's so small. - // POINT vertices[] = {{to_x, bottom}, {to_x - _pixel_scale, bottom + _pixel_scale * 2}, {to_x + _pixel_scale, bottom + _pixel_scale * 2}}; - // Polygon(_bitmap_dc, vertices, 3); - //} - } - else { - SelectObject(_bitmap_dc, brush); - RoundRect(_bitmap_dc, - std::max(from_x, -_pixel_scale - 1), - top, - std::min(std::max(to_x, from_x + 1), get_xsize() + _pixel_scale), - bottom, - _pixel_scale, - _pixel_scale); - - if ((to_x - from_x) >= _pixel_scale * 4) { - // Only bother drawing the text if we've got some space to draw on. - // Choose a suitable foreground color. - SetTextColor(_bitmap_dc, get_collector_text_color(collector_index, is_highlighted)); - - // Make sure that the text doesn't run off the chart. - SIZE size; - GetTextExtentPoint32(_bitmap_dc, collector_name.data(), collector_name.size(), &size); - int center = (from_x + to_x) / 2; - int left = std::max(from_x, 0) + _pixel_scale / 2; - int right = std::min(to_x, get_xsize()) - _pixel_scale / 2; - - if (size.cx >= right - left) { - if (right - left < _pixel_scale * 6) { - // It's a really tiny space. Draw a single letter. - RECT rect = {left, top, right, bottom}; - DrawText(_bitmap_dc, collector_name.data(), 1, - &rect, DT_CENTER | DT_SINGLELINE | DT_VCENTER); - } else { - // It's going to be tricky to fit it, let Windows figure it out via - // the more expensive DrawText call. - RECT rect = {left, top, right, bottom}; - DrawText(_bitmap_dc, collector_name.data(), collector_name.size(), - &rect, DT_CENTER | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER); - } - } - else { - int text_top = top + (bottom - top - size.cy) / 2; - if (center - size.cx / 2 < 0) { - // Put it against the left-most edge. - TextOut(_bitmap_dc, _pixel_scale, text_top, - collector_name.data(), collector_name.length()); - } - else if (center + size.cx / 2 >= get_xsize()) { - // Put it against the right-most edge. - TextOut(_bitmap_dc, get_xsize() - _pixel_scale - size.cx, text_top, - collector_name.data(), collector_name.length()); - } - else { - // It fits just fine, center it. - TextOut(_bitmap_dc, center - size.cx / 2, text_top, - collector_name.data(), collector_name.length()); - } - } - } - } -} - -/** - * Called after all the bars have been drawn, this triggers a refresh event to - * draw it to the window. - */ -void WinStatsTimeline:: -end_draw() { - InvalidateRect(_graph_window, nullptr, FALSE); - - if (_threads_changed) { - RECT rect; - GetClientRect(_window, &rect); - rect.top = _top_margin; - rect.right = _left_margin; - InvalidateRect(_window, &rect, TRUE); - _threads_changed = false; - } - - if (_guide_bars_changed) { - RECT rect; - GetClientRect(_window, &rect); - rect.bottom = _top_margin; - InvalidateRect(_window, &rect, TRUE); - _guide_bars_changed = false; - } -} - -/** - * Called at the end of the draw cycle. - */ -void WinStatsTimeline:: -idle() { -} - -/** - * Overridden by a derived class to implement an animation. If it returns - * false, the animation timer is stopped. - */ -bool WinStatsTimeline:: -animate(double time, double dt) { - return PStatTimeline::animate(time, dt); -} - -/** - * Returns the current window dimensions. - */ -bool WinStatsTimeline:: -get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const { - WinStatsGraph::get_window_state(x, y, width, height, maximized, minimized); - return true; -} - -/** - * Called to restore the graph window to its previous dimensions. - */ -void WinStatsTimeline:: -set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized) { - WinStatsGraph::set_window_state(x, y, width, height, maximized, minimized); -} - -/** - * - */ -LONG WinStatsTimeline:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_MOUSELEAVE: - SetFocus(nullptr); - break; - - default: - break; - } - - return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam); -} - -/** - * - */ -LONG WinStatsTimeline:: -graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_LBUTTONDOWN: - if (_potential_drag_mode == DM_none) { - set_drag_mode(DM_pan); - int16_t x = LOWORD(lparam); - _drag_start_x = x; - _scroll_speed = 0.0; - _zoom_center = pixel_to_timestamp(x); - SetCapture(_graph_window); - return 0; - } - break; - - case WM_MOUSEMOVE: - // Make sure we can accept keyboard events, except if we're inactive. - if (GetActiveWindow() == _window) { - SetFocus(hwnd); - } - - if (_drag_mode == DM_none && _potential_drag_mode == DM_none) { - // When the mouse is over a color bar, highlight it. - int x = LOWORD(lparam); - int y = HIWORD(lparam); - double time = pixel_to_timestamp(x); - - int row = pixel_to_row(y); - - if (row != _highlighted_row) { - clear_graph_tooltip(); - } - else if (_highlighted_row >= 0) { - // Is the mouse on the same bar? If not, clear the tooltip. - ColorBar bar; - if (find_bar(row, x, bar)) { - double prev_time = pixel_to_timestamp(_highlighted_x); - if (prev_time < bar._start || prev_time > bar._end) { - clear_graph_tooltip(); - } - } else { - clear_graph_tooltip(); - } - } - - std::swap(_highlighted_x, x); - std::swap(_highlighted_row, row); - - if (row >= 0) { - PStatTimeline::force_redraw(row, x, x); - } - PStatTimeline::force_redraw(_highlighted_row, _highlighted_x, _highlighted_x); - - if ((_keys_held & (F_w | F_s)) != 0) { - // Update the zoom center if we move the mouse while zooming with the - // keyboard. - _zoom_center = time; - } - - // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph - // window. - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - _graph_window, - 0 - }; - TrackMouseEvent(&tme); - } - else { - // If the mouse is in some drag mode, stop highlighting. - if (_highlighted_row != -1) { - int row = _highlighted_row; - _highlighted_row = -1; - PStatTimeline::force_redraw(row, _highlighted_x, _highlighted_x); - clear_graph_tooltip(); - } - } - - if (_drag_mode == DM_pan) { - int16_t x = LOWORD(lparam); - int delta = _drag_start_x - x; - set_horizontal_scroll(get_horizontal_scroll() + pixel_to_height(delta)); - _drag_start_x = x; - return 0; - } - break; - - case WM_MOUSELEAVE: - // When the mouse leaves the graph, stop highlighting. - if (_highlighted_row != -1) { - int row = _highlighted_row; - _highlighted_row = -1; - PStatTimeline::force_redraw(row, _highlighted_x, _highlighted_x); - clear_graph_tooltip(); - } - SetFocus(nullptr); - break; - - case WM_LBUTTONUP: - if (_drag_mode == DM_pan) { - set_drag_mode(DM_none); - ReleaseCapture(); - return 0; - } - break; - - case WM_LBUTTONDBLCLK: - { - // Double-clicking on a color bar in the graph will zoom the graph into - // that collector. - int16_t x = LOWORD(lparam); - int16_t y = HIWORD(lparam); - int row = pixel_to_row(y); - ColorBar bar; - if (find_bar(row, x, bar)) { - double width = bar._end - bar._start; - zoom_to(width * 1.5, pixel_to_timestamp(x)); - scroll_to(bar._start - width / 4.0); - } else { - // Double-clicking the white area zooms out. - _zoom_speed -= 100.0; - } - start_animation(); - return 0; - } - break; - - case WM_CONTEXTMENU: - { - // Right-clicking a color bar brings up a context menu. - POINT point; - if (GetCursorPos(&point)) { - POINT graph_point = point; - if (ScreenToClient(_graph_window, &graph_point)) { - int row = pixel_to_row(graph_point.y); - ColorBar bar; - if (find_bar(row, graph_point.x, bar)) { - _popup_bar = bar; - - HMENU popup = CreatePopupMenu(); - - std::string label = get_bar_tooltip(row, graph_point.x); - if (!label.empty()) { - AppendMenu(popup, MF_STRING | MF_DISABLED, 0, label.c_str()); - } - AppendMenu(popup, MF_STRING, 101, "Zoom To"); - AppendMenu(popup, MF_STRING, 102, "Open Strip Chart"); - AppendMenu(popup, MF_STRING, 103, "Open Flame Graph"); - AppendMenu(popup, MF_STRING, 104, "Open Piano Roll"); - AppendMenu(popup, MF_STRING | MF_SEPARATOR, 0, nullptr); - AppendMenu(popup, MF_STRING, 105, "Change Color..."); - AppendMenu(popup, MF_STRING, 106, "Reset Color"); - TrackPopupMenu(popup, TPM_LEFTBUTTON, point.x, point.y, 0, _graph_window, nullptr); - } - } - } - return 0; - } - break; - - case WM_COMMAND: - switch (LOWORD(wparam)) { - case 101: - { - double width = _popup_bar._end - _popup_bar._start; - zoom_to(width * 1.5, (_popup_bar._end + _popup_bar._start) / 2.0); - scroll_to(_popup_bar._start - width / 4.0); - start_animation(); - } - return 0; - - case 102: - WinStatsGraph::_monitor->open_strip_chart(_popup_bar._thread_index, _popup_bar._collector_index, false); - return 0; - - case 103: - WinStatsGraph::_monitor->open_flame_graph(_popup_bar._thread_index, _popup_bar._collector_index, _popup_bar._frame_number); - return 0; - - case 104: - WinStatsGraph::_monitor->open_piano_roll(_popup_bar._thread_index); - return 0; - - case 105: - WinStatsGraph::_monitor->choose_collector_color(_popup_bar._collector_index); - return 0; - - case 106: - WinStatsGraph::_monitor->reset_collector_color(_popup_bar._collector_index); - return 0; - } - break; - - case WM_MOUSEWHEEL: - { - if (GET_KEYSTATE_WPARAM(wparam) & MK_CONTROL) { - // Zoom in/out around the cursor position. - POINT point; - if (GetCursorPos(&point) && ScreenToClient(_graph_window, &point)) { - int delta = GET_WHEEL_DELTA_WPARAM(wparam); - zoom_by(delta / 120.0, pixel_to_timestamp(point.x)); - start_animation(); - } - } else { - int delta = GET_WHEEL_DELTA_WPARAM(wparam); - delta = (delta * _pixel_scale * 5) / 120; - int new_scroll = _scroll - delta; - if (_threads.empty()) { - new_scroll = 0; - } else { - new_scroll = (std::min)(new_scroll, get_num_rows() * _pixel_scale * 5 + _pixel_scale * 2 - get_ysize()); - new_scroll = (std::max)(new_scroll, 0); - } - delta = new_scroll - _scroll; - if (delta != 0) { - _scroll = new_scroll; - _threads_changed = true; - PStatTimeline::force_redraw(); - } - } - return 0; - } - break; - - case WM_MOUSEHWHEEL: - { - int delta = GET_WHEEL_DELTA_WPARAM(wparam); - _scroll_speed += delta / 12.0; - start_animation(); - return 0; - } - break; - - case WM_KEYDOWN: - case WM_KEYUP: - { - int flag = 0; - int vsc = (lparam & 0xff0000) >> 16; - if ((lparam & 0x1000000) == 0) { - // Accept WASD based on their position rather than their mapping - switch (vsc) { - case 17: - flag = F_w; - break; - case 30: - flag = F_a; - break; - case 31: - flag = F_s; - break; - case 32: - flag = F_d; - break; - } - } - if (flag == 0) { - switch (wparam) { - case VK_LEFT: - flag = F_left; - break; - case VK_RIGHT: - flag = F_right; - break; - case 'W': - flag = F_w; - break; - case 'A': - flag = F_a; - break; - case 'S': - flag = F_s; - break; - case 'D': - flag = F_d; - break; - } - } - if (flag != 0) { - if (msg == WM_KEYDOWN) { - if (flag & (F_w | F_s)) { - POINT point; - if (GetCursorPos(&point) && ScreenToClient(_graph_window, &point)) { - _zoom_center = pixel_to_timestamp(point.x); - } else { - _zoom_center = get_horizontal_scroll() + get_horizontal_scale() / 2.0; - } - } - if (_keys_held == 0) { - start_animation(); - } - _keys_held |= flag; - } - else if (_keys_held != 0) { - _keys_held &= ~flag; - } - } - } - break; - - case WM_KILLFOCUS: - _keys_held = 0; - break; - - default: - break; - } - - return WinStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam); -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsTimeline:: -additional_window_paint(HDC hdc) { - // Draw in the labels for the guide bars. - SelectObject(hdc, WinStatsGraph::_monitor->get_font()); - SetTextAlign(hdc, TA_LEFT | TA_BOTTOM); - SetBkMode(hdc, TRANSPARENT); - - int y = _top_margin - 2; - - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; ++i) { - draw_guide_label(hdc, y, get_guide_bar(i)); - } - - SetTextColor(hdc, _dark_color); - SetTextAlign(hdc, TA_LEFT | TA_TOP | TA_NOUPDATECP); - - for (const ThreadRow &thread_row : _threads) { - if (thread_row._visible) { - draw_thread_label(hdc, thread_row); - } - } -} - -/** - * This is called during the servicing of WM_PAINT; it gives a derived class - * opportunity to do some further painting into the window (the outer window, - * not the graph window). - */ -void WinStatsTimeline:: -additional_graph_window_paint(HDC hdc) { -} - -/** - * Called when the mouse hovers over the graph, and should return the text that - * should appear on the tooltip. - */ -std::string WinStatsTimeline:: -get_graph_tooltip(int mouse_x, int mouse_y) const { - return PStatTimeline::get_bar_tooltip(pixel_to_row(mouse_y), mouse_x); -} - -/** - * Based on the mouse position within the window's client area, look for - * draggable things the mouse might be hovering over and return the - * apprioprate DragMode enum or DM_none if nothing is indicated. - */ -WinStatsGraph::DragMode WinStatsTimeline:: -consider_drag_start(int mouse_x, int mouse_y, int width, int height) { - DragMode mode = WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height); - if (mode == DM_right_margin) { - mode = DM_none; - } - return mode; -} - -/** - * Draws the text for the indicated guide bar label at the top of the graph. - */ -void WinStatsTimeline:: -draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar) { - const std::string &label = bar._label; - if (label.empty()) { - return; - } - - bool center = true; - switch (bar._style) { - case GBS_target: - SetTextColor(hdc, _light_color); - break; - - case GBS_user: - SetTextColor(hdc, _user_guide_bar_color); - break; - - case GBS_normal: - SetTextColor(hdc, _light_color); - break; - - case GBS_frame: - SetTextColor(hdc, _dark_color); - center = false; - break; - } - - int x = timestamp_to_pixel(bar._height); - SIZE size; - GetTextExtentPoint32(hdc, label.data(), label.length(), &size); - - int this_x = _graph_left + x; - if (center) { - this_x -= size.cx / 2; - } - if (x >= 0 && x < get_xsize()) { - TextOut(hdc, this_x, y, - label.data(), label.length()); - } -} - -/** - * Draws the text for the indicated thread on the side of the graph. - */ -void WinStatsTimeline:: -draw_thread_label(HDC hdc, const ThreadRow &thread_row) { - int top = row_to_pixel(thread_row._row_offset + 1); - int bottom = row_to_pixel(thread_row._row_offset + 2); - - RECT rect = {_pixel_scale * 2, top, _left_margin - _pixel_scale * 2, bottom}; - DrawText(hdc, thread_row._label.data(), thread_row._label.size(), - &rect, DT_RIGHT | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER); -} - -/** - * Creates the window for this strip chart. - */ -void WinStatsTimeline:: -create_window() { - if (_window) { - return; - } - - HINSTANCE application = GetModuleHandle(nullptr); - register_window_class(application); - - POINT window_pos = WinStatsGraph::_monitor->get_new_window_pos(); - - RECT win_rect = { - 0, 0, - _left_margin + get_xsize() + _right_margin, - _top_margin + get_ysize() + _bottom_margin - }; - - // compute window size based on desired client area size - AdjustWindowRect(&win_rect, graph_window_style, FALSE); - - _window = - CreateWindowEx(WS_EX_DLGMODALFRAME, _window_class_name, - "Timeline", graph_window_style, - window_pos.x, window_pos.y, - win_rect.right - win_rect.left, - win_rect.bottom - win_rect.top, - WinStatsGraph::_monitor->get_window(), nullptr, application, 0); - if (!_window) { - nout << "Could not create timeline window!\n"; - exit(1); - } - - SetWindowLongPtr(_window, 0, (LONG_PTR)this); - - // Ensure that the window is on top of the stack. - SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - - SetFocus(_window); -} - -/** - * Registers the window class for the Timeline window, if it has not already - * been registered. - */ -void WinStatsTimeline:: -register_window_class(HINSTANCE application) { - if (_window_class_registered) { - return; - } - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(WNDCLASS)); - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = application; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = (HBRUSH)COLOR_WINDOW; - wc.lpszMenuName = nullptr; - wc.lpszClassName = _window_class_name; - - // Reserve space to associate the this pointer with the window. - wc.cbWndExtra = sizeof(WinStatsTimeline *); - - if (!RegisterClass(&wc)) { - nout << "Could not register Timeline window class!\n"; - exit(1); - } - - _window_class_registered = true; -} - -/** - * - */ -LONG WINAPI WinStatsTimeline:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - WinStatsTimeline *self = (WinStatsTimeline *)GetWindowLongPtr(hwnd, 0); - if (self != nullptr && self->_window == hwnd) { - return self->window_proc(hwnd, msg, wparam, lparam); - } else { - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} diff --git a/pandatool/src/win-stats/winStatsTimeline.h b/pandatool/src/win-stats/winStatsTimeline.h deleted file mode 100644 index 8c66b2b1..00000000 --- a/pandatool/src/win-stats/winStatsTimeline.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file winStatsTimeline.h - * @author rdb - * @date 2022-02-11 - */ - -#ifndef WINSTATSTIMELINE_H -#define WINSTATSTIMELINE_H - -#include "pandatoolbase.h" - -#include "winStatsGraph.h" -#include "pStatTimeline.h" - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN 1 -#endif -#include - -class WinStatsMonitor; - -/** - * A window that draws all of the start/stop event pairs on each thread on a - * horizontal scrolling timeline, with concurrent start/stop pairs stacked - * underneath each other. - */ -class WinStatsTimeline : public PStatTimeline, public WinStatsGraph { -public: - WinStatsTimeline(WinStatsMonitor *monitor); - virtual ~WinStatsTimeline(); - - virtual void new_data(int thread_index, int frame_number); - virtual void force_redraw(); - virtual void changed_graph_size(int graph_xsize, int graph_ysize); - -protected: - virtual void clear_region(); - virtual void begin_draw(); - virtual void draw_separator(int row); - virtual void draw_guide_bar(int x, GuideBarStyle style); - virtual void draw_bar(int row, int from_x, int to_x, int collector_index, - const std::string &collector_name); - virtual void end_draw(); - virtual void idle(); - - virtual bool animate(double time, double dt); - - virtual bool get_window_state(int &x, int &y, int &width, int &height, - bool &maximized, bool &minimized) const; - virtual void set_window_state(int x, int y, int width, int height, - bool maximized, bool minimized); - - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual LONG graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - virtual void additional_window_paint(HDC hdc); - virtual void additional_graph_window_paint(HDC hdc); - virtual std::string get_graph_tooltip(int mouse_x, int mouse_y) const; - virtual DragMode consider_drag_start(int mouse_x, int mouse_y, - int width, int height); - -private: - void draw_guide_label(HDC hdc, int y, const GuideBar &bar); - void draw_thread_label(HDC hdc, const ThreadRow &thread_row); - - void create_window(); - static void register_window_class(HINSTANCE application); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - int row_to_pixel(int y) const { - return y * _pixel_scale * 5 + _pixel_scale - _scroll; - } - int pixel_to_row(int y) const { - return (y + _scroll - _pixel_scale) / (_pixel_scale * 5); - } - - static bool _window_class_registered; - static const char * const _window_class_name; - - HBRUSH _grid_brush; - - int _highlighted_row = -1; - int _highlighted_x = 0; - int _scroll = 0; - ColorBar _popup_bar; -}; - -#endif diff --git a/pandatool/src/win-stats/winstats_composite1.cxx b/pandatool/src/win-stats/winstats_composite1.cxx deleted file mode 100644 index ef632802..00000000 --- a/pandatool/src/win-stats/winstats_composite1.cxx +++ /dev/null @@ -1,11 +0,0 @@ -#include "winStats.cxx" -#include "winStatsChartMenu.cxx" -#include "winStatsFlameGraph.cxx" -#include "winStatsGraph.cxx" -#include "winStatsLabel.cxx" -#include "winStatsLabelStack.cxx" -#include "winStatsMonitor.cxx" -#include "winStatsPianoRoll.cxx" -#include "winStatsTimeline.cxx" -#include "winStatsServer.cxx" -#include "winStatsStripChart.cxx" diff --git a/pandatool/src/xfile/CMakeLists.txt b/pandatool/src/xfile/CMakeLists.txt deleted file mode 100644 index 1768ef35..00000000 --- a/pandatool/src/xfile/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -set(P3XFILE_HEADERS - config_xfile.h - standard_templates.h - windowsGuid.h windowsGuid.I - xFileArrayDef.h xFileArrayDef.I - xFileDataDef.h xFileDataDef.I - xFileDataNode.h xFileDataNode.I - xFileDataNodeReference.h xFileDataNodeReference.I - xFileDataNodeTemplate.h xFileDataNodeTemplate.I - xFileDataObjectArray.h xFileDataObjectArray.I - xFileDataObjectDouble.h xFileDataObjectDouble.I - xFileDataObject.h xFileDataObject.I - xFileDataObjectInteger.h xFileDataObjectInteger.I - xFileDataObjectString.h xFileDataObjectString.I - xFile.h xFile.I - xFileNode.h xFileNode.I - xFileParseData.h xFileParseData.I - xFileTemplate.h xFileTemplate.I - xLexerDefs.h - xParserDefs.h -) - -set(P3XFILE_SOURCES - config_xfile.cxx - standard_templates.cxx - windowsGuid.cxx - xFileArrayDef.cxx - xFile.cxx - xFileDataDef.cxx - xFileDataNode.cxx - xFileDataNodeReference.cxx - xFileDataNodeTemplate.cxx - xFileDataObjectArray.cxx - xFileDataObject.cxx - xFileDataObjectDouble.cxx - xFileDataObjectInteger.cxx - xFileDataObjectString.cxx - xFileNode.cxx - xFileParseData.cxx - xFileTemplate.cxx -) - -set(P3XFILE_PARSER_SOURCES - xParser.cxx - xLexer.cxx -) - -add_bison_target(xParser.cxx xParser.yxx DEFINES xParser.h PREFIX xyy) -add_flex_target(xLexer.cxx xLexer.lxx CASE_INSENSITIVE PREFIX xyy) - -composite_sources(p3xfile P3XFILE_SOURCES) -add_library(p3xfile STATIC ${P3XFILE_HEADERS} ${P3XFILE_SOURCES} ${P3XFILE_PARSER_SOURCES}) -target_link_libraries(p3xfile p3pandatoolbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/xfile/config_xfile.cxx b/pandatool/src/xfile/config_xfile.cxx deleted file mode 100644 index b3f878c0..00000000 --- a/pandatool/src/xfile/config_xfile.cxx +++ /dev/null @@ -1,68 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_xfile.cxx - * @author drose - * @date 2000-08-24 - */ - -#include "config_xfile.h" -#include "xFile.h" -#include "xFileDataDef.h" -#include "xFileDataObject.h" -#include "xFileDataObjectArray.h" -#include "xFileDataObjectDouble.h" -#include "xFileDataObjectInteger.h" -#include "xFileDataObjectString.h" -#include "xFileDataNode.h" -#include "xFileDataNodeReference.h" -#include "xFileDataNodeTemplate.h" -#include "xFileNode.h" -#include "xFileTemplate.h" - -#include "dconfig.h" - -Configure(config_xfile); -NotifyCategoryDef(xfile, ""); - -// This is set true, typically by the user's command-line options, to indicate -// that when a X file is generated it should include all geometry in one big -// mesh, instead of preserving the hierarchy from the source egg file. -bool xfile_one_mesh = false; - -ConfigureFn(config_xfile) { - init_libxfile(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libxfile() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - XFile::init_type(); - XFileDataDef::init_type(); - XFileDataObject::init_type(); - XFileDataObjectArray::init_type(); - XFileDataObjectDouble::init_type(); - XFileDataObjectInteger::init_type(); - XFileDataObjectString::init_type(); - XFileDataNode::init_type(); - XFileDataNodeReference::init_type(); - XFileDataNodeTemplate::init_type(); - XFileNode::init_type(); - XFileTemplate::init_type(); -} diff --git a/pandatool/src/xfile/config_xfile.h b/pandatool/src/xfile/config_xfile.h deleted file mode 100644 index 770d058f..00000000 --- a/pandatool/src/xfile/config_xfile.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file config_xfile.h - * @author drose - * @date 2001-06-22 - */ - -#ifndef CONFIG_XFILE_H -#define CONFIG_XFILE_H - -#include "pandatoolbase.h" - -#include "notifyCategoryProxy.h" - -NotifyCategoryDeclNoExport(xfile); - -extern bool xfile_one_mesh; - -extern void init_libxfile(); - -#endif diff --git a/pandatool/src/xfile/p3xfile_composite1.cxx b/pandatool/src/xfile/p3xfile_composite1.cxx deleted file mode 100644 index 3a4f74d9..00000000 --- a/pandatool/src/xfile/p3xfile_composite1.cxx +++ /dev/null @@ -1,17 +0,0 @@ -#include "config_xfile.cxx" -#include "standard_templates.cxx" -#include "windowsGuid.cxx" -#include "xFile.cxx" -#include "xFileArrayDef.cxx" -#include "xFileDataDef.cxx" -#include "xFileDataNode.cxx" -#include "xFileDataNodeReference.cxx" -#include "xFileDataNodeTemplate.cxx" -#include "xFileDataObject.cxx" -#include "xFileDataObjectArray.cxx" -#include "xFileDataObjectDouble.cxx" -#include "xFileDataObjectInteger.cxx" -#include "xFileDataObjectString.cxx" -#include "xFileNode.cxx" -#include "xFileParseData.cxx" -#include "xFileTemplate.cxx" diff --git a/pandatool/src/xfile/standardTemplates.x b/pandatool/src/xfile/standardTemplates.x deleted file mode 100644 index 20199a32..00000000 --- a/pandatool/src/xfile/standardTemplates.x +++ /dev/null @@ -1,274 +0,0 @@ -xof 0303txt 0032 - -# This file contains the standard template definitions for Direct3D -# Retained Mode. I extracted these from the DirectX API via something -# like the following code: -# -# #include -# -# LPDIRECTXFILE dx_file; -# LPDIRECTXFILESAVEOBJECT dx_file_save; -# HRESULT hr; -# -# hr = DirectXFileCreate(&dx_file); -# hr = dx_file->RegisterTemplates(D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES); -# hr = dx_file->CreateSaveObject("filename.x", DXFILEFORMAT_TEXT, -# &dx_file_save); -# static const GUID *temps[] = { -# &TID_D3DRMInfo, -# &TID_D3DRMMesh, -# &TID_D3DRMVector, -# ... -# }; -# static const int num_temps = sizeof(temps) / sizeof(temps[0]); -# hr = dx_file_save->SaveTemplates(num_temps, temps); -# - - -template Header { - <3d82ab43-62da-11cf-ab39-0020af71e433> - WORD major; - WORD minor; - DWORD flags; -} - -template Vector { - <3d82ab5e-62da-11cf-ab39-0020af71e433> - FLOAT x; - FLOAT y; - FLOAT z; -} - -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 ColorRGBA { - <35ff44e0-6c7c-11cf-8f52-0040333594a3> - FLOAT red; - FLOAT green; - FLOAT blue; - FLOAT alpha; -} - -template ColorRGB { - - FLOAT red; - FLOAT green; - FLOAT blue; -} - -template Material { - <3d82ab4d-62da-11cf-ab39-0020af71e433> - ColorRGBA faceColor; - FLOAT power; - ColorRGB specularColor; - ColorRGB emissiveColor; - [...] -} - -template Frame { - <3d82ab46-62da-11cf-ab39-0020af71e433> - [...] -} - -template Matrix4x4 { - - array FLOAT matrix[16]; -} - -template FrameTransformMatrix { - - Matrix4x4 frameMatrix; -} - -template MeshMaterialList { - - DWORD nMaterials; - DWORD nFaceIndexes; - array DWORD faceIndexes[nFaceIndexes]; - [Material <3d82ab4d-62da-11cf-ab39-0020af71e433>] -} - -template Coords2d { - - FLOAT u; - FLOAT v; -} - -template MeshTextureCoords { - - DWORD nTextureCoords; - array Coords2d textureCoords[nTextureCoords]; -} - -template MeshNormals { - - DWORD nNormals; - array Vector normals[nNormals]; - DWORD nFaceNormals; - array MeshFace faceNormals[nFaceNormals]; -} - -template Animation { - <3d82ab4f-62da-11cf-ab39-0020af71e433> - [...] -} - -template AnimationSet { - <3d82ab50-62da-11cf-ab39-0020af71e433> - [Animation <3d82ab4f-62da-11cf-ab39-0020af71e433>] -} - -template FloatKeys { - <10dd46a9-775b-11cf-8f52-0040333594a3> - DWORD nValues; - array FLOAT values[nValues]; -} - -template TimedFloatKeys { - - DWORD time; - FloatKeys tfkeys; -} - -template AnimationKey { - <10dd46a8-775b-11cf-8f52-0040333594a3> - DWORD keyType; - DWORD nKeys; - array TimedFloatKeys keys[nKeys]; -} - -template Guid { - - DWORD data1; - WORD data2; - WORD data3; - array UCHAR data4[8]; -} - -template TextureFilename { - - STRING filename; -} - -template IndexedColor { - <1630b820-7842-11cf-8f52-0040333594a3> - DWORD index; - ColorRGBA indexColor; -} - -template MeshVertexColors { - <1630b821-7842-11cf-8f52-0040333594a3> - DWORD nVertexColors; - array IndexedColor vertexColors[nVertexColors]; -} - -template Boolean { - <537da6a0-ca37-11d0-941c-0080c80cfa7b> - DWORD truefalse; -} - -template MaterialWrap { - <4885ae60-78e8-11cf-8f52-0040333594a3> - Boolean u; - Boolean v; -} - -template Boolean2d { - <4885ae63-78e8-11cf-8f52-0040333594a3> - Boolean u; - Boolean v; -} - -template MeshFaceWraps { - - DWORD nFaceWrapValues; - array Boolean2d faceWrapValues[nFaceWrapValues]; -} - -template AnimationOptions { - - DWORD openclosed; - DWORD positionquality; -} - -# Since I don't have documentation on the precise semantic meaning of -# the BINARY keyword, I can't parse the following yet. - -#template InlineData { -# <3a23eea0-94b1-11d0-ab39-0020af71e433> -# [BINARY] -#} -# -#template Url { -# <3a23eea1-94b1-11d0-ab39-0020af71e433> -# DWORD nUrls; -# array STRING urls[nUrls]; -#} -# -#template ProgressiveMesh { -# <8a63c360-997d-11d0-941c-0080c80cfa7b> -# [Url <3a23eea1-94b1-11d0-ab39-0020af71e433>, InlineData <3a23eea0-94b1-11d0-ab39-0020af71e433>] -#} - -template ExternalVisual { - <98116aa0-bdba-11d1-82c0-00a0c9697271> - Guid guidExternalVisual; - [...] -} - -template StringProperty { - <7f0f21e0-bfe1-11d1-82c0-00a0c9697271> - STRING key; - STRING value; -} - -template PropertyBag { - <7f0f21e1-bfe1-11d1-82c0-00a0c9697271> - [StringProperty <7f0f21e0-bfe1-11d1-82c0-00a0c9697271>] -} - -template RightHanded { - <7f5d5ea0-d53a-11d1-82c0-00a0c9697271> - DWORD bRightHanded; -} - -template XSkinMeshHeader { - <3cf169ce-ff7c-44ab-93c0-f78f62d172e2> - WORD nMaxSkinWeightsPerVertex; - WORD nMaxSkinWeightsPerFace; - WORD nBones; -} - -template VertexDuplicationIndices { - - DWORD nIndices; - DWORD nOriginalVertices; - array DWORD indices[nIndices]; -} - -template SkinWeights { - <6f0d123b-bad2-4167-a0d0-80224f25fabb> - STRING transformNodeName; - DWORD nWeights; - array DWORD vertexIndices[nWeights]; - array FLOAT weights[nWeights]; - Matrix4x4 matrixOffset; -} - -template AnimTicksPerSecond { - <9E415A43-7BA6-4a73-8743-B73D47E88476> - DWORD AnimTicksPerSecond; -} diff --git a/pandatool/src/xfile/standardTemplates.x.c b/pandatool/src/xfile/standardTemplates.x.c deleted file mode 100644 index d4c8213d..00000000 --- a/pandatool/src/xfile/standardTemplates.x.c +++ /dev/null @@ -1,515 +0,0 @@ - -/* - * This table was generated by the command: - * - * bin2c -n standard_templates_data -o standardTemplates.x.c standardTemplates.x - */ - -#include - -const unsigned char standard_templates_data[] = { - 0x78, 0x6f, 0x66, 0x20, 0x30, 0x33, 0x30, 0x33, 0x74, 0x78, 0x74, - 0x20, 0x30, 0x30, 0x33, 0x32, 0x0a, 0x0a, 0x23, 0x20, 0x54, 0x68, - 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x33, 0x44, 0x0a, 0x23, 0x20, - 0x52, 0x65, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x4d, 0x6f, - 0x64, 0x65, 0x2e, 0x20, 0x20, 0x49, 0x20, 0x65, 0x78, 0x74, 0x72, - 0x61, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, - 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x44, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x58, 0x20, 0x41, 0x50, 0x49, 0x20, - 0x76, 0x69, 0x61, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, - 0x6e, 0x67, 0x0a, 0x23, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, - 0x67, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x3a, 0x0a, 0x23, 0x0a, 0x23, - 0x20, 0x20, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, - 0x3c, 0x72, 0x6d, 0x78, 0x66, 0x74, 0x6d, 0x70, 0x6c, 0x2e, 0x68, - 0x3e, 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x20, 0x4c, 0x50, 0x44, 0x49, - 0x52, 0x45, 0x43, 0x54, 0x58, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x64, - 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x3b, 0x0a, 0x23, 0x20, 0x20, - 0x4c, 0x50, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x58, 0x46, 0x49, - 0x4c, 0x45, 0x53, 0x41, 0x56, 0x45, 0x4f, 0x42, 0x4a, 0x45, 0x43, - 0x54, 0x20, 0x64, 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, - 0x61, 0x76, 0x65, 0x3b, 0x0a, 0x23, 0x20, 0x20, 0x48, 0x52, 0x45, - 0x53, 0x55, 0x4c, 0x54, 0x20, 0x68, 0x72, 0x3b, 0x0a, 0x23, 0x0a, - 0x23, 0x20, 0x20, 0x68, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x58, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x28, 0x26, 0x64, 0x78, 0x5f, 0x66, 0x69, 0x6c, - 0x65, 0x29, 0x3b, 0x0a, 0x23, 0x20, 0x20, 0x68, 0x72, 0x20, 0x3d, - 0x20, 0x64, 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x3e, 0x52, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x28, 0x44, 0x33, 0x44, 0x52, 0x4d, - 0x5f, 0x58, 0x54, 0x45, 0x4d, 0x50, 0x4c, 0x41, 0x54, 0x45, 0x53, - 0x2c, 0x20, 0x44, 0x33, 0x44, 0x52, 0x4d, 0x5f, 0x58, 0x54, 0x45, - 0x4d, 0x50, 0x4c, 0x41, 0x54, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45, - 0x53, 0x29, 0x3b, 0x0a, 0x23, 0x20, 0x20, 0x68, 0x72, 0x20, 0x3d, - 0x20, 0x64, 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x3e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x28, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x2e, 0x78, 0x22, 0x2c, 0x20, 0x44, 0x58, 0x46, - 0x49, 0x4c, 0x45, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x54, - 0x45, 0x58, 0x54, 0x2c, 0x0a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x26, 0x64, 0x78, 0x5f, - 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x61, 0x76, 0x65, 0x29, 0x3b, - 0x0a, 0x23, 0x20, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x20, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x47, 0x55, 0x49, 0x44, 0x20, - 0x2a, 0x74, 0x65, 0x6d, 0x70, 0x73, 0x5b, 0x5d, 0x20, 0x3d, 0x20, - 0x7b, 0x0a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x26, 0x54, 0x49, 0x44, - 0x5f, 0x44, 0x33, 0x44, 0x52, 0x4d, 0x49, 0x6e, 0x66, 0x6f, 0x2c, - 0x0a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x26, 0x54, 0x49, 0x44, 0x5f, - 0x44, 0x33, 0x44, 0x52, 0x4d, 0x4d, 0x65, 0x73, 0x68, 0x2c, 0x0a, - 0x23, 0x20, 0x20, 0x20, 0x20, 0x26, 0x54, 0x49, 0x44, 0x5f, 0x44, - 0x33, 0x44, 0x52, 0x4d, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2c, - 0x0a, 0x23, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x0a, 0x23, - 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x23, 0x20, 0x20, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, - 0x6e, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x65, 0x6d, 0x70, - 0x73, 0x20, 0x3d, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x6f, 0x66, 0x28, - 0x74, 0x65, 0x6d, 0x70, 0x73, 0x29, 0x20, 0x2f, 0x20, 0x73, 0x69, - 0x7a, 0x65, 0x6f, 0x66, 0x28, 0x74, 0x65, 0x6d, 0x70, 0x73, 0x5b, - 0x30, 0x5d, 0x29, 0x3b, 0x0a, 0x23, 0x20, 0x20, 0x68, 0x72, 0x20, - 0x3d, 0x20, 0x64, 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, - 0x61, 0x76, 0x65, 0x2d, 0x3e, 0x53, 0x61, 0x76, 0x65, 0x54, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x28, 0x6e, 0x75, 0x6d, - 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x73, 0x2c, 0x20, 0x74, 0x65, 0x6d, - 0x70, 0x73, 0x29, 0x3b, 0x0a, 0x23, 0x0a, 0x0a, 0x0a, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x33, 0x64, 0x38, 0x32, - 0x61, 0x62, 0x34, 0x33, 0x2d, 0x36, 0x32, 0x64, 0x61, 0x2d, 0x31, - 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, 0x33, 0x39, 0x2d, 0x30, 0x30, - 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, 0x34, 0x33, 0x33, 0x3e, - 0x0a, 0x20, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6d, 0x61, 0x6a, 0x6f, - 0x72, 0x3b, 0x0a, 0x20, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6d, 0x69, - 0x6e, 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, - 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x56, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x33, 0x64, - 0x38, 0x32, 0x61, 0x62, 0x35, 0x65, 0x2d, 0x36, 0x32, 0x64, 0x61, - 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, 0x33, 0x39, 0x2d, - 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, 0x34, 0x33, - 0x33, 0x3e, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x78, - 0x3b, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x79, 0x3b, - 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x7a, 0x3b, 0x0a, - 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x20, 0x4d, 0x65, 0x73, 0x68, 0x46, 0x61, 0x63, 0x65, 0x20, 0x7b, - 0x0a, 0x20, 0x3c, 0x33, 0x64, 0x38, 0x32, 0x61, 0x62, 0x35, 0x66, - 0x2d, 0x36, 0x32, 0x64, 0x61, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, - 0x61, 0x62, 0x33, 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, - 0x37, 0x31, 0x65, 0x34, 0x33, 0x33, 0x3e, 0x0a, 0x20, 0x44, 0x57, - 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x46, 0x61, 0x63, 0x65, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x44, 0x57, - 0x4f, 0x52, 0x44, 0x20, 0x66, 0x61, 0x63, 0x65, 0x56, 0x65, 0x72, - 0x74, 0x65, 0x78, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, - 0x6e, 0x46, 0x61, 0x63, 0x65, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5d, 0x3b, 0x0a, 0x7d, - 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x4d, 0x65, 0x73, 0x68, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x33, 0x64, - 0x38, 0x32, 0x61, 0x62, 0x34, 0x34, 0x2d, 0x36, 0x32, 0x64, 0x61, - 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, 0x33, 0x39, 0x2d, - 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, 0x34, 0x33, - 0x33, 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, - 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x0a, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x5b, - 0x6e, 0x56, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x5d, 0x3b, - 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x46, 0x61, - 0x63, 0x65, 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x4d, 0x65, 0x73, 0x68, 0x46, 0x61, 0x63, 0x65, 0x20, 0x66, - 0x61, 0x63, 0x65, 0x73, 0x5b, 0x6e, 0x46, 0x61, 0x63, 0x65, 0x73, - 0x5d, 0x3b, 0x0a, 0x20, 0x5b, 0x2e, 0x2e, 0x2e, 0x5d, 0x0a, 0x7d, - 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 0x41, 0x20, 0x7b, - 0x0a, 0x20, 0x3c, 0x33, 0x35, 0x66, 0x66, 0x34, 0x34, 0x65, 0x30, - 0x2d, 0x36, 0x63, 0x37, 0x63, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, - 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, - 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, 0x46, 0x4c, - 0x4f, 0x41, 0x54, 0x20, 0x72, 0x65, 0x64, 0x3b, 0x0a, 0x20, 0x46, - 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x3b, - 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x62, 0x6c, 0x75, - 0x65, 0x3b, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x52, 0x47, 0x42, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x64, 0x33, - 0x65, 0x31, 0x36, 0x65, 0x38, 0x31, 0x2d, 0x37, 0x38, 0x33, 0x35, - 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, - 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, - 0x33, 0x3e, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x72, - 0x65, 0x64, 0x3b, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, - 0x67, 0x72, 0x65, 0x65, 0x6e, 0x3b, 0x0a, 0x20, 0x46, 0x4c, 0x4f, - 0x41, 0x54, 0x20, 0x62, 0x6c, 0x75, 0x65, 0x3b, 0x0a, 0x7d, 0x0a, - 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x7b, 0x0a, 0x20, - 0x3c, 0x33, 0x64, 0x38, 0x32, 0x61, 0x62, 0x34, 0x64, 0x2d, 0x36, - 0x32, 0x64, 0x61, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, - 0x33, 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, - 0x65, 0x34, 0x33, 0x33, 0x3e, 0x0a, 0x20, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x52, 0x47, 0x42, 0x41, 0x20, 0x66, 0x61, 0x63, 0x65, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, - 0x54, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x3b, 0x0a, 0x20, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 0x20, 0x73, 0x70, 0x65, - 0x63, 0x75, 0x6c, 0x61, 0x72, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, - 0x0a, 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, 0x42, 0x20, - 0x65, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x5b, 0x2e, 0x2e, 0x2e, 0x5d, 0x0a, - 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x20, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x3c, - 0x33, 0x64, 0x38, 0x32, 0x61, 0x62, 0x34, 0x36, 0x2d, 0x36, 0x32, - 0x64, 0x61, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, 0x33, - 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, - 0x34, 0x33, 0x33, 0x3e, 0x0a, 0x20, 0x5b, 0x2e, 0x2e, 0x2e, 0x5d, - 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x20, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x34, 0x78, 0x34, - 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x66, 0x36, 0x66, 0x32, 0x33, 0x66, - 0x34, 0x35, 0x2d, 0x37, 0x36, 0x38, 0x36, 0x2d, 0x31, 0x31, 0x63, - 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, - 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, - 0x20, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x5b, 0x31, 0x36, 0x5d, - 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x20, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x4d, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x66, 0x36, 0x66, 0x32, 0x33, - 0x66, 0x34, 0x31, 0x2d, 0x37, 0x36, 0x38, 0x36, 0x2d, 0x31, 0x31, - 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, - 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, - 0x20, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x34, 0x78, 0x34, 0x20, - 0x66, 0x72, 0x61, 0x6d, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x20, 0x4d, 0x65, 0x73, 0x68, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x7b, 0x0a, - 0x20, 0x3c, 0x66, 0x36, 0x66, 0x32, 0x33, 0x66, 0x34, 0x32, 0x2d, - 0x37, 0x36, 0x38, 0x36, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, - 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, - 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, - 0x52, 0x44, 0x20, 0x6e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, - 0x6c, 0x73, 0x3b, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, - 0x6e, 0x46, 0x61, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, - 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x44, - 0x57, 0x4f, 0x52, 0x44, 0x20, 0x66, 0x61, 0x63, 0x65, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x65, 0x73, 0x5b, 0x6e, 0x46, 0x61, 0x63, 0x65, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x5d, 0x3b, 0x0a, 0x20, - 0x5b, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x3c, - 0x33, 0x64, 0x38, 0x32, 0x61, 0x62, 0x34, 0x64, 0x2d, 0x36, 0x32, - 0x64, 0x61, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, 0x33, - 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, - 0x34, 0x33, 0x33, 0x3e, 0x5d, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6f, 0x72, - 0x64, 0x73, 0x32, 0x64, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x66, 0x36, - 0x66, 0x32, 0x33, 0x66, 0x34, 0x34, 0x2d, 0x37, 0x36, 0x38, 0x36, - 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, - 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, - 0x33, 0x3e, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x75, - 0x3b, 0x0a, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, 0x76, 0x3b, - 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x20, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x65, 0x78, 0x74, 0x75, - 0x72, 0x65, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x7b, 0x0a, - 0x20, 0x3c, 0x66, 0x36, 0x66, 0x32, 0x33, 0x66, 0x34, 0x30, 0x2d, - 0x37, 0x36, 0x38, 0x36, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, - 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, - 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, - 0x52, 0x44, 0x20, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, - 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x20, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x32, - 0x64, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, - 0x6f, 0x72, 0x64, 0x73, 0x5b, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x75, - 0x72, 0x65, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x5d, 0x3b, 0x0a, - 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x20, 0x4d, 0x65, 0x73, 0x68, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x66, 0x36, 0x66, 0x32, 0x33, - 0x66, 0x34, 0x33, 0x2d, 0x37, 0x36, 0x38, 0x36, 0x2d, 0x31, 0x31, - 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, - 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, - 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x4e, 0x6f, 0x72, - 0x6d, 0x61, 0x6c, 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, - 0x79, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x6e, 0x6f, - 0x72, 0x6d, 0x61, 0x6c, 0x73, 0x5b, 0x6e, 0x4e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x73, 0x5d, 0x3b, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, - 0x44, 0x20, 0x6e, 0x46, 0x61, 0x63, 0x65, 0x4e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x4d, 0x65, 0x73, 0x68, 0x46, 0x61, 0x63, 0x65, 0x20, 0x66, - 0x61, 0x63, 0x65, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x73, 0x5b, - 0x6e, 0x46, 0x61, 0x63, 0x65, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x73, 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x20, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x33, 0x64, 0x38, - 0x32, 0x61, 0x62, 0x34, 0x66, 0x2d, 0x36, 0x32, 0x64, 0x61, 0x2d, - 0x31, 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, 0x33, 0x39, 0x2d, 0x30, - 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, 0x34, 0x33, 0x33, - 0x3e, 0x0a, 0x20, 0x5b, 0x2e, 0x2e, 0x2e, 0x5d, 0x0a, 0x7d, 0x0a, - 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x74, - 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x33, 0x64, 0x38, 0x32, 0x61, 0x62, - 0x35, 0x30, 0x2d, 0x36, 0x32, 0x64, 0x61, 0x2d, 0x31, 0x31, 0x63, - 0x66, 0x2d, 0x61, 0x62, 0x33, 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, - 0x61, 0x66, 0x37, 0x31, 0x65, 0x34, 0x33, 0x33, 0x3e, 0x0a, 0x20, - 0x5b, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x3c, 0x33, 0x64, 0x38, 0x32, 0x61, 0x62, 0x34, 0x66, 0x2d, 0x36, - 0x32, 0x64, 0x61, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x61, 0x62, - 0x33, 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, - 0x65, 0x34, 0x33, 0x33, 0x3e, 0x5d, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x46, 0x6c, 0x6f, - 0x61, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x3c, - 0x31, 0x30, 0x64, 0x64, 0x34, 0x36, 0x61, 0x39, 0x2d, 0x37, 0x37, - 0x35, 0x62, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, - 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, - 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, - 0x20, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3b, 0x0a, 0x20, - 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, - 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5b, 0x6e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x54, 0x69, 0x6d, - 0x65, 0x64, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x4b, 0x65, 0x79, 0x73, - 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x66, 0x34, 0x30, 0x36, 0x62, 0x31, - 0x38, 0x30, 0x2d, 0x37, 0x62, 0x33, 0x62, 0x2d, 0x31, 0x31, 0x63, - 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, - 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, - 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x3b, - 0x0a, 0x20, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x4b, 0x65, 0x79, 0x73, - 0x20, 0x74, 0x66, 0x6b, 0x65, 0x79, 0x73, 0x3b, 0x0a, 0x7d, 0x0a, - 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, - 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x31, 0x30, 0x64, 0x64, 0x34, 0x36, - 0x61, 0x38, 0x2d, 0x37, 0x37, 0x35, 0x62, 0x2d, 0x31, 0x31, 0x63, - 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, - 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, - 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6b, 0x65, 0x79, 0x54, 0x79, - 0x70, 0x65, 0x3b, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, - 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, - 0x61, 0x79, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x64, 0x46, 0x6c, 0x6f, - 0x61, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x20, 0x6b, 0x65, 0x79, 0x73, - 0x5b, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, - 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x47, - 0x75, 0x69, 0x64, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x61, 0x34, 0x32, - 0x37, 0x39, 0x30, 0x65, 0x30, 0x2d, 0x37, 0x38, 0x31, 0x30, 0x2d, - 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, - 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, - 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x64, 0x61, - 0x74, 0x61, 0x31, 0x3b, 0x0a, 0x20, 0x57, 0x4f, 0x52, 0x44, 0x20, - 0x64, 0x61, 0x74, 0x61, 0x32, 0x3b, 0x0a, 0x20, 0x57, 0x4f, 0x52, - 0x44, 0x20, 0x64, 0x61, 0x74, 0x61, 0x33, 0x3b, 0x0a, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x55, 0x43, 0x48, 0x41, 0x52, 0x20, - 0x64, 0x61, 0x74, 0x61, 0x34, 0x5b, 0x38, 0x5d, 0x3b, 0x0a, 0x7d, - 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x46, 0x69, 0x6c, 0x65, - 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x61, 0x34, - 0x32, 0x37, 0x39, 0x30, 0x65, 0x31, 0x2d, 0x37, 0x38, 0x31, 0x30, - 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, - 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, - 0x33, 0x3e, 0x0a, 0x20, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x20, - 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x3b, 0x0a, 0x7d, - 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x31, 0x36, 0x33, 0x30, 0x62, - 0x38, 0x32, 0x30, 0x2d, 0x37, 0x38, 0x34, 0x32, 0x2d, 0x31, 0x31, - 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, - 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, - 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x3b, 0x0a, 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x52, 0x47, - 0x42, 0x41, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x20, 0x4d, 0x65, 0x73, 0x68, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x20, - 0x7b, 0x0a, 0x20, 0x3c, 0x31, 0x36, 0x33, 0x30, 0x62, 0x38, 0x32, - 0x31, 0x2d, 0x37, 0x38, 0x34, 0x32, 0x2d, 0x31, 0x31, 0x63, 0x66, - 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, 0x33, - 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, 0x44, - 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x3b, 0x0a, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, - 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x74, - 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x6e, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x73, - 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x74, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, - 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x35, 0x33, 0x37, 0x64, 0x61, 0x36, - 0x61, 0x30, 0x2d, 0x63, 0x61, 0x33, 0x37, 0x2d, 0x31, 0x31, 0x64, - 0x30, 0x2d, 0x39, 0x34, 0x31, 0x63, 0x2d, 0x30, 0x30, 0x38, 0x30, - 0x63, 0x38, 0x30, 0x63, 0x66, 0x61, 0x37, 0x62, 0x3e, 0x0a, 0x20, - 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x74, 0x72, 0x75, 0x65, 0x66, - 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x57, 0x72, 0x61, 0x70, 0x20, 0x7b, 0x0a, - 0x20, 0x3c, 0x34, 0x38, 0x38, 0x35, 0x61, 0x65, 0x36, 0x30, 0x2d, - 0x37, 0x38, 0x65, 0x38, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, - 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, - 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, 0x42, 0x6f, 0x6f, - 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x75, 0x3b, 0x0a, 0x20, 0x42, 0x6f, - 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x76, 0x3b, 0x0a, 0x7d, 0x0a, - 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x42, - 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x32, 0x64, 0x20, 0x7b, 0x0a, - 0x20, 0x3c, 0x34, 0x38, 0x38, 0x35, 0x61, 0x65, 0x36, 0x33, 0x2d, - 0x37, 0x38, 0x65, 0x38, 0x2d, 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, - 0x66, 0x35, 0x32, 0x2d, 0x30, 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, - 0x35, 0x39, 0x34, 0x61, 0x33, 0x3e, 0x0a, 0x20, 0x42, 0x6f, 0x6f, - 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x75, 0x3b, 0x0a, 0x20, 0x42, 0x6f, - 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x76, 0x3b, 0x0a, 0x7d, 0x0a, - 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x4d, - 0x65, 0x73, 0x68, 0x46, 0x61, 0x63, 0x65, 0x57, 0x72, 0x61, 0x70, - 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x65, 0x64, 0x31, 0x65, 0x63, - 0x35, 0x63, 0x30, 0x2d, 0x63, 0x30, 0x61, 0x38, 0x2d, 0x31, 0x31, - 0x64, 0x30, 0x2d, 0x39, 0x34, 0x31, 0x63, 0x2d, 0x30, 0x30, 0x38, - 0x30, 0x63, 0x38, 0x30, 0x63, 0x66, 0x61, 0x37, 0x62, 0x3e, 0x0a, - 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x46, 0x61, 0x63, - 0x65, 0x57, 0x72, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x42, 0x6f, - 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x32, 0x64, 0x20, 0x66, 0x61, 0x63, - 0x65, 0x57, 0x72, 0x61, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x5b, 0x6e, 0x46, 0x61, 0x63, 0x65, 0x57, 0x72, 0x61, 0x70, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, - 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x41, 0x6e, - 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x65, 0x32, 0x62, - 0x66, 0x35, 0x36, 0x63, 0x30, 0x2d, 0x38, 0x34, 0x30, 0x66, 0x2d, - 0x31, 0x31, 0x63, 0x66, 0x2d, 0x38, 0x66, 0x35, 0x32, 0x2d, 0x30, - 0x30, 0x34, 0x30, 0x33, 0x33, 0x33, 0x35, 0x39, 0x34, 0x61, 0x33, - 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6f, 0x70, - 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x3b, 0x0a, 0x20, - 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x3b, - 0x0a, 0x7d, 0x0a, 0x0a, 0x23, 0x20, 0x53, 0x69, 0x6e, 0x63, 0x65, - 0x20, 0x49, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x68, 0x61, - 0x76, 0x65, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x20, 0x73, - 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x20, 0x6d, 0x65, 0x61, - 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x0a, 0x23, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x20, 0x6b, - 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x63, - 0x61, 0x6e, 0x27, 0x74, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, - 0x6e, 0x67, 0x20, 0x79, 0x65, 0x74, 0x2e, 0x0a, 0x0a, 0x23, 0x74, - 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x49, 0x6e, 0x6c, - 0x69, 0x6e, 0x65, 0x44, 0x61, 0x74, 0x61, 0x20, 0x7b, 0x0a, 0x23, - 0x20, 0x3c, 0x33, 0x61, 0x32, 0x33, 0x65, 0x65, 0x61, 0x30, 0x2d, - 0x39, 0x34, 0x62, 0x31, 0x2d, 0x31, 0x31, 0x64, 0x30, 0x2d, 0x61, - 0x62, 0x33, 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, - 0x31, 0x65, 0x34, 0x33, 0x33, 0x3e, 0x0a, 0x23, 0x20, 0x5b, 0x42, - 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5d, 0x0a, 0x23, 0x7d, 0x0a, 0x23, - 0x0a, 0x23, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x55, 0x72, 0x6c, 0x20, 0x7b, 0x0a, 0x23, 0x20, 0x3c, 0x33, 0x61, - 0x32, 0x33, 0x65, 0x65, 0x61, 0x31, 0x2d, 0x39, 0x34, 0x62, 0x31, - 0x2d, 0x31, 0x31, 0x64, 0x30, 0x2d, 0x61, 0x62, 0x33, 0x39, 0x2d, - 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, 0x34, 0x33, - 0x33, 0x3e, 0x0a, 0x23, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, - 0x6e, 0x55, 0x72, 0x6c, 0x73, 0x3b, 0x0a, 0x23, 0x20, 0x61, 0x72, - 0x72, 0x61, 0x79, 0x20, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x20, - 0x75, 0x72, 0x6c, 0x73, 0x5b, 0x6e, 0x55, 0x72, 0x6c, 0x73, 0x5d, - 0x3b, 0x0a, 0x23, 0x7d, 0x0a, 0x23, 0x0a, 0x23, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x50, 0x72, 0x6f, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x65, 0x73, 0x68, 0x20, - 0x7b, 0x0a, 0x23, 0x20, 0x3c, 0x38, 0x61, 0x36, 0x33, 0x63, 0x33, - 0x36, 0x30, 0x2d, 0x39, 0x39, 0x37, 0x64, 0x2d, 0x31, 0x31, 0x64, - 0x30, 0x2d, 0x39, 0x34, 0x31, 0x63, 0x2d, 0x30, 0x30, 0x38, 0x30, - 0x63, 0x38, 0x30, 0x63, 0x66, 0x61, 0x37, 0x62, 0x3e, 0x0a, 0x23, - 0x20, 0x5b, 0x55, 0x72, 0x6c, 0x20, 0x3c, 0x33, 0x61, 0x32, 0x33, - 0x65, 0x65, 0x61, 0x31, 0x2d, 0x39, 0x34, 0x62, 0x31, 0x2d, 0x31, - 0x31, 0x64, 0x30, 0x2d, 0x61, 0x62, 0x33, 0x39, 0x2d, 0x30, 0x30, - 0x32, 0x30, 0x61, 0x66, 0x37, 0x31, 0x65, 0x34, 0x33, 0x33, 0x3e, - 0x2c, 0x20, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x61, 0x74, - 0x61, 0x20, 0x3c, 0x33, 0x61, 0x32, 0x33, 0x65, 0x65, 0x61, 0x30, - 0x2d, 0x39, 0x34, 0x62, 0x31, 0x2d, 0x31, 0x31, 0x64, 0x30, 0x2d, - 0x61, 0x62, 0x33, 0x39, 0x2d, 0x30, 0x30, 0x32, 0x30, 0x61, 0x66, - 0x37, 0x31, 0x65, 0x34, 0x33, 0x33, 0x3e, 0x5d, 0x0a, 0x23, 0x7d, - 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, - 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x56, 0x69, 0x73, - 0x75, 0x61, 0x6c, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x39, 0x38, 0x31, - 0x31, 0x36, 0x61, 0x61, 0x30, 0x2d, 0x62, 0x64, 0x62, 0x61, 0x2d, - 0x31, 0x31, 0x64, 0x31, 0x2d, 0x38, 0x32, 0x63, 0x30, 0x2d, 0x30, - 0x30, 0x61, 0x30, 0x63, 0x39, 0x36, 0x39, 0x37, 0x32, 0x37, 0x31, - 0x3e, 0x0a, 0x20, 0x47, 0x75, 0x69, 0x64, 0x20, 0x67, 0x75, 0x69, - 0x64, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x56, 0x69, - 0x73, 0x75, 0x61, 0x6c, 0x3b, 0x0a, 0x20, 0x5b, 0x2e, 0x2e, 0x2e, - 0x5d, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, - 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x7b, 0x0a, 0x20, 0x3c, - 0x37, 0x66, 0x30, 0x66, 0x32, 0x31, 0x65, 0x30, 0x2d, 0x62, 0x66, - 0x65, 0x31, 0x2d, 0x31, 0x31, 0x64, 0x31, 0x2d, 0x38, 0x32, 0x63, - 0x30, 0x2d, 0x30, 0x30, 0x61, 0x30, 0x63, 0x39, 0x36, 0x39, 0x37, - 0x32, 0x37, 0x31, 0x3e, 0x0a, 0x20, 0x53, 0x54, 0x52, 0x49, 0x4e, - 0x47, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x0a, 0x20, 0x53, 0x54, 0x52, - 0x49, 0x4e, 0x47, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3b, 0x0a, - 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x20, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x42, 0x61, - 0x67, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x37, 0x66, 0x30, 0x66, 0x32, - 0x31, 0x65, 0x31, 0x2d, 0x62, 0x66, 0x65, 0x31, 0x2d, 0x31, 0x31, - 0x64, 0x31, 0x2d, 0x38, 0x32, 0x63, 0x30, 0x2d, 0x30, 0x30, 0x61, - 0x30, 0x63, 0x39, 0x36, 0x39, 0x37, 0x32, 0x37, 0x31, 0x3e, 0x0a, - 0x20, 0x5b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x3c, 0x37, 0x66, 0x30, 0x66, - 0x32, 0x31, 0x65, 0x30, 0x2d, 0x62, 0x66, 0x65, 0x31, 0x2d, 0x31, - 0x31, 0x64, 0x31, 0x2d, 0x38, 0x32, 0x63, 0x30, 0x2d, 0x30, 0x30, - 0x61, 0x30, 0x63, 0x39, 0x36, 0x39, 0x37, 0x32, 0x37, 0x31, 0x3e, - 0x5d, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x48, 0x61, 0x6e, - 0x64, 0x65, 0x64, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x37, 0x66, 0x35, - 0x64, 0x35, 0x65, 0x61, 0x30, 0x2d, 0x64, 0x35, 0x33, 0x61, 0x2d, - 0x31, 0x31, 0x64, 0x31, 0x2d, 0x38, 0x32, 0x63, 0x30, 0x2d, 0x30, - 0x30, 0x61, 0x30, 0x63, 0x39, 0x36, 0x39, 0x37, 0x32, 0x37, 0x31, - 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x62, 0x52, - 0x69, 0x67, 0x68, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x3b, - 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x20, 0x58, 0x53, 0x6b, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x68, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x3c, - 0x33, 0x63, 0x66, 0x31, 0x36, 0x39, 0x63, 0x65, 0x2d, 0x66, 0x66, - 0x37, 0x63, 0x2d, 0x34, 0x34, 0x61, 0x62, 0x2d, 0x39, 0x33, 0x63, - 0x30, 0x2d, 0x66, 0x37, 0x38, 0x66, 0x36, 0x32, 0x64, 0x31, 0x37, - 0x32, 0x65, 0x32, 0x3e, 0x0a, 0x20, 0x57, 0x4f, 0x52, 0x44, 0x20, - 0x6e, 0x4d, 0x61, 0x78, 0x53, 0x6b, 0x69, 0x6e, 0x57, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x73, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, - 0x65, 0x78, 0x3b, 0x0a, 0x20, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, - 0x4d, 0x61, 0x78, 0x53, 0x6b, 0x69, 0x6e, 0x57, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x73, 0x50, 0x65, 0x72, 0x46, 0x61, 0x63, 0x65, 0x3b, - 0x0a, 0x20, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x42, 0x6f, 0x6e, - 0x65, 0x73, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x20, 0x7b, 0x0a, 0x20, - 0x3c, 0x62, 0x38, 0x64, 0x36, 0x35, 0x35, 0x34, 0x39, 0x2d, 0x64, - 0x37, 0x63, 0x39, 0x2d, 0x34, 0x39, 0x39, 0x35, 0x2d, 0x38, 0x39, - 0x63, 0x66, 0x2d, 0x35, 0x33, 0x61, 0x39, 0x61, 0x38, 0x62, 0x30, - 0x33, 0x31, 0x65, 0x33, 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, - 0x44, 0x20, 0x6e, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x3b, - 0x0a, 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x4f, 0x72, - 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x56, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, - 0x20, 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x69, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x5b, 0x6e, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x5d, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, - 0x6c, 0x61, 0x74, 0x65, 0x20, 0x53, 0x6b, 0x69, 0x6e, 0x57, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x7b, 0x0a, 0x20, 0x3c, 0x36, - 0x66, 0x30, 0x64, 0x31, 0x32, 0x33, 0x62, 0x2d, 0x62, 0x61, 0x64, - 0x32, 0x2d, 0x34, 0x31, 0x36, 0x37, 0x2d, 0x61, 0x30, 0x64, 0x30, - 0x2d, 0x38, 0x30, 0x32, 0x32, 0x34, 0x66, 0x32, 0x35, 0x66, 0x61, - 0x62, 0x62, 0x3e, 0x0a, 0x20, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, - 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x4e, - 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x3b, 0x0a, 0x20, 0x44, - 0x57, 0x4f, 0x52, 0x44, 0x20, 0x6e, 0x57, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x73, 0x3b, 0x0a, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, - 0x44, 0x57, 0x4f, 0x52, 0x44, 0x20, 0x76, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x6e, 0x57, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x5d, 0x3b, 0x0a, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x20, - 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x5b, 0x6e, 0x57, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x73, 0x5d, 0x3b, 0x0a, 0x20, 0x4d, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x34, 0x78, 0x34, 0x20, 0x6d, 0x61, 0x74, - 0x72, 0x69, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3b, 0x0a, - 0x7d, 0x0a, 0x0a, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, - 0x20, 0x41, 0x6e, 0x69, 0x6d, 0x54, 0x69, 0x63, 0x6b, 0x73, 0x50, - 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x7b, 0x0a, - 0x20, 0x3c, 0x39, 0x45, 0x34, 0x31, 0x35, 0x41, 0x34, 0x33, 0x2d, - 0x37, 0x42, 0x41, 0x36, 0x2d, 0x34, 0x61, 0x37, 0x33, 0x2d, 0x38, - 0x37, 0x34, 0x33, 0x2d, 0x42, 0x37, 0x33, 0x44, 0x34, 0x37, 0x45, - 0x38, 0x38, 0x34, 0x37, 0x36, 0x3e, 0x0a, 0x20, 0x44, 0x57, 0x4f, - 0x52, 0x44, 0x20, 0x41, 0x6e, 0x69, 0x6d, 0x54, 0x69, 0x63, 0x6b, - 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x3b, - 0x0a, 0x7d, 0x20, 0x0a -}; - -const int standard_templates_data_len = 5504; - diff --git a/pandatool/src/xfile/standardTemplates.x.pz.c b/pandatool/src/xfile/standardTemplates.x.pz.c deleted file mode 100644 index 4613dc55..00000000 --- a/pandatool/src/xfile/standardTemplates.x.pz.c +++ /dev/null @@ -1,184 +0,0 @@ - -/* - * This table was generated by the command: - * - * bin2c -n standard_templates_data -o standardTemplates.x.pz.c standardTemplates.x.pz - */ - -#include - -const unsigned char standard_templates_data[] = { - 0x78, 0x9c, 0xa5, 0x58, 0x6b, 0x6f, 0xdb, 0x38, 0x16, 0xfd, 0xee, - 0x5f, 0x41, 0x4c, 0x80, 0x6e, 0x67, 0x11, 0x65, 0xf5, 0x7e, 0xac, - 0xbb, 0x05, 0xec, 0xda, 0x69, 0xbd, 0x93, 0x17, 0x6c, 0x35, 0xcd, - 0xc0, 0x08, 0x02, 0x4a, 0x24, 0x6d, 0x4d, 0x65, 0xc9, 0x2b, 0xc9, - 0xa9, 0x33, 0x8b, 0xfe, 0xf7, 0xbd, 0x24, 0x25, 0x59, 0x92, 0x93, - 0x95, 0x81, 0x09, 0x82, 0xc4, 0x7c, 0x9d, 0x7b, 0xee, 0xe1, 0xe5, - 0x25, 0xaf, 0xf7, 0x29, 0x43, 0xaa, 0xa1, 0x1a, 0xc5, 0xbe, 0x40, - 0xaa, 0x6a, 0xe8, 0x83, 0xc1, 0x19, 0xf2, 0xd7, 0x51, 0x8e, 0x58, - 0x14, 0x53, 0x14, 0xa6, 0x49, 0x81, 0xa3, 0x24, 0x47, 0xc5, 0x9a, - 0xa2, 0xbc, 0xc0, 0x09, 0xc1, 0x19, 0x41, 0x05, 0xdd, 0x6c, 0x63, - 0x5c, 0x50, 0x44, 0x28, 0x8b, 0x92, 0xa8, 0x88, 0x52, 0x98, 0xc1, - 0xd2, 0x0c, 0x4d, 0xa2, 0x8c, 0x86, 0x85, 0x31, 0x01, 0x8c, 0x39, - 0xe5, 0x0b, 0x29, 0x41, 0xd7, 0x29, 0xa1, 0x17, 0x08, 0xcd, 0x10, - 0xdd, 0x17, 0x19, 0x0e, 0x0b, 0xe8, 0x02, 0xb0, 0x9c, 0x22, 0x96, - 0xa5, 0x1b, 0x81, 0x2b, 0x57, 0x3d, 0xa0, 0xd1, 0xdd, 0x0c, 0x3d, - 0x47, 0x18, 0xe5, 0xe9, 0x86, 0x16, 0xeb, 0x28, 0x59, 0x01, 0x4c, - 0x1c, 0x7d, 0xa7, 0x62, 0x12, 0x4b, 0xe3, 0x38, 0xfd, 0x01, 0x9d, - 0xc0, 0x89, 0xd0, 0x7f, 0x0e, 0xce, 0x60, 0x10, 0x9d, 0x45, 0x49, - 0x18, 0xef, 0x08, 0x45, 0x1f, 0xb2, 0xcd, 0x9e, 0x15, 0xc0, 0xea, - 0x62, 0xfd, 0x51, 0x0e, 0x5d, 0xdd, 0x4d, 0x66, 0xf3, 0xe9, 0x27, - 0xff, 0xe1, 0x72, 0x76, 0x35, 0x45, 0x64, 0xff, 0xc4, 0xfd, 0x19, - 0x1e, 0x8d, 0x2c, 0x46, 0xf7, 0xd3, 0xdb, 0xf1, 0xbf, 0xa1, 0x59, - 0xcd, 0x79, 0xca, 0xf1, 0xb3, 0x9c, 0xf8, 0x65, 0x3e, 0x5d, 0x7c, - 0xbd, 0xf2, 0xd1, 0x3a, 0x1b, 0x4a, 0xcc, 0x75, 0x86, 0xfe, 0x55, - 0xb1, 0xbd, 0x84, 0xa9, 0x9f, 0x32, 0x0a, 0x2a, 0xbc, 0x7f, 0x57, - 0xae, 0xfc, 0x75, 0x58, 0x4f, 0x2a, 0x7b, 0x94, 0x8f, 0x73, 0xba, - 0x8a, 0xf2, 0x82, 0x66, 0x7e, 0x29, 0x59, 0xfe, 0x7e, 0x62, 0x4c, - 0xe6, 0xd7, 0x4f, 0x0f, 0xfe, 0xf4, 0xfa, 0xee, 0x6a, 0xe4, 0x4f, - 0x17, 0xe7, 0xa8, 0xd3, 0xf3, 0x34, 0xfe, 0x1d, 0xba, 0x5f, 0x03, - 0x93, 0xf6, 0x16, 0xc0, 0xef, 0x36, 0xf8, 0x03, 0x48, 0xbc, 0xff, - 0x85, 0xf7, 0x27, 0x78, 0x43, 0x2f, 0xf6, 0xbf, 0x00, 0x8e, 0xf0, - 0xe8, 0xf2, 0x76, 0x7e, 0x3d, 0xf2, 0x9f, 0xfc, 0xe9, 0x83, 0x7f, - 0xce, 0x21, 0xfa, 0x7e, 0xde, 0x35, 0xfd, 0x96, 0x56, 0x61, 0xa3, - 0x8b, 0x28, 0xe4, 0x9b, 0x9f, 0x17, 0xe8, 0xf3, 0xd7, 0xd9, 0x04, - 0xfd, 0x9d, 0x6f, 0x79, 0xbe, 0x7c, 0x04, 0x36, 0xff, 0x95, 0xa0, - 0xef, 0xfc, 0xd9, 0xe4, 0x49, 0x30, 0x9f, 0x25, 0x2c, 0x3d, 0xef, - 0x76, 0x5e, 0xd3, 0x7c, 0x7d, 0xd4, 0x79, 0x0f, 0x9c, 0xd3, 0xac, - 0xec, 0xbe, 0xb8, 0xb8, 0xe0, 0x1f, 0x7e, 0x1e, 0x5b, 0x8c, 0x92, - 0x02, 0x25, 0xbb, 0xcd, 0x93, 0xb0, 0x09, 0x16, 0xf3, 0xe8, 0x4f, - 0x9a, 0xb2, 0xf7, 0xa2, 0xf9, 0x2b, 0xfa, 0x47, 0xab, 0xbd, 0x54, - 0x1f, 0x8f, 0x95, 0x12, 0xae, 0x28, 0x1f, 0xb9, 0x50, 0x07, 0xdd, - 0x6b, 0xc4, 0x73, 0x24, 0x91, 0xf8, 0xa6, 0x0e, 0x06, 0x75, 0x2c, - 0x7f, 0xa1, 0x98, 0xd0, 0x0c, 0xdc, 0x43, 0x1f, 0x0c, 0xe2, 0xea, - 0x38, 0x30, 0x0d, 0xc5, 0xd6, 0x09, 0x56, 0x34, 0x2d, 0x64, 0x0a, - 0x0e, 0x0c, 0x4f, 0x51, 0x55, 0x5d, 0xc5, 0xcc, 0xd1, 0xa8, 0x69, - 0x18, 0x1f, 0x07, 0xe8, 0xdb, 0xed, 0x7c, 0x82, 0x36, 0xf8, 0x8f, - 0x14, 0xe2, 0xa3, 0x6c, 0x44, 0x89, 0x68, 0x4c, 0x44, 0x8b, 0xc5, - 0x78, 0x95, 0x0f, 0x07, 0x3f, 0x1b, 0x46, 0xa4, 0x02, 0x0d, 0x23, - 0x16, 0xed, 0x31, 0x72, 0x79, 0x75, 0x3b, 0xf2, 0xd1, 0x7e, 0x58, - 0x7d, 0x7a, 0xa9, 0x3f, 0xfd, 0xd9, 0x86, 0xe6, 0x8a, 0x5f, 0xe2, - 0x90, 0x36, 0xc1, 0x59, 0x0f, 0xb8, 0xe4, 0x99, 0xf0, 0x65, 0xf7, - 0x34, 0x2b, 0xe8, 0x7e, 0x96, 0x90, 0x28, 0xa4, 0x40, 0x1a, 0xe1, - 0x2c, 0xc3, 0x2f, 0x95, 0x23, 0xdd, 0xf1, 0xe5, 0xf1, 0x92, 0xc7, - 0x63, 0x36, 0x4d, 0x2d, 0xcd, 0xd3, 0x98, 0x70, 0xc8, 0x16, 0x81, - 0x52, 0xb0, 0xe7, 0xb2, 0x7f, 0x59, 0xcf, 0x78, 0x1c, 0xb6, 0xe8, - 0x1f, 0x56, 0xd4, 0x3a, 0x70, 0xd6, 0x25, 0x53, 0x31, 0x7b, 0x09, - 0x11, 0xf7, 0xd8, 0x22, 0xf9, 0x29, 0x8d, 0xd3, 0x6c, 0xfe, 0x79, - 0x3c, 0x92, 0x4c, 0x2d, 0xc6, 0x4c, 0x93, 0xaa, 0x8a, 0x1d, 0x3a, - 0xa1, 0x64, 0xea, 0x32, 0x4b, 0x07, 0xa6, 0xa6, 0x6a, 0x18, 0x86, - 0xe5, 0x99, 0xf8, 0xb0, 0x21, 0x19, 0x25, 0xf5, 0x46, 0xac, 0x32, - 0x4a, 0x93, 0xba, 0x15, 0xc4, 0x3b, 0x5a, 0x37, 0x70, 0xbc, 0x5d, - 0xe3, 0xe1, 0xab, 0x46, 0x85, 0x4d, 0x62, 0x50, 0xcd, 0xa6, 0xae, - 0xa6, 0x38, 0xae, 0x61, 0xfd, 0x55, 0x9b, 0x2d, 0xfd, 0xe1, 0x4f, - 0x16, 0xe1, 0xb8, 0xb9, 0x07, 0xa4, 0x67, 0x0f, 0x0e, 0x72, 0x70, - 0xe9, 0x44, 0xab, 0xb6, 0xb0, 0x4d, 0x7f, 0x50, 0xde, 0xaa, 0xd9, - 0xe7, 0x5b, 0x1a, 0xee, 0x62, 0x9c, 0x55, 0xd3, 0xea, 0x01, 0xba, - 0x89, 0xf2, 0x3c, 0x7a, 0xae, 0xd7, 0x1f, 0xcb, 0x7e, 0x99, 0x41, - 0xc6, 0x6a, 0x12, 0xb3, 0x7b, 0x88, 0x1d, 0x43, 0x80, 0x7b, 0x59, - 0xb4, 0x37, 0xf7, 0xa6, 0x80, 0x61, 0x36, 0xd3, 0x0d, 0x66, 0x5a, - 0x8a, 0x63, 0xbb, 0xf6, 0xdb, 0x2a, 0xca, 0xf8, 0x90, 0xfe, 0x6c, - 0x04, 0xc0, 0x52, 0xb3, 0x3b, 0x71, 0x2b, 0xb8, 0xf9, 0x19, 0x4e, - 0x72, 0xb8, 0xcf, 0x36, 0xd2, 0x4c, 0xd3, 0x86, 0xd6, 0x63, 0xe3, - 0x40, 0x8c, 0x71, 0x24, 0xd9, 0x3c, 0x3e, 0x1a, 0xd5, 0xf6, 0x5c, - 0xc1, 0xe5, 0xd0, 0x84, 0xd7, 0x7b, 0xe0, 0xcb, 0x88, 0xaf, 0x96, - 0xe7, 0xed, 0x43, 0x00, 0x47, 0x91, 0xee, 0x5f, 0x3d, 0xbd, 0xe5, - 0xc8, 0xb2, 0x39, 0x4d, 0x9c, 0x89, 0x3a, 0x4e, 0x4e, 0x0b, 0x92, - 0xee, 0xf9, 0x49, 0x33, 0x92, 0xeb, 0xa4, 0xe9, 0x81, 0xd9, 0xe3, - 0x81, 0x94, 0x7f, 0x57, 0x07, 0xd6, 0xf3, 0xb1, 0x38, 0x3e, 0xbc, - 0x14, 0x76, 0x19, 0x95, 0xe8, 0x4d, 0x6c, 0xf5, 0x34, 0x75, 0x5a, - 0xeb, 0x6b, 0x31, 0x6a, 0xb2, 0x45, 0x73, 0x78, 0xd9, 0x9e, 0xfd, - 0x4a, 0x16, 0xbb, 0x81, 0x38, 0x00, 0xa5, 0x9b, 0x3c, 0x8c, 0xd3, - 0x78, 0x94, 0x2b, 0xbb, 0xb9, 0x2c, 0x91, 0xdd, 0xcb, 0x6a, 0xbc, - 0x93, 0xc9, 0xba, 0xab, 0x5a, 0xf9, 0xec, 0xa6, 0x5a, 0xdb, 0x98, - 0xd9, 0xe1, 0x3c, 0x4a, 0x22, 0x08, 0x6e, 0x78, 0x92, 0x35, 0x4f, - 0x58, 0xdf, 0x45, 0x70, 0x7c, 0xc2, 0x6a, 0x98, 0x05, 0x2d, 0x9a, - 0x57, 0x8a, 0xda, 0x87, 0x74, 0xb0, 0x7f, 0x9a, 0xf1, 0x4e, 0x6e, - 0x88, 0x53, 0x5c, 0xfc, 0x46, 0x5f, 0xa4, 0xde, 0x9a, 0x4a, 0x88, - 0x69, 0x63, 0x4f, 0x71, 0x1c, 0x2b, 0xe8, 0xd5, 0xfb, 0x1e, 0x43, - 0x1a, 0x3c, 0x08, 0x57, 0xc6, 0x97, 0xe8, 0x5c, 0x96, 0x83, 0x1d, - 0xad, 0xfc, 0x68, 0x43, 0x49, 0xdb, 0x24, 0x44, 0x99, 0x1d, 0x68, - 0x2e, 0x84, 0x5a, 0x60, 0xf4, 0x9a, 0x2c, 0x60, 0x3d, 0x8f, 0xe4, - 0x1a, 0xa1, 0x60, 0xdf, 0xe1, 0xdf, 0x1b, 0x1b, 0x02, 0x33, 0x9a, - 0x5e, 0xb9, 0x27, 0x79, 0x05, 0x78, 0xfe, 0xcb, 0x96, 0x1e, 0x62, - 0xe4, 0x37, 0x61, 0xa0, 0xf4, 0xb1, 0xe3, 0x00, 0x37, 0xbe, 0x14, - 0x33, 0x3a, 0x8e, 0x7e, 0xde, 0x45, 0xf2, 0x94, 0x62, 0x53, 0x77, - 0x3c, 0x15, 0x2e, 0x39, 0xc7, 0xd5, 0xd4, 0x3e, 0xdb, 0x04, 0x17, - 0x58, 0xab, 0xde, 0x36, 0xbc, 0xa1, 0x37, 0x1b, 0x46, 0xcd, 0xe2, - 0xeb, 0xa7, 0x2f, 0xa3, 0xb9, 0xe8, 0x33, 0x97, 0x6e, 0x57, 0x62, - 0x79, 0xbc, 0x2e, 0xcb, 0x87, 0x6a, 0x93, 0x84, 0xd6, 0x43, 0x62, - 0xe1, 0xcf, 0x67, 0x37, 0x9f, 0x51, 0xf5, 0xc6, 0x6d, 0xe3, 0xca, - 0x24, 0x46, 0xc4, 0x2d, 0x23, 0x55, 0xb5, 0x0d, 0x35, 0x70, 0x75, - 0xee, 0x19, 0xa4, 0xd1, 0x1e, 0xcf, 0x22, 0xbe, 0x7a, 0xd8, 0xbc, - 0xf2, 0x44, 0x4f, 0x79, 0x67, 0x75, 0x53, 0x80, 0x7c, 0xe8, 0x88, - 0xc1, 0xbc, 0x69, 0x4b, 0x3b, 0xc9, 0x56, 0xd2, 0x5c, 0x5e, 0x6b, - 0xd6, 0xe2, 0xff, 0xdc, 0x98, 0xb1, 0x6c, 0xcd, 0xef, 0xa8, 0x39, - 0x4e, 0xd3, 0x98, 0x62, 0x79, 0xb4, 0x2d, 0xc3, 0x21, 0xd8, 0xc6, - 0xaa, 0x12, 0x62, 0xc3, 0x01, 0x12, 0x44, 0x55, 0x3c, 0x53, 0x0b, - 0x81, 0x84, 0xab, 0x86, 0xf0, 0xcb, 0xb0, 0x13, 0x1c, 0x22, 0x35, - 0xdb, 0x51, 0x06, 0xc9, 0xe2, 0x8d, 0x67, 0xc2, 0xb7, 0x0c, 0x6f, - 0x05, 0xa8, 0xe9, 0xba, 0x16, 0xa6, 0x36, 0x57, 0x91, 0xba, 0x6f, - 0x7b, 0x56, 0xf1, 0xe0, 0x79, 0xbc, 0xfa, 0xfc, 0xfc, 0x2a, 0xd5, - 0xf2, 0x76, 0x28, 0x71, 0x8d, 0xbf, 0x8e, 0x5b, 0xe5, 0x43, 0x4e, - 0x59, 0xee, 0x06, 0x25, 0x1a, 0x0d, 0xad, 0x10, 0x84, 0x50, 0xb1, - 0xdb, 0x27, 0x44, 0x52, 0xad, 0xed, 0x64, 0x8b, 0x03, 0x5d, 0xd6, - 0x9a, 0xb0, 0xec, 0x2c, 0x78, 0x2b, 0xdb, 0xde, 0x6e, 0x65, 0x19, - 0x2c, 0x08, 0xe9, 0x01, 0xb3, 0x6c, 0x20, 0xe4, 0x9a, 0x2a, 0xeb, - 0x0b, 0x8f, 0x74, 0x4b, 0xa1, 0x88, 0x4d, 0x73, 0xf1, 0xb8, 0x93, - 0x5d, 0xdb, 0x34, 0x17, 0x45, 0xf5, 0x7f, 0x76, 0x38, 0x8e, 0x8a, - 0x17, 0x61, 0xf1, 0x0c, 0x2d, 0xa0, 0xd8, 0x85, 0xb8, 0x47, 0x24, - 0x4d, 0xfe, 0x56, 0xa0, 0x35, 0x14, 0x37, 0xf0, 0x31, 0xdc, 0x6d, - 0x68, 0x52, 0xc8, 0x7c, 0x0b, 0xbf, 0xbc, 0x52, 0xde, 0x42, 0x7d, - 0x1a, 0x41, 0x7d, 0x9d, 0xd3, 0x0d, 0x4e, 0x78, 0x55, 0xb5, 0x01, - 0xbf, 0x78, 0xe1, 0x9c, 0x32, 0x40, 0xe1, 0x33, 0xc6, 0xb3, 0x9b, - 0xd1, 0xfc, 0x77, 0x9e, 0x2d, 0x7e, 0xc0, 0xa5, 0x77, 0x0e, 0x98, - 0x21, 0xe6, 0x98, 0x5b, 0x9c, 0xe5, 0xdd, 0x6a, 0xfb, 0x85, 0x16, - 0x17, 0x60, 0xbd, 0x71, 0xee, 0x62, 0x28, 0xeb, 0x27, 0x70, 0xd6, - 0x45, 0x25, 0xf8, 0xc1, 0xc0, 0xba, 0x41, 0x29, 0xe6, 0x92, 0x07, - 0x9a, 0x14, 0xff, 0x95, 0x6b, 0xe1, 0x0c, 0x2d, 0xa5, 0xd1, 0xc7, - 0xc1, 0xd9, 0x4f, 0x5e, 0x4c, 0xd7, 0x78, 0x5f, 0xb3, 0xb8, 0x05, - 0xa4, 0xf5, 0x01, 0x95, 0xdb, 0x08, 0xeb, 0x72, 0x5e, 0xf8, 0xc9, - 0xdd, 0x2b, 0x53, 0xc5, 0x2e, 0xe3, 0x77, 0x23, 0x1f, 0x82, 0x6d, - 0xea, 0x18, 0xba, 0xcb, 0x52, 0x78, 0x34, 0x8b, 0xa7, 0x69, 0x59, - 0x9c, 0x80, 0x51, 0x17, 0xdb, 0x46, 0x68, 0x40, 0xb8, 0x7b, 0x9e, - 0x43, 0xde, 0x0c, 0x1d, 0x60, 0xcf, 0x69, 0x9e, 0x46, 0xf1, 0xbc, - 0x29, 0xd1, 0x69, 0xf2, 0x08, 0x51, 0x0e, 0x31, 0x35, 0xdd, 0xc3, - 0xa1, 0x4c, 0x70, 0x7c, 0x1f, 0xe5, 0xbb, 0xf2, 0x05, 0xef, 0xb9, - 0x9a, 0x66, 0x63, 0x80, 0x09, 0x48, 0xc0, 0x6f, 0x52, 0xa2, 0x29, - 0xae, 0x0e, 0x01, 0xa6, 0xaa, 0x58, 0x0d, 0x3d, 0xdb, 0x73, 0x74, - 0x47, 0x83, 0x88, 0x12, 0x69, 0x7e, 0x05, 0x7f, 0xda, 0x10, 0xaf, - 0xbe, 0xc2, 0x17, 0xf0, 0x32, 0x4d, 0x56, 0xa0, 0xca, 0x16, 0xd2, - 0x8d, 0xbc, 0x98, 0x1c, 0xa6, 0x32, 0x5d, 0x83, 0xcb, 0x21, 0x60, - 0x54, 0x7b, 0xdb, 0x4a, 0x29, 0x36, 0x84, 0xcf, 0xb0, 0x6e, 0x88, - 0x6b, 0xb6, 0x7d, 0x34, 0x2a, 0xe8, 0x31, 0x5e, 0x35, 0xd1, 0xb5, - 0x1e, 0xf4, 0x65, 0x87, 0xd8, 0x69, 0xac, 0xda, 0xbe, 0xcd, 0xa3, - 0xd5, 0xba, 0xf8, 0x82, 0x21, 0xc5, 0x92, 0xd2, 0xb4, 0x45, 0x2c, - 0xbe, 0x0b, 0xc4, 0x32, 0xfe, 0x8f, 0x7c, 0x32, 0xb4, 0x82, 0xc6, - 0xea, 0xb6, 0x47, 0x0f, 0x8b, 0xef, 0x51, 0xc2, 0x83, 0xa7, 0xf9, - 0x5d, 0x41, 0xc8, 0x34, 0xdb, 0x0b, 0xa9, 0xc2, 0x18, 0x54, 0x8d, - 0xa6, 0x89, 0x03, 0xc5, 0x33, 0x00, 0x9a, 0x39, 0x2e, 0x83, 0x67, - 0x8f, 0xe6, 0xe8, 0x54, 0xaf, 0xbe, 0x2b, 0x80, 0x77, 0xfb, 0x9e, - 0x43, 0x7c, 0xa3, 0xdc, 0x42, 0x7e, 0x47, 0x33, 0x99, 0xea, 0x87, - 0x6f, 0x8e, 0xf3, 0xdc, 0x53, 0x8f, 0x8e, 0xd3, 0x84, 0x1e, 0x7d, - 0x9f, 0xc0, 0xd7, 0x4f, 0x76, 0xdb, 0x38, 0x0a, 0x45, 0x12, 0x28, - 0xab, 0x71, 0x41, 0x2d, 0x70, 0x89, 0x6d, 0x59, 0xa6, 0xa7, 0x10, - 0x27, 0xf4, 0x14, 0xd3, 0xf3, 0x2c, 0xc5, 0xf5, 0x20, 0x17, 0x81, - 0x06, 0x1e, 0x76, 0x03, 0xd5, 0xd0, 0x68, 0xe3, 0x96, 0x3a, 0x94, - 0xfe, 0x65, 0xc7, 0x6d, 0x16, 0xad, 0x22, 0x1e, 0x43, 0xdd, 0x9a, - 0xbc, 0xbe, 0x42, 0x65, 0x45, 0xfe, 0xfa, 0x17, 0x00, 0x0d, 0x3f, - 0x04, 0x19, 0x9b, 0xa9, 0x44, 0xd3, 0xe1, 0x49, 0x15, 0x60, 0xa2, - 0x2b, 0xa6, 0x66, 0x3b, 0x0a, 0x56, 0xe1, 0x34, 0xb8, 0xaa, 0xae, - 0x9b, 0x4c, 0xb7, 0x18, 0x0e, 0x82, 0x43, 0x6c, 0x15, 0x55, 0x05, - 0x76, 0x93, 0x12, 0x7a, 0x23, 0x2e, 0xff, 0x8a, 0x56, 0x09, 0xda, - 0x61, 0xf3, 0xdc, 0xfe, 0x7a, 0xa2, 0x9c, 0xf4, 0xd8, 0x79, 0x0c, - 0xfe, 0x90, 0xdd, 0xad, 0xf1, 0x43, 0xc5, 0x26, 0x6b, 0xc2, 0x5b, - 0xc6, 0x72, 0x5a, 0x1c, 0x67, 0x79, 0x3f, 0x0a, 0xbf, 0xf3, 0x2d, - 0x59, 0xd0, 0x30, 0x4d, 0x64, 0x58, 0x79, 0x53, 0x53, 0xb3, 0x46, - 0xbc, 0x1c, 0x18, 0x8f, 0x6c, 0xc5, 0xc4, 0x8e, 0xa1, 0xb8, 0x0e, - 0x34, 0xc7, 0x8e, 0x31, 0x31, 0x9d, 0xa9, 0xeb, 0x9a, 0x8e, 0x5d, - 0x0b, 0x7c, 0x8c, 0x01, 0x36, 0xd0, 0xe0, 0x7f, 0x49, 0x95, 0x76, - 0xa7 -}; - -const int standard_templates_data_len = 1860; - diff --git a/pandatool/src/xfile/standard_templates.cxx b/pandatool/src/xfile/standard_templates.cxx deleted file mode 100644 index d9706bb9..00000000 --- a/pandatool/src/xfile/standard_templates.cxx +++ /dev/null @@ -1,48 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file standard_templates.cxx - * @author drose - * @date 2004-10-04 - */ - -#include "standard_templates.h" - -// The binary data included here was generated from standardTemplates.x (in -// this directory) file via the utility program bin2c (defined in pandatool). -// It contains the set of template definitions that must be loaded before any -// standard template file can be properly interpreted. - -#ifndef CPPPARSER - -#if defined(HAVE_ZLIB) - -// If we have zlib available, we can store this file compressed, which is much -// smaller. - -// Regenerate this file with: - -// pcompress standardTemplates.x standardTemplates.x.pz bin2c -n -// standard_templates_data -o standardTemplates.x.pz.c standardTemplates.x.pz - -#include "standardTemplates.x.pz.c" - -#else // HAVE_ZLIB - -// If we don't have zlib, just include the whole uncompressed file. - -// Regenerate this file with: - -// bin2c -n standard_templates_data -o standardTemplates.x.c -// standardTemplates.x - -#include "standardTemplates.x.c" - -#endif // HAVE_ZLIB - -#endif // CPPPARSER diff --git a/pandatool/src/xfile/standard_templates.h b/pandatool/src/xfile/standard_templates.h deleted file mode 100644 index b542f667..00000000 --- a/pandatool/src/xfile/standard_templates.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file standard_templates.h - * @author drose - * @date 2004-10-04 - */ - -#ifndef STANDARD_TEMPLATES_H -#define STANDARD_TEMPLATES_H - -#include "pandatoolbase.h" - -#ifndef CPPPARSER - -extern const unsigned char standard_templates_data[]; -extern const int standard_templates_data_len; - -#endif // CPPPARSER - -#endif diff --git a/pandatool/src/xfile/windowsGuid.I b/pandatool/src/xfile/windowsGuid.I deleted file mode 100644 index 5d0ce220..00000000 --- a/pandatool/src/xfile/windowsGuid.I +++ /dev/null @@ -1,98 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file windowsGuid.I - * @author drose - * @date 2004-10-03 - */ - -/** - * - */ -INLINE WindowsGuid:: -WindowsGuid() { - memset(this, 0, sizeof(WindowsGuid)); -} - -/** - * - */ -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) -{ -} - -/** - * - */ -INLINE WindowsGuid:: -WindowsGuid(const WindowsGuid ©) { - (*this) = copy; -} - -/** - * - */ -INLINE void WindowsGuid:: -operator = (const WindowsGuid ©) { - memcpy(this, ©, sizeof(WindowsGuid)); -} - -/** - * - */ -INLINE bool WindowsGuid:: -operator == (const WindowsGuid &other) const { - return compare_to(other) == 0; -} - -/** - * - */ -INLINE bool WindowsGuid:: -operator != (const WindowsGuid &other) const { - return compare_to(other) != 0; -} - -/** - * - */ -INLINE bool WindowsGuid:: -operator < (const WindowsGuid &other) const { - return compare_to(other) < 0; -} - -/** - * 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 std::ostream & -operator << (std::ostream &out, const WindowsGuid &guid) { - guid.output(out); - return out; -} diff --git a/pandatool/src/xfile/windowsGuid.cxx b/pandatool/src/xfile/windowsGuid.cxx deleted file mode 100644 index fbe64967..00000000 --- a/pandatool/src/xfile/windowsGuid.cxx +++ /dev/null @@ -1,76 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file windowsGuid.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "windowsGuid.h" -#include "pnotify.h" - -#include // for sscanf, sprintf - -using std::string; - -/** - * 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) { - unsigned long data1; - unsigned int data2, data3; - unsigned int b1, b2, b3, b4, b5, b6, b7, b8; - int result = sscanf(str.c_str(), - "%08lx-%04x-%04x-%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; -} - -/** - * 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((int)strlen(buffer) < buf_length, string()); - - return string(buffer); -} - -/** - * Outputs a hex representation of the GUID. - */ -void WindowsGuid:: -output(std::ostream &out) const { - out << format_string(); -} diff --git a/pandatool/src/xfile/windowsGuid.h b/pandatool/src/xfile/windowsGuid.h deleted file mode 100644 index ea79d0be..00000000 --- a/pandatool/src/xfile/windowsGuid.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file windowsGuid.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef WINDOWS_GUID_H -#define WINDOWS_GUID_H - -#include "pandatoolbase.h" - -#include // For memcpy, memcmp - -/** - * 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 ©); - INLINE void operator = (const WindowsGuid ©); - - 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 std::string &str); - std::string format_string() const; - - void output(std::ostream &out) const; - -private: - unsigned long _data1; - unsigned short _data2; - unsigned short _data3; - unsigned char _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8; -}; - -INLINE std::ostream &operator << (std::ostream &out, const WindowsGuid &guid); - -#include "windowsGuid.I" - -#endif diff --git a/pandatool/src/xfile/xFile.I b/pandatool/src/xfile/xFile.I deleted file mode 100644 index cf223955..00000000 --- a/pandatool/src/xfile/xFile.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFile.I - * @author drose - * @date 2004-10-03 - */ diff --git a/pandatool/src/xfile/xFile.cxx b/pandatool/src/xfile/xFile.cxx deleted file mode 100644 index 3c0d7b34..00000000 --- a/pandatool/src/xfile/xFile.cxx +++ /dev/null @@ -1,479 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFile.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFile.h" -#include "xParserDefs.h" -#include "xLexerDefs.h" -#include "xFileTemplate.h" -#include "xFileDataNodeTemplate.h" -#include "config_xfile.h" -#include "standard_templates.h" -#include "zStream.h" -#include "virtualFileSystem.h" -#include "dcast.h" - -using std::istream; -using std::istringstream; -using std::ostream; -using std::string; - -TypeHandle XFile::_type_handle; -PT(XFile) XFile::_standard_templates; - -/** - * - */ -XFile:: -XFile(bool keep_names) : XFileNode(this) { - _major_version = 3; - _minor_version = 2; - _format_type = FT_text; - _float_size = FS_64; - _keep_names = keep_names; -} - -/** - * - */ -XFile:: -~XFile() { - clear(); -} - -/** - * Removes all of the classes defined within the XFile and prepares it for - * reading a new file. - */ -void XFile:: -clear() { - XFileNode::clear(); - - _nodes_by_guid.clear(); -} - -/** - * 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) { - filename.set_text(); - VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); - istream *in = vfs->open_read_file(filename, true); - if (in == nullptr) { - xfile_cat.error() - << "Cannot open " << filename << " for reading.\n"; - return false; - } - bool okflag = read(*in, filename); - vfs->close_read_file(in); - return okflag; -} - -/** - * 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; - } - - // We must call this first so the standard templates file will be parsed and - // available by the time we need it--it's tricky to invoke the parser from - // within another parser instance. - get_standard_templates(); - - x_init_parser(in, filename, *this); - xyyparse(); - x_cleanup_parser(); - - return (x_error_count() == 0); -} - -/** - * 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 { - std::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; - } - -#ifdef HAVE_ZLIB - if (filename.get_extension() == "pz") { - // The filename ends in .pz, which means to automatically compress the X - // file that we write. - OCompressStream compressor(&out, false); - return write(compressor); - } -#endif // HAVE_ZLIB - - return write(out); -} - -/** - * 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; -} - -/** - * Returns the template associated with the indicated name, if any, or NULL if - * none. - */ -XFileTemplate *XFile:: -find_template(const string &name) const { - XFileTemplate *standard = nullptr; - const XFile *standard_templates = get_standard_templates(); - if (standard_templates != this) { - standard = standard_templates->find_template(name); - } - - XFileNode *child = find_child(name); - if (child != nullptr && - child->is_of_type(XFileTemplate::get_class_type())) { - XFileTemplate *xtemplate = DCAST(XFileTemplate, child); - if (standard != nullptr && xtemplate->matches(standard)) { - // If the template matches a standard template, return the standard - // instead. The assumption is that code may expect a certain naming - // scheme for the data elements of the standard template, so we want to - // be sure to provide it. - return standard; - } - return xtemplate; - } - - return standard; -} - -/** - * Returns the template associated with the indicated GUID, if any, or NULL if - * none. - */ -XFileTemplate *XFile:: -find_template(const WindowsGuid &guid) const { - XFileTemplate *standard = nullptr; - const XFile *standard_templates = get_standard_templates(); - if (standard_templates != this) { - standard = standard_templates->find_template(guid); - } - - NodesByGuid::const_iterator gi; - gi = _nodes_by_guid.find(guid); - if (gi != _nodes_by_guid.end() && - (*gi).second->is_of_type(XFileTemplate::get_class_type())) { - XFileTemplate *xtemplate = DCAST(XFileTemplate, (*gi).second); - if (standard != nullptr && xtemplate->matches(standard)) { - // If the template matches a standard template, return the standard - // instead. The assumption is that code may expect a certain naming - // scheme for the data elements of the standard template, so we want to - // be sure to provide it. - return standard; - } - return xtemplate; - } - - return standard; -} - -/** - * Returns the standard template associated with the indicated name, if any, - * or NULL if none. - */ -XFileTemplate *XFile:: -find_standard_template(const string &name) { - const XFile *standard_templates = get_standard_templates(); - return standard_templates->find_template(name); -} - -/** - * Returns the template associated with the indicated GUID, if any, or NULL if - * none. - */ -XFileTemplate *XFile:: -find_standard_template(const WindowsGuid &guid) { - const XFile *standard_templates = get_standard_templates(); - return standard_templates->find_template(guid); -} - -/** - * Returns the data object associated with the indicated name, if any, or NULL - * if none. - */ -XFileDataNodeTemplate *XFile:: -find_data_object(const string &name) const { - XFileNode *child = find_descendent(name); - if (child != nullptr && - child->is_of_type(XFileDataNodeTemplate::get_class_type())) { - return DCAST(XFileDataNodeTemplate, child); - } - - return nullptr; -} - -/** - * Returns the data object associated with the indicated GUID, if any, or NULL - * if none. - */ -XFileDataNodeTemplate *XFile:: -find_data_object(const WindowsGuid &guid) const { - NodesByGuid::const_iterator gi; - gi = _nodes_by_guid.find(guid); - if (gi != _nodes_by_guid.end() && - (*gi).second->is_of_type(XFileDataNodeTemplate::get_class_type())) { - return DCAST(XFileDataNodeTemplate, (*gi).second); - } - - return nullptr; -} - -/** - * 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"; - } -} - -/** - * 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; -} - -/** - * 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; -} - -/** - * Returns a global XFile object that contains the standard list of Direct3D - * template definitions that may be assumed to be at the head of every file. - */ -const XFile *XFile:: -get_standard_templates() { - if (_standard_templates == nullptr) { - // The standardTemplates.x file has been compiled into this binary. - // Extract it out. - - string data((const char *)standard_templates_data, standard_templates_data_len); - -#ifdef HAVE_ZLIB - // The data is stored compressed; decompress it on-the-fly. - istringstream inz(data); - IDecompressStream in(&inz, false); - -#else - // The data is stored uncompressed, so just load it. - istringstream in(data); -#endif // HAVE_ZLIB - - _standard_templates = new XFile; - if (!_standard_templates->read(in, "standardTemplates.x")) { - xfile_cat.error() - << "Internal error: Unable to parse built-in standardTemplates.x!\n"; - } - - // Now flag all of these templates as "standard". - for (int i = 0; i < _standard_templates->get_num_children(); i++) { - XFileNode *child = _standard_templates->get_child(i); - if (child->is_of_type(XFileTemplate::get_class_type())) { - XFileTemplate *xtemplate = DCAST(XFileTemplate, child); - xtemplate->_is_standard = true; - } - } - } - - return _standard_templates; -} diff --git a/pandatool/src/xfile/xFile.h b/pandatool/src/xfile/xFile.h deleted file mode 100644 index 5dacb3c4..00000000 --- a/pandatool/src/xfile/xFile.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFile.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILE_H -#define XFILE_H - -#include "pandatoolbase.h" -#include "xFileNode.h" -#include "xFileDataNode.h" -#include "windowsGuid.h" -#include "filename.h" -#include "pmap.h" -#include "pointerTo.h" - -class XFileTemplate; -class XFileDataNodeTemplate; - -/** - * 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(bool keep_names=false); - ~XFile(); - - virtual void clear() final; - - bool read(Filename filename); - bool read(std::istream &in, const std::string &filename = std::string()); - - bool write(Filename filename) const; - bool write(std::ostream &out) const; - - XFileTemplate *find_template(const std::string &name) const; - XFileTemplate *find_template(const WindowsGuid &guid) const; - - static XFileTemplate *find_standard_template(const std::string &name); - static XFileTemplate *find_standard_template(const WindowsGuid &guid); - - XFileDataNodeTemplate *find_data_object(const std::string &name) const; - XFileDataNodeTemplate *find_data_object(const WindowsGuid &guid) const; - - virtual void write_text(std::ostream &out, int indent_level) const; - - enum FormatType { - FT_text, - FT_binary, - FT_compressed, - }; - enum FloatSize { - FS_32, - FS_64, - }; - -private: - bool read_header(std::istream &in); - bool write_header(std::ostream &out) const; - - static const XFile *get_standard_templates(); - - int _major_version, _minor_version; - FormatType _format_type; - FloatSize _float_size; - bool _keep_names; - - typedef pmap NodesByGuid; - NodesByGuid _nodes_by_guid; - - static PT(XFile) _standard_templates; - -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; - - friend class XFileNode; -}; - -#include "xFile.I" - -#endif diff --git a/pandatool/src/xfile/xFileArrayDef.I b/pandatool/src/xfile/xFileArrayDef.I deleted file mode 100644 index f231f0c6..00000000 --- a/pandatool/src/xfile/xFileArrayDef.I +++ /dev/null @@ -1,60 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileArrayDef.I - * @author drose - * @date 2004-10-03 - */ - -/** - * - */ -INLINE XFileArrayDef:: -XFileArrayDef(int fixed_size) : - _fixed_size(fixed_size), - _dynamic_size(nullptr) -{ -} - -/** - * - */ -INLINE XFileArrayDef:: -XFileArrayDef(XFileDataDef *dynamic_size) : - _fixed_size(0), - _dynamic_size(dynamic_size) -{ -} - -/** - * 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 == nullptr); -} - -/** - * 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; -} - -/** - * 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(), nullptr); - return _dynamic_size; -} diff --git a/pandatool/src/xfile/xFileArrayDef.cxx b/pandatool/src/xfile/xFileArrayDef.cxx deleted file mode 100644 index 91078f55..00000000 --- a/pandatool/src/xfile/xFileArrayDef.cxx +++ /dev/null @@ -1,75 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileArrayDef.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFileArrayDef.h" -#include "xFileDataDef.h" -#include "xFileDataObject.h" - -/** - * Returns the size of the array dimension. If this is a fixed array, the - * size is trivial; if it is dynamic, the size is determined by looking up the - * dynamic_size element in the prev_data table (which lists all of the data - * values already defined at this scoping level). - */ -int XFileArrayDef:: -get_size(const XFileNode::PrevData &prev_data) const { - if (is_fixed_size()) { - return _fixed_size; - } else { - XFileNode::PrevData::const_iterator pi; - pi = prev_data.find(_dynamic_size); - nassertr_always(pi != prev_data.end(), 0); - nassertr((*pi).second != nullptr, 0); - return (*pi).second->i(); - } -} - -/** - * - */ -void XFileArrayDef:: -output(std::ostream &out) const { - if (is_fixed_size()) { - out << "[" << _fixed_size << "]"; - } else { - out << "[" << _dynamic_size->get_name() << "]"; - } -} - -/** - * Returns true if the node, particularly a template node, is structurally - * equivalent to the other node (which must be of the same type). This checks - * data element types, but does not compare data element names. - */ -bool XFileArrayDef:: -matches(const XFileArrayDef &other, const XFileDataDef *parent, - const XFileDataDef *other_parent) const { - if (other.is_fixed_size() != is_fixed_size()) { - return false; - } - if (is_fixed_size()) { - if (other.get_fixed_size() != get_fixed_size()) { - return false; - } - - } else { - int child_index = parent->find_child_index(get_dynamic_size()); - int other_child_index = - other_parent->find_child_index(other.get_dynamic_size()); - if (other_child_index != child_index) { - return false; - } - } - - return true; -} diff --git a/pandatool/src/xfile/xFileArrayDef.h b/pandatool/src/xfile/xFileArrayDef.h deleted file mode 100644 index 5871e6e2..00000000 --- a/pandatool/src/xfile/xFileArrayDef.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileArrayDef.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILEARRAYDEF_H -#define XFILEARRAYDEF_H - -#include "pandatoolbase.h" -#include "pnotify.h" -#include "xFileNode.h" - -class XFileDataDef; - -/** - * 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; - - int get_size(const XFileNode::PrevData &prev_data) const; - - void output(std::ostream &out) const; - - bool matches(const XFileArrayDef &other, const XFileDataDef *parent, - const XFileDataDef *other_parent) const; - -private: - int _fixed_size; - XFileDataDef *_dynamic_size; -}; - -#include "xFileArrayDef.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataDef.I b/pandatool/src/xfile/xFileDataDef.I deleted file mode 100644 index 65a7d9c3..00000000 --- a/pandatool/src/xfile/xFileDataDef.I +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataDef.I - * @author drose - * @date 2004-10-03 - */ - -/** - * - */ -INLINE XFileDataDef:: -XFileDataDef(XFile *x_file, const std::string &name, - XFileDataDef::Type type, XFileTemplate *xtemplate) : - XFileNode(x_file, name), - _type(type), - _template(xtemplate) -{ -} - -/** - * Returns the primitive type of this element, or T_template if this - * represents a nested template object. - */ -INLINE XFileDataDef::Type XFileDataDef:: -get_data_type() const { - return _type; -} - -/** - * If get_data_type() returned T_template, this returns the particular - * template pointer that this object represents. - */ -INLINE XFileTemplate *XFileDataDef:: -get_template() const { - return _template; -} - -/** - * Returns the number of dimensions of array elements on this data object, or - * 0 if the data object is not an array. - */ -INLINE int XFileDataDef:: -get_num_array_defs() const { - return _array_def.size(); -} - -/** - * Returns the description of the nth dimension of array elements on this data - * object. - */ -INLINE const XFileArrayDef &XFileDataDef:: -get_array_def(int i) const { - nassertr(i >= 0 && i < (int)_array_def.size(), _array_def[0]); - return _array_def[i]; -} diff --git a/pandatool/src/xfile/xFileDataDef.cxx b/pandatool/src/xfile/xFileDataDef.cxx deleted file mode 100644 index 5fe98389..00000000 --- a/pandatool/src/xfile/xFileDataDef.cxx +++ /dev/null @@ -1,496 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataDef.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFileDataDef.h" -#include "indent.h" -#include "xLexerDefs.h" -#include "xFileParseData.h" -#include "xFileDataObjectInteger.h" -#include "xFileDataObjectDouble.h" -#include "xFileDataObjectString.h" -#include "xFileDataNodeTemplate.h" -#include "xFileDataObjectArray.h" -#include "string_utils.h" - -TypeHandle XFileDataDef::_type_handle; - -/** - * - */ -XFileDataDef:: -~XFileDataDef() { - clear(); -} - -/** - * - */ -void XFileDataDef:: -clear() { - XFileNode::clear(); - _array_def.clear(); -} - -/** - * Adds an additional array dimension to the data description. - */ -void XFileDataDef:: -add_array_def(const XFileArrayDef &array_def) { - _array_def.push_back(array_def); -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataDef:: -write_text(std::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_sword: - out << "SWORD"; - break; - - case T_sdword: - out << "SDWORD"; - 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"; -} - -/** - * This is called on the template that defines an object, once the data for - * the object has been parsed. It is responsible for identifying which - * component of the template owns each data element, and packing the data - * elements appropriately back into the object. - * - * It returns true on success, or false on an error (e.g. not enough data - * elements, mismatched data type). - */ -bool XFileDataDef:: -repack_data(XFileDataObject *object, - const XFileParseDataList &parse_data_list, - XFileDataDef::PrevData &prev_data, - size_t &index, size_t &sub_index) const { - // We'll fill this in with the data value we pack, if any. - PT(XFileDataObject) data_value; - - // What kind of data element are we expecting? - switch (_type) { - case T_word: - case T_dword: - case T_char: - case T_uchar: - case T_sword: - case T_sdword: - // Expected integer data. - data_value = unpack_value(parse_data_list, 0, - prev_data, index, sub_index, - &XFileDataDef::unpack_integer_value); - break; - - case T_float: - case T_double: - data_value = unpack_value(parse_data_list, 0, - prev_data, index, sub_index, - &XFileDataDef::unpack_double_value); - break; - - case T_string: - case T_cstring: - case T_unicode: - data_value = unpack_value(parse_data_list, 0, - prev_data, index, sub_index, - &XFileDataDef::unpack_string_value); - break; - - case T_template: - data_value = unpack_value(parse_data_list, 0, - prev_data, index, sub_index, - &XFileDataDef::unpack_template_value); - break; - } - - if (data_value != nullptr) { - object->add_element(data_value); - prev_data[this] = data_value; - } - - return XFileNode::repack_data(object, parse_data_list, - prev_data, index, sub_index); -} - -/** - * This is similar to repack_data(), except it is used to fill the initial - * values for a newly-created template object to zero. - */ -bool XFileDataDef:: -fill_zero_data(XFileDataObject *object) const { - PT(XFileDataObject) data_value; - - // What kind of data element are we expecting? - switch (_type) { - case T_word: - case T_dword: - case T_char: - case T_uchar: - case T_sword: - case T_sdword: - data_value = zero_fill_value(0, &XFileDataDef::zero_fill_integer_value); - break; - - case T_float: - case T_double: - data_value = zero_fill_value(0, &XFileDataDef::zero_fill_double_value); - break; - - case T_string: - case T_cstring: - case T_unicode: - data_value = zero_fill_value(0, &XFileDataDef::zero_fill_string_value); - break; - - case T_template: - data_value = zero_fill_value(0, &XFileDataDef::zero_fill_template_value); - break; - } - - if (data_value != nullptr) { - object->add_element(data_value); - } - - return XFileNode::fill_zero_data(object); -} - -/** - * Returns true if the node, particularly a template node, is structurally - * equivalent to the other node (which must be of the same type). This checks - * data element types, but does not compare data element names. - */ -bool XFileDataDef:: -matches(const XFileNode *other) const { - if (!XFileNode::matches(other)) { - return false; - } - - const XFileDataDef *data_def = DCAST(XFileDataDef, other); - if (data_def->get_data_type() != get_data_type()) { - return false; - } - - if (get_data_type() == T_template && - !get_template()->matches(data_def->get_template())) { - return false; - } - - if (data_def->get_num_array_defs() != get_num_array_defs()) { - return false; - } - - for (int i = 0; i < get_num_array_defs(); i++) { - if (!get_array_def(i).matches(data_def->get_array_def(i), - this, data_def)) { - return false; - } - } - - return true; -} - - -/** - * Unpacks and returns the next sequential integer value from the - * parse_data_list. - */ -PT(XFileDataObject) XFileDataDef:: -unpack_integer_value(const XFileParseDataList &parse_data_list, - const XFileDataDef::PrevData &prev_data, - size_t &index, size_t &sub_index) const { - nassertr(index < parse_data_list._list.size(), nullptr); - const XFileParseData &parse_data = parse_data_list._list[index]; - - PT(XFileDataObject) data_value; - - if ((parse_data._parse_flags & XFileParseData::PF_int) != 0) { - nassertr(sub_index < parse_data._int_list.size(), nullptr); - int value = parse_data._int_list[sub_index]; - data_value = new XFileDataObjectInteger(this, value); - - sub_index++; - if (sub_index >= parse_data._int_list.size()) { - index++; - sub_index = 0; - } - - } else { - parse_data.yyerror("Expected integer data for " + get_name()); - } - - return data_value; -} - -/** - * Unpacks and returns the next sequential double value from the - * parse_data_list. - */ -PT(XFileDataObject) XFileDataDef:: -unpack_double_value(const XFileParseDataList &parse_data_list, - const XFileDataDef::PrevData &prev_data, - size_t &index, size_t &sub_index) const { - nassertr(index < parse_data_list._list.size(), nullptr); - const XFileParseData &parse_data = parse_data_list._list[index]; - - PT(XFileDataObject) data_value; - - if ((parse_data._parse_flags & XFileParseData::PF_double) != 0) { - nassertr(sub_index < parse_data._double_list.size(), nullptr); - double value = parse_data._double_list[sub_index]; - data_value = new XFileDataObjectDouble(this, value); - - sub_index++; - if (sub_index >= parse_data._double_list.size()) { - index++; - sub_index = 0; - } - - } else if ((parse_data._parse_flags & XFileParseData::PF_int) != 0) { - nassertr(sub_index < parse_data._int_list.size(), nullptr); - int value = parse_data._int_list[sub_index]; - data_value = new XFileDataObjectDouble(this, value); - - sub_index++; - if (sub_index >= parse_data._int_list.size()) { - index++; - sub_index = 0; - } - - } else { - parse_data.yyerror("Expected floating-point data for " + get_name()); - } - - return data_value; -} - -/** - * Unpacks and returns the next sequential string value from the - * parse_data_list. - */ -PT(XFileDataObject) XFileDataDef:: -unpack_string_value(const XFileParseDataList &parse_data_list, - const XFileDataDef::PrevData &prev_data, - size_t &index, size_t &sub_index) const { - nassertr(index < parse_data_list._list.size(), nullptr); - const XFileParseData &parse_data = parse_data_list._list[index]; - - PT(XFileDataObject) data_value; - - if ((parse_data._parse_flags & XFileParseData::PF_string) != 0) { - data_value = new XFileDataObjectString(this, parse_data._string); - index++; - sub_index = 0; - - } else { - parse_data.yyerror("Expected string data for " + get_name()); - } - - return data_value; -} - -/** - * Unpacks a nested template object's data. - */ -PT(XFileDataObject) XFileDataDef:: -unpack_template_value(const XFileParseDataList &parse_data_list, - const XFileDataDef::PrevData &prev_data, - size_t &index, size_t &sub_index) const { - PT(XFileDataNodeTemplate) data_value = - new XFileDataNodeTemplate(get_x_file(), get_name(), _template); - - PrevData nested_prev_data(prev_data); - if (!_template->repack_data(data_value, parse_data_list, - nested_prev_data, index, sub_index)) { - return nullptr; - } - - return data_value; -} - -/** - * Unpacks and returns the next sequential value, of the type supported by the - * unpack_method. If the value is an array type, unpacks all the elements of - * the array. - */ -PT(XFileDataObject) XFileDataDef:: -unpack_value(const XFileParseDataList &parse_data_list, int array_index, - const XFileDataDef::PrevData &prev_data, - size_t &index, size_t &sub_index, - XFileDataDef::UnpackMethod unpack_method) const { - PT(XFileDataObject) data_value; - - if (array_index == (int)_array_def.size()) { - if (index >= parse_data_list._list.size()) { - xyyerror("Not enough data elements in structure at " + get_name()); - return nullptr; - } - data_value = (this->*unpack_method)(parse_data_list, prev_data, - index, sub_index); - - } else { - data_value = new XFileDataObjectArray(this); - int array_size = _array_def[array_index].get_size(prev_data); - - for (int i = 0; i < array_size; i++) { - if (index >= parse_data_list._list.size()) { - xyyerror(std::string("Expected ") + format_string(array_size) - + " array elements, found " + format_string(i)); - return data_value; - } - - PT(XFileDataObject) array_element = - unpack_value(parse_data_list, array_index + 1, - prev_data, index, sub_index, - unpack_method); - if (array_element == nullptr) { - return data_value; - } - data_value->add_element(array_element); - } - } - - return data_value; -} - -/** - * Returns a newly-allocated zero integer value. - */ -PT(XFileDataObject) XFileDataDef:: -zero_fill_integer_value() const { - return new XFileDataObjectInteger(this, 0); -} - -/** - * Returns a newly-allocated zero floating-point value. - */ -PT(XFileDataObject) XFileDataDef:: -zero_fill_double_value() const { - return new XFileDataObjectDouble(this, 0.0); -} - -/** - * Returns a newly-allocated empty string value. - */ -PT(XFileDataObject) XFileDataDef:: -zero_fill_string_value() const { - return new XFileDataObjectString(this, ""); -} - -/** - * Returns a newly-allocated zero-filled nested template value. - */ -PT(XFileDataObject) XFileDataDef:: -zero_fill_template_value() const { - PT(XFileDataObject) data_value = - new XFileDataNodeTemplate(get_x_file(), get_name(), _template); - if (!_template->fill_zero_data(data_value)) { - return nullptr; - } - - return data_value; -} - -/** - * Creates a zero-valued element for the next sequential value, of the type - * returned by the zero_fill_method. If the value is a fixed-size array type, - * zero-fills all the elements of the array. - */ -PT(XFileDataObject) XFileDataDef:: -zero_fill_value(int array_index, - XFileDataDef::ZeroFillMethod zero_fill_method) const { - PT(XFileDataObject) data_value; - - if (array_index == (int)_array_def.size()) { - data_value = (this->*zero_fill_method)(); - - } else { - data_value = new XFileDataObjectArray(this); - int array_size = 0; - if (_array_def[array_index].is_fixed_size()) { - array_size = _array_def[array_index].get_fixed_size(); - } - - for (int i = 0; i < array_size; i++) { - PT(XFileDataObject) array_element = - zero_fill_value(array_index + 1, zero_fill_method); - if (array_element == nullptr) { - return nullptr; - } - data_value->add_element(array_element); - } - } - - return data_value; -} diff --git a/pandatool/src/xfile/xFileDataDef.h b/pandatool/src/xfile/xFileDataDef.h deleted file mode 100644 index adcac50d..00000000 --- a/pandatool/src/xfile/xFileDataDef.h +++ /dev/null @@ -1,137 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataDef.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILEDATADEF_H -#define XFILEDATADEF_H - -#include "pandatoolbase.h" -#include "namable.h" -#include "xFileNode.h" -#include "xFileArrayDef.h" -#include "xFileTemplate.h" -#include "xFileDataObject.h" -#include "pvector.h" -#include "pointerTo.h" - -/** - * A definition of a single data element appearing within a template record. - * This class represents the *definition* of the data element (e.g. DWORD - * nVertices); see XFileDataObject for its *value* (e.g. 12). - */ -class XFileDataDef : public XFileNode { -public: - enum Type { - T_word, - T_dword, - T_float, - T_double, - T_char, - T_uchar, - T_sword, - T_sdword, - T_string, - T_cstring, - T_unicode, - T_template, - }; - - INLINE XFileDataDef(XFile *x_file, const std::string &name, - Type type, XFileTemplate *xtemplate = nullptr); - virtual ~XFileDataDef(); - - virtual void clear() final; - void add_array_def(const XFileArrayDef &array_def); - - INLINE Type get_data_type() const; - INLINE XFileTemplate *get_template() const; - - INLINE int get_num_array_defs() const; - INLINE const XFileArrayDef &get_array_def(int i) const; - - virtual void write_text(std::ostream &out, int indent_level) const; - - virtual bool repack_data(XFileDataObject *object, - const XFileParseDataList &parse_data_list, - PrevData &prev_data, - size_t &index, size_t &sub_index) const; - - virtual bool fill_zero_data(XFileDataObject *object) const; - - virtual bool matches(const XFileNode *other) const; - -private: - typedef PT(XFileDataObject) - (XFileDataDef::*UnpackMethod)(const XFileParseDataList &parse_data_list, - const PrevData &prev_data, - size_t &index, size_t &sub_index) const; - typedef PT(XFileDataObject) - (XFileDataDef::*ZeroFillMethod)() const; - - PT(XFileDataObject) - unpack_integer_value(const XFileParseDataList &parse_data_list, - const PrevData &prev_data, - size_t &index, size_t &sub_index) const; - PT(XFileDataObject) - unpack_double_value(const XFileParseDataList &parse_data_list, - const PrevData &prev_data, - size_t &index, size_t &sub_index) const; - PT(XFileDataObject) - unpack_string_value(const XFileParseDataList &parse_data_list, - const PrevData &prev_data, - size_t &index, size_t &sub_index) const; - PT(XFileDataObject) - unpack_template_value(const XFileParseDataList &parse_data_list, - const PrevData &prev_data, - size_t &index, size_t &sub_index) const; - - PT(XFileDataObject) - unpack_value(const XFileParseDataList &parse_data_list, int array_index, - const PrevData &prev_data, - size_t &index, size_t &sub_index, - UnpackMethod unpack_method) const; - - PT(XFileDataObject) zero_fill_integer_value() const; - PT(XFileDataObject) zero_fill_double_value() const; - PT(XFileDataObject) zero_fill_string_value() const; - PT(XFileDataObject) zero_fill_template_value() const; - PT(XFileDataObject) - zero_fill_value(int array_index, ZeroFillMethod zero_fill_method) const; - -private: - Type _type; - PT(XFileTemplate) _template; - - typedef pvector 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 diff --git a/pandatool/src/xfile/xFileDataNode.I b/pandatool/src/xfile/xFileDataNode.I deleted file mode 100644 index 5591778e..00000000 --- a/pandatool/src/xfile/xFileDataNode.I +++ /dev/null @@ -1,45 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNode.I - * @author drose - * @date 2004-10-08 - */ - -/** - * Since the children of an XFileDataNode are syntactically constrained to - * themselves be XFileDataNodes, this is a convenience function that returns - * the same thing as XFileNode::get_child(), but it is cast to a type - * XFileDataNode and dereferenced. - */ -INLINE const XFileDataNode &XFileDataNode:: -get_data_child(int n) const { - return *DCAST(XFileDataNode, get_child(n)); -} - - -/** - * Returns the template used to define this data object. Since the only - * classes to inherit from XFileDataNode are XFileDataNodeTemplate and - * XFileDataNodeReference, both of which represent a class that is defined by - * a template, it makes sense to put this common method here in the base - * class. - */ -INLINE XFileTemplate *XFileDataNode:: -get_template() const { - return _template; -} - -/** - * A convenience function to return the name of the template used to define - * this data object. - */ -INLINE const std::string &XFileDataNode:: -get_template_name() const { - return _template->get_name(); -} diff --git a/pandatool/src/xfile/xFileDataNode.cxx b/pandatool/src/xfile/xFileDataNode.cxx deleted file mode 100644 index bc132669..00000000 --- a/pandatool/src/xfile/xFileDataNode.cxx +++ /dev/null @@ -1,65 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNode.cxx - * @author drose - * @date 2004-10-08 - */ - -#include "xFileDataNode.h" -#include "indent.h" - -TypeHandle XFileDataNode::_type_handle; - -/** - * - */ -XFileDataNode:: -XFileDataNode(XFile *x_file, const std::string &name, - XFileTemplate *xtemplate) : - XFileNode(x_file, name), - _template(xtemplate) -{ -} - -/** - * Returns true if this node represents a data object that is the instance of - * some template, or false otherwise. This also returns true for references - * to objects (which are generally treated just like the objects themselves). - * - * If this returns true, the node must be of type XFileDataNode (it is either - * an XFileDataNodeTemplate or an XFileDataNodeReference). - */ -bool XFileDataNode:: -is_object() const { - return true; -} - -/** - * Returns true if this node represents an instance of the standard template - * with the indicated name, or false otherwise. If this returns true, the - * object must be of type XFileDataNode. - */ -bool XFileDataNode:: -is_standard_object(const std::string &template_name) const { - if (_template->is_standard() && - _template->get_name() == template_name) { - return true; - } - - return false; -} - -/** - * Returns a string that represents the type of object this data object - * represents. - */ -std::string XFileDataNode:: -get_type_name() const { - return _template->get_name(); -} diff --git a/pandatool/src/xfile/xFileDataNode.h b/pandatool/src/xfile/xFileDataNode.h deleted file mode 100644 index c04df4a3..00000000 --- a/pandatool/src/xfile/xFileDataNode.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNode.h - * @author drose - * @date 2004-10-08 - */ - -#ifndef XFILEDATANODE_H -#define XFILEDATANODE_H - -#include "pandatoolbase.h" -#include "xFileNode.h" -#include "xFileDataObject.h" -#include "xFileTemplate.h" -#include "pointerTo.h" -#include "dcast.h" - -/** - * This is an abstract base class for an XFileNode which is also an - * XFileDataObject. That is to say, objects that inherit from this class may - * be added to the toplevel X file graph as nodes, and they also may be - * containers for data elements. - * - * Specifically, this is the base class of both XFileDataNodeTemplate and - * XFileDataNodeReference. - */ -class XFileDataNode : public XFileNode, public XFileDataObject { -public: - XFileDataNode(XFile *x_file, const std::string &name, - XFileTemplate *xtemplate); - - virtual bool is_object() const; - virtual bool is_standard_object(const std::string &template_name) const; - virtual std::string get_type_name() const; - - INLINE const XFileDataNode &get_data_child(int n) const; - - INLINE XFileTemplate *get_template() const; - INLINE const std::string &get_template_name() const; - -protected: - PT(XFileTemplate) _template; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - XFileNode::init_type(); - XFileDataObject::init_type(); - register_type(_type_handle, "XFileDataNode", - XFileNode::get_class_type(), - XFileDataObject::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 "xFileDataNode.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataNodeReference.I b/pandatool/src/xfile/xFileDataNodeReference.I deleted file mode 100644 index ea98beec..00000000 --- a/pandatool/src/xfile/xFileDataNodeReference.I +++ /dev/null @@ -1,20 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNodeReference.I - * @author drose - * @date 2004-10-08 - */ - -/** - * Returns the actual data object being referenced. - */ -INLINE XFileDataNodeTemplate *XFileDataNodeReference:: -get_object() const { - return _object; -} diff --git a/pandatool/src/xfile/xFileDataNodeReference.cxx b/pandatool/src/xfile/xFileDataNodeReference.cxx deleted file mode 100644 index 7796aeee..00000000 --- a/pandatool/src/xfile/xFileDataNodeReference.cxx +++ /dev/null @@ -1,94 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNodeReference.cxx - * @author drose - * @date 2004-10-08 - */ - -#include "xFileDataNodeReference.h" -#include "indent.h" - -TypeHandle XFileDataNodeReference::_type_handle; - -/** - * - */ -XFileDataNodeReference:: -XFileDataNodeReference(XFileDataNodeTemplate *object) : - XFileDataNode(object->get_x_file(), object->get_name(), - object->get_template()), - _object(object) -{ - // We steal a copy of the referenced object's children. This is just a one- - // time copy, so if you go and change the list of children of the referenced - // object, it won't be reflected here in the reference. Since presumably - // the reference is only used when parsing static files, that shouldn't be a - // problem; but you do need to be aware of it. - _children = object->_children; - _objects = object->_objects; - _children_by_name = object->_children_by_name; -} - -/** - * Returns true if this node represents an indirect reference to an object - * defined previously in the file. References are generally transparent, so - * in most cases you never need to call this, unless you actually need to - * differentiate between references and instances; you can simply use the - * reference node as if it were itself the object it references. - * - * If this returns true, the node must be of type XFileDataNodeReference. - */ -bool XFileDataNodeReference:: -is_reference() const { - return true; -} - -/** - * Returns true if this kind of data object is a complex object that can hold - * nested data elements, false otherwise. - */ -bool XFileDataNodeReference:: -is_complex_object() const { - return true; -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataNodeReference:: -write_text(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << "{ " << _object->get_name() << " }\n"; -} - -/** - * Returns the number of nested data elements within the object. This may be, - * e.g. the size of the array, if it is an array. - */ -int XFileDataNodeReference:: -get_num_elements() const { - return _object->size(); -} - -/** - * Returns the nth nested data element within the object. - */ -XFileDataObject *XFileDataNodeReference:: -get_element(int n) { - return &((*_object)[n]); -} - -/** - * Returns the nested data element within the object that has the indicated - * name. - */ -XFileDataObject *XFileDataNodeReference:: -get_element(const std::string &name) { - return &((*_object)[name]); -} diff --git a/pandatool/src/xfile/xFileDataNodeReference.h b/pandatool/src/xfile/xFileDataNodeReference.h deleted file mode 100644 index f1e9eb4c..00000000 --- a/pandatool/src/xfile/xFileDataNodeReference.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNodeReference.h - * @author drose - * @date 2004-10-08 - */ - -#ifndef XFILEDATANODEREFERENCE_H -#define XFILEDATANODEREFERENCE_H - -#include "pandatoolbase.h" -#include "xFileDataNodeTemplate.h" -#include "pointerTo.h" - -/** - * This is a nested reference to an instance of a template object, declared - * via the syntax: - * - * { InstanceName } - * - * in the X File. - */ -class XFileDataNodeReference : public XFileDataNode { -public: - XFileDataNodeReference(XFileDataNodeTemplate *object); - - INLINE XFileTemplate *get_template() const; - INLINE XFileDataNodeTemplate *get_object() const; - - virtual bool is_reference() const; - virtual bool is_complex_object() const; - - virtual void write_text(std::ostream &out, int indent_level) const; - -protected: - virtual int get_num_elements() const; - virtual XFileDataObject *get_element(int n); - virtual XFileDataObject *get_element(const std::string &name); - -private: - PT(XFileDataNodeTemplate) _object; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - XFileDataNode::init_type(); - register_type(_type_handle, "XFileDataNodeReference", - XFileDataNode::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 "xFileDataNodeReference.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataNodeTemplate.I b/pandatool/src/xfile/xFileDataNodeTemplate.I deleted file mode 100644 index 5e3f6604..00000000 --- a/pandatool/src/xfile/xFileDataNodeTemplate.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNodeTemplate.I - * @author drose - * @date 2004-10-03 - */ diff --git a/pandatool/src/xfile/xFileDataNodeTemplate.cxx b/pandatool/src/xfile/xFileDataNodeTemplate.cxx deleted file mode 100644 index 64647169..00000000 --- a/pandatool/src/xfile/xFileDataNodeTemplate.cxx +++ /dev/null @@ -1,228 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNodeTemplate.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFileDataNodeTemplate.h" -#include "indent.h" -#include "xFileParseData.h" -#include "xLexerDefs.h" -#include "config_xfile.h" - -using std::string; - -TypeHandle XFileDataNodeTemplate::_type_handle; - -/** - * - */ -XFileDataNodeTemplate:: -XFileDataNodeTemplate(XFile *x_file, const string &name, - XFileTemplate *xtemplate) : - XFileDataNode(x_file, name, xtemplate) -{ -} - -/** - * Fills the data node with zero-valued elements appropriate to the template. - */ -void XFileDataNodeTemplate:: -zero_fill() { - _template->fill_zero_data(this); -} - -/** - * Returns true if this kind of data object is a complex object that can hold - * nested data elements, false otherwise. - */ -bool XFileDataNodeTemplate:: -is_complex_object() const { - return true; -} - -/** - * Adds the indicated list of doubles as a data element encountered in the - * parser. It will later be processed by finalize_parse_data(). - */ -void XFileDataNodeTemplate:: -add_parse_double(PTA_double double_list) { - XFileParseData pdata; - pdata._double_list = double_list; - pdata._parse_flags = XFileParseData::PF_double; - - _parse_data_list._list.push_back(pdata); -} - -/** - * Adds the indicated list of ints as a data element encountered in the - * parser. It will later be processed by finalize_parse_data(). - */ -void XFileDataNodeTemplate:: -add_parse_int(PTA_int int_list) { - XFileParseData pdata; - pdata._int_list = int_list; - pdata._parse_flags = XFileParseData::PF_int; - - _parse_data_list._list.push_back(pdata); -} - -/** - * Adds the indicated string as a data element encountered in the parser. It - * will later be processed by finalize_parse_data(). - */ -void XFileDataNodeTemplate:: -add_parse_string(const string &str) { - XFileParseData pdata; - pdata._string = str; - pdata._parse_flags = XFileParseData::PF_string; - - _parse_data_list._list.push_back(pdata); -} - -/** - * Processes all of the data elements added by add_parse_*(), checks them for - * syntactic and semantic correctness against the Template definition, and - * stores the appropriate child data elements. Returns true on success, false - * if there is a mismatch. - */ -bool XFileDataNodeTemplate:: -finalize_parse_data() { - // Recursively walk through our template definition, while simultaneously - // walking through the list of parse data elements we encountered, and re- - // pack them as actual nested elements. - PrevData prev_data; - size_t index = 0; - size_t sub_index = 0; - - if (!_template->repack_data(this, _parse_data_list, - prev_data, index, sub_index)) { - return false; - } - - if (index != _parse_data_list._list.size()) { - xyywarning("Too many data elements in structure."); - } - - return true; -} - -/** - * Adds the indicated element as a nested data element, if this data object - * type supports it. Returns true if added successfully, false if the data - * object type does not support nested data elements. - */ -bool XFileDataNodeTemplate:: -add_element(XFileDataObject *element) { - _nested_elements.push_back(element); - return true; -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataNodeTemplate:: -write_text(std::ostream &out, int indent_level) const { - indent(out, indent_level) - << _template->get_name(); - if (has_name()) { - out << " " << get_name(); - } - out << " {\n"; - - NestedElements::const_iterator ni; - for (ni = _nested_elements.begin(); ni != _nested_elements.end(); ++ni) { - (*ni)->write_data(out, indent_level + 2, ";"); - } - - XFileNode::write_text(out, indent_level + 2); - indent(out, indent_level) - << "}\n"; -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataNodeTemplate:: -write_data(std::ostream &out, int indent_level, const char *separator) const { - if (!_nested_elements.empty()) { - bool indented = false; - for (size_t i = 0; i < _nested_elements.size() - 1; i++) { - XFileDataObject *object = _nested_elements[i]; - if (object->is_complex_object()) { - // If we have a "complex" nested object, output it on its own line. - if (indented) { - out << "\n"; - indented = false; - } - object->write_data(out, indent_level, ";"); - - } else { - // Otherwise, output them all on the same line. - if (!indented) { - indent(out, indent_level); - indented = true; - } - out << *object << "; "; - } - } - - // The last object is the set is different, because it gets separator - // appended to it, and it always gets a newline. - XFileDataObject *object = _nested_elements.back(); - if (object->is_complex_object()) { - if (indented) { - out << "\n"; - } - string combined_separator = string(";") + string(separator); - object->write_data(out, indent_level, combined_separator.c_str()); - - } else { - if (!indented) { - indent(out, indent_level); - } - out << *object << ";" << separator << "\n"; - } - } -} - -/** - * Returns the number of nested data elements within the object. This may be, - * e.g. the size of the array, if it is an array. - */ -int XFileDataNodeTemplate:: -get_num_elements() const { - return _nested_elements.size(); -} - -/** - * Returns the nth nested data element within the object. - */ -XFileDataObject *XFileDataNodeTemplate:: -get_element(int n) { - nassertr(n >= 0 && n < (int)_nested_elements.size(), nullptr); - return _nested_elements[n]; -} - -/** - * Returns the nested data element within the object that has the indicated - * name. - */ -XFileDataObject *XFileDataNodeTemplate:: -get_element(const string &name) { - int child_index = _template->find_child_index(name); - if (child_index >= 0) { - return get_element(child_index); - } - xfile_cat.warning() - << "\"" << name << "\" not a member of " << _template->get_name() - << "\n"; - return nullptr; -} diff --git a/pandatool/src/xfile/xFileDataNodeTemplate.h b/pandatool/src/xfile/xFileDataNodeTemplate.h deleted file mode 100644 index 521c3752..00000000 --- a/pandatool/src/xfile/xFileDataNodeTemplate.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataNodeTemplate.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILEDATANODETEMPLATE_H -#define XFILEDATANODETEMPLATE_H - -#include "pandatoolbase.h" -#include "xFileDataNode.h" -#include "xFileTemplate.h" -#include "xFileParseData.h" -#include "pointerTo.h" -#include "pta_int.h" -#include "pta_double.h" - -/** - * This is a node which contains all of the data elements defined by a - * template. See XFileTemplate for the definition of the template; this class - * only contains the data members for a particular instance of a template. - */ -class XFileDataNodeTemplate : public XFileDataNode { -public: - XFileDataNodeTemplate(XFile *x_file, const std::string &name, - XFileTemplate *xtemplate); - - void zero_fill(); - - virtual bool is_complex_object() const; - - void add_parse_double(PTA_double double_list); - void add_parse_int(PTA_int int_list); - void add_parse_string(const std::string &str); - bool finalize_parse_data(); - - virtual bool add_element(XFileDataObject *element); - - virtual void write_text(std::ostream &out, int indent_level) const; - virtual void write_data(std::ostream &out, int indent_level, - const char *separator) const; - -protected: - virtual int get_num_elements() const; - virtual XFileDataObject *get_element(int n); - virtual XFileDataObject *get_element(const std::string &name); - -private: - XFileParseDataList _parse_data_list; - - typedef pvector< PT(XFileDataObject) > NestedElements; - NestedElements _nested_elements; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - XFileDataNode::init_type(); - register_type(_type_handle, "XFileDataNodeTemplate", - XFileDataNode::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 "xFileDataNodeTemplate.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataObject.I b/pandatool/src/xfile/xFileDataObject.I deleted file mode 100644 index 269bc0b0..00000000 --- a/pandatool/src/xfile/xFileDataObject.I +++ /dev/null @@ -1,304 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObject.I - * @author drose - * @date 2004-10-03 - */ - -/** - * - */ -INLINE XFileDataObject:: -XFileDataObject(const XFileDataDef *data_def) : - _data_def(data_def) -{ -} - -/** - * Returns the data object that this object is represented by, if any, or NULL - * if there is none. - */ -INLINE const XFileDataDef *XFileDataObject:: -get_data_def() const { - return _data_def; -} - -/** - * Stores the indicated integer value into the object, if it makes sense to do - * so. It is an error to call this on an object that cannot accept an integer - * value. - */ -INLINE void XFileDataObject:: -operator = (int int_value) { - set(int_value); -} - -/** - * Stores the indicated floating-point value into the object, if it makes - * sense to do so. It is an error to call this on an object that cannot - * accept a floating-point value. - */ -INLINE void XFileDataObject:: -operator = (double double_value) { - set(double_value); -} - -/** - * Stores the indicated string value into the object, if it makes sense to do - * so. It is an error to call this on an object that cannot accept a string - * value. - */ -INLINE void XFileDataObject:: -operator = (const std::string &string_value) { - set(string_value); -} - -/** - * Stores the indicated Vec2 value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store two - * floating-point values. - */ -INLINE void XFileDataObject:: -operator = (const LVecBase2d &vec) { - set(vec); -} - -/** - * Stores the indicated Vec3 value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store three - * floating-point values. - */ -INLINE void XFileDataObject:: -operator = (const LVecBase3d &vec) { - set(vec); -} - -/** - * Stores the indicated Vec4 value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store four - * floating-point values. - */ -INLINE void XFileDataObject:: -operator = (const LVecBase4d &vec) { - set(vec); -} - -/** - * Stores the indicated Matrix value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store sixteen - * floating-point values. - */ -INLINE void XFileDataObject:: -operator = (const LMatrix4d &mat) { - set(mat); -} - -/** - * Stores the indicated integer value into the object, if it makes sense to do - * so. It is an error to call this on an object that cannot accept an integer - * value. - */ -INLINE void XFileDataObject:: -set(int int_value) { - set_int_value(int_value); -} - -/** - * Stores the indicated floating-point value into the object, if it makes - * sense to do so. It is an error to call this on an object that cannot - * accept a floating-point value. - */ -INLINE void XFileDataObject:: -set(double double_value) { - set_double_value(double_value); -} - -/** - * Stores the indicated string value into the object, if it makes sense to do - * so. It is an error to call this on an object that cannot accept a string - * value. - */ -INLINE void XFileDataObject:: -set(const std::string &string_value) { - set_string_value(string_value); -} - -/** - * Stores the indicated Vec2 value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store two - * floating-point values. - */ -INLINE void XFileDataObject:: -set(const LVecBase2d &vec) { - store_double_array(2, vec.get_data()); -} - -/** - * Stores the indicated Vec3 value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store three - * floating-point values. - */ -INLINE void XFileDataObject:: -set(const LVecBase3d &vec) { - store_double_array(3, vec.get_data()); -} - -/** - * Stores the indicated Vec4 value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store four - * floating-point values. - */ -INLINE void XFileDataObject:: -set(const LVecBase4d &vec) { - store_double_array(4, vec.get_data()); -} - -/** - * Stores the indicated Matrix value into the object, if it makes sense to do - * so. It is an error to call this on an object that does not store sixteen - * floating-point values. - */ -INLINE void XFileDataObject:: -set(const LMatrix4d &mat) { - store_double_array(16, mat.get_data()); -} - -/** - * Unambiguously returns the object's representation as an integer, or 0 if - * the object has no integer representation. See also get_data_def() to - * determine what kind of representation this object has. - */ -INLINE int XFileDataObject:: -i() const { - return get_int_value(); -} - -/** - * Unambiguously returns the object's representation as a double, or 0.0 if - * the object has no double representation. See also get_data_def() to - * determine what kind of representation this object has. - */ -INLINE double XFileDataObject:: -d() const { - return get_double_value(); -} - -/** - * Unambiguously returns the object's representation as a string, or empty - * string if the object has no string representation. See also get_data_def() - * to determine what kind of representation this object has. - */ -INLINE std::string XFileDataObject:: -s() const { - return get_string_value(); -} - -/** - * Returns the object's representation as an LVecBase2d. It is an error if - * the object does not have two nested objects that store a double value. - */ -INLINE LVecBase2d XFileDataObject:: -vec2() const { - LVecBase2d vec; - get_double_array(2, &vec[0]); - return vec; -} - -/** - * Returns the object's representation as an LVecBase3d. It is an error if - * the object does not have three nested objects that store a double value. - */ -INLINE LVecBase3d XFileDataObject:: -vec3() const { - LVecBase3d vec; - get_double_array(3, &vec[0]); - return vec; -} - -/** - * Returns the object's representation as an LVecBase4d. It is an error if - * the object does not have four nested objects that store a double value. - */ -INLINE LVecBase4d XFileDataObject:: -vec4() const { - LVecBase4d vec; - get_double_array(4, &vec[0]); - return vec; -} - -/** - * Returns the object's representation as an LMatrix4d. It is an error if the - * object does not have sixteen nested objects that store a double value. - */ -INLINE LMatrix4d XFileDataObject:: -mat4() const { - LMatrix4d mat; - get_double_array(16, &mat(0, 0)); - return mat; -} - -/** - * Returns the number of nested data objects within this object. - */ -INLINE int XFileDataObject:: -size() const { - return get_num_elements(); -} - -/** - * Returns the nth nested object within this object. Call get_num_children() - * to determine the number of nested objects. - */ -INLINE const XFileDataObject &XFileDataObject:: -operator [] (int n) const { - const XFileDataObject *element = ((XFileDataObject *)this)->get_element(n); - nassertr(element != nullptr, *this); - return *element; -} - -/** - * Returns the named nested object within this object. It is an error if the - * named object does not exist. Call find_child() instead if there is any - * doubt. - */ -INLINE const XFileDataObject &XFileDataObject:: -operator [] (const std::string &name) const { - const XFileDataObject *element = ((XFileDataObject *)this)->get_element(name); - nassertr(element != nullptr, *this); - return *element; -} - -/** - * Returns the nth nested object within this object. Call get_num_children() - * to determine the number of nested objects. - */ -INLINE XFileDataObject &XFileDataObject:: -operator [] (int n) { - XFileDataObject *element = get_element(n); - nassertr(element != nullptr, *this); - return *element; -} - -/** - * Returns the named nested object within this object. It is an error if the - * named object does not exist. Call find_child() instead if there is any - * doubt. - */ -INLINE XFileDataObject &XFileDataObject:: -operator [] (const std::string &name) { - XFileDataObject *element = get_element(name); - nassertr(element != nullptr, *this); - return *element; -} - -INLINE std::ostream & -operator << (std::ostream &out, const XFileDataObject &data_object) { - data_object.output_data(out); - return out; -} diff --git a/pandatool/src/xfile/xFileDataObject.cxx b/pandatool/src/xfile/xFileDataObject.cxx deleted file mode 100644 index f3cf0b03..00000000 --- a/pandatool/src/xfile/xFileDataObject.cxx +++ /dev/null @@ -1,306 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObject.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFileDataObject.h" -#include "xFileTemplate.h" -#include "xFile.h" -#include "xFileDataNodeTemplate.h" -#include "xFileDataObjectInteger.h" -#include "xFileDataObjectDouble.h" -#include "xFileDataObjectString.h" -#include "config_xfile.h" -#include "indent.h" - -using std::string; - -TypeHandle XFileDataObject::_type_handle; - -/** - * - */ -XFileDataObject:: -~XFileDataObject() { -} - -/** - * Returns true if this kind of data object is a complex object that can hold - * nested data elements, false otherwise. - */ -bool XFileDataObject:: -is_complex_object() const { - return false; -} - -/** - * Returns a string that represents the type of object this data object - * represents. - */ -string XFileDataObject:: -get_type_name() const { - return get_type().get_name(); -} - -/** - * Appends a new integer value to the data object, if it makes sense to do so. - * Normally, this is valid only for a DataObjectArray, or in certain special - * cases for a DataNodeTemplate. - */ -XFileDataObject &XFileDataObject:: -add_int(int int_value) { - XFileDataObject *object = - new XFileDataObjectInteger(get_data_def(), int_value); - add_element(object); - return *object; -} - -/** - * Appends a new floating-point value to the data object, if it makes sense to - * do so. Normally, this is valid only for a DataObjectArray, or in certain - * special cases for a DataNodeTemplate. - */ -XFileDataObject &XFileDataObject:: -add_double(double double_value) { - XFileDataObject *object = - new XFileDataObjectDouble(get_data_def(), double_value); - add_element(object); - return *object; -} - -/** - * Appends a new string value to the data object, if it makes sense to do so. - * Normally, this is valid only for a DataObjectArray, or in certain special - * cases for a DataNodeTemplate. - */ -XFileDataObject &XFileDataObject:: -add_string(const string &string_value) { - XFileDataObject *object = - new XFileDataObjectString(get_data_def(), string_value); - add_element(object); - return *object; -} - -/** - * Appends a new Vector instance. - */ -XFileDataObject &XFileDataObject:: -add_Vector(XFile *x_file, const LVecBase3d &vector) { - XFileTemplate *xtemplate = XFile::find_standard_template("Vector"); - nassertr(xtemplate != nullptr, *this); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(x_file, "", xtemplate); - add_element(node); - node->zero_fill(); - - node->set(vector); - - return *node; -} - -/** - * Appends a new MeshFace instance. - */ -XFileDataObject &XFileDataObject:: -add_MeshFace(XFile *x_file) { - XFileTemplate *xtemplate = XFile::find_standard_template("MeshFace"); - nassertr(xtemplate != nullptr, *this); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(x_file, "", xtemplate); - add_element(node); - node->zero_fill(); - - return *node; -} - -/** - * Appends a new IndexedColor instance. - */ -XFileDataObject &XFileDataObject:: -add_IndexedColor(XFile *x_file, int index, const LColor &color) { - XFileTemplate *xtemplate = XFile::find_standard_template("IndexedColor"); - nassertr(xtemplate != nullptr, *this); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(x_file, "", xtemplate); - add_element(node); - node->zero_fill(); - - (*node)["index"] = index; - (*node)["indexColor"] = LCAST(double, color); - - return *node; -} - -/** - * Appends a new Coords2d instance. - */ -XFileDataObject &XFileDataObject:: -add_Coords2d(XFile *x_file, const LVecBase2d &coords) { - XFileTemplate *xtemplate = XFile::find_standard_template("Coords2d"); - nassertr(xtemplate != nullptr, *this); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(x_file, "", xtemplate); - add_element(node); - node->zero_fill(); - - node->set(coords); - - return *node; -} - -/** - * Adds the indicated element as a nested data element, if this data object - * type supports it. Returns true if added successfully, false if the data - * object type does not support nested data elements. - */ -bool XFileDataObject:: -add_element(XFileDataObject *element) { - return false; -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObject:: -output_data(std::ostream &out) const { - out << "(" << get_type() << "::output_data() not implemented.)"; -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObject:: -write_data(std::ostream &out, int indent_level, const char *) const { - indent(out, indent_level) - << "(" << get_type() << "::write_data() not implemented.)\n"; -} - -/** - * Sets the object's value as an integer, if this is legal. - */ -void XFileDataObject:: -set_int_value(int int_value) { - xfile_cat.error() - << get_type_name() << " does not support integer values.\n"; -} - -/** - * Sets the object's value as a floating-point number, if this is legal. - */ -void XFileDataObject:: -set_double_value(double double_value) { - xfile_cat.error() - << get_type_name() << " does not support floating-point values.\n"; -} - -/** - * Sets the object's value as a string, if this is legal. - */ -void XFileDataObject:: -set_string_value(const string &string_value) { - xfile_cat.error() - << get_type_name() << " does not support string values.\n"; -} - -/** - * Stores the indicated array of doubles in the nested elements within this - * object. There must be exactly the indicated number of nested values, and - * they must all accept a double. - */ -void XFileDataObject:: -store_double_array(int num_elements, const double *values) { - if (get_num_elements() != num_elements) { - xfile_cat.error() - << get_type_name() << " does not accept " - << num_elements << " values.\n"; - return; - } - - for (int i = 0; i < num_elements; i++) { - get_element(i)->set_double_value(values[i]); - } -} - - -/** - * Returns the object's representation as an integer, if it has one. - */ -int XFileDataObject:: -get_int_value() const { - return 0; -} - -/** - * Returns the object's representation as a double, if it has one. - */ -double XFileDataObject:: -get_double_value() const { - return 0.0; -} - -/** - * Returns the object's representation as a string, if it has one. - */ -string XFileDataObject:: -get_string_value() const { - return string(); -} - -/** - * Fills the indicated array of doubles with the values from the nested - * elements within this object. There must be exactly the indicated number of - * nested values, and they must all return a double. - */ -void XFileDataObject:: -get_double_array(int num_elements, double *values) const { - if (get_num_elements() != num_elements) { - xfile_cat.error() - << get_type_name() << " does not contain " - << num_elements << " values.\n"; - return; - } - - for (int i = 0; i < num_elements; i++) { - values[i] = ((XFileDataObject *)this)->get_element(i)->get_double_value(); - } -} - -/** - * Returns the number of nested data elements within the object. This may be, - * e.g. the size of the array, if it is an array. - */ -int XFileDataObject:: -get_num_elements() const { - return 0; -} - -/** - * Returns the nth nested data element within the object. - */ -XFileDataObject *XFileDataObject:: -get_element(int n) { - xfile_cat.warning() - << "Looking for [" << n << "] within data object of type " - << get_type_name() << ", does not support nested objects.\n"; - return nullptr; -} - -/** - * Returns the nested data element within the object that has the indicated - * name. - */ -XFileDataObject *XFileDataObject:: -get_element(const string &name) { - xfile_cat.warning() - << "Looking for [\"" << name << "\"] within data object of type " - << get_type_name() << ", does not support nested objects.\n"; - return nullptr; -} diff --git a/pandatool/src/xfile/xFileDataObject.h b/pandatool/src/xfile/xFileDataObject.h deleted file mode 100644 index 814d5f3c..00000000 --- a/pandatool/src/xfile/xFileDataObject.h +++ /dev/null @@ -1,133 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObject.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILEDATAOBJECT_H -#define XFILEDATAOBJECT_H - -#include "pandatoolbase.h" -#include "referenceCount.h" -#include "pointerTo.h" -#include "dcast.h" -#include "luse.h" - -class XFile; -class XFileDataDef; - -/** - * The abstract base class for a number of different types of data elements - * that may be stored in the X file. - */ -class XFileDataObject : virtual public ReferenceCount { -public: - INLINE XFileDataObject(const XFileDataDef *data_def = nullptr); - virtual ~XFileDataObject(); - - INLINE const XFileDataDef *get_data_def() const; - - virtual bool is_complex_object() const; - virtual std::string get_type_name() const; - - INLINE void operator = (int int_value); - INLINE void operator = (double double_value); - INLINE void operator = (const std::string &string_value); - INLINE void operator = (const LVecBase2d &vec); - INLINE void operator = (const LVecBase3d &vec); - INLINE void operator = (const LVecBase4d &vec); - INLINE void operator = (const LMatrix4d &mat); - - INLINE void set(int int_value); - INLINE void set(double double_value); - INLINE void set(const std::string &string_value); - INLINE void set(const LVecBase2d &vec); - INLINE void set(const LVecBase3d &vec); - INLINE void set(const LVecBase4d &vec); - INLINE void set(const LMatrix4d &mat); - - INLINE int i() const; - INLINE double d() const; - INLINE std::string s() const; - INLINE LVecBase2d vec2() const; - INLINE LVecBase3d vec3() const; - INLINE LVecBase4d vec4() const; - INLINE LMatrix4d mat4() const; - - INLINE int size() const; - INLINE const XFileDataObject &operator [] (int n) const; - INLINE const XFileDataObject &operator [] (const std::string &name) const; - - INLINE XFileDataObject &operator [] (int n); - INLINE XFileDataObject &operator [] (const std::string &name); - - // The following methods can be used to add elements of a specific type to a - // complex object, e.g. an array or a template object. - - XFileDataObject &add_int(int int_value); - XFileDataObject &add_double(double double_value); - XFileDataObject &add_string(const std::string &string_value); - - // The following methods can be used to add elements of a specific type, - // based on one of the standard templates. - - XFileDataObject &add_Vector(XFile *x_file, const LVecBase3d &vector); - XFileDataObject &add_MeshFace(XFile *x_file); - XFileDataObject &add_IndexedColor(XFile *x_file, int index, - const LColor &color); - XFileDataObject &add_Coords2d(XFile *x_file, const LVecBase2d &coords); - -public: - virtual bool add_element(XFileDataObject *element); - - virtual void output_data(std::ostream &out) const; - virtual void write_data(std::ostream &out, int indent_level, - const char *separator) const; - -protected: - virtual void set_int_value(int int_value); - virtual void set_double_value(double double_value); - virtual void set_string_value(const std::string &string_value); - void store_double_array(int num_elements, const double *values); - - virtual int get_int_value() const; - virtual double get_double_value() const; - virtual std::string get_string_value() const; - void get_double_array(int num_elements, double *values) const; - - virtual int get_num_elements() const; - virtual XFileDataObject *get_element(int n); - virtual XFileDataObject *get_element(const std::string &name); - - const XFileDataDef *_data_def; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - ReferenceCount::init_type(); - register_type(_type_handle, "XFileDataObject", - ReferenceCount::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; -}; - -INLINE std::ostream &operator << (std::ostream &out, const XFileDataObject &data_object); - -#include "xFileDataObject.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataObjectArray.I b/pandatool/src/xfile/xFileDataObjectArray.I deleted file mode 100644 index fefe7e60..00000000 --- a/pandatool/src/xfile/xFileDataObjectArray.I +++ /dev/null @@ -1,21 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectArray.I - * @author drose - * @date 2004-10-07 - */ - -/** - * - */ -XFileDataObjectArray:: -XFileDataObjectArray(const XFileDataDef *data_def) : - XFileDataObject(data_def) -{ -} diff --git a/pandatool/src/xfile/xFileDataObjectArray.cxx b/pandatool/src/xfile/xFileDataObjectArray.cxx deleted file mode 100644 index e648ef2c..00000000 --- a/pandatool/src/xfile/xFileDataObjectArray.cxx +++ /dev/null @@ -1,103 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectArray.cxx - * @author drose - * @date 2004-10-07 - */ - -#include "xFileDataObjectArray.h" -#include "string_utils.h" -#include "indent.h" - -TypeHandle XFileDataObjectArray::_type_handle; - -/** - * Returns true if this kind of data object is a complex object that can hold - * nested data elements, false otherwise. - */ -bool XFileDataObjectArray:: -is_complex_object() const { - return true; -} - -/** - * Adds the indicated element as a nested data element, if this data object - * type supports it. Returns true if added successfully, false if the data - * object type does not support nested data elements. - */ -bool XFileDataObjectArray:: -add_element(XFileDataObject *element) { - _nested_elements.push_back(element); - return true; -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObjectArray:: -write_data(std::ostream &out, int indent_level, const char *separator) const { - if (!_nested_elements.empty()) { - bool indented = false; - for (size_t i = 0; i < _nested_elements.size() - 1; i++) { - XFileDataObject *object = _nested_elements[i]; - if (object->is_complex_object() || - _nested_elements.size() > 16) { - // If we have a "complex" nested object, or more than 16 elements in - // the array, output it on its own line. - if (indented) { - out << "\n"; - indented = false; - } - object->write_data(out, indent_level, ","); - - } else { - // Otherwise, output them all on the same line. - if (!indented) { - indent(out, indent_level); - indented = true; - } - out << *object << ", "; - } - } - - // The last object in the set is different, because it gets separator - // instead of a semicolon, and it always gets a newline. - XFileDataObject *object = _nested_elements.back(); - if (object->is_complex_object()) { - if (indented) { - out << "\n"; - } - object->write_data(out, indent_level, separator); - - } else { - if (!indented) { - indent(out, indent_level); - } - out << *object << separator << "\n"; - } - } -} - -/** - * Returns the number of nested data elements within the object. This may be, - * e.g. the size of the array, if it is an array. - */ -int XFileDataObjectArray:: -get_num_elements() const { - return _nested_elements.size(); -} - -/** - * Returns the nth nested data element within the object. - */ -XFileDataObject *XFileDataObjectArray:: -get_element(int n) { - nassertr(n >= 0 && n < (int)_nested_elements.size(), nullptr); - return _nested_elements[n]; -} diff --git a/pandatool/src/xfile/xFileDataObjectArray.h b/pandatool/src/xfile/xFileDataObjectArray.h deleted file mode 100644 index 3b9000c9..00000000 --- a/pandatool/src/xfile/xFileDataObjectArray.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectArray.h - * @author drose - * @date 2004-10-07 - */ - -#ifndef XFILEDATAOBJECTARRAY_H -#define XFILEDATAOBJECTARRAY_H - -#include "pandatoolbase.h" -#include "xFileDataObject.h" - -/** - * An array of nested data elements. - */ -class XFileDataObjectArray : public XFileDataObject { -public: - INLINE XFileDataObjectArray(const XFileDataDef *data_def); - - virtual bool is_complex_object() const; - - virtual bool add_element(XFileDataObject *element); - - virtual void write_data(std::ostream &out, int indent_level, - const char *separator) const; - -protected: - virtual int get_num_elements() const; - virtual XFileDataObject *get_element(int n); - -private: - typedef pvector< PT(XFileDataObject) > NestedElements; - NestedElements _nested_elements; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - XFileDataObject::init_type(); - register_type(_type_handle, "XFileDataObjectArray", - XFileDataObject::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 "xFileDataObjectArray.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataObjectDouble.I b/pandatool/src/xfile/xFileDataObjectDouble.I deleted file mode 100644 index 339d3b08..00000000 --- a/pandatool/src/xfile/xFileDataObjectDouble.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectDouble.I - * @author drose - * @date 2004-10-07 - */ diff --git a/pandatool/src/xfile/xFileDataObjectDouble.cxx b/pandatool/src/xfile/xFileDataObjectDouble.cxx deleted file mode 100644 index d17b2bbb..00000000 --- a/pandatool/src/xfile/xFileDataObjectDouble.cxx +++ /dev/null @@ -1,91 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectDouble.cxx - * @author drose - * @date 2004-10-07 - */ - -#include "xFileDataObjectDouble.h" -#include "string_utils.h" -#include "indent.h" - -TypeHandle XFileDataObjectDouble::_type_handle; - -/** - * - */ -XFileDataObjectDouble:: -XFileDataObjectDouble(const XFileDataDef *data_def, double value) : - XFileDataObject(data_def), - _value(value) -{ -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObjectDouble:: -output_data(std::ostream &out) const { - out << get_string_value(); -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObjectDouble:: -write_data(std::ostream &out, int indent_level, const char *separator) const { - indent(out, indent_level) - << get_string_value() << separator << "\n"; -} - -/** - * Sets the object's value as an integer, if this is legal. - */ -void XFileDataObjectDouble:: -set_int_value(int int_value) { - _value = (double)int_value; -} - -/** - * Sets the object's value as a floating-point number, if this is legal. - */ -void XFileDataObjectDouble:: -set_double_value(double double_value) { - _value = double_value; -} - -/** - * Returns the object's representation as an integer, if it has one. - */ -int XFileDataObjectDouble:: -get_int_value() const { - return (int)_value; -} - -/** - * Returns the object's representation as a double, if it has one. - */ -double XFileDataObjectDouble:: -get_double_value() const { - return _value; -} - -/** - * Returns the object's representation as a string, if it has one. - */ -std::string XFileDataObjectDouble:: -get_string_value() const { - // It's important to format with a decimal point, even if the value is - // integral, since the DirectX .x reader differentiates betweens doubles and - // integers on parsing. - char buffer[128]; - sprintf(buffer, "%f", _value); - - return buffer; -} diff --git a/pandatool/src/xfile/xFileDataObjectDouble.h b/pandatool/src/xfile/xFileDataObjectDouble.h deleted file mode 100644 index 4450f452..00000000 --- a/pandatool/src/xfile/xFileDataObjectDouble.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectDouble.h - * @author drose - * @date 2004-10-07 - */ - -#ifndef XFILEDATAOBJECTDOUBLE_H -#define XFILEDATAOBJECTDOUBLE_H - -#include "pandatoolbase.h" -#include "xFileDataObject.h" - -/** - * An double-valued data element. This matches one double data member of a - * template, or a single element of an double array. - */ -class XFileDataObjectDouble : public XFileDataObject { -public: - XFileDataObjectDouble(const XFileDataDef *data_def, double value); - - virtual void output_data(std::ostream &out) const; - virtual void write_data(std::ostream &out, int indent_level, - const char *separator) const; - -protected: - virtual void set_int_value(int int_value); - virtual void set_double_value(double double_value); - - virtual int get_int_value() const; - virtual double get_double_value() const; - virtual std::string get_string_value() const; - -private: - double _value; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - XFileDataObject::init_type(); - register_type(_type_handle, "XFileDataObjectDouble", - XFileDataObject::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 "xFileDataObjectDouble.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataObjectInteger.I b/pandatool/src/xfile/xFileDataObjectInteger.I deleted file mode 100644 index 07f27b7a..00000000 --- a/pandatool/src/xfile/xFileDataObjectInteger.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectInteger.I - * @author drose - * @date 2004-10-07 - */ diff --git a/pandatool/src/xfile/xFileDataObjectInteger.cxx b/pandatool/src/xfile/xFileDataObjectInteger.cxx deleted file mode 100644 index ee3c539d..00000000 --- a/pandatool/src/xfile/xFileDataObjectInteger.cxx +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectInteger.cxx - * @author drose - * @date 2004-10-07 - */ - -#include "xFileDataObjectInteger.h" -#include "string_utils.h" -#include "indent.h" - -TypeHandle XFileDataObjectInteger::_type_handle; - -/** - * - */ -XFileDataObjectInteger:: -XFileDataObjectInteger(const XFileDataDef *data_def, int value) : - XFileDataObject(data_def), - _value(value) -{ -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObjectInteger:: -output_data(std::ostream &out) const { - out << _value; -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObjectInteger:: -write_data(std::ostream &out, int indent_level, const char *separator) const { - indent(out, indent_level) - << _value << separator << "\n"; -} - -/** - * Sets the object's value as an integer, if this is legal. - */ -void XFileDataObjectInteger:: -set_int_value(int int_value) { - _value = int_value; -} - -/** - * Returns the object's representation as an integer, if it has one. - */ -int XFileDataObjectInteger:: -get_int_value() const { - return _value; -} - -/** - * Returns the object's representation as a double, if it has one. - */ -double XFileDataObjectInteger:: -get_double_value() const { - return _value; -} - -/** - * Returns the object's representation as a string, if it has one. - */ -std::string XFileDataObjectInteger:: -get_string_value() const { - return format_string(_value); -} diff --git a/pandatool/src/xfile/xFileDataObjectInteger.h b/pandatool/src/xfile/xFileDataObjectInteger.h deleted file mode 100644 index b185ea93..00000000 --- a/pandatool/src/xfile/xFileDataObjectInteger.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectInteger.h - * @author drose - * @date 2004-10-07 - */ - -#ifndef XFILEDATAOBJECTINTEGER_H -#define XFILEDATAOBJECTINTEGER_H - -#include "pandatoolbase.h" -#include "xFileDataObject.h" - -/** - * An integer-valued data element. This matches one integer data member of a - * template, or a single element of an integer array. - */ -class XFileDataObjectInteger : public XFileDataObject { -public: - XFileDataObjectInteger(const XFileDataDef *data_def, int value); - - virtual void output_data(std::ostream &out) const; - virtual void write_data(std::ostream &out, int indent_level, - const char *separator) const; - -protected: - virtual void set_int_value(int int_value); - - virtual int get_int_value() const; - virtual double get_double_value() const; - virtual std::string get_string_value() const; - -private: - int _value; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - XFileDataObject::init_type(); - register_type(_type_handle, "XFileDataObjectInteger", - XFileDataObject::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 "xFileDataObjectInteger.I" - -#endif diff --git a/pandatool/src/xfile/xFileDataObjectString.I b/pandatool/src/xfile/xFileDataObjectString.I deleted file mode 100644 index 8e55118d..00000000 --- a/pandatool/src/xfile/xFileDataObjectString.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectString.I - * @author drose - * @date 2004-10-08 - */ diff --git a/pandatool/src/xfile/xFileDataObjectString.cxx b/pandatool/src/xfile/xFileDataObjectString.cxx deleted file mode 100644 index 99ef31a8..00000000 --- a/pandatool/src/xfile/xFileDataObjectString.cxx +++ /dev/null @@ -1,97 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectString.cxx - * @author drose - * @date 2004-10-08 - */ - -#include "xFileDataObjectString.h" -#include "string_utils.h" -#include "indent.h" - -using std::string; - -TypeHandle XFileDataObjectString::_type_handle; - -/** - * - */ -XFileDataObjectString:: -XFileDataObjectString(const XFileDataDef *data_def, const string &value) : - XFileDataObject(data_def), - _value(value) -{ -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObjectString:: -output_data(std::ostream &out) const { - enquote_string(out); -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileDataObjectString:: -write_data(std::ostream &out, int indent_level, const char *separator) const { - indent(out, indent_level); - enquote_string(out); - out << separator << "\n"; -} - -/** - * Sets the object's value as a string, if this is legal. - */ -void XFileDataObjectString:: -set_string_value(const string &string_value) { - _value = string_value; -} - -/** - * Returns the object's representation as a string, if it has one. - */ -string XFileDataObjectString:: -get_string_value() const { - return _value; -} - -/** - * Writes the string to the output stream without quotation marks, quoting - * special characters as needed. - */ -void XFileDataObjectString:: -enquote_string(std::ostream &out) const { - // Actually, the XFile spec doesn't tell us how to escape special characters - // within quotation marks. We'll just take a stab in the dark here. - - out << '"'; - string::const_iterator si; - for (si = _value.begin(); si != _value.end(); ++si) { - switch (*si) { - case '\n': - out << "\\n"; - break; - - case '\r': - out << "\\r"; - break; - - case '"': - case '\\': - out << '\\' << (*si); - break; - - default: - out << (*si); - } - } - out << '"'; -} diff --git a/pandatool/src/xfile/xFileDataObjectString.h b/pandatool/src/xfile/xFileDataObjectString.h deleted file mode 100644 index 1fd10dea..00000000 --- a/pandatool/src/xfile/xFileDataObjectString.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileDataObjectString.h - * @author drose - * @date 2004-10-08 - */ - -#ifndef XFILEDATAOBJECTSTRING_H -#define XFILEDATAOBJECTSTRING_H - -#include "pandatoolbase.h" -#include "xFileDataObject.h" - -/** - * An string-valued data element. This matches one string data member of a - * template, or a single element of an string array. - */ -class XFileDataObjectString : public XFileDataObject { -public: - XFileDataObjectString(const XFileDataDef *data_def, const std::string &value); - - virtual void output_data(std::ostream &out) const; - virtual void write_data(std::ostream &out, int indent_level, - const char *separator) const; - -protected: - virtual void set_string_value(const std::string &string_value); - virtual std::string get_string_value() const; - -private: - void enquote_string(std::ostream &out) const; - - std::string _value; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - XFileDataObject::init_type(); - register_type(_type_handle, "XFileDataObjectString", - XFileDataObject::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 "xFileDataObjectString.I" - -#endif diff --git a/pandatool/src/xfile/xFileNode.I b/pandatool/src/xfile/xFileNode.I deleted file mode 100644 index 735c2dce..00000000 --- a/pandatool/src/xfile/xFileNode.I +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileNode.I - * @author drose - * @date 2004-10-03 - */ - -/** - * - */ -INLINE XFileNode:: -XFileNode(XFile *x_file) : - Namable(), - _x_file(x_file) -{ -} - -/** - * - */ -INLINE XFile *XFileNode:: -get_x_file() const { - return _x_file; -} - -/** - * Returns the list of children of this node. This list includes templates as - * well as data objects. - */ -INLINE int XFileNode:: -get_num_children() const { - return _children.size(); -} - -/** - * Returns the nth child of this node. This list includes templates as well - * as data objects. - */ -INLINE XFileNode *XFileNode:: -get_child(int n) const { - nassertr(n >= 0 && n < (int)_children.size(), nullptr); - return _children[n]; -} - -/** - * Returns the list of child objects of this node. This list does not include - * template definitions; it is strictly the list of children that are also - * data objects (instances of templates). - */ -INLINE int XFileNode:: -get_num_objects() const { - return _objects.size(); -} - -/** - * Returns the nth child object of this node. This list does not include - * template definitions; it is strictly the list of children that are also - * data objects (instances of templates). - */ -INLINE XFileDataNode *XFileNode:: -get_object(int n) const { - nassertr(n >= 0 && n < (int)_objects.size(), nullptr); - return _objects[n]; -} diff --git a/pandatool/src/xfile/xFileNode.cxx b/pandatool/src/xfile/xFileNode.cxx deleted file mode 100644 index 51c795e4..00000000 --- a/pandatool/src/xfile/xFileNode.cxx +++ /dev/null @@ -1,499 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileNode.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFileNode.h" -#include "windowsGuid.h" -#include "xFile.h" -#include "xLexerDefs.h" -#include "xFileParseData.h" -#include "xFile.h" -#include "xFileDataNodeTemplate.h" -#include "filename.h" -#include "string_utils.h" - -using std::string; - -TypeHandle XFileNode::_type_handle; - -/** - * - */ -XFileNode:: -XFileNode(XFile *x_file, const string &name) : - Namable(), - _x_file(x_file) -{ - if (x_file && x_file->_keep_names) { - set_name(name); - } else { - set_name(make_nice_name(name)); - } -} - -/** - * - */ -XFileNode:: -~XFileNode() { - clear(); -} - -/** - * 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(downcase(name)); - if (ni != _children_by_name.end()) { - return get_child((*ni).second); - } - - return nullptr; -} - -/** - * Returns the index number of the child with the indicated name, if any, or - * -1 if none. - */ -int XFileNode:: -find_child_index(const string &name) const { - ChildrenByName::const_iterator ni; - ni = _children_by_name.find(downcase(name)); - if (ni != _children_by_name.end()) { - return (*ni).second; - } - - return -1; -} - -/** - * Returns the index number of the indicated child, or -1 if none. - */ -int XFileNode:: -find_child_index(const XFileNode *child) const { - for (int i = 0; i < (int)_children.size(); i++) { - if (_children[i] == child) { - return i; - } - } - - return -1; -} - -/** - * Returns the first child or descendent found with the indicated name after a - * depth-first search, if any, or NULL if none. - */ -XFileNode *XFileNode:: -find_descendent(const string &name) const { - XFileNode *child = find_child(name); - if (child != nullptr) { - return child; - } - - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - XFileNode *child = (*ci)->find_descendent(name); - if (child != nullptr){ - return child; - } - } - - return nullptr; -} - -/** - * Returns true if this node has a GUID associated. - */ -bool XFileNode:: -has_guid() const { - return false; -} - -/** - * If has_guid() returned true, returns the particular GUID associated with - * this node. - */ -const WindowsGuid &XFileNode:: -get_guid() const { - static WindowsGuid empty; - return empty; -} - -/** - * Returns true if this node represents the definition of some template. This - * is the template definition, not an actual data object that represents an - * instance of the template. If the file strictly uses standard templates, - * the presence of template definitions is optional. - * - * If this returns true, the node must be of type XFileTemplate. - */ -bool XFileNode:: -is_template_def() const { - return false; -} - -/** - * Returns true if this node represents an indirect reference to an object - * defined previously in the file. References are generally transparent, so - * in most cases you never need to call this, unless you actually need to - * differentiate between references and instances; you can simply use the - * reference node as if it were itself the object it references. - * - * If this returns true, the node must be of type XFileDataNodeReference. - */ -bool XFileNode:: -is_reference() const { - return false; -} - -/** - * Returns true if this node represents a data object that is the instance of - * some template, or false otherwise. This also returns true for references - * to objects (which are generally treated just like the objects themselves). - * - * If this returns true, the node must be of type XFileDataNode (it is either - * an XFileDataNodeTemplate or an XFileDataNodeReference). - */ -bool XFileNode:: -is_object() const { - return false; -} - -/** - * Returns true if this node represents an instance of the standard template - * with the indicated name, or false otherwise. This returns also returns - * true for references to standard objects. - * - * If this returns true, the node must be of type XFileDataNode (it is either - * an XFileDataNodeTemplate or an XFileDataNodeReference). - */ -bool XFileNode:: -is_standard_object(const string &template_name) const { - return false; -} - -/** - * Adds the indicated node as a child of this node. - */ -void XFileNode:: -add_child(XFileNode *node) { - if (node->has_name()) { - _children_by_name[downcase(node->get_name())] = (int)_children.size(); - } - if (node->has_guid()) { - _x_file->_nodes_by_guid[node->get_guid()] = node; - } - if (node->is_of_type(XFileDataNode::get_class_type())) { - _objects.push_back(DCAST(XFileDataNode, node)); - } - _children.push_back(node); -} - -/** - * Removes all children from the node, and otherwise resets it to its initial - * state. - */ -void XFileNode:: -clear() { - _children.clear(); - _objects.clear(); - _children_by_name.clear(); -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileNode:: -write_text(std::ostream &out, int indent_level) const { - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - (*ci)->write_text(out, indent_level); - } -} - -/** - * This is called on the template that defines an object, once the data for - * the object has been parsed. It is responsible for identifying which - * component of the template owns each data element, and packing the data - * elements appropriately back into the object. - * - * It returns true on success, or false on an error (e.g. not enough data - * elements, mismatched data type). - */ -bool XFileNode:: -repack_data(XFileDataObject *object, - const XFileParseDataList &parse_data_list, - XFileNode::PrevData &prev_data, - size_t &index, size_t &sub_index) const { - // This method should be specialized for data types that actually consume a - // data element. Here in the base class, it just walks through its - // children, asking each one to pull off the appropriate number of data - // elements. - - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - if (!(*ci)->repack_data(object, parse_data_list, - prev_data, index, sub_index)) { - return false; - } - } - - return true; -} - -/** - * This is similar to repack_data(), except it is used to fill the initial - * values for a newly-created template object to zero. - */ -bool XFileNode:: -fill_zero_data(XFileDataObject *object) const { - Children::const_iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - if (!(*ci)->fill_zero_data(object)) { - return false; - } - } - - return true; -} - -/** - * Returns true if the node, particularly a template node, is structurally - * equivalent to the other node (which must be of the same type). This checks - * data element types, but does not compare data element names. - */ -bool XFileNode:: -matches(const XFileNode *other) const { - if (other->get_type() != get_type()) { - return false; - } - - if (other->get_num_children() != get_num_children()) { - return false; - } - - for (int i = 0; i < get_num_children(); i++) { - if (!get_child(i)->matches(other->get_child(i))) { - return false; - } - } - - return true; -} - -/** - * Creates a new Mesh instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_Mesh(const string &name) { - XFileTemplate *xtemplate = XFile::find_standard_template("Mesh"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - return node; -} - -/** - * Creates a new MeshNormals instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_MeshNormals(const string &name) { - XFileTemplate *xtemplate = XFile::find_standard_template("MeshNormals"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - return node; -} - -/** - * Creates a new MeshVertexColors instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_MeshVertexColors(const string &name) { - XFileTemplate *xtemplate = XFile::find_standard_template("MeshVertexColors"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - return node; -} - -/** - * Creates a new MeshTextureCoords instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_MeshTextureCoords(const string &name) { - XFileTemplate *xtemplate = XFile::find_standard_template("MeshTextureCoords"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - return node; -} - -/** - * Creates a new MeshMaterialList instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_MeshMaterialList(const string &name) { - XFileTemplate *xtemplate = XFile::find_standard_template("MeshMaterialList"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - return node; -} - -/** - * Creates a new Material instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_Material(const string &name, const LColor &face_color, - double power, const LRGBColor &specular_color, - const LRGBColor &emissive_color) { - XFileTemplate *xtemplate = XFile::find_standard_template("Material"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - (*node)["faceColor"]["red"] = face_color[0]; - (*node)["faceColor"]["green"] = face_color[1]; - (*node)["faceColor"]["blue"] = face_color[2]; - (*node)["faceColor"]["alpha"] = face_color[3]; - (*node)["power"] = power; - (*node)["specularColor"]["red"] = specular_color[0]; - (*node)["specularColor"]["green"] = specular_color[1]; - (*node)["specularColor"]["blue"] = specular_color[2]; - (*node)["emissiveColor"]["red"] = emissive_color[0]; - (*node)["emissiveColor"]["green"] = emissive_color[1]; - (*node)["emissiveColor"]["blue"] = emissive_color[2]; - - return node; -} - -/** - * Creates a new TextureFilename instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_TextureFilename(const string &name, const Filename &filename) { - XFileTemplate *xtemplate = XFile::find_standard_template("TextureFilename"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - (*node)["filename"] = filename.to_os_specific(); - - return node; -} - -/** - * Creates a new Frame instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_Frame(const string &name) { - XFileTemplate *xtemplate = XFile::find_standard_template("Frame"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), name, xtemplate); - add_child(node); - node->zero_fill(); - - return node; -} - -/** - * Creates a new FrameTransformMatrix instance, as a child of this node. - */ -XFileDataNode *XFileNode:: -add_FrameTransformMatrix(const LMatrix4d &mat) { - XFileTemplate *xtemplate = - XFile::find_standard_template("FrameTransformMatrix"); - nassertr(xtemplate != nullptr, nullptr); - XFileDataNodeTemplate *node = - new XFileDataNodeTemplate(get_x_file(), "", xtemplate); - add_child(node); - node->zero_fill(); - - XFileDataObject &xmat = (*node)["frameMatrix"]["matrix"]; - xmat[0] = mat(0, 0); - xmat[1] = mat(0, 1); - xmat[2] = mat(0, 2); - xmat[3] = mat(0, 3); - - xmat[4] = mat(1, 0); - xmat[5] = mat(1, 1); - xmat[6] = mat(1, 2); - xmat[7] = mat(1, 3); - - xmat[8] = mat(2, 0); - xmat[9] = mat(2, 1); - xmat[10] = mat(2, 2); - xmat[11] = mat(2, 3); - - xmat[12] = mat(3, 0); - xmat[13] = mat(3, 1); - xmat[14] = mat(3, 2); - xmat[15] = mat(3, 3); - - return node; -} - -/** - * Transforms the indicated egg name to a name that is acceptable for a node - * in the X File format. - */ -string XFileNode:: -make_nice_name(const string &str) { - string result; - - string::const_iterator si; - for (si = str.begin(); si != str.end(); ++si) { - if (isalnum(*si)) { - result += (*si); - } else { - switch (*si) { - case '-': - result += (*si); - break; - default: - result += "_"; - } - } - } - - if (str.empty() || isdigit(str[0])) { - // If the name begins with a digit, or if it is empty, then we must make - // it begin with something else, like for instance an underscore. - result = '_' + result; - } - - return result; -} diff --git a/pandatool/src/xfile/xFileNode.h b/pandatool/src/xfile/xFileNode.h deleted file mode 100644 index 2cd9f6d3..00000000 --- a/pandatool/src/xfile/xFileNode.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileNode.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILENODE_H -#define XFILENODE_H - -#include "pandatoolbase.h" -#include "typedObject.h" -#include "referenceCount.h" -#include "pointerTo.h" -#include "namable.h" -#include "pnotify.h" -#include "pvector.h" -#include "pmap.h" -#include "luse.h" - -class XFile; -class WindowsGuid; -class XFileParseDataList; -class XFileDataDef; -class XFileDataObject; -class XFileDataNode; -class XFileDataNodeTemplate; -class Filename; - -/** - * A single node of an X file. This may be either a template or a data node. - */ -class XFileNode : public TypedObject, public Namable, - virtual public ReferenceCount { -protected: - INLINE XFileNode(XFile *x_file); - -public: - XFileNode(XFile *x_file, const std::string &name); - virtual ~XFileNode(); - - INLINE XFile *get_x_file() const; - - INLINE int get_num_children() const; - INLINE XFileNode *get_child(int n) const; - XFileNode *find_child(const std::string &name) const; - int find_child_index(const std::string &name) const; - int find_child_index(const XFileNode *child) const; - XFileNode *find_descendent(const std::string &name) const; - - INLINE int get_num_objects() const; - INLINE XFileDataNode *get_object(int n) const; - - virtual bool has_guid() const; - virtual const WindowsGuid &get_guid() const; - - virtual bool is_template_def() const; - virtual bool is_reference() const; - virtual bool is_object() const; - virtual bool is_standard_object(const std::string &template_name) const; - - void add_child(XFileNode *node); - virtual void clear(); - - virtual void write_text(std::ostream &out, int indent_level) const; - - typedef pmap PrevData; - - virtual bool repack_data(XFileDataObject *object, - const XFileParseDataList &parse_data_list, - PrevData &prev_data, - size_t &index, size_t &sub_index) const; - - virtual bool fill_zero_data(XFileDataObject *object) const; - - virtual bool matches(const XFileNode *other) const; - - // The following methods can be used to create instances of the standard - // template objects. These definitions match those defined in - // standardTemplates.x in this directory (and compiled into the executable). - XFileDataNode *add_Mesh(const std::string &name); - XFileDataNode *add_MeshNormals(const std::string &name); - XFileDataNode *add_MeshVertexColors(const std::string &name); - XFileDataNode *add_MeshTextureCoords(const std::string &name); - XFileDataNode *add_MeshMaterialList(const std::string &name); - XFileDataNode *add_Material(const std::string &name, const LColor &face_color, - double power, const LRGBColor &specular_color, - const LRGBColor &emissive_color); - XFileDataNode *add_TextureFilename(const std::string &name, - const Filename &filename); - XFileDataNode *add_Frame(const std::string &name); - XFileDataNode *add_FrameTransformMatrix(const LMatrix4d &mat); - -public: - static std::string make_nice_name(const std::string &str); - -protected: - XFile *_x_file; - - typedef pvector< PT(XFileNode) > Children; - Children _children; - - typedef pvector Objects; - Objects _objects; - - typedef pmap ChildrenByName; - ChildrenByName _children_by_name; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedObject::init_type(); - ReferenceCount::init_type(); - register_type(_type_handle, "XFileNode", - TypedObject::get_class_type(), - ReferenceCount::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; - - friend class XFileDataNodeReference; -}; - -#include "xFileNode.I" - -#endif diff --git a/pandatool/src/xfile/xFileParseData.I b/pandatool/src/xfile/xFileParseData.I deleted file mode 100644 index 64199737..00000000 --- a/pandatool/src/xfile/xFileParseData.I +++ /dev/null @@ -1,12 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileParseData.I - * @author drose - * @date 2004-10-07 - */ diff --git a/pandatool/src/xfile/xFileParseData.cxx b/pandatool/src/xfile/xFileParseData.cxx deleted file mode 100644 index 0fcd8dbe..00000000 --- a/pandatool/src/xfile/xFileParseData.cxx +++ /dev/null @@ -1,39 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileParseData.cxx - * @author drose - * @date 2004-10-07 - */ - -#include "xFileParseData.h" -#include "xLexerDefs.h" - - -/** - * - */ -XFileParseData:: -XFileParseData() : - _parse_flags(0) -{ - // Save the line number, column number, and line text in case we detect an - // error later and want to report a meaningful message to the user. - _line_number = x_line_number; - _col_number = x_col_number; - _current_line = x_current_line; -} - -/** - * Reports a parsing error message to the user, showing the line and column - * from which this object was originally parsed. - */ -void XFileParseData:: -yyerror(const std::string &message) const { - xyyerror(message, _line_number, _col_number, _current_line); -} diff --git a/pandatool/src/xfile/xFileParseData.h b/pandatool/src/xfile/xFileParseData.h deleted file mode 100644 index 2e7ef8db..00000000 --- a/pandatool/src/xfile/xFileParseData.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileParseData.h - * @author drose - * @date 2004-10-07 - */ - -#ifndef XFILEPARSEDATA_H -#define XFILEPARSEDATA_H - -#include "pandatoolbase.h" -#include "xFileDataObject.h" -#include "pointerTo.h" -#include "pta_int.h" -#include "pta_double.h" -#include "pvector.h" - -/** - * This class is used to fill up the data into an XFileDataNodeTemplate object - * as the data values are parsed out of the X file. It only has a temporary - * lifespan; it will be converted into actual data by - * XFileDataNodeTemplate::finalize_parse_data(). - */ -class XFileParseData { -public: - XFileParseData(); - - void yyerror(const std::string &message) const; - - enum ParseFlags { - PF_object = 0x001, - PF_reference = 0x002, - PF_double = 0x004, - PF_int = 0x008, - PF_string = 0x010, - PF_any_data = 0x01f, - }; - - PT(XFileDataObject) _object; - PTA_double _double_list; - PTA_int _int_list; - std::string _string; - int _parse_flags; - - int _line_number; - int _col_number; - std::string _current_line; -}; - -/** - * A container for a pvector of the above objects. We need this wrapper class - * to avoid circular #includes; this allows XFileNode to define a forward - * reference to this class (without having to include this file or know that - * it contains a template class). - */ -class XFileParseDataList { -public: - typedef pvector List; - List _list; -}; - -#include "xFileParseData.I" - -#endif diff --git a/pandatool/src/xfile/xFileTemplate.I b/pandatool/src/xfile/xFileTemplate.I deleted file mode 100644 index d56ff289..00000000 --- a/pandatool/src/xfile/xFileTemplate.I +++ /dev/null @@ -1,70 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileTemplate.I - * @author drose - * @date 2004-10-03 - */ - -/** - * Returns true if this particular template is one of the "standard" templates - * defined by standardTemplates.x in this directory (and compiled into the - * binary), or false if it is a user-custom template. - */ -INLINE bool XFileTemplate:: -is_standard() const { - return _is_standard; -} - -/** - * Sets whether the template is considered "open" or not. If it is open (this - * flag is true), the set of options is ignored and the instances of this - * template may include any types of children. If it is closed (false), only - * the named types may be added. - */ -INLINE void XFileTemplate:: -set_open(bool open) { - _open = open; -} - -/** - * Returns whether the template is considered "open" or not. If it is open - * (this flag is true), the set of options is ignored and the instances of - * this template may include any types of children. If it is closed (false), - * only the named types may be added. - */ -INLINE bool XFileTemplate:: -get_open() const { - return _open; -} - -/** - * Adds a new type to the list of allowable types of child nodes for an - * instance of this template. - */ -INLINE void XFileTemplate:: -add_option(XFileTemplate *option) { - _options.push_back(option); -} - -/** - * Returns the number of templates on the options list. - */ -INLINE int XFileTemplate:: -get_num_options() const { - return _options.size(); -} - -/** - * Returns the nth template on the options list. - */ -INLINE XFileTemplate *XFileTemplate:: -get_option(int n) const { - nassertr(n >= 0 && n < (int)_options.size(), nullptr); - return _options[n]; -} diff --git a/pandatool/src/xfile/xFileTemplate.cxx b/pandatool/src/xfile/xFileTemplate.cxx deleted file mode 100644 index e4ef5e2c..00000000 --- a/pandatool/src/xfile/xFileTemplate.cxx +++ /dev/null @@ -1,131 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileTemplate.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFileTemplate.h" -#include "indent.h" - -TypeHandle XFileTemplate::_type_handle; - -/** - * - */ -XFileTemplate:: -XFileTemplate(XFile *x_file, const std::string &name, const WindowsGuid &guid) : - XFileNode(x_file, name), - _guid(guid), - _is_standard(false), - _open(false) -{ -} - -/** - * - */ -XFileTemplate:: -~XFileTemplate() { - clear(); -} - -/** - * Returns true if this node has a GUID associated. - */ -bool XFileTemplate:: -has_guid() const { - return true; -} - -/** - * Returns the GUID associated with this template. - */ -const WindowsGuid &XFileTemplate:: -get_guid() const { - return _guid; -} - -/** - * Returns true if this node represents the definition of some template. This - * is the template definition, not an actual data object that represents an - * instance of the template. If the file strictly uses standard templates, - * the presence of template definitions is optional. - * - * If this returns true, the node must be of type XFileTemplate. - */ -bool XFileTemplate:: -is_template_def() const { - return true; -} - -/** - * Removes all children from the node, and otherwise resets it to its initial - * state. - */ -void XFileTemplate:: -clear() { - XFileNode::clear(); - _options.clear(); -} - -/** - * Writes a suitable representation of this node to an .x file in text mode. - */ -void XFileTemplate:: -write_text(std::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); - - if (get_open()) { - // An open template - indent(out, indent_level + 2) - << "[ ... ]\n"; - - } else if (!_options.empty()) { - // A restricted template - indent(out, indent_level + 2); - - char delimiter = '['; - Options::const_iterator ri; - for (ri = _options.begin(); ri != _options.end(); ++ri) { - XFileTemplate *option = (*ri); - out << delimiter << " " - << option->get_name() << " <" << option->get_guid() - << ">"; - delimiter = ','; - } - out << " ]\n"; - } - - indent(out, indent_level) - << "}\n"; -} - -/** - * Returns true if the node, particularly a template node, is structurally - * equivalent to the other node (which must be of the same type). This checks - * data element types, but does not compare data element names. - */ -bool XFileTemplate:: -matches(const XFileNode *other) const { - if (!XFileNode::matches(other)) { - return false; - } - - // We *could* compare the openclosedoptions associated with the template, - // but since this is only used for validating the set of children for the - // instances of this template (which we don't even bother to do anyway), it - // doesn't seem to matter. - return true; -} diff --git a/pandatool/src/xfile/xFileTemplate.h b/pandatool/src/xfile/xFileTemplate.h deleted file mode 100644 index d119a297..00000000 --- a/pandatool/src/xfile/xFileTemplate.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileTemplate.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILETEMPLATE_H -#define XFILETEMPLATE_H - -#include "pandatoolbase.h" -#include "xFileNode.h" -#include "windowsGuid.h" - -class XFileDataDef; - -/** - * A template definition in the X file. This defines the data structures that - * may be subsequently read. - */ -class XFileTemplate : public XFileNode { -public: - XFileTemplate(XFile *x_file, const std::string &name, const WindowsGuid &guid); - virtual ~XFileTemplate(); - - virtual bool has_guid() const; - virtual const WindowsGuid &get_guid() const; - - virtual bool is_template_def() const; - - virtual void clear() final; - virtual void write_text(std::ostream &out, int indent_level) const; - - INLINE bool is_standard() const; - - INLINE void set_open(bool open); - INLINE bool get_open() const; - - INLINE void add_option(XFileTemplate *option); - INLINE int get_num_options() const; - INLINE XFileTemplate *get_option(int n) const; - - virtual bool matches(const XFileNode *other) const; - -private: - WindowsGuid _guid; - bool _is_standard; - bool _open; - - typedef pvector< PT(XFileTemplate) > Options; - Options _options; - -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; - - friend class XFile; -}; - -#include "xFileTemplate.I" - -#endif diff --git a/pandatool/src/xfile/xLexer.cxx.prebuilt b/pandatool/src/xfile/xLexer.cxx.prebuilt deleted file mode 100644 index 92eb941a..00000000 --- a/pandatool/src/xfile/xLexer.cxx.prebuilt +++ /dev/null @@ -1,2637 +0,0 @@ -#line 2 "lex.yy.c" - -#line 4 "lex.yy.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ - -#define yy_create_buffer xyy_create_buffer -#define yy_delete_buffer xyy_delete_buffer -#define yy_flex_debug xyy_flex_debug -#define yy_init_buffer xyy_init_buffer -#define yy_flush_buffer xyy_flush_buffer -#define yy_load_buffer_state xyy_load_buffer_state -#define yy_switch_to_buffer xyy_switch_to_buffer -#define yyin xyyin -#define yyleng xyyleng -#define yylex xyylex -#define yylineno xyylineno -#define yyout xyyout -#define yyrestart xyyrestart -#define yytext xyytext -#define yywrap xyywrap -#define yyalloc xyyalloc -#define yyrealloc xyyrealloc -#define yyfree xyyfree - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ - -/* begin standard C headers. */ -#include -#include -#include -#include - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have . Non-C99 systems may or may not. */ - -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif - -#endif /* ! FLEXINT_H */ - -#ifdef __cplusplus - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -/* C99 requires __STDC__ to be defined as 1. */ -#if defined (__STDC__) - -#define YY_USE_CONST - -#endif /* defined (__STDC__) */ -#endif /* ! __cplusplus */ - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN (yy_start) = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START (((yy_start) - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE xyyrestart(xyyin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#define YY_BUF_SIZE 16384 -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif - -extern int xyyleng; - -extern FILE *xyyin, *xyyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up xyytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ - YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up xyytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, (yytext_ptr) ) - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; - -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via xyyrestart()), so that the user can continue scanning by - * just pointing xyyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ - -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) - -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] - -/* yy_hold_char holds the character lost when xyytext is formed. */ -static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int xyyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow xyywrap()'s to do buffer switches - * instead of setting up a fresh xyyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void xyyrestart (FILE *input_file ); -void xyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE xyy_create_buffer (FILE *file,int size ); -void xyy_delete_buffer (YY_BUFFER_STATE b ); -void xyy_flush_buffer (YY_BUFFER_STATE b ); -void xyypush_buffer_state (YY_BUFFER_STATE new_buffer ); -void xyypop_buffer_state (void ); - -static void xyyensure_buffer_stack (void ); -static void xyy_load_buffer_state (void ); -static void xyy_init_buffer (YY_BUFFER_STATE b,FILE *file ); - -#define YY_FLUSH_BUFFER xyy_flush_buffer(YY_CURRENT_BUFFER ) - -YY_BUFFER_STATE xyy_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE xyy_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE xyy_scan_bytes (yyconst char *bytes,int len ); - -void *xyyalloc (yy_size_t ); -void *xyyrealloc (void *,yy_size_t ); -void xyyfree (void * ); - -#define yy_new_buffer xyy_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - xyyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - xyy_create_buffer(xyyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - xyyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - xyy_create_buffer(xyyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -typedef unsigned char YY_CHAR; - -FILE *xyyin = (FILE *) 0, *xyyout = (FILE *) 0; - -typedef int yy_state_type; - -extern int xyylineno; - -int xyylineno = 1; - -extern char *xyytext; -#define yytext_ptr xyytext - -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up xyytext. - */ -#define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - xyyleng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; - -#define YY_NUM_RULES 35 -#define YY_END_OF_BUFFER 36 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_acclist[200] = - { 0, - 36, 34, 35, 2, 34, 35, 1, 35, 30, 34, - 35, 4, 34, 35, 32, 34, 35, 34, 35, 10, - 34, 35, 32, 34, 35, 9, 34, 35, 34, 35, - 26, 34, 35, 11, 34, 35, 31, 34, 35, 32, - 34, 35, 32, 34, 35, 32, 34, 35, 32, 34, - 35, 32, 34, 35, 32, 34, 35, 32, 34, 35, - 32, 34, 35, 32, 34, 35, 7, 34, 35, 8, - 34, 35, 5, 34, 35, 6, 34, 35, 1, 4, - 32, 26, 32, 33, 32, 33, 32, 26, 32, 3, - 27,16412, 26, 27,16412, 33, 33, 26, 32, 32, - - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 33, 32, 33, 32, 33, 32, 33, - 32, 32, 29, 3, 27, 33, 33, 33, 33, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 8220, 32, 13, 32, 14, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 25, 32, 32, 32, 29, 29, 12, 32, 32, 32, - 17, 32, 19, 32, 32, 32, 24, 32, 32, 22, - 32, 32, 32, 16, 32, 18, 32, 20, 32, 32, - 32, 29, 15, 32, 32, 23, 32, 21, 32 - - } ; - -static yyconst flex_int16_t yy_accept[142] = - { 0, - 1, 1, 1, 2, 4, 7, 9, 12, 15, 18, - 20, 23, 26, 29, 31, 34, 37, 40, 43, 46, - 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, - 79, 80, 81, 82, 82, 83, 85, 87, 88, 90, - 90, 91, 93, 96, 97, 98, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 115, 117, 119, 121, 122, 123, 124, 124, - 125, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 145, 145, 145, 145, 145, 146, 147, 149, - - 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 163, 164, 165, 166, 167, 169, 170, 171, 173, - 175, 176, 177, 179, 180, 182, 183, 183, 184, 186, - 188, 190, 191, 192, 192, 193, 195, 196, 198, 200, - 200 - } ; - -static yyconst flex_int32_t yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 5, 1, 6, 7, 1, 1, 1, 1, 8, - 8, 1, 9, 10, 11, 12, 13, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 1, 15, 16, - 1, 1, 1, 1, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 8, 8, 26, 27, 28, 29, 30, - 8, 31, 32, 33, 34, 8, 35, 8, 36, 8, - 37, 1, 38, 1, 8, 1, 39, 40, 41, 42, - - 43, 44, 45, 46, 47, 8, 8, 48, 49, 50, - 51, 52, 8, 53, 54, 55, 56, 8, 57, 8, - 58, 8, 59, 1, 60, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst flex_int32_t yy_meta[61] = - { 0, - 1, 2, 3, 1, 2, 1, 1, 4, 1, 2, - 4, 4, 1, 4, 2, 1, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 1, 1, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 1, 1 - } ; - -static yyconst flex_int16_t yy_base[151] = - { 0, - 0, 0, 336, 370, 370, 0, 370, 0, 0, 49, - 370, 53, 320, 290, 64, 370, 370, 31, 32, 48, - 42, 44, 53, 60, 63, 54, 370, 370, 370, 370, - 0, 0, 0, 248, 104, 0, 86, 215, 110, 121, - 0, 135, 146, 0, 116, 157, 171, 54, 56, 100, - 99, 107, 114, 118, 117, 122, 129, 139, 144, 145, - 146, 0, 0, 182, 190, 193, 207, 228, 202, 0, - 201, 239, 0, 0, 212, 220, 167, 176, 174, 194, - 217, 214, 229, 219, 227, 224, 226, 241, 240, 240, - 252, 175, 196, 206, 177, 274, 370, 228, 0, 0, - - 240, 243, 251, 239, 242, 247, 263, 259, 259, 263, - 0, 165, 294, 296, 311, 0, 272, 281, 0, 0, - 295, 295, 0, 302, 0, 300, 319, 300, 0, 0, - 0, 294, 308, 124, 333, 0, 310, 0, 0, 370, - 354, 358, 130, 129, 361, 125, 97, 365, 92, 83 - } ; - -static yyconst flex_int16_t yy_def[151] = - { 0, - 140, 1, 140, 140, 140, 141, 140, 142, 143, 140, - 140, 144, 140, 140, 145, 140, 140, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 140, 140, 140, 140, - 141, 142, 143, 140, 140, 146, 147, 143, 144, 140, - 148, 140, 140, 149, 150, 140, 145, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 146, 146, 147, 147, 143, 143, 140, 140, 148, - 140, 140, 149, 149, 150, 150, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 140, 140, 140, 140, 140, 140, 143, 143, 143, - - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 140, 140, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 140, 143, 143, 143, - 143, 143, 143, 140, 140, 143, 143, 143, 143, 0, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140 - } ; - -static yyconst flex_int16_t yy_nxt[431] = - { 0, - 4, 5, 6, 5, 5, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 23, 24, 25, 26, 9, 27, 28, 18, 19, - 20, 21, 9, 22, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 23, 24, 25, 26, 9, 29, 30, - 34, 48, 35, 37, 38, 42, 39, 49, 43, 54, - 52, 50, 55, 42, 45, 46, 53, 47, 42, 51, - 58, 59, 61, 48, 77, 56, 74, 57, 78, 49, - 60, 54, 52, 50, 55, 73, 64, 62, 53, 65, - - 63, 51, 58, 59, 61, 42, 77, 56, 43, 57, - 78, 42, 60, 42, 43, 46, 79, 35, 42, 42, - 37, 67, 68, 39, 42, 68, 75, 73, 62, 76, - 68, 80, 36, 33, 40, 68, 42, 135, 79, 42, - 81, 69, 82, 71, 42, 71, 83, 42, 72, 42, - 43, 84, 85, 80, 71, 42, 71, 86, 68, 72, - 42, 68, 81, 69, 82, 87, 68, 88, 83, 89, - 40, 68, 42, 84, 85, 43, 90, 69, 113, 86, - 42, 45, 46, 98, 47, 42, 93, 87, 94, 88, - 96, 89, 64, 62, 68, 65, 99, 68, 90, 69, - - 64, 62, 68, 65, 100, 98, 66, 68, 68, 114, - 95, 68, 95, 91, 72, 96, 68, 115, 99, 94, - 66, 68, 75, 73, 101, 76, 100, 91, 66, 68, - 75, 73, 68, 76, 102, 91, 92, 68, 92, 93, - 42, 94, 68, 42, 103, 104, 101, 105, 42, 91, - 97, 106, 72, 42, 107, 108, 102, 109, 110, 111, - 95, 40, 112, 116, 117, 113, 103, 104, 118, 105, - 119, 120, 121, 106, 122, 68, 107, 108, 68, 109, - 110, 111, 123, 68, 124, 116, 117, 96, 68, 125, - 118, 126, 119, 120, 121, 68, 122, 68, 68, 128, - - 68, 129, 41, 68, 123, 68, 124, 113, 68, 114, - 68, 125, 68, 126, 130, 68, 127, 131, 132, 133, - 68, 128, 136, 129, 114, 68, 137, 134, 138, 134, - 139, 127, 135, 40, 68, 140, 130, 68, 127, 131, - 132, 133, 68, 140, 136, 140, 135, 68, 137, 140, - 138, 140, 139, 127, 31, 31, 140, 31, 32, 32, - 140, 32, 44, 140, 44, 70, 70, 140, 70, 3, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140 - } ; - -static yyconst flex_int16_t yy_chk[431] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 10, 18, 10, 12, 12, 15, 12, 19, 15, 22, - 21, 20, 23, 15, 15, 15, 21, 15, 15, 20, - 24, 25, 26, 18, 48, 23, 150, 23, 49, 19, - 25, 22, 21, 20, 23, 149, 37, 37, 21, 37, - - 147, 20, 24, 25, 26, 35, 48, 23, 35, 23, - 49, 39, 25, 35, 39, 35, 50, 35, 35, 39, - 39, 39, 40, 39, 39, 40, 45, 45, 146, 45, - 40, 51, 144, 143, 40, 40, 42, 134, 50, 42, - 52, 40, 53, 42, 42, 42, 54, 43, 42, 42, - 43, 55, 56, 51, 43, 43, 43, 57, 46, 43, - 43, 46, 52, 40, 53, 58, 46, 59, 54, 60, - 46, 46, 47, 55, 56, 47, 61, 46, 112, 57, - 47, 47, 47, 77, 47, 47, 92, 58, 92, 59, - 95, 60, 64, 64, 66, 64, 78, 66, 61, 46, - - 65, 65, 66, 65, 79, 77, 66, 66, 67, 93, - 69, 67, 69, 66, 71, 69, 67, 94, 78, 94, - 67, 67, 75, 75, 80, 75, 79, 67, 38, 68, - 76, 76, 68, 76, 81, 66, 68, 68, 68, 68, - 72, 68, 68, 72, 82, 83, 80, 84, 72, 67, - 72, 85, 72, 72, 86, 87, 81, 88, 89, 90, - 91, 34, 91, 98, 101, 91, 82, 83, 102, 84, - 103, 104, 105, 85, 106, 96, 86, 87, 96, 88, - 89, 90, 107, 96, 108, 98, 101, 96, 96, 109, - 102, 110, 103, 104, 105, 113, 106, 114, 113, 117, - - 114, 118, 14, 113, 107, 114, 108, 113, 113, 114, - 114, 109, 115, 110, 121, 115, 114, 122, 124, 126, - 115, 117, 128, 118, 115, 115, 132, 127, 133, 127, - 137, 115, 127, 13, 135, 3, 121, 135, 114, 122, - 124, 126, 135, 0, 128, 0, 135, 135, 132, 0, - 133, 0, 137, 115, 141, 141, 0, 141, 142, 142, - 0, 142, 145, 0, 145, 148, 148, 0, 148, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, - 140, 140, 140, 140, 140, 140, 140, 140, 140, 140 - } ; - -extern int xyy_flex_debug; -int xyy_flex_debug = 0; - -static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; -static char *yy_full_match; -static int yy_lp; -static int yy_looking_for_trail_begin = 0; -static int yy_full_lp; -static int *yy_full_state; -#define YY_TRAILING_MASK 0x2000 -#define YY_TRAILING_HEAD_MASK 0x4000 -#define REJECT \ -{ \ -*yy_cp = (yy_hold_char); /* undo effects of setting up xyytext */ \ -yy_cp = (yy_full_match); /* restore poss. backed-over text */ \ -(yy_lp) = (yy_full_lp); /* restore orig. accepting pos. */ \ -(yy_state_ptr) = (yy_full_state); /* restore orig. state */ \ -yy_current_state = *(yy_state_ptr); /* restore curr. state */ \ -++(yy_lp); \ -goto find_rule; \ -} - -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *xyytext; -#line 1 "xLexer.lxx" -/** - * @file xLexer.lxx - * @author drose - * @date 2004-10-03 - */ -#line 9 "xLexer.lxx" -#include "xLexerDefs.h" -#include "xParserDefs.h" -#include "xParser.h" -#include "indent.h" -#include "string_utils.h" -#include "config_xfile.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. -int x_line_number = 0; -int x_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; -char x_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 std::istream *input_p = nullptr; - -// This is the name of the x file we're parsing. We keep it so we -// can print it out for error messages. -static std::string x_filename; - - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the lexer. -//////////////////////////////////////////////////////////////////// - -void -x_init_lexer(std::istream &in, const std::string &filename) { - input_p = ∈ - x_filename = filename; - x_line_number = 0; - x_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 std::string &msg) { - xyyerror(msg, x_line_number, x_col_number, x_current_line); -} - -void -xyyerror(const std::string &msg, int line_number, int col_number, - const std::string ¤t_line) { - xfile_cat.error(false) << "\nError"; - if (!x_filename.empty()) { - xfile_cat.error(false) << " in " << x_filename; - } - xfile_cat.error(false) - << " at line " << line_number << ", column " << col_number << ":\n" - << current_line << "\n"; - indent(xfile_cat.error(false), col_number-1) - << "^\n" << msg << "\n\n"; - - error_count++; -} - -void -xyywarning(const std::string &msg) { - xfile_cat.warning(false) << "\nWarning"; - if (!x_filename.empty()) { - xfile_cat.warning(false) << " in " << x_filename; - } - xfile_cat.warning(false) - << " at line " << x_line_number << ", column " << x_col_number << ":\n" - << x_current_line << "\n"; - indent(xfile_cat.warning(false), x_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(input_p != NULL); - if (*input_p) { - input_p->read(buffer, max_size); - result = input_p->gcount(); - if (result >= 0 && result < max_size) { - // Truncate at the end of the read. - buffer[result] = '\0'; - } - - if (x_line_number == 0) { - // This is a special case. If we are reading the very first bit - // from the stream, copy it into the x_current_line array. This - // is because the \n.* rule below, which fills x_current_line - // normally, doesn't catch the first line. - strncpy(x_current_line, xyytext, max_error_width); - x_current_line[max_error_width] = '\0'; - x_line_number++; - x_col_number = 0; - - // Truncate it at the newline. - char *end = strchr(x_current_line, '\n'); - if (end != NULL) { - *end = '\0'; - } - } - - } else { - // End of file or I/O error. - result = 0; - } -} -#undef YY_INPUT - -// Define this macro carefully, since different flex versions call it -// with a different type for result. -#define YY_INPUT(buffer, result, max_size) { \ - int int_result = 0; \ - input_chars((buffer), int_result, (max_size)); \ - (result) = int_result; \ -} - -// 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 std::string -scan_quoted_string(char quote_mark) { - std::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 x_line_number and x_col_number - // variables, we'll operate on our own local variables for the - // interim. - int line = x_line_number; - int col = x_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."); - } - - x_line_number = line; - x_col_number = col; - - return result; -} - -// scan_guid_string reads a string of hexadecimal digits delimited by -// angle brackets and returns the corresponding string. -static std::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 x_line_number and x_col_number - // variables, we'll operate on our own local variables for the - // interim. - int line = x_line_number; - int col = x_col_number; - - int num_digits = 0; - int num_hyphens = 0; - - std::string result; - - int c; - c = read_char(line, col); - while (c != '>' && c != EOF) { - if (isxdigit(c)) { - num_digits++; - - } else if (c == '-') { - num_hyphens++; - - } else { - x_line_number = line; - x_col_number = col; - xyyerror("Invalid character in GUID."); - return std::string(); - } - - result += c; - - c = read_char(line, col); - } - - if (c == EOF) { - xyyerror("This GUID string is unterminated."); - return std::string(); - - } else if (num_digits != 32) { - xyyerror("Incorrect number of hex digits in GUID."); - return std::string(); - - } else if (num_hyphens != 4) { - xyyerror("Incorrect number of hyphens in GUID."); - return std::string(); - } - - x_line_number = line; - x_col_number = col; - - return result; -} - -// Parses the text into a list of integers and returns them. -static PTA_int -scan_int_list(const std::string &text) { - PTA_int result; - - vector_string words; - tokenize(text, words, ",;"); - - vector_string::const_iterator wi; - for (wi = words.begin(); wi != words.end(); ++wi) { - std::string trimmed = trim(*wi); - if (!trimmed.empty()) { - int number = 0; - string_to_int(trimmed, number); - result.push_back(number); - } - } - - return result; -} - -// Parses the text into a list of doubles and returns them. -static PTA_double -scan_double_list(const std::string &text) { - PTA_double result; - - vector_string words; - tokenize(text, words, ",;"); - - vector_string::const_iterator wi; - for (wi = words.begin(); wi != words.end(); ++wi) { - std::string trimmed = trim(*wi); - if (!trimmed.empty()) { - double number = 0.0; - string_to_double(trimmed, number); - result.push_back(number); - } - } - - 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() { - x_col_number += xyyleng; -} - -#line 1052 "lex.yy.c" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); - -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ - -int xyylex_destroy (void ); - -int xyyget_debug (void ); - -void xyyset_debug (int debug_flag ); - -YY_EXTRA_TYPE xyyget_extra (void ); - -void xyyset_extra (YY_EXTRA_TYPE user_defined ); - -FILE *xyyget_in (void ); - -void xyyset_in (FILE * in_str ); - -FILE *xyyget_out (void ); - -void xyyset_out (FILE * out_str ); - -int xyyget_leng (void ); - -char *xyyget_text (void ); - -int xyyget_lineno (void ); - -void xyyset_lineno (int line_number ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int xyywrap (void ); -#else -extern int xyywrap (void ); -#endif -#endif - - static void yyunput (int c,char *buf_ptr ); - -#ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); -#endif - -#ifndef YY_NO_INPUT - -#ifdef __cplusplus -static int yyinput (void ); -#else -static int input (void ); -#endif - -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#define YY_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO fwrite( xyytext, xyyleng, 1, xyyout ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - int n; \ - for ( n = 0; n < max_size && \ - (c = getc( xyyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( xyyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, xyyin))==0 && ferror(xyyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(xyyin); \ - } \ - }\ -\ - -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* end tables serialization structures and prototypes */ - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int xyylex (void); - -#define YY_DECL int xyylex (void) -#endif /* !YY_DECL */ - -/* Code executed at the beginning of each rule, after xyytext and xyyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - YY_USER_ACTION - -/** The main scanner function which does all the work. - */ -YY_DECL -{ - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 414 "xLexer.lxx" - - - - - -#line 1240 "lex.yy.c" - - if ( !(yy_init) ) - { - (yy_init) = 1; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - /* Create the reject buffer large enough to save one state per allowed character. */ - if ( ! (yy_state_buf) ) - (yy_state_buf) = (yy_state_type *)xyyalloc(YY_STATE_BUF_SIZE ); - if ( ! (yy_state_buf) ) - YY_FATAL_ERROR( "out of dynamic memory in xyylex()" ); - - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ - - if ( ! xyyin ) - xyyin = stdin; - - if ( ! xyyout ) - xyyout = stdout; - - if ( ! YY_CURRENT_BUFFER ) { - xyyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - xyy_create_buffer(xyyin,YY_BUF_SIZE ); - } - - xyy_load_buffer_state( ); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = (yy_c_buf_p); - - /* Support of xyytext. */ - *yy_cp = (yy_hold_char); - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = (yy_start); - - (yy_state_ptr) = (yy_state_buf); - *(yy_state_ptr)++ = yy_current_state; - -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 141 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - *(yy_state_ptr)++ = yy_current_state; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 370 ); - -yy_find_action: - yy_current_state = *--(yy_state_ptr); - (yy_lp) = yy_accept[yy_current_state]; -find_rule: /* we branch to this label when backing up */ - for ( ; ; ) /* until we find what rule we matched */ - { - if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] ) - { - yy_act = yy_acclist[(yy_lp)]; - if ( yy_act & YY_TRAILING_HEAD_MASK || - (yy_looking_for_trail_begin) ) - { - if ( yy_act == (yy_looking_for_trail_begin) ) - { - (yy_looking_for_trail_begin) = 0; - yy_act &= ~YY_TRAILING_HEAD_MASK; - break; - } - } - else if ( yy_act & YY_TRAILING_MASK ) - { - (yy_looking_for_trail_begin) = yy_act & ~YY_TRAILING_MASK; - (yy_looking_for_trail_begin) |= YY_TRAILING_HEAD_MASK; - } - else - { - (yy_full_match) = yy_cp; - (yy_full_state) = (yy_state_ptr); - (yy_full_lp) = (yy_lp); - break; - } - ++(yy_lp); - goto find_rule; - } - --yy_cp; - yy_current_state = *--(yy_state_ptr); - (yy_lp) = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - -do_action: /* This label is used only to access EOF actions. */ - - switch ( yy_act ) - { /* beginning of action switch */ -case 1: -/* rule 1 can match eol */ -YY_RULE_SETUP -#line 419 "xLexer.lxx" -{ - // 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(x_current_line, xyytext+1, max_error_width); - x_current_line[max_error_width] = '\0'; - x_line_number++; - x_col_number=0; - - // Return the whole line to the lexer, except the newline character, - // which we eat. - yyless(1); -} - YY_BREAK -case 2: -YY_RULE_SETUP -#line 433 "xLexer.lxx" -{ - // Eat whitespace. - accept(); -} - YY_BREAK -case 3: -YY_RULE_SETUP -#line 438 "xLexer.lxx" -{ - // Eat C++-style comments. - accept(); -} - YY_BREAK -case 4: -YY_RULE_SETUP -#line 443 "xLexer.lxx" -{ - // Eat sh-style comments. - accept(); -} - YY_BREAK -case 5: -YY_RULE_SETUP -#line 448 "xLexer.lxx" -{ - accept(); - return TOKEN_OBRACE; -} - YY_BREAK -case 6: -YY_RULE_SETUP -#line 453 "xLexer.lxx" -{ - accept(); - return TOKEN_CBRACE; -} - YY_BREAK -case 7: -YY_RULE_SETUP -#line 458 "xLexer.lxx" -{ - accept(); - return TOKEN_OBRACKET; -} - YY_BREAK -case 8: -YY_RULE_SETUP -#line 463 "xLexer.lxx" -{ - accept(); - return TOKEN_CBRACKET; -} - YY_BREAK -case 9: -YY_RULE_SETUP -#line 468 "xLexer.lxx" -{ - accept(); - return TOKEN_DOT; -} - YY_BREAK -case 10: -YY_RULE_SETUP -#line 473 "xLexer.lxx" -{ - accept(); - return TOKEN_COMMA; -} - YY_BREAK -case 11: -YY_RULE_SETUP -#line 478 "xLexer.lxx" -{ - accept(); - return TOKEN_SEMICOLON; -} - YY_BREAK -case 12: -YY_RULE_SETUP -#line 483 "xLexer.lxx" -{ - accept(); - return TOKEN_ARRAY; -} - YY_BREAK -case 13: -YY_RULE_SETUP -#line 488 "xLexer.lxx" -{ - accept(); - return TOKEN_UCHAR; -} - YY_BREAK -case 14: -YY_RULE_SETUP -#line 493 "xLexer.lxx" -{ - accept(); - return TOKEN_CHAR; -} - YY_BREAK -case 15: -YY_RULE_SETUP -#line 498 "xLexer.lxx" -{ - accept(); - return TOKEN_CSTRING; -} - YY_BREAK -case 16: -YY_RULE_SETUP -#line 503 "xLexer.lxx" -{ - accept(); - return TOKEN_DOUBLE; -} - YY_BREAK -case 17: -YY_RULE_SETUP -#line 508 "xLexer.lxx" -{ - accept(); - return TOKEN_DWORD; -} - YY_BREAK -case 18: -YY_RULE_SETUP -#line 513 "xLexer.lxx" -{ - accept(); - return TOKEN_SDWORD; -} - YY_BREAK -case 19: -YY_RULE_SETUP -#line 518 "xLexer.lxx" -{ - accept(); - return TOKEN_FLOAT; -} - YY_BREAK -case 20: -YY_RULE_SETUP -#line 523 "xLexer.lxx" -{ - accept(); - return TOKEN_LPSTR; -} - YY_BREAK -case 21: -YY_RULE_SETUP -#line 528 "xLexer.lxx" -{ - accept(); - return TOKEN_TEMPLATE; -} - YY_BREAK -case 22: -YY_RULE_SETUP -#line 533 "xLexer.lxx" -{ - accept(); - return TOKEN_UCHAR; -} - YY_BREAK -case 23: -YY_RULE_SETUP -#line 538 "xLexer.lxx" -{ - accept(); - return TOKEN_UNICODE; -} - YY_BREAK -case 24: -YY_RULE_SETUP -#line 543 "xLexer.lxx" -{ - accept(); - return TOKEN_SWORD; -} - YY_BREAK -case 25: -YY_RULE_SETUP -#line 548 "xLexer.lxx" -{ - accept(); - return TOKEN_WORD; -} - YY_BREAK -case 26: -YY_RULE_SETUP -#line 553 "xLexer.lxx" -{ - // A signed or unsigned integer number. - accept(); - xyylval.u.number = atol(xyytext); - xyylval.str = trim_right(xyytext); - - return TOKEN_INTEGER; -} - YY_BREAK -case 27: -YY_RULE_SETUP -#line 562 "xLexer.lxx" -{ - // An integer as part of a semicolon- or comma-delimited list. - accept(); - xyylval.int_list = scan_int_list(xyytext); - - return TOKEN_INTEGER_LIST; -} - YY_BREAK -case 28: -YY_RULE_SETUP -#line 570 "xLexer.lxx" -{ - // This rule is used to match an integer list that is followed by a - // floating-point number. It's designed to prevent "0;0.5" from - // being interpreted as "0;0" followed by ".5". - accept(); - xyylval.int_list = scan_int_list(xyytext); - - return TOKEN_INTEGER_LIST; -} - YY_BREAK -case 29: -YY_RULE_SETUP -#line 580 "xLexer.lxx" -{ - // A floating-point number as part of a semicolon- or comma-delimited list. - accept(); - xyylval.double_list = scan_double_list(xyytext); - - return TOKEN_REALNUM_LIST; -} - YY_BREAK -case 30: -YY_RULE_SETUP -#line 588 "xLexer.lxx" -{ - // Quoted string. - accept(); - xyylval.str = scan_quoted_string('"'); - return TOKEN_STRING; -} - YY_BREAK -case 31: -YY_RULE_SETUP -#line 595 "xLexer.lxx" -{ - // Long GUID string. - accept(); - xyylval.str = scan_guid_string(); - - if (!xyylval.guid.parse_string(xyylval.str)) { - xyyerror("Malformed GUID."); - } - - return TOKEN_GUID; -} - YY_BREAK -case 32: -YY_RULE_SETUP -#line 607 "xLexer.lxx" -{ - // Identifier. - accept(); - xyylval.str = xyytext; - return TOKEN_NAME; -} - YY_BREAK -case 33: -YY_RULE_SETUP -#line 614 "xLexer.lxx" -{ - // Identifier with leading digit. - accept(); - xyylval.str = xyytext; - return TOKEN_NAME; -} - YY_BREAK -case 34: -YY_RULE_SETUP -#line 621 "xLexer.lxx" -{ - // Any other character is invalid. - accept(); - xyyerror("Invalid character '" + std::string(xyytext) + "'."); -} - YY_BREAK -case 35: -YY_RULE_SETUP -#line 626 "xLexer.lxx" -ECHO; - YY_BREAK -#line 1668 "lex.yy.c" - case YY_STATE_EOF(INITIAL): - yyterminate(); - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); - YY_RESTORE_YY_MORE_OFFSET - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed xyyin at a new source and called - * xyylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = xyyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = (yy_c_buf_p); - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_END_OF_FILE: - { - (yy_did_buffer_switch_on_eof) = 0; - - if ( xyywrap( ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * xyytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; - - yy_current_state = yy_get_previous_state( ); - - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -} /* end of xyylex */ - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ -static int yy_get_next_buffer (void) -{ - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); - register int number_to_move, i; - int ret_val; - - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; - - else - { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); - - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - if ( (yy_n_chars) == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - xyyrestart(xyyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) xyyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - } - - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; - - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; - - return ret_val; -} - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - - static yy_state_type yy_get_previous_state (void) -{ - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = (yy_start); - - (yy_state_ptr) = (yy_state_buf); - *(yy_state_ptr)++ = yy_current_state; - - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 141 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - *(yy_state_ptr)++ = yy_current_state; - } - - return yy_current_state; -} - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ - register int yy_is_jam; - - register YY_CHAR yy_c = 1; - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 141 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 140); - if ( ! yy_is_jam ) - *(yy_state_ptr)++ = yy_current_state; - - return yy_is_jam ? 0 : yy_current_state; -} - - static void yyunput (int c, register char * yy_bp ) -{ - register char *yy_cp; - - yy_cp = (yy_c_buf_p); - - /* undo effects of setting up xyytext */ - *yy_cp = (yy_hold_char); - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; - register char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; - - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; - - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} - -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (void) -#else - static int input (void) -#endif - -{ - int c; - - *(yy_c_buf_p) = (yy_hold_char); - - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) - /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; - - else - { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - xyyrestart(xyyin ); - - /*FALLTHROUGH*/ - - case EOB_ACT_END_OF_FILE: - { - if ( xyywrap( ) ) - return EOF; - - if ( ! (yy_did_buffer_switch_on_eof) ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; - break; - } - } - } - - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve xyytext */ - (yy_hold_char) = *++(yy_c_buf_p); - - return c; -} -#endif /* ifndef YY_NO_INPUT */ - -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void xyyrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - xyyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - xyy_create_buffer(xyyin,YY_BUF_SIZE ); - } - - xyy_init_buffer(YY_CURRENT_BUFFER,input_file ); - xyy_load_buffer_state( ); -} - -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void xyy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * xyypop_buffer_state(); - * xyypush_buffer_state(new_buffer); - */ - xyyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; - - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - YY_CURRENT_BUFFER_LVALUE = new_buffer; - xyy_load_buffer_state( ); - - /* We don't actually know whether we did this switch during - * EOF (xyywrap()) processing, but the only time this flag - * is looked at is after xyywrap() is called, so it's safe - * to go ahead and always set it. - */ - (yy_did_buffer_switch_on_eof) = 1; -} - -static void xyy_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - xyyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} - -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE xyy_create_buffer (FILE * file, int size ) -{ - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) xyyalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in xyy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) xyyalloc(b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in xyy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - xyy_init_buffer(b,file ); - - return b; -} - -/** Destroy the buffer. - * @param b a buffer created with xyy_create_buffer() - * - */ - void xyy_delete_buffer (YY_BUFFER_STATE b ) -{ - - if ( ! b ) - return; - - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - xyyfree((void *) b->yy_ch_buf ); - - xyyfree((void *) b ); -} - -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a xyyrestart() or at EOF. - */ - static void xyy_init_buffer (YY_BUFFER_STATE b, FILE * file ) - -{ - int oerrno = errno; - - xyy_flush_buffer(b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - - /* If b is the current buffer, then xyy_init_buffer was _probably_ - * called from xyyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} - -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void xyy_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == YY_CURRENT_BUFFER ) - xyy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void xyypush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - xyyensure_buffer_stack(); - - /* This block is copied from xyy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from xyy_switch_to_buffer. */ - xyy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void xyypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - xyy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - xyy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void xyyensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)xyyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in xyyensure_buffer_stack()" ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; - } - - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)xyyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - if ( ! (yy_buffer_stack) ) - YY_FATAL_ERROR( "out of dynamic memory in xyyensure_buffer_stack()" ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE xyy_scan_buffer (char * base, yy_size_t size ) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) xyyalloc(sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in xyy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - xyy_switch_to_buffer(b ); - - return b; -} - -/** Setup the input buffer state to scan a string. The next call to xyylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * xyy_scan_bytes() instead. - */ -YY_BUFFER_STATE xyy_scan_string (yyconst char * yystr ) -{ - - return xyy_scan_bytes(yystr,strlen(yystr) ); -} - -/** Setup the input buffer state to scan the given bytes. The next call to xyylex() will - * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE xyy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) xyyalloc(n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in xyy_scan_bytes()" ); - - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - - b = xyy_scan_buffer(buf,n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in xyy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up xyytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - xyytext[xyyleng] = (yy_hold_char); \ - (yy_c_buf_p) = xyytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - xyyleng = yyless_macro_arg; \ - } \ - while ( 0 ) - -/* Accessor methods (get/set functions) to struct members. */ - -/** Get the current line number. - * - */ -int xyyget_lineno (void) -{ - - return xyylineno; -} - -/** Get the input stream. - * - */ -FILE *xyyget_in (void) -{ - return xyyin; -} - -/** Get the output stream. - * - */ -FILE *xyyget_out (void) -{ - return xyyout; -} - -/** Get the length of the current token. - * - */ -int xyyget_leng (void) -{ - return xyyleng; -} - -/** Get the current token. - * - */ - -char *xyyget_text (void) -{ - return xyytext; -} - -/** Set the current line number. - * @param line_number - * - */ -void xyyset_lineno (int line_number ) -{ - - xyylineno = line_number; -} - -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see xyy_switch_to_buffer - */ -void xyyset_in (FILE * in_str ) -{ - xyyin = in_str ; -} - -void xyyset_out (FILE * out_str ) -{ - xyyout = out_str ; -} - -int xyyget_debug (void) -{ - return xyy_flex_debug; -} - -void xyyset_debug (int bdebug ) -{ - xyy_flex_debug = bdebug ; -} - -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from xyylex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - - (yy_state_buf) = 0; - (yy_state_ptr) = 0; - (yy_full_match) = 0; - (yy_lp) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - xyyin = stdin; - xyyout = stdout; -#else - xyyin = (FILE *) 0; - xyyout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * xyylex_init() - */ - return 0; -} - -/* xyylex_destroy is for both reentrant and non-reentrant scanners. */ -int xyylex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - xyy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - xyypop_buffer_state(); - } - - /* Destroy the stack itself. */ - xyyfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; - - xyyfree ( (yy_state_buf) ); - (yy_state_buf) = NULL; - - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * xyylex() is called, initialization will occur. */ - yy_init_globals( ); - - return 0; -} - -/* - * Internal utility routines. - */ - -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; -} -#endif - -void *xyyalloc (yy_size_t size ) -{ - return (void *) malloc( size ); -} - -void *xyyrealloc (void * ptr, yy_size_t size ) -{ - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); -} - -void xyyfree (void * ptr ) -{ - free( (char *) ptr ); /* see xyyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" - -#line 626 "xLexer.lxx" diff --git a/pandatool/src/xfile/xLexer.lxx b/pandatool/src/xfile/xLexer.lxx deleted file mode 100644 index 7a5aac98..00000000 --- a/pandatool/src/xfile/xLexer.lxx +++ /dev/null @@ -1,624 +0,0 @@ -/** - * @file xLexer.lxx - * @author drose - * @date 2004-10-03 - */ - -%{ -#include "xLexerDefs.h" -#include "xParserDefs.h" -#include "xParser.h" -#include "indent.h" -#include "string_utils.h" -#include "config_xfile.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. -int x_line_number = 0; -int x_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; -char x_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 std::istream *input_p = nullptr; - -// This is the name of the x file we're parsing. We keep it so we -// can print it out for error messages. -static std::string x_filename; - - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the lexer. -//////////////////////////////////////////////////////////////////// - -void -x_init_lexer(std::istream &in, const std::string &filename) { - input_p = ∈ - x_filename = filename; - x_line_number = 0; - x_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 std::string &msg) { - xyyerror(msg, x_line_number, x_col_number, x_current_line); -} - -void -xyyerror(const std::string &msg, int line_number, int col_number, - const std::string ¤t_line) { - xfile_cat.error(false) << "\nError"; - if (!x_filename.empty()) { - xfile_cat.error(false) << " in " << x_filename; - } - xfile_cat.error(false) - << " at line " << line_number << ", column " << col_number << ":\n" - << current_line << "\n"; - indent(xfile_cat.error(false), col_number-1) - << "^\n" << msg << "\n\n"; - - error_count++; -} - -void -xyywarning(const std::string &msg) { - xfile_cat.warning(false) << "\nWarning"; - if (!x_filename.empty()) { - xfile_cat.warning(false) << " in " << x_filename; - } - xfile_cat.warning(false) - << " at line " << x_line_number << ", column " << x_col_number << ":\n" - << x_current_line << "\n"; - indent(xfile_cat.warning(false), x_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(input_p != nullptr); - if (*input_p) { - input_p->read(buffer, max_size); - result = input_p->gcount(); - if (result >= 0 && result < max_size) { - // Truncate at the end of the read. - buffer[result] = '\0'; - } - - if (x_line_number == 0) { - // This is a special case. If we are reading the very first bit - // from the stream, copy it into the x_current_line array. This - // is because the \n.* rule below, which fills x_current_line - // normally, doesn't catch the first line. - strncpy(x_current_line, xyytext, max_error_width); - x_current_line[max_error_width] = '\0'; - x_line_number++; - x_col_number = 0; - - // Truncate it at the newline. - char *end = strchr(x_current_line, '\n'); - if (end != nullptr) { - *end = '\0'; - } - } - - } else { - // End of file or I/O error. - result = 0; - } -} -#undef YY_INPUT - -// Define this macro carefully, since different flex versions call it -// with a different type for result. -#define YY_INPUT(buffer, result, max_size) { \ - int int_result = 0; \ - input_chars((buffer), int_result, (max_size)); \ - (result) = int_result; \ -} - -// 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 std::string -scan_quoted_string(char quote_mark) { - std::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 x_line_number and x_col_number - // variables, we'll operate on our own local variables for the - // interim. - int line = x_line_number; - int col = x_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."); - } - - x_line_number = line; - x_col_number = col; - - return result; -} - -// scan_guid_string reads a string of hexadecimal digits delimited by -// angle brackets and returns the corresponding string. -static std::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 x_line_number and x_col_number - // variables, we'll operate on our own local variables for the - // interim. - int line = x_line_number; - int col = x_col_number; - - int num_digits = 0; - int num_hyphens = 0; - - std::string result; - - int c; - c = read_char(line, col); - while (c != '>' && c != EOF) { - if (isxdigit(c)) { - num_digits++; - - } else if (c == '-') { - num_hyphens++; - - } else { - x_line_number = line; - x_col_number = col; - xyyerror("Invalid character in GUID."); - return std::string(); - } - - result += c; - - c = read_char(line, col); - } - - if (c == EOF) { - xyyerror("This GUID string is unterminated."); - return std::string(); - - } else if (num_digits != 32) { - xyyerror("Incorrect number of hex digits in GUID."); - return std::string(); - - } else if (num_hyphens != 4) { - xyyerror("Incorrect number of hyphens in GUID."); - return std::string(); - } - - x_line_number = line; - x_col_number = col; - - return result; -} - -// Parses the text into a list of integers and returns them. -static PTA_int -scan_int_list(const std::string &text) { - PTA_int result; - - vector_string words; - tokenize(text, words, ",;"); - - vector_string::const_iterator wi; - for (wi = words.begin(); wi != words.end(); ++wi) { - std::string trimmed = trim(*wi); - if (!trimmed.empty()) { - int number = 0; - string_to_int(trimmed, number); - result.push_back(number); - } - } - - return result; -} - -// Parses the text into a list of doubles and returns them. -static PTA_double -scan_double_list(const std::string &text) { - PTA_double result; - - vector_string words; - tokenize(text, words, ",;"); - - vector_string::const_iterator wi; - for (wi = words.begin(); wi != words.end(); ++wi) { - std::string trimmed = trim(*wi); - if (!trimmed.empty()) { - double number = 0.0; - string_to_double(trimmed, number); - result.push_back(number); - } - } - - 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() { - x_col_number += yyleng; -} - -%} - -INTEGERNUM ([+-]?([0-9]+)) -REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) -SEPARATOR [ \t;,]+ -WHITESPACE [ ]+ - -%% - -%{ -%} - -\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(x_current_line, xyytext+1, max_error_width); - x_current_line[max_error_width] = '\0'; - x_line_number++; - x_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(); -} - -"{" { - accept(); - return TOKEN_OBRACE; -} - -"}" { - accept(); - return TOKEN_CBRACE; -} - -"[" { - accept(); - return TOKEN_OBRACKET; -} - -"]" { - accept(); - return TOKEN_CBRACKET; -} - -"." { - accept(); - return TOKEN_DOT; -} - -"," { - accept(); - return TOKEN_COMMA; -} - -";" { - accept(); - return TOKEN_SEMICOLON; -} - -"array" { - accept(); - return TOKEN_ARRAY; -} - -"byte" { - accept(); - return TOKEN_UCHAR; -} - -"char" { - accept(); - return TOKEN_CHAR; -} - -"cstring" { - accept(); - return TOKEN_CSTRING; -} - -"double" { - accept(); - return TOKEN_DOUBLE; -} - -"dword" { - accept(); - return TOKEN_DWORD; -} - -"sdword" { - accept(); - return TOKEN_SDWORD; -} - -"float" { - accept(); - return TOKEN_FLOAT; -} - -"string" { - accept(); - return TOKEN_LPSTR; -} - -"template" { - accept(); - return TOKEN_TEMPLATE; -} - -"uchar" { - accept(); - return TOKEN_UCHAR; -} - -"unicode" { - accept(); - return TOKEN_UNICODE; -} - -"sword" { - accept(); - return TOKEN_SWORD; -} - -"word" { - accept(); - return TOKEN_WORD; -} - -{INTEGERNUM}({WHITESPACE})? { - // A signed or unsigned integer number. - accept(); - xyylval.u.number = atol(xyytext); - xyylval.str = trim_right(xyytext); - - return TOKEN_INTEGER; -} - -({INTEGERNUM}{SEPARATOR})+({INTEGERNUM})? { - // An integer as part of a semicolon- or comma-delimited list. - accept(); - xyylval.int_list = scan_int_list(xyytext); - - return TOKEN_INTEGER_LIST; -} - -({INTEGERNUM}{SEPARATOR})+/{INTEGERNUM}[.] { - // This rule is used to match an integer list that is followed by a - // floating-point number. It's designed to prevent "0;0.5" from - // being interpreted as "0;0" followed by ".5". - accept(); - xyylval.int_list = scan_int_list(xyytext); - - return TOKEN_INTEGER_LIST; -} - -({REALNUM}{SEPARATOR})+({REALNUM})? { - // A floating-point number as part of a semicolon- or comma-delimited list. - accept(); - xyylval.double_list = scan_double_list(xyytext); - - return TOKEN_REALNUM_LIST; -} - -["] { - // Quoted string. - accept(); - xyylval.str = scan_quoted_string('"'); - return TOKEN_STRING; -} - -[<] { - // Long GUID string. - accept(); - xyylval.str = scan_guid_string(); - - if (!xyylval.guid.parse_string(xyylval.str)) { - xyyerror("Malformed GUID."); - } - - return TOKEN_GUID; -} - -[A-Za-z_()-][A-Za-z0-9_.()-]* { - // Identifier. - accept(); - xyylval.str = xyytext; - return TOKEN_NAME; -} - -[0-9-]+[A-Za-z_()-][A-Za-z0-9_.()-]* { - // Identifier with leading digit. - accept(); - xyylval.str = xyytext; - return TOKEN_NAME; -} - -. { - // Any other character is invalid. - accept(); - xyyerror("Invalid character '" + std::string(xyytext) + "'."); -} diff --git a/pandatool/src/xfile/xLexerDefs.h b/pandatool/src/xfile/xLexerDefs.h deleted file mode 100644 index c256cd0d..00000000 --- a/pandatool/src/xfile/xLexerDefs.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xLexerDefs.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XLEXERDEFS_H -#define XLEXERDEFS_H - -#include "pandatoolbase.h" - -void x_init_lexer(std::istream &in, const std::string &filename); -int x_error_count(); -int x_warning_count(); - -void xyyerror(const std::string &msg); -void xyyerror(const std::string &msg, int line_number, int col_number, - const std::string ¤t_line); -void xyywarning(const std::string &msg); - -int xyylex(); - -extern int x_line_number; -extern int x_col_number; -extern char x_current_line[]; - -#endif diff --git a/pandatool/src/xfile/xParser.cxx.prebuilt b/pandatool/src/xfile/xParser.cxx.prebuilt deleted file mode 100644 index 03b2d8e6..00000000 --- a/pandatool/src/xfile/xParser.cxx.prebuilt +++ /dev/null @@ -1,2166 +0,0 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "2.4.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - -/* Using locations. */ -#define YYLSP_NEEDED 0 - -/* Substitute the variable and function names. */ -#define yyparse xyyparse -#define yylex xyylex -#define yyerror xyyerror -#define yylval xyylval -#define yychar xyychar -#define yydebug xyydebug -#define yynerrs xyynerrs - - -/* Copy the first part of user declarations. */ - -/* Line 189 of yacc.c */ -#line 12 "xParser.yxx" - -#include "xLexerDefs.h" -#include "xParserDefs.h" -#include "xFile.h" -#include "xFileTemplate.h" -#include "xFileDataDef.h" -#include "xFileArrayDef.h" -#include "xFileDataNodeTemplate.h" -#include "xFileDataNodeReference.h" -#include "pointerTo.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 = nullptr; -static XFileNode *current_node = nullptr; -static PT(XFileDataDef) current_data_def; - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the parser. -//////////////////////////////////////////////////////////////////// - -void -x_init_parser(std::istream &in, const std::string &filename, XFile &file) { - x_file = &file; - current_node = &file; - x_init_lexer(in, filename); -} - -void -x_cleanup_parser() { - x_file = nullptr; - current_node = nullptr; -} - - - -/* Line 189 of yacc.c */ -#line 124 "y.tab.c" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - TOKEN_NAME = 1, - TOKEN_STRING = 2, - TOKEN_INTEGER = 3, - TOKEN_GUID = 5, - TOKEN_INTEGER_LIST = 6, - TOKEN_REALNUM_LIST = 7, - TOKEN_OBRACE = 10, - TOKEN_CBRACE = 11, - TOKEN_OPAREN = 12, - TOKEN_CPAREN = 13, - TOKEN_OBRACKET = 14, - TOKEN_CBRACKET = 15, - TOKEN_OANGLE = 16, - TOKEN_CANGLE = 17, - TOKEN_DOT = 18, - TOKEN_COMMA = 19, - TOKEN_SEMICOLON = 20, - TOKEN_TEMPLATE = 31, - TOKEN_WORD = 40, - TOKEN_DWORD = 41, - TOKEN_FLOAT = 42, - TOKEN_DOUBLE = 43, - TOKEN_CHAR = 44, - TOKEN_UCHAR = 45, - TOKEN_SWORD = 46, - TOKEN_SDWORD = 47, - TOKEN_VOID = 48, - TOKEN_LPSTR = 49, - TOKEN_UNICODE = 50, - TOKEN_CSTRING = 51, - TOKEN_ARRAY = 52 - }; -#endif -/* Tokens. */ -#define TOKEN_NAME 1 -#define TOKEN_STRING 2 -#define TOKEN_INTEGER 3 -#define TOKEN_GUID 5 -#define TOKEN_INTEGER_LIST 6 -#define TOKEN_REALNUM_LIST 7 -#define TOKEN_OBRACE 10 -#define TOKEN_CBRACE 11 -#define TOKEN_OPAREN 12 -#define TOKEN_CPAREN 13 -#define TOKEN_OBRACKET 14 -#define TOKEN_CBRACKET 15 -#define TOKEN_OANGLE 16 -#define TOKEN_CANGLE 17 -#define TOKEN_DOT 18 -#define TOKEN_COMMA 19 -#define TOKEN_SEMICOLON 20 -#define TOKEN_TEMPLATE 31 -#define TOKEN_WORD 40 -#define TOKEN_DWORD 41 -#define TOKEN_FLOAT 42 -#define TOKEN_DOUBLE 43 -#define TOKEN_CHAR 44 -#define TOKEN_UCHAR 45 -#define TOKEN_SWORD 46 -#define TOKEN_SDWORD 47 -#define TOKEN_VOID 48 -#define TOKEN_LPSTR 49 -#define TOKEN_UNICODE 50 -#define TOKEN_CSTRING 51 -#define TOKEN_ARRAY 52 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - - -/* Copy the second part of user declarations. */ - - -/* Line 264 of yacc.c */ -#line 231 "y.tab.c" - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; -#else -typedef short int yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef YY_ -# define YY_(msgid) msgid -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) -#else -# define YYUSE(e) /* empty */ -#endif - -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) -#else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int yyi) -#else -static int -YYID (yyi) - int yyi; -#endif -{ - return yyi; -} -#endif - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined _STDLIB_H \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (YYID (0)) - -#endif - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 3 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 114 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 34 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 35 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 71 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 100 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 257 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 3, 4, 5, 2, 6, 7, 8, 2, 2, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 20, 2, 2, 2, 2, 2, 2, 2, 2, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2 -}; - -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint8 yyprhs[] = -{ - 0, 0, 3, 5, 8, 11, 14, 15, 23, 28, - 30, 32, 34, 36, 38, 40, 43, 45, 47, 49, - 53, 58, 62, 64, 66, 68, 70, 72, 74, 76, - 78, 80, 82, 84, 87, 90, 92, 95, 99, 101, - 103, 105, 108, 110, 113, 115, 117, 120, 123, 125, - 127, 129, 131, 133, 137, 138, 146, 148, 151, 155, - 157, 159, 161, 164, 166, 168, 170, 172, 174, 176, - 178, 181 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 35, 0, -1, 68, -1, 35, 36, -1, 35, 59, - -1, 35, 10, -1, -1, 20, 53, 9, 56, 37, - 38, 10, -1, 39, 13, 40, 14, -1, 41, -1, - 68, -1, 41, -1, 58, -1, 51, -1, 42, -1, - 41, 42, -1, 43, -1, 44, -1, 45, -1, 46, - 55, 19, -1, 33, 47, 48, 19, -1, 53, 55, - 19, -1, 21, -1, 22, -1, 23, -1, 24, -1, - 25, -1, 26, -1, 27, -1, 28, -1, 30, -1, - 31, -1, 32, -1, 46, 54, -1, 53, 54, -1, - 49, -1, 48, 49, -1, 13, 50, 14, -1, 5, - -1, 54, -1, 52, -1, 51, 52, -1, 53, -1, - 53, 56, -1, 3, -1, 3, -1, 54, 3, -1, - 54, 5, -1, 68, -1, 54, -1, 6, -1, 68, - -1, 56, -1, 17, 17, 17, -1, -1, 53, 55, - 9, 60, 57, 61, 10, -1, 68, -1, 61, 62, - -1, 9, 67, 10, -1, 59, -1, 63, -1, 64, - -1, 65, 66, -1, 66, -1, 7, -1, 8, -1, - 4, -1, 19, -1, 18, -1, 54, -1, 54, 56, - -1, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 108, 108, 109, 110, 111, 116, 115, 130, 131, - 135, 136, 140, 144, 148, 149, 153, 154, 155, 159, - 167, 171, 184, 188, 192, 196, 200, 204, 208, 212, - 216, 220, 224, 231, 236, 249, 250, 254, 258, 262, - 274, 277, 283, 292, 308, 312, 313, 317, 324, 328, - 332, 336, 340, 344, 349, 348, 376, 377, 381, 386, - 390, 398, 406, 414, 420, 424, 428, 432, 433, 437, - 446, 462 -}; -#endif - -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "TOKEN_NAME", "TOKEN_STRING", - "TOKEN_INTEGER", "TOKEN_GUID", "TOKEN_INTEGER_LIST", - "TOKEN_REALNUM_LIST", "TOKEN_OBRACE", "TOKEN_CBRACE", "TOKEN_OPAREN", - "TOKEN_CPAREN", "TOKEN_OBRACKET", "TOKEN_CBRACKET", "TOKEN_OANGLE", - "TOKEN_CANGLE", "TOKEN_DOT", "TOKEN_COMMA", "TOKEN_SEMICOLON", - "TOKEN_TEMPLATE", "TOKEN_WORD", "TOKEN_DWORD", "TOKEN_FLOAT", - "TOKEN_DOUBLE", "TOKEN_CHAR", "TOKEN_UCHAR", "TOKEN_SWORD", - "TOKEN_SDWORD", "TOKEN_VOID", "TOKEN_LPSTR", "TOKEN_UNICODE", - "TOKEN_CSTRING", "TOKEN_ARRAY", "$accept", "xfile", "template", "@1", - "template_parts", "template_members_part", "template_option_info", - "template_members_list", "template_members", "primitive", "array", - "template_reference", "primitive_type", "array_data_type", - "dimension_list", "dimension", "dimension_size", "template_option_list", - "template_option_part", "singleword_name", "multiword_name", - "optional_multiword_name", "class_id", "optional_class_id", "ellipsis", - "object", "@2", "data_parts_list", "data_part", "integer_list", - "realnum_list", "string", "list_separator", "data_reference", "empty", 0 -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 1, 2, 3, 5, 6, 7, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 31, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52 -}; -# endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 34, 35, 35, 35, 35, 37, 36, 38, 38, - 39, 39, 40, 40, 41, 41, 42, 42, 42, 43, - 44, 45, 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 47, 47, 48, 48, 49, 50, 50, - 51, 51, 52, 52, 53, 54, 54, 54, 55, 55, - 56, 57, 57, 58, 60, 59, 61, 61, 62, 62, - 62, 62, 62, 62, 63, 64, 65, 66, 66, 67, - 67, 68 -}; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 1, 2, 2, 2, 0, 7, 4, 1, - 1, 1, 1, 1, 1, 2, 1, 1, 1, 3, - 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 1, 2, 3, 1, 1, - 1, 2, 1, 2, 1, 1, 2, 2, 1, 1, - 1, 1, 1, 3, 0, 7, 1, 2, 3, 1, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, - 2, 0 -}; - -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 71, 0, 2, 1, 44, 5, 0, 3, 71, 4, - 0, 45, 49, 0, 48, 0, 46, 47, 54, 50, - 6, 71, 71, 52, 71, 51, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, - 9, 14, 16, 17, 18, 71, 71, 10, 0, 56, - 0, 0, 0, 7, 0, 15, 0, 0, 66, 64, - 65, 0, 55, 68, 67, 59, 57, 60, 61, 0, - 63, 33, 0, 0, 35, 34, 0, 0, 13, 40, - 42, 12, 19, 21, 69, 0, 62, 38, 0, 39, - 20, 36, 0, 8, 41, 43, 70, 58, 37, 53 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int8 yydefgoto[] = -{ - -1, 1, 7, 22, 38, 39, 77, 40, 41, 42, - 43, 44, 45, 51, 73, 74, 88, 78, 79, 8, - 12, 13, 20, 24, 81, 9, 21, 48, 66, 67, - 68, 69, 70, 85, 14 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -48 -static const yytype_int8 yypact[] = -{ - -48, 8, -48, -48, -48, -48, 9, -48, 40, -48, - 41, -48, 4, 42, -48, 43, -48, -48, -48, -48, - -48, 43, 52, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -48, -48, 65, 44, 39, - 14, -48, -48, -48, -48, 40, 40, -48, 95, -48, - 40, 45, 40, -48, 3, -48, 34, 37, -48, -48, - -48, 40, -48, -48, -48, -48, -48, -48, -48, 11, - -48, 4, 10, -9, -48, 4, 46, 47, 9, -48, - 43, -48, -48, -48, 16, 49, -48, -48, 48, 4, - -48, -48, 50, -48, -48, -48, -48, -48, -48, -48 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = -{ - -48, -48, -48, -48, -48, -48, -48, -48, 17, -48, - -48, -48, 28, -48, -48, -7, -48, -48, -8, -6, - -47, -13, -20, -48, -48, 21, -48, -48, -48, -48, - -48, -48, 12, -48, 2 -}; - -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -12 -static const yytype_int8 yytable[] = -{ - 10, 23, 2, 71, 72, 75, 4, 16, 3, 17, - 90, 4, 4, 11, 84, 87, 46, 4, 5, 16, - 76, 17, 19, 25, 47, 89, 49, -11, 6, 63, - 64, 52, 56, 57, 46, 26, 27, 28, 29, 30, - 31, 32, 33, 11, 34, 35, 36, 37, 80, 19, - 15, 18, 54, 82, 53, 4, 83, 55, 72, 97, - 95, 93, 98, 92, 96, 50, 91, 99, 4, 65, - 94, 0, 80, 26, 27, 28, 29, 30, 31, 32, - 33, 86, 34, 35, 36, 37, 26, 27, 28, 29, - 30, 31, 32, 33, 0, 34, 35, 36, 4, 58, - 0, 0, 59, 60, 61, 62, 0, 0, 0, 0, - 0, 0, 0, 63, 64 -}; - -static const yytype_int8 yycheck[] = -{ - 6, 21, 0, 50, 13, 52, 3, 3, 0, 5, - 19, 3, 3, 3, 61, 5, 22, 3, 10, 3, - 17, 5, 6, 21, 22, 72, 24, 13, 20, 18, - 19, 37, 45, 46, 40, 21, 22, 23, 24, 25, - 26, 27, 28, 3, 30, 31, 32, 33, 54, 6, - 9, 9, 13, 19, 10, 3, 19, 40, 13, 10, - 80, 14, 14, 17, 84, 37, 73, 17, 3, 48, - 78, -1, 78, 21, 22, 23, 24, 25, 26, 27, - 28, 69, 30, 31, 32, 33, 21, 22, 23, 24, - 25, 26, 27, 28, -1, 30, 31, 32, 3, 4, - -1, -1, 7, 8, 9, 10, -1, -1, -1, -1, - -1, -1, -1, 18, 19 -}; - -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 35, 68, 0, 3, 10, 20, 36, 53, 59, - 53, 3, 54, 55, 68, 9, 3, 5, 9, 6, - 56, 60, 37, 56, 57, 68, 21, 22, 23, 24, - 25, 26, 27, 28, 30, 31, 32, 33, 38, 39, - 41, 42, 43, 44, 45, 46, 53, 68, 61, 68, - 46, 47, 53, 10, 13, 42, 55, 55, 4, 7, - 8, 9, 10, 18, 19, 59, 62, 63, 64, 65, - 66, 54, 13, 48, 49, 54, 17, 40, 51, 52, - 53, 58, 19, 19, 54, 67, 66, 5, 50, 54, - 19, 49, 17, 14, 52, 56, 56, 10, 14, 17 -}; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. However, - YYFAIL appears to be in use. Nevertheless, it is formally deprecated - in Bison 2.4.2's NEWS entry, where a plan to phase it out is - discussed. */ - -#define YYFAIL goto yyerrlab -#if defined YYFAIL - /* This is here to suppress warnings from the GCC cpp's - -Wunused-macros. Normally we don't worry about that warning, but - some users do, and we want to make it easy for users to remove - YYFAIL uses, which will produce warnings from Bison 2.5. */ -#endif - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) - - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) -#else -# define YYLEX yylex () -#endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) - { - default: - break; - } -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif -{ - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - - yy_symbol_value_print (yyoutput, yytype, yyvaluep); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -#else -static void -yy_stack_print (yybottom, yytop) - yytype_int16 *yybottom; - yytype_int16 *yytop; -#endif -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif -{ - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; - - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - - if (yysize_overflow) - return YYSIZE_MAXIMUM; - - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } -} -#endif /* YYERROR_VERBOSE */ - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else -static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif -{ - YYUSE (yyvaluep); - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - - default: - break; - } -} - -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ - -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else -int -yyparse () - -#endif -#endif -{ - - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - `yyss': related to states. - `yyvs': related to semantic values. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - *++yyvsp = yylval; - - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 6: - -/* Line 1464 of yacc.c */ -#line 116 "xParser.yxx" - { - (yyval.u.node) = current_node; - XFileTemplate *templ = new XFileTemplate(x_file, (yyvsp[(2) - (4)].str), (yyvsp[(4) - (4)].guid)); - current_node->add_child(templ); - current_node = templ; -} - break; - - case 7: - -/* Line 1464 of yacc.c */ -#line 123 "xParser.yxx" - { - (yyval.u.node) = current_node; - current_node = (yyvsp[(5) - (7)].u.node); -} - break; - - case 12: - -/* Line 1464 of yacc.c */ -#line 141 "xParser.yxx" - { - DCAST(XFileTemplate, current_node)->set_open(true); -} - break; - - case 19: - -/* Line 1464 of yacc.c */ -#line 160 "xParser.yxx" - { - current_data_def = new XFileDataDef(x_file, (yyvsp[(2) - (3)].str), (yyvsp[(1) - (3)].u.primitive_type)); - current_node->add_child(current_data_def); -} - break; - - case 21: - -/* Line 1464 of yacc.c */ -#line 172 "xParser.yxx" - { - XFileTemplate *xtemplate = x_file->find_template((yyvsp[(1) - (3)].str)); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + (yyvsp[(1) - (3)].str)); - } else { - current_data_def = new XFileDataDef(x_file, (yyvsp[(2) - (3)].str), XFileDataDef::T_template, xtemplate); - current_node->add_child(current_data_def); - } -} - break; - - case 22: - -/* Line 1464 of yacc.c */ -#line 185 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_word; -} - break; - - case 23: - -/* Line 1464 of yacc.c */ -#line 189 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_dword; -} - break; - - case 24: - -/* Line 1464 of yacc.c */ -#line 193 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_float; -} - break; - - case 25: - -/* Line 1464 of yacc.c */ -#line 197 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_double; -} - break; - - case 26: - -/* Line 1464 of yacc.c */ -#line 201 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_char; -} - break; - - case 27: - -/* Line 1464 of yacc.c */ -#line 205 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_uchar; -} - break; - - case 28: - -/* Line 1464 of yacc.c */ -#line 209 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_sword; -} - break; - - case 29: - -/* Line 1464 of yacc.c */ -#line 213 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_sdword; -} - break; - - case 30: - -/* Line 1464 of yacc.c */ -#line 217 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_string; -} - break; - - case 31: - -/* Line 1464 of yacc.c */ -#line 221 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_unicode; -} - break; - - case 32: - -/* Line 1464 of yacc.c */ -#line 225 "xParser.yxx" - { - (yyval.u.primitive_type) = XFileDataDef::T_cstring; -} - break; - - case 33: - -/* Line 1464 of yacc.c */ -#line 232 "xParser.yxx" - { - current_data_def = new XFileDataDef(x_file, (yyvsp[(2) - (2)].str), (yyvsp[(1) - (2)].u.primitive_type)); - current_node->add_child(current_data_def); -} - break; - - case 34: - -/* Line 1464 of yacc.c */ -#line 237 "xParser.yxx" - { - XFileTemplate *xtemplate = x_file->find_template((yyvsp[(1) - (2)].str)); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + (yyvsp[(1) - (2)].str)); - } else { - current_data_def = new XFileDataDef(x_file, (yyvsp[(2) - (2)].str), XFileDataDef::T_template, xtemplate); - current_node->add_child(current_data_def); - } -} - break; - - case 38: - -/* Line 1464 of yacc.c */ -#line 259 "xParser.yxx" - { - current_data_def->add_array_def(XFileArrayDef((yyvsp[(1) - (1)].u.number))); -} - break; - - case 39: - -/* Line 1464 of yacc.c */ -#line 263 "xParser.yxx" - { - XFileNode *data_def = current_node->find_child((yyvsp[(1) - (1)].str)); - if (data_def == nullptr) { - yyerror("Unknown identifier: " + (yyvsp[(1) - (1)].str)); - } else { - current_data_def->add_array_def(XFileArrayDef(DCAST(XFileDataDef, data_def))); - } -} - break; - - case 40: - -/* Line 1464 of yacc.c */ -#line 275 "xParser.yxx" - { -} - break; - - case 41: - -/* Line 1464 of yacc.c */ -#line 278 "xParser.yxx" - { -} - break; - - case 42: - -/* Line 1464 of yacc.c */ -#line 284 "xParser.yxx" - { - XFileTemplate *xtemplate = x_file->find_template((yyvsp[(1) - (1)].str)); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + (yyvsp[(1) - (1)].str)); - } else { - DCAST(XFileTemplate, current_node)->add_option(xtemplate); - } -} - break; - - case 43: - -/* Line 1464 of yacc.c */ -#line 293 "xParser.yxx" - { - XFileTemplate *xtemplate = x_file->find_template((yyvsp[(2) - (2)].guid)); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + (yyvsp[(1) - (2)].str)); - } else { - if (xtemplate->get_name() != (yyvsp[(1) - (2)].str)) { - xyywarning("GUID identifies template " + xtemplate->get_name() + - ", not " + (yyvsp[(1) - (2)].str)); - } - DCAST(XFileTemplate, current_node)->add_option(xtemplate); - } -} - break; - - case 46: - -/* Line 1464 of yacc.c */ -#line 314 "xParser.yxx" - { - (yyval.str) = (yyvsp[(1) - (2)].str) + " " + (yyvsp[(2) - (2)].str); -} - break; - - case 47: - -/* Line 1464 of yacc.c */ -#line 318 "xParser.yxx" - { - (yyval.str) = (yyvsp[(1) - (2)].str) + " " + (yyvsp[(2) - (2)].str); -} - break; - - case 48: - -/* Line 1464 of yacc.c */ -#line 325 "xParser.yxx" - { - (yyval.str) = std::string(); -} - break; - - case 51: - -/* Line 1464 of yacc.c */ -#line 337 "xParser.yxx" - { - (yyval.guid) = WindowsGuid(); -} - break; - - case 54: - -/* Line 1464 of yacc.c */ -#line 349 "xParser.yxx" - { - XFileTemplate *xtemplate = x_file->find_template((yyvsp[(1) - (3)].str)); - (yyval.u.node) = current_node; - - if (xtemplate == nullptr) { - yyerror("Unknown template: " + (yyvsp[(1) - (3)].str)); - } else { - XFileDataNodeTemplate *templ = - new XFileDataNodeTemplate(x_file, (yyvsp[(2) - (3)].str), xtemplate); - current_node->add_child(templ); - current_node = templ; - } -} - break; - - case 55: - -/* Line 1464 of yacc.c */ -#line 363 "xParser.yxx" - { - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->finalize_parse_data(); - } - - (yyval.u.node) = current_node; - current_node = (yyvsp[(4) - (7)].u.node); -} - break; - - case 58: - -/* Line 1464 of yacc.c */ -#line 382 "xParser.yxx" - { - // nested references should be added as children too. - current_node->add_child((yyvsp[(2) - (3)].u.node)); -} - break; - - case 59: - -/* Line 1464 of yacc.c */ -#line 387 "xParser.yxx" - { - // nested objects are just quietly added as children. -} - break; - - case 60: - -/* Line 1464 of yacc.c */ -#line 391 "xParser.yxx" - { - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->add_parse_int((yyvsp[(1) - (1)].int_list)); - } -} - break; - - case 61: - -/* Line 1464 of yacc.c */ -#line 399 "xParser.yxx" - { - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->add_parse_double((yyvsp[(1) - (1)].double_list)); - } -} - break; - - case 62: - -/* Line 1464 of yacc.c */ -#line 407 "xParser.yxx" - { - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->add_parse_string((yyvsp[(1) - (2)].str)); - } -} - break; - - case 63: - -/* Line 1464 of yacc.c */ -#line 415 "xParser.yxx" - { -} - break; - - case 69: - -/* Line 1464 of yacc.c */ -#line 438 "xParser.yxx" - { - XFileDataNodeTemplate *data_object = x_file->find_data_object((yyvsp[(1) - (1)].str)); - if (data_object == nullptr) { - yyerror("Unknown data_object: " + (yyvsp[(1) - (1)].str)); - } - - (yyval.u.node) = new XFileDataNodeReference(data_object); -} - break; - - case 70: - -/* Line 1464 of yacc.c */ -#line 447 "xParser.yxx" - { - XFileDataNodeTemplate *data_object = x_file->find_data_object((yyvsp[(2) - (2)].guid)); - if (data_object == nullptr) { - yyerror("Unknown data_object: " + (yyvsp[(1) - (2)].str)); - } else { - if (data_object->get_name() != (yyvsp[(1) - (2)].str)) { - xyywarning("GUID identifies data_object " + data_object->get_name() + - ", not " + (yyvsp[(1) - (2)].str)); - } - } - - (yyval.u.node) = new XFileDataNodeReference(data_object); -} - break; - - - -/* Line 1464 of yacc.c */ -#line 1957 "y.tab.c" - default: break; - } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } -#endif - } - - - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - yystos[yystate], yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - *++yyvsp = yylval; - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined(yyoverflow) || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - /* Make sure YYID is used. */ - return YYID (yyresult); -} - - - diff --git a/pandatool/src/xfile/xParser.h.prebuilt b/pandatool/src/xfile/xParser.h.prebuilt deleted file mode 100644 index ab80d042..00000000 --- a/pandatool/src/xfile/xParser.h.prebuilt +++ /dev/null @@ -1,118 +0,0 @@ -/* A Bison parser, made by GNU Bison 2.4.2. */ - -/* Skeleton interface for Bison's Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software - Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - TOKEN_NAME = 1, - TOKEN_STRING = 2, - TOKEN_INTEGER = 3, - TOKEN_GUID = 5, - TOKEN_INTEGER_LIST = 6, - TOKEN_REALNUM_LIST = 7, - TOKEN_OBRACE = 10, - TOKEN_CBRACE = 11, - TOKEN_OPAREN = 12, - TOKEN_CPAREN = 13, - TOKEN_OBRACKET = 14, - TOKEN_CBRACKET = 15, - TOKEN_OANGLE = 16, - TOKEN_CANGLE = 17, - TOKEN_DOT = 18, - TOKEN_COMMA = 19, - TOKEN_SEMICOLON = 20, - TOKEN_TEMPLATE = 31, - TOKEN_WORD = 40, - TOKEN_DWORD = 41, - TOKEN_FLOAT = 42, - TOKEN_DOUBLE = 43, - TOKEN_CHAR = 44, - TOKEN_UCHAR = 45, - TOKEN_SWORD = 46, - TOKEN_SDWORD = 47, - TOKEN_VOID = 48, - TOKEN_LPSTR = 49, - TOKEN_UNICODE = 50, - TOKEN_CSTRING = 51, - TOKEN_ARRAY = 52 - }; -#endif -/* Tokens. */ -#define TOKEN_NAME 1 -#define TOKEN_STRING 2 -#define TOKEN_INTEGER 3 -#define TOKEN_GUID 5 -#define TOKEN_INTEGER_LIST 6 -#define TOKEN_REALNUM_LIST 7 -#define TOKEN_OBRACE 10 -#define TOKEN_CBRACE 11 -#define TOKEN_OPAREN 12 -#define TOKEN_CPAREN 13 -#define TOKEN_OBRACKET 14 -#define TOKEN_CBRACKET 15 -#define TOKEN_OANGLE 16 -#define TOKEN_CANGLE 17 -#define TOKEN_DOT 18 -#define TOKEN_COMMA 19 -#define TOKEN_SEMICOLON 20 -#define TOKEN_TEMPLATE 31 -#define TOKEN_WORD 40 -#define TOKEN_DWORD 41 -#define TOKEN_FLOAT 42 -#define TOKEN_DOUBLE 43 -#define TOKEN_CHAR 44 -#define TOKEN_UCHAR 45 -#define TOKEN_SWORD 46 -#define TOKEN_SDWORD 47 -#define TOKEN_VOID 48 -#define TOKEN_LPSTR 49 -#define TOKEN_UNICODE 50 -#define TOKEN_CSTRING 51 -#define TOKEN_ARRAY 52 - - - - -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED - -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -#endif - -extern YYSTYPE xyylval; - - diff --git a/pandatool/src/xfile/xParser.yxx b/pandatool/src/xfile/xParser.yxx deleted file mode 100644 index 0352a4d4..00000000 --- a/pandatool/src/xfile/xParser.yxx +++ /dev/null @@ -1,464 +0,0 @@ -/** - * @file xParser.yxx - * @author drose - * @date 2004-10-03 - */ - -// The grammar defined in this file is taken more-or-less from the -// Microsoft DirectX File Format Specification document, version 1.13. -// The document actually describes a slightly incomplete and incorrect -// grammar, so small changes had to be made, but an attempt was made -// to be as faithful as possible to the intention of the spec. - -%{ -#include "xLexerDefs.h" -#include "xParserDefs.h" -#include "xFile.h" -#include "xFileTemplate.h" -#include "xFileDataDef.h" -#include "xFileArrayDef.h" -#include "xFileDataNodeTemplate.h" -#include "xFileDataNodeReference.h" -#include "pointerTo.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 = nullptr; -static XFileNode *current_node = nullptr; -static PT(XFileDataDef) current_data_def; - -//////////////////////////////////////////////////////////////////// -// Defining the interface to the parser. -//////////////////////////////////////////////////////////////////// - -void -x_init_parser(std::istream &in, const std::string &filename, XFile &file) { - x_file = &file; - current_node = &file; - x_init_lexer(in, filename); -} - -void -x_cleanup_parser() { - x_file = nullptr; - current_node = nullptr; -} - -%} - -// These token values are taken from the DirectX spec; the particular -// numeric values are useful when reading an .x file in binary mode -// (which basically just streams the tokens retrieved by the lexer). - -%token TOKEN_NAME 1 -%token TOKEN_STRING 2 -%token TOKEN_INTEGER 3 -%token TOKEN_GUID 5 -%token TOKEN_INTEGER_LIST 6 -%token TOKEN_REALNUM_LIST 7 - -%token TOKEN_OBRACE 10 -%token TOKEN_CBRACE 11 -%token TOKEN_OPAREN 12 -%token TOKEN_CPAREN 13 -%token TOKEN_OBRACKET 14 -%token TOKEN_CBRACKET 15 -%token TOKEN_OANGLE 16 -%token TOKEN_CANGLE 17 -%token TOKEN_DOT 18 -%token TOKEN_COMMA 19 -%token TOKEN_SEMICOLON 20 -%token TOKEN_TEMPLATE 31 -%token TOKEN_WORD 40 -%token TOKEN_DWORD 41 -%token TOKEN_FLOAT 42 -%token TOKEN_DOUBLE 43 -%token TOKEN_CHAR 44 -%token TOKEN_UCHAR 45 -%token TOKEN_SWORD 46 -%token TOKEN_SDWORD 47 -%token TOKEN_VOID 48 -%token TOKEN_LPSTR 49 -%token TOKEN_UNICODE 50 -%token TOKEN_CSTRING 51 -%token TOKEN_ARRAY 52 - -%type template -%type object -%type primitive_type -%type integer_list -%type realnum_list -%type singleword_name -%type multiword_name -%type optional_multiword_name -%type string -%type class_id -%type optional_class_id -%type data_reference - -%% - -xfile: - empty - | xfile template - | xfile object - | xfile TOKEN_CBRACE /* the 3dsMax converter writes an extra one. */ - ; - -template: - TOKEN_TEMPLATE singleword_name TOKEN_OBRACE class_id -{ - $$ = current_node; - XFileTemplate *templ = new XFileTemplate(x_file, $2, $4); - current_node->add_child(templ); - current_node = templ; -} - template_parts TOKEN_CBRACE -{ - $$ = current_node; - current_node = $5; -} - ; - -template_parts: - template_members_part TOKEN_OBRACKET template_option_info TOKEN_CBRACKET - | template_members_list - ; - -template_members_part: - empty - | template_members_list - ; - -template_option_info: - ellipsis -{ - DCAST(XFileTemplate, current_node)->set_open(true); -} - | template_option_list - ; - -template_members_list: - template_members - | template_members_list template_members - ; - -template_members: - primitive - | array - | template_reference - ; - -primitive: - primitive_type optional_multiword_name TOKEN_SEMICOLON -{ - current_data_def = new XFileDataDef(x_file, $2, $1); - current_node->add_child(current_data_def); -} - ; - -array: - TOKEN_ARRAY array_data_type dimension_list TOKEN_SEMICOLON - ; - -template_reference: - singleword_name optional_multiword_name TOKEN_SEMICOLON -{ - XFileTemplate *xtemplate = x_file->find_template($1); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + $1); - } else { - current_data_def = new XFileDataDef(x_file, $2, XFileDataDef::T_template, xtemplate); - current_node->add_child(current_data_def); - } -} - ; - -primitive_type: - TOKEN_WORD -{ - $$ = XFileDataDef::T_word; -} - | TOKEN_DWORD -{ - $$ = XFileDataDef::T_dword; -} - | TOKEN_FLOAT -{ - $$ = XFileDataDef::T_float; -} - | TOKEN_DOUBLE -{ - $$ = XFileDataDef::T_double; -} - | TOKEN_CHAR -{ - $$ = XFileDataDef::T_char; -} - | TOKEN_UCHAR -{ - $$ = XFileDataDef::T_uchar; -} - | TOKEN_SWORD -{ - $$ = XFileDataDef::T_sword; -} - | TOKEN_SDWORD -{ - $$ = XFileDataDef::T_sdword; -} - | TOKEN_LPSTR -{ - $$ = XFileDataDef::T_string; -} - | TOKEN_UNICODE -{ - $$ = XFileDataDef::T_unicode; -} - | TOKEN_CSTRING -{ - $$ = XFileDataDef::T_cstring; -} - ; - -array_data_type: - primitive_type multiword_name -{ - current_data_def = new XFileDataDef(x_file, $2, $1); - current_node->add_child(current_data_def); -} - | singleword_name multiword_name -{ - XFileTemplate *xtemplate = x_file->find_template($1); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + $1); - } else { - current_data_def = new XFileDataDef(x_file, $2, XFileDataDef::T_template, xtemplate); - current_node->add_child(current_data_def); - } -} - ; - -dimension_list: - dimension - | dimension_list dimension - ; - -dimension: - TOKEN_OBRACKET dimension_size TOKEN_CBRACKET - ; - -dimension_size: - TOKEN_INTEGER -{ - current_data_def->add_array_def(XFileArrayDef($1)); -} - | multiword_name -{ - XFileNode *data_def = current_node->find_child($1); - if (data_def == nullptr) { - yyerror("Unknown identifier: " + $1); - } else { - current_data_def->add_array_def(XFileArrayDef(DCAST(XFileDataDef, data_def))); - } -} - ; - -template_option_list: - template_option_part -{ -} - | template_option_list template_option_part -{ -} - ; - -template_option_part: - singleword_name -{ - XFileTemplate *xtemplate = x_file->find_template($1); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + $1); - } else { - DCAST(XFileTemplate, current_node)->add_option(xtemplate); - } -} - | singleword_name class_id -{ - XFileTemplate *xtemplate = x_file->find_template($2); - if (xtemplate == nullptr) { - yyerror("Unknown template: " + $1); - } else { - if (xtemplate->get_name() != $1) { - xyywarning("GUID identifies template " + xtemplate->get_name() + - ", not " + $1); - } - DCAST(XFileTemplate, current_node)->add_option(xtemplate); - } -} - ; - -singleword_name: - TOKEN_NAME - ; - -multiword_name: - TOKEN_NAME - | multiword_name TOKEN_NAME -{ - $$ = $1 + " " + $2; -} - | multiword_name TOKEN_INTEGER -{ - $$ = $1 + " " + $2; -} - ; - -optional_multiword_name: - empty -{ - $$ = std::string(); -} - | multiword_name - ; - -class_id: - TOKEN_GUID - ; - -optional_class_id: - empty -{ - $$ = WindowsGuid(); -} - | class_id - ; - -ellipsis: - TOKEN_DOT TOKEN_DOT TOKEN_DOT - ; - -object: - singleword_name optional_multiword_name TOKEN_OBRACE -{ - XFileTemplate *xtemplate = x_file->find_template($1); - $$ = current_node; - - if (xtemplate == nullptr) { - yyerror("Unknown template: " + $1); - } else { - XFileDataNodeTemplate *templ = - new XFileDataNodeTemplate(x_file, $2, xtemplate); - current_node->add_child(templ); - current_node = templ; - } -} - optional_class_id data_parts_list TOKEN_CBRACE -{ - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->finalize_parse_data(); - } - - $$ = current_node; - current_node = $4; -} - ; - -data_parts_list: - empty - | data_parts_list data_part - ; - -data_part: - TOKEN_OBRACE data_reference TOKEN_CBRACE -{ - // nested references should be added as children too. - current_node->add_child($2); -} - | object -{ - // nested objects are just quietly added as children. -} - | integer_list -{ - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->add_parse_int($1); - } -} - | realnum_list -{ - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->add_parse_double($1); - } -} - | string list_separator -{ - if (current_node->is_exact_type(XFileDataNodeTemplate::get_class_type())) { - XFileDataNodeTemplate *current_template = - DCAST(XFileDataNodeTemplate, current_node); - current_template->add_parse_string($1); - } -} - | list_separator -{ -} - ; - -integer_list: - TOKEN_INTEGER_LIST - ; - -realnum_list: - TOKEN_REALNUM_LIST - ; - -string: - TOKEN_STRING - ; - -list_separator: - TOKEN_SEMICOLON - | TOKEN_COMMA - ; - -data_reference: - multiword_name -{ - XFileDataNodeTemplate *data_object = x_file->find_data_object($1); - if (data_object == nullptr) { - yyerror("Unknown data_object: " + $1); - } - - $$ = new XFileDataNodeReference(data_object); -} - | multiword_name class_id -{ - XFileDataNodeTemplate *data_object = x_file->find_data_object($2); - if (data_object == nullptr) { - yyerror("Unknown data_object: " + $1); - } else { - if (data_object->get_name() != $1) { - xyywarning("GUID identifies data_object " + data_object->get_name() + - ", not " + $1); - } - } - - $$ = new XFileDataNodeReference(data_object); -} - ; - -empty: - ; diff --git a/pandatool/src/xfile/xParserDefs.h b/pandatool/src/xfile/xParserDefs.h deleted file mode 100644 index 0900ae42..00000000 --- a/pandatool/src/xfile/xParserDefs.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xParserDefs.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XPARSERDEFS_H -#define XPARSERDEFS_H - -#include "pandatoolbase.h" -#include "windowsGuid.h" -#include "xFileDataDef.h" -#include "pta_int.h" -#include "pta_double.h" - -class XFile; -class XFileNode; - -void x_init_parser(std::istream &in, const std::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 number; - XFileNode *node; - XFileDataDef::Type primitive_type; - } u; - std::string str; - WindowsGuid guid; - PTA_double double_list; - PTA_int int_list; -}; - -// The yacc-generated code expects to use the symbol 'YYSTYPE' to refer to the -// above class. -#define YYSTYPE XTokenType - -#endif diff --git a/pandatool/src/xfileegg/CMakeLists.txt b/pandatool/src/xfileegg/CMakeLists.txt deleted file mode 100644 index eb8bd12e..00000000 --- a/pandatool/src/xfileegg/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -if(NOT HAVE_EGG) - return() -endif() - -set(P3XFILEEGG_HEADERS - xFileAnimationSet.h xFileAnimationSet.I - xFileFace.h xFileMaker.h - xFileMaterial.h xFileMesh.h xFileNormal.h - xFileToEggConverter.h - xFileVertex.h xFileVertexPool.h -) - -set(P3XFILEEGG_SOURCES - xFileAnimationSet.cxx - xFileFace.cxx xFileMaker.cxx - xFileMaterial.cxx xFileMesh.cxx xFileNormal.cxx - xFileToEggConverter.cxx - xFileVertex.cxx -) - -composite_sources(p3xfileegg P3XFILEEGG_SOURCES) -add_library(p3xfileegg STATIC ${P3XFILEEGG_HEADERS} ${P3XFILEEGG_SOURCES}) -target_link_libraries(p3xfileegg p3xfile p3eggbase) - -# This is only needed for binaries in the pandatool package. It is not useful -# for user applications, so it is not installed. diff --git a/pandatool/src/xfileegg/p3xfileegg_composite1.cxx b/pandatool/src/xfileegg/p3xfileegg_composite1.cxx deleted file mode 100644 index d87e0f5b..00000000 --- a/pandatool/src/xfileegg/p3xfileegg_composite1.cxx +++ /dev/null @@ -1,11 +0,0 @@ - -#include "xFileAnimationSet.cxx" -#include "xFileFace.cxx" -#include "xFileMaker.cxx" -#include "xFileMaterial.cxx" -#include "xFileMesh.cxx" -#include "xFileNormal.cxx" -#include "xFileToEggConverter.cxx" -#include "xFileVertex.cxx" - - diff --git a/pandatool/src/xfileegg/xFileAnimationSet.I b/pandatool/src/xfileegg/xFileAnimationSet.I deleted file mode 100644 index a8501f9c..00000000 --- a/pandatool/src/xfileegg/xFileAnimationSet.I +++ /dev/null @@ -1,46 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileAnimationSet.I - * @author drose - * @date 2004-10-04 - */ - -/** - * - */ -INLINE XFileAnimationSet::FrameEntry:: -FrameEntry() : - _scale(1.0, 1.0, 1.0), - _rot(LQuaterniond::ident_quat()), - _trans(LVector3d::zero()), - _mat(LMatrix4d::ident_mat()) -{ -} - -/** - * Returns the frame's data as a matrix, composing the matrix first if - * necessary, as indicated by the FrameData's _flags member. - */ -INLINE const LMatrix4d &XFileAnimationSet::FrameEntry:: -get_mat(int flags) const { - if ((flags & FDF_mat) == 0) { - ((FrameEntry *)this)->_mat = LMatrix4d::scale_mat(_scale) * _rot; - ((FrameEntry *)this)->_mat.set_row(3, _trans); - } - return _mat; -} - -/** - * - */ -INLINE XFileAnimationSet::FrameData:: -FrameData() : - _flags(0) -{ -} diff --git a/pandatool/src/xfileegg/xFileAnimationSet.cxx b/pandatool/src/xfileegg/xFileAnimationSet.cxx deleted file mode 100644 index f76bc33e..00000000 --- a/pandatool/src/xfileegg/xFileAnimationSet.cxx +++ /dev/null @@ -1,153 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileAnimationSet.cxx - * @author drose - * @date 2004-10-02 - */ - -#include "xFileAnimationSet.h" -#include "xFileToEggConverter.h" -#include "config_xfile.h" -#include "eggGroup.h" -#include "eggTable.h" -#include "eggData.h" -#include "eggXfmSAnim.h" -#include "dcast.h" - -/** - * - */ -XFileAnimationSet:: -XFileAnimationSet() { - _frame_rate = 0.0; -} - -/** - * - */ -XFileAnimationSet:: -~XFileAnimationSet() { -} - -/** - * Sets up the hierarchy of EggTables corresponding to this AnimationSet. - */ -bool XFileAnimationSet:: -create_hierarchy(XFileToEggConverter *converter) { - // Egg animation tables start off with one Table entry, enclosing a Bundle - // entry. - EggTable *table = new EggTable(get_name()); - converter->get_egg_data()->add_child(table); - EggTable *bundle = new EggTable(converter->_char_name); - table->add_child(bundle); - bundle->set_table_type(EggTable::TT_bundle); - - // Then the Bundle contains a "" entry, which begins the animation - // table hierarchy. - EggTable *skeleton = new EggTable(""); - bundle->add_child(skeleton); - - // Fill in the rest of the hierarchy with empty tables. - mirror_table(converter, converter->get_dart_node(), skeleton); - - // Now populate those empty tables with the frame data. - JointData::const_iterator ji; - for (ji = _joint_data.begin(); ji != _joint_data.end(); ++ji) { - const std::string &joint_name = (*ji).first; - const FrameData &table = (*ji).second; - - EggXfmSAnim *anim_table = get_table(joint_name); - if (anim_table == nullptr) { - xfile_cat.warning() - << "Frame " << joint_name << ", named by animation data, not defined.\n"; - } else { - // If we have animation data, apply it. - FrameEntries::const_iterator fi; - for (fi = table._entries.begin(); fi != table._entries.end(); ++fi) { - anim_table->add_data((*fi).get_mat(table._flags)); - } - anim_table->optimize(); - } - } - - // Put some data in the empty tables also. - Tables::iterator ti; - for (ti = _tables.begin(); ti != _tables.end(); ++ti) { - EggXfmSAnim *anim_table = (*ti).second._table; - EggGroup *joint = (*ti).second._joint; - if (anim_table->empty() && joint != nullptr) { - // If there's no animation data, assign the rest transform. - anim_table->add_data(joint->get_transform3d()); - } - anim_table->optimize(); - if (_frame_rate != 0.0) { - anim_table->set_fps(_frame_rate); - } - } - - return true; -} - -/** - * Returns the table associated with the indicated joint name. - */ -EggXfmSAnim *XFileAnimationSet:: -get_table(const std::string &joint_name) const { - Tables::const_iterator ti; - ti = _tables.find(joint_name); - if (ti != _tables.end()) { - return (*ti).second._table; - } - return nullptr; -} - -/** - * Returns a reference to a new FrameData table corresponding to the indicated - * joint. - */ -XFileAnimationSet::FrameData &XFileAnimationSet:: -create_frame_data(const std::string &joint_name) { - return _joint_data[joint_name]; -} - -/** - * Builds up a new set of EggTable nodes, as a mirror of the existing set of - * EggGroup (joint) nodes, and saves each new table in the _tables record. - */ -void XFileAnimationSet:: -mirror_table(XFileToEggConverter *converter, - EggGroup *model_node, EggTable *anim_node) { - EggGroupNode::iterator gi; - for (gi = model_node->begin(); gi != model_node->end(); ++gi) { - EggNode *child = (*gi); - if (child->is_of_type(EggGroup::get_class_type())) { - EggGroup *group = DCAST(EggGroup, child); - if (group->get_group_type() == EggGroup::GT_joint) { - // When we come to a , create a new Table for it. - EggTable *new_table = new EggTable(group->get_name()); - anim_node->add_child(new_table); - CoordinateSystem cs = - converter->get_egg_data()->get_coordinate_system(); - EggXfmSAnim *xform = new EggXfmSAnim("xform", cs); - new_table->add_child(xform); - xform->set_fps(converter->_frame_rate); - TablePair &table_pair = _tables[group->get_name()]; - table_pair._table = xform; - table_pair._joint = group; - - // Now recurse. - mirror_table(converter, group, new_table); - - } else { - // If we come to an ordinary , skip past it. - mirror_table(converter, group, anim_node); - } - } - } -} diff --git a/pandatool/src/xfileegg/xFileAnimationSet.h b/pandatool/src/xfileegg/xFileAnimationSet.h deleted file mode 100644 index a0bec7d4..00000000 --- a/pandatool/src/xfileegg/xFileAnimationSet.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileAnimationSet.h - * @author drose - * @date 2004-10-02 - */ - -#ifndef XFILEANIMATIONSET_H -#define XFILEANIMATIONSET_H - -#include "pandatoolbase.h" -#include "pmap.h" -#include "epvector.h" -#include "luse.h" -#include "namable.h" - -class XFileToEggConverter; -class EggGroup; -class EggTable; -class EggXfmSAnim; - -/** - * This represents a tree of EggTables, corresponding to Animation entries in - * the X file. There is one EggTable for each joint in the character's joint - * set, and the whole tree is structured as a mirror of the joint set. - */ -class XFileAnimationSet : public Namable { -public: - XFileAnimationSet(); - ~XFileAnimationSet(); - - bool create_hierarchy(XFileToEggConverter *converter); - EggXfmSAnim *get_table(const std::string &joint_name) const; - - enum FrameDataFlags { - FDF_scale = 0x01, - FDF_rot = 0x02, - FDF_trans = 0x04, - FDF_mat = 0x08, - }; - - class FrameEntry { - public: - INLINE FrameEntry(); - INLINE const LMatrix4d &get_mat(int flags) const; - - LVecBase3d _scale; - LQuaterniond _rot; - LVector3d _trans; - LMatrix4d _mat; - }; - - typedef epvector FrameEntries; - - class FrameData { - public: - INLINE FrameData(); - FrameEntries _entries; - int _flags; - }; - - FrameData &create_frame_data(const std::string &joint_name); - -public: - double _frame_rate; - -private: - void mirror_table(XFileToEggConverter *converter, - EggGroup *model_node, EggTable *anim_node); - - typedef pmap JointData; - JointData _joint_data; - - class TablePair { - public: - EggGroup *_joint; - EggXfmSAnim *_table; - }; - - typedef pmap Tables; - Tables _tables; -}; - -#include "xFileAnimationSet.I" - -#endif diff --git a/pandatool/src/xfileegg/xFileFace.cxx b/pandatool/src/xfileegg/xFileFace.cxx deleted file mode 100644 index ecb1378c..00000000 --- a/pandatool/src/xfileegg/xFileFace.cxx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileFace.cxx - * @author drose - * @date 2001-06-19 - */ - -#include "xFileFace.h" -#include "xFileMesh.h" -#include "eggPolygon.h" - -/** - * - */ -XFileFace:: -XFileFace() { - _material_index = -1; -} - -/** - * Sets the structure up from the indicated egg data. - */ -void XFileFace:: -set_from_egg(XFileMesh *mesh, EggPolygon *egg_poly) { - // Walk through the polygon's vertices in reverse order, to change from - // Egg's counter-clockwise convention to DX's clockwise. - EggPolygon::reverse_iterator vi; - for (vi = egg_poly->rbegin(); vi != egg_poly->rend(); ++vi) { - EggVertex *egg_vertex = (*vi); - Vertex v; - v._vertex_index = mesh->add_vertex(egg_vertex, egg_poly); - v._normal_index = mesh->add_normal(egg_vertex, egg_poly); - _vertices.push_back(v); - } - - _material_index = mesh->add_material(egg_poly); -} diff --git a/pandatool/src/xfileegg/xFileFace.h b/pandatool/src/xfileegg/xFileFace.h deleted file mode 100644 index 788d664e..00000000 --- a/pandatool/src/xfileegg/xFileFace.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileFace.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef XFILEFACE_H -#define XFILEFACE_H - -#include "pandatoolbase.h" -#include "pvector.h" - -class XFileMesh; -class EggPolygon; - -/** - * This represents a single face of an XFileMesh. - */ -class XFileFace { -public: - XFileFace(); - void set_from_egg(XFileMesh *mesh, EggPolygon *egg_poly); - - class Vertex { - public: - int _vertex_index; - int _normal_index; - }; - typedef pvector Vertices; - Vertices _vertices; - - int _material_index; -}; - -#endif diff --git a/pandatool/src/xfileegg/xFileMaker.cxx b/pandatool/src/xfileegg/xFileMaker.cxx deleted file mode 100644 index e3d07cea..00000000 --- a/pandatool/src/xfileegg/xFileMaker.cxx +++ /dev/null @@ -1,243 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileMaker.cxx - * @author drose - * @date 2001-06-19 - */ - -#include "xFileMaker.h" -#include "xFileMesh.h" -#include "xFileMaterial.h" -#include "config_xfile.h" - -#include "pnotify.h" -#include "eggGroupNode.h" -#include "eggGroup.h" -#include "eggBin.h" -#include "eggPolysetMaker.h" -#include "eggVertexPool.h" -#include "eggVertex.h" -#include "eggPolygon.h" -#include "eggData.h" -#include "pvector.h" -#include "vector_int.h" -#include "string_utils.h" -#include "datagram.h" - -/** - * - */ -XFileMaker:: -XFileMaker() { - _mesh_index = 0; - _x_file = new XFile; -} - -/** - * - */ -XFileMaker:: -~XFileMaker() { -} - -/** - * Writes the .x file data to the indicated filename; returns true on success, - * false otherwise. - */ -bool XFileMaker:: -write(const Filename &filename) { - return _x_file->write(filename); -} - -/** - * Adds the egg tree rooted at the indicated node to the X structure. This - * may be somewhat destructive of the egg tree. Returns true on success, - * false on failure. - */ -bool XFileMaker:: -add_tree(EggData *egg_data) { - _meshes.clear(); - - // Now collect all the polygons together into polysets. - EggPolysetMaker pmaker; - pmaker.make_bins(egg_data); - - // And now we're ready to traverse the egg hierarchy. - if (!recurse_nodes(egg_data, _x_file)) { - return false; - } - - // Create X structures for all of the meshes we built up. - Meshes::iterator mi; - for (mi = _meshes.begin(); mi != _meshes.end(); ++mi) { - if (!finalize_mesh((*mi).first, (*mi).second)) { - return false; - } - } - _meshes.clear(); - - return true; -} - -/** - * Adds the node to the DX structure, in whatever form it is supported. - */ -bool XFileMaker:: -add_node(EggNode *egg_node, XFileNode *x_parent) { - if (egg_node->is_of_type(EggBin::get_class_type())) { - return add_bin(DCAST(EggBin, egg_node), x_parent); - - } else if (egg_node->is_of_type(EggGroup::get_class_type())) { - return add_group(DCAST(EggGroup, egg_node), x_parent); - - } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) { - // A grouping node of some kind. - EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); - - if (xfile_one_mesh) { - // Don't create any additional frames representing the egg hierarchy. - if (!recurse_nodes(egg_group, x_parent)) { - return false; - } - - } else { - // Create a Frame for each EggGroup. - XFileDataNode *x_frame = x_parent->add_Frame(egg_group->get_name()); - - if (!recurse_nodes(egg_group, x_frame)) { - return false; - } - } - - return true; - } - - // Some unsupported node type. Ignore it. - return true; -} - -/** - * Adds a frame for the indicated group node. - */ -bool XFileMaker:: -add_group(EggGroup *egg_group, XFileNode *x_parent) { - if (xfile_one_mesh) { - // Don't create any additional frames representing the egg hierarchy. - if (!recurse_nodes(egg_group, x_parent)) { - return false; - } - - } else { - // Create a frame for each EggGroup. - XFileDataNode *x_frame = x_parent->add_Frame(egg_group->get_name()); - - // Set the transform on the frame, if we have one. - if (egg_group->has_transform()) { - x_frame->add_FrameTransformMatrix(egg_group->get_transform3d()); - } - - if (!recurse_nodes(egg_group, x_frame)) { - return false; - } - } - - return true; -} - -/** - * Determines what kind of object needs to be added for the indicated bin - * node. - */ -bool XFileMaker:: -add_bin(EggBin *egg_bin, XFileNode *x_parent) { - switch (egg_bin->get_bin_number()) { - case EggPolysetMaker::BN_polyset: - return add_polyset(egg_bin, x_parent); - } - - xfile_cat.error() - << "Unexpected bin type " << egg_bin->get_bin_number() << "\n"; - return false; -} - -/** - * Adds a mesh object corresponding to the collection of polygons within the - * indicated bin. - */ -bool XFileMaker:: -add_polyset(EggBin *egg_bin, XFileNode *x_parent) { - // Make sure that all our polygons are reasonable. - egg_bin->remove_invalid_primitives(true); - - XFileMesh *mesh = get_mesh(x_parent); - - EggGroupNode::iterator ci; - for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) { - EggPolygon *poly; - DCAST_INTO_R(poly, *ci, false); - - mesh->add_polygon(poly); - } - - return true; -} - - -/** - * Adds each child of the indicated Node as a child of the indicated DX - * object. - */ -bool XFileMaker:: -recurse_nodes(EggGroupNode *egg_node, XFileNode *x_parent) { - EggGroupNode::iterator ci; - for (ci = egg_node->begin(); ci != egg_node->end(); ++ci) { - EggNode *child = (*ci); - if (!add_node(child, x_parent)) { - return false; - } - } - - return true; -} - -/** - * Returns a suitable XFileMesh object for creating meshes within the - * indicated x_parent object. - */ -XFileMesh *XFileMaker:: -get_mesh(XFileNode *x_parent) { - Meshes::iterator mi = _meshes.find(x_parent); - if (mi != _meshes.end()) { - // We've already started working on this x_parent before; use the same - // mesh object. - return (*mi).second; - } - - // We haven't seen this x_parent before; create a new mesh object. - XFileMesh *mesh = new XFileMesh; - _meshes.insert(Meshes::value_type(x_parent, mesh)); - return mesh; -} - - -/** - * Creates the actual X structures corresponding to the indicated XFileMesh - * object. - */ -bool XFileMaker:: -finalize_mesh(XFileNode *x_parent, XFileMesh *mesh) { - // Get a unique number for each mesh. - _mesh_index++; - std::string mesh_index = format_string(_mesh_index); - - // Finally, create the Mesh object. - mesh->make_x_mesh(x_parent, mesh_index); - - return true; -} diff --git a/pandatool/src/xfileegg/xFileMaker.h b/pandatool/src/xfileegg/xFileMaker.h deleted file mode 100644 index 18ba2a99..00000000 --- a/pandatool/src/xfileegg/xFileMaker.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileMaker.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef XFILEMAKER_H -#define XFILEMAKER_H - -#include "pandatoolbase.h" - -#include "filename.h" -#include "pmap.h" -#include "luse.h" -#include "xFile.h" - -class EggNode; -class EggGroupNode; -class EggGroup; -class EggBin; -class EggData; -class EggVertexPool; -class Datagram; -class XFileMesh; - -/** - * This class converts a Panda scene graph into a .X file and writes it out. - */ -class XFileMaker { -public: - XFileMaker(); - ~XFileMaker(); - - bool write(const Filename &filename); - - bool add_tree(EggData *egg_data); - -private: - bool add_node(EggNode *egg_node, XFileNode *x_parent); - bool add_group(EggGroup *egg_group, XFileNode *x_parent); - bool add_bin(EggBin *egg_bin, XFileNode *x_parent); - bool add_polyset(EggBin *egg_bin, XFileNode *x_parent); - - bool recurse_nodes(EggGroupNode *egg_node, XFileNode *x_parent); - - XFileMesh *get_mesh(XFileNode *x_parent); - bool finalize_mesh(XFileNode *x_parent, XFileMesh *mesh); - - PT(XFile) _x_file; - - int _mesh_index; - - typedef pmap Meshes; - Meshes _meshes; -}; - -#endif diff --git a/pandatool/src/xfileegg/xFileMaterial.cxx b/pandatool/src/xfileegg/xFileMaterial.cxx deleted file mode 100644 index 9eaac25f..00000000 --- a/pandatool/src/xfileegg/xFileMaterial.cxx +++ /dev/null @@ -1,209 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileMaterial.cxx - * @author drose - * @date 2001-06-19 - */ - -#include "xFileMaterial.h" -#include "xFileToEggConverter.h" -#include "xFileDataNode.h" -#include "eggMaterial.h" -#include "eggTexture.h" -#include "eggPrimitive.h" -#include "datagram.h" -#include "config_xfile.h" - -#include // for strcmp, strdup - -/** - * - */ -XFileMaterial:: -XFileMaterial() { - _face_color.set(1.0, 1.0, 1.0, 1.0); - _specular_color.set(0.0, 0.0, 0.0); - _emissive_color.set(0.0, 0.0, 0.0); - _power = 64.0; - - _has_material = false; - _has_texture = false; -} - -/** - * - */ -XFileMaterial:: -~XFileMaterial() { -} - -/** - * Sets the structure up from the indicated egg data. - */ -void XFileMaterial:: -set_from_egg(EggPrimitive *egg_prim) { - // First, determine the face color. - if (egg_prim->has_color()) { - _face_color = egg_prim->get_color(); - _has_material = true; - } - - // Do we have an actual EggMaterial, to control lighting effects? - if (egg_prim->has_material()) { - _has_material = true; - EggMaterial *egg_mat = egg_prim->get_material(); - if (egg_mat->has_diff()) { - _face_color = egg_mat->get_diff(); - } - if (egg_mat->has_spec()) { - const LColor &spec = egg_mat->get_spec(); - _specular_color.set(spec[0], spec[1], spec[2]); - } - if (egg_mat->has_emit()) { - const LColor &emit = egg_mat->get_emit(); - _emissive_color.set(emit[0], emit[1], emit[2]); - } - if (egg_mat->has_shininess()) { - _power = egg_mat->get_shininess(); - } - } - - // Finally, if we also have a texture, record that. - if (egg_prim->has_texture()) { - _has_material = true; - _has_texture = true; - EggTexture *egg_tex = egg_prim->get_texture(); - _texture = egg_tex->get_filename(); - } -} - -/** - * Applies the properties in the material to the indicated egg primitive. - */ -void XFileMaterial:: -apply_to_egg(EggPrimitive *egg_prim, XFileToEggConverter *converter) { - // Is there a texture? - if (_has_texture) { - Filename texture = converter->convert_model_path(_texture); - EggTexture temp("", texture); - EggTexture *egg_tex = converter->create_unique_texture(temp); - egg_prim->set_texture(egg_tex); - } - - // Are there any fancy lighting effects? - bool got_spec = (_specular_color != LRGBColor::zero()); - bool got_emit = (_emissive_color != LRGBColor::zero()); - if (got_spec || got_emit) { - EggMaterial temp(""); - temp.set_diff(_face_color); - if (got_spec) { - temp.set_shininess(_power); - temp.set_spec(LColor(_specular_color[0], _specular_color[1], - _specular_color[2], 1.0)); - } - if (got_emit) { - temp.set_emit(LColor(_emissive_color[0], _emissive_color[1], - _emissive_color[2], 1.0)); - } - EggMaterial *egg_mat = converter->create_unique_material(temp); - egg_prim->set_material(egg_mat); - } - - // Also apply the face color. - egg_prim->set_color(_face_color); -} - -/** - * - */ -int XFileMaterial:: -compare_to(const XFileMaterial &other) const { - int ct; - ct = _face_color.compare_to(other._face_color); - if (ct == 0) { - ct = (_power == other._power) ? 0 : ((_power < other._power) ? -1 : 1); - } - if (ct == 0) { - ct = _specular_color.compare_to(other._specular_color); - } - if (ct == 0) { - ct = _emissive_color.compare_to(other._emissive_color); - } - if (ct == 0) { - ct = strcmp(_texture.c_str(), other._texture.c_str()); - } - return ct; -} - -/** - * Returns true if this material represents something meaningful, or false if - * the default material is sufficient. - */ -bool XFileMaterial:: -has_material() const { - return _has_material; -} - -/** - * Returns true if this material includes a texture map, false otherwise. - */ -bool XFileMaterial:: -has_texture() const { - return _has_texture; -} - -/** - * Creates a Material object for the material list. - */ -XFileDataNode *XFileMaterial:: -make_x_material(XFileNode *x_meshMaterials, const std::string &suffix) { - XFileDataNode *x_material = - x_meshMaterials->add_Material("material" + suffix, - _face_color, _power, - _specular_color, _emissive_color); - - if (has_texture()) { - x_material->add_TextureFilename("texture" + suffix, _texture); - } - - return x_material; -} - -/** - * Fills the structure based on the raw data from the X file's Material - * object. - */ -bool XFileMaterial:: -fill_material(XFileDataNode *obj) { - _face_color = LCAST(PN_stdfloat, (*obj)["faceColor"].vec4()); - _power = (*obj)["power"].d(); - _specular_color = LCAST(PN_stdfloat, (*obj)["specularColor"].vec3()); - _emissive_color = LCAST(PN_stdfloat, (*obj)["emissiveColor"].vec3()); - _has_material = true; - - // Walk through the children of the material. If there are any, there - // should be only one, and it should be just a Texture. - int num_objects = obj->get_num_objects(); - for (int i = 0; i < num_objects; i++) { - XFileDataNode *child = obj->get_object(i); - if (child->is_standard_object("TextureFilename")) { - _texture = Filename::from_os_specific((*child)["filename"].s()); - _has_texture = true; - - } else { - if (xfile_cat.is_debug()) { - xfile_cat.debug() - << "Ignoring material object of unknown type: " - << child->get_template_name() << "\n"; - } - } - } - - return true; -} diff --git a/pandatool/src/xfileegg/xFileMaterial.h b/pandatool/src/xfileegg/xFileMaterial.h deleted file mode 100644 index dc6a586d..00000000 --- a/pandatool/src/xfileegg/xFileMaterial.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileMaterial.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef XFILEMATERIAL_H -#define XFILEMATERIAL_H - -#include "pandatoolbase.h" -#include "luse.h" -#include "filename.h" - -class EggPrimitive; -class Datagram; -class XFileToEggConverter; -class XFileNode; -class XFileDataNode; - -/** - * This represents an X file "material", which consists of a color, lighting, - * and/or texture specification. - */ -class XFileMaterial { -public: - XFileMaterial(); - ~XFileMaterial(); - - void set_from_egg(EggPrimitive *egg_prim); - void apply_to_egg(EggPrimitive *egg_prim, XFileToEggConverter *converter); - - int compare_to(const XFileMaterial &other) const; - - bool has_material() const; - bool has_texture() const; - - XFileDataNode *make_x_material(XFileNode *x_meshMaterials, const std::string &suffix); - bool fill_material(XFileDataNode *obj); - -private: - LColor _face_color; - double _power; - LRGBColor _specular_color; - LRGBColor _emissive_color; - Filename _texture; - - bool _has_material; - bool _has_texture; -}; - -#endif diff --git a/pandatool/src/xfileegg/xFileMesh.cxx b/pandatool/src/xfileegg/xFileMesh.cxx deleted file mode 100644 index e253ee38..00000000 --- a/pandatool/src/xfileegg/xFileMesh.cxx +++ /dev/null @@ -1,884 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileMesh.cxx - * @author drose - * @date 2001-06-19 - */ - -#include "xFileMesh.h" -#include "xFileToEggConverter.h" -#include "xFileFace.h" -#include "xFileVertex.h" -#include "xFileNormal.h" -#include "xFileMaterial.h" -#include "xFileDataNode.h" -#include "config_xfile.h" -#include "string_utils.h" -#include "eggVertexPool.h" -#include "eggVertex.h" -#include "eggPolygon.h" -#include "eggGroup.h" -#include "eggGroupNode.h" - -using std::min; -using std::string; - -/** - * - */ -XFileMesh:: -XFileMesh(CoordinateSystem cs) : _cs(cs) { - _has_normals = false; - _has_colors = false; - _has_uvs = false; - _has_materials = false; - _egg_parent = nullptr; -} - -/** - * - */ -XFileMesh:: -~XFileMesh() { - clear(); -} - -/** - * Empties all data from the mesh. - */ -void XFileMesh:: -clear() { - Vertices::iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - XFileVertex *vertex = (*vi); - delete vertex; - } - Normals::iterator ni; - for (ni = _normals.begin(); ni != _normals.end(); ++ni) { - XFileNormal *normal = (*ni); - delete normal; - } - Materials::iterator mi; - for (mi = _materials.begin(); mi != _materials.end(); ++mi) { - XFileMaterial *material = (*mi); - delete material; - } - Faces::iterator fi; - for (fi = _faces.begin(); fi != _faces.end(); ++fi) { - XFileFace *face = (*fi); - delete face; - } - - _vertices.clear(); - _normals.clear(); - _materials.clear(); - _faces.clear(); - - _unique_vertices.clear(); - _unique_normals.clear(); - _unique_materials.clear(); - - _has_normals = false; - _has_colors = false; - _has_uvs = false; - _has_materials = false; -} - -/** - * Adds the indicated polygon to the mesh. - */ -void XFileMesh:: -add_polygon(EggPolygon *egg_poly) { - XFileFace *face = new XFileFace; - face->set_from_egg(this, egg_poly); - _faces.push_back(face); -} - -/** - * Creates a new XFileVertex, if one does not already exist for the indicated - * vertex, and returns its index. - */ -int XFileMesh:: -add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim) { - int next_index = _vertices.size(); - XFileVertex *vertex = new XFileVertex; - vertex->set_from_egg(egg_vertex, egg_prim); - if (vertex->_has_color) { - _has_colors = true; - } - if (vertex->_has_uv) { - _has_uvs = true; - } - - std::pair result = - _unique_vertices.insert(UniqueVertices::value_type(vertex, next_index)); - - if (result.second) { - // Successfully added; this is a new vertex. - _vertices.push_back(vertex); - return next_index; - } else { - // Not successfully added; there is already a vertex with these - // properties. Return that one instead. - delete vertex; - return (*result.first).second; - } -} - - -/** - * Creates a new XFileNormal, if one does not already exist for the indicated - * normal, and returns its index. - */ -int XFileMesh:: -add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim) { - int next_index = _normals.size(); - XFileNormal *normal = new XFileNormal; - normal->set_from_egg(egg_vertex, egg_prim); - if (normal->_has_normal) { - _has_normals = true; - } - - std::pair result = - _unique_normals.insert(UniqueNormals::value_type(normal, next_index)); - - if (result.second) { - // Successfully added; this is a new normal. - _normals.push_back(normal); - return next_index; - } else { - // Not successfully added; there is already a normal with these - // properties. Return that one instead. - delete normal; - return (*result.first).second; - } -} - -/** - * Creates a new XFileMaterial, if one does not already exist for the - * indicated material, and returns its index. - */ -int XFileMesh:: -add_material(EggPrimitive *egg_prim) { - int next_index = _materials.size(); - XFileMaterial *material = new XFileMaterial; - material->set_from_egg(egg_prim); - if (material->has_material()) { - _has_materials = true; - } - - std::pair result = - _unique_materials.insert(UniqueMaterials::value_type(material, next_index)); - - if (result.second) { - // Successfully added; this is a new material. - _materials.push_back(material); - return next_index; - } else { - // Not successfully added; there is already a material with these - // properties. Return that one instead. - delete material; - return (*result.first).second; - } -} - - -/** - * Adds the newly-created XFileVertex unequivocally to the mesh, returning its - * index number. The XFileMesh object becomes the owner of the XFileVertex - * pointer, and will delete it when it destructs. - */ -int XFileMesh:: -add_vertex(XFileVertex *vertex) { - if (vertex->_has_color) { - _has_colors = true; - } - if (vertex->_has_uv) { - _has_uvs = true; - } - - int next_index = _vertices.size(); - _unique_vertices.insert(UniqueVertices::value_type(vertex, next_index)); - _vertices.push_back(vertex); - return next_index; -} - -/** - * Adds the newly-created XFileNormal unequivocally to the mesh, returning its - * index number. The XFileMesh object becomes the owner of the XFileNormal - * pointer, and will delete it when it destructs. - */ -int XFileMesh:: -add_normal(XFileNormal *normal) { - if (normal->_has_normal) { - _has_normals = true; - } - - int next_index = _normals.size(); - _unique_normals.insert(UniqueNormals::value_type(normal, next_index)); - _normals.push_back(normal); - return next_index; -} - -/** - * Adds the newly-created XFileMaterial unequivocally to the mesh, returning - * its index number. The XFileMesh object becomes the owner of the - * XFileMaterial pointer, and will delete it when it destructs. - */ -int XFileMesh:: -add_material(XFileMaterial *material) { - if (material->has_material()) { - _has_materials = true; - } - - int next_index = _materials.size(); - _unique_materials.insert(UniqueMaterials::value_type(material, next_index)); - _materials.push_back(material); - return next_index; -} - -/** - * Specifies the egg node that will eventually be the parent of this mesh, - * when create_polygons() is later called. - */ -void XFileMesh:: -set_egg_parent(EggGroupNode *egg_parent) { - // We actually put the mesh under its own group. - EggGroup *egg_group = new EggGroup(get_name()); - egg_parent->add_child(egg_group); - - _egg_parent = egg_group; -} - -/** - * Creates a slew of EggPolygons according to the faces in the mesh, and adds - * them to the previously-indicated parent node. - */ -bool XFileMesh:: -create_polygons(XFileToEggConverter *converter) { - nassertr(_egg_parent != nullptr, false); - - EggVertexPool *vpool = new EggVertexPool(get_name()); - _egg_parent->add_child(vpool); - Faces::const_iterator fi; - for (fi = _faces.begin(); fi != _faces.end(); ++fi) { - XFileFace *face = (*fi); - - EggPolygon *egg_poly = new EggPolygon; - _egg_parent->add_child(egg_poly); - - // Set up the vertices for the polygon. - XFileFace::Vertices::reverse_iterator vi; - for (vi = face->_vertices.rbegin(); vi != face->_vertices.rend(); ++vi) { - int vertex_index = (*vi)._vertex_index; - int normal_index = (*vi)._normal_index; - if (vertex_index < 0 || vertex_index >= (int)_vertices.size()) { - xfile_cat.warning() - << "Vertex index out of range in Mesh " << get_name() << "\n"; - continue; - } - XFileVertex *vertex = _vertices[vertex_index]; - XFileNormal *normal = nullptr; - - if (normal_index >= 0 && normal_index < (int)_normals.size()) { - normal = _normals[normal_index]; - } - - // Create a temporary EggVertex before adding it to the pool. - EggVertex temp_vtx; - temp_vtx.set_external_index(vertex_index); - temp_vtx.set_pos(vertex->_point); - if (vertex->_has_color) { - temp_vtx.set_color(vertex->_color); - } - if (vertex->_has_uv) { - LTexCoordd uv = vertex->_uv; - // Windows draws the UV's upside-down. - uv[1] = 1.0 - uv[1]; - temp_vtx.set_uv(uv); - } - - if (normal != nullptr && normal->_has_normal) { - temp_vtx.set_normal(normal->_normal); - } - - // We are given the vertex in local space; we need to transform it into - // global space. If the vertex has been skinned, that means the global - // space of all of its joints (modified by the matrix_offset provided in - // the skinning data). - double net_weight = 0.0; - LMatrix4d weighted_transform(0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0); - SkinWeights::const_iterator swi; - for (swi = _skin_weights.begin(); swi != _skin_weights.end(); ++swi) { - const SkinWeightsData &data = (*swi); - WeightMap::const_iterator wmi = data._weight_map.find(vertex_index); - if (wmi != data._weight_map.end()) { - EggGroup *joint = converter->find_joint(data._joint_name); - if (joint != nullptr) { - double weight = (*wmi).second; - LMatrix4d mat = data._matrix_offset; - mat *= joint->get_node_to_vertex(); - weighted_transform += mat * weight; - net_weight += weight; - } - } - } - - if (net_weight == 0.0) { - // The vertex had no joint membership. Transform it into the - // appropriate (global) space based on its parent. - temp_vtx.transform(_egg_parent->get_node_to_vertex()); - - } else { - // The vertex was skinned into one or more joints. Therefore, - // transform it according to the blended matrix_offset from the - // skinning data. - weighted_transform /= net_weight; - temp_vtx.transform(weighted_transform); - } - - // Now get a real EggVertex matching our template. - EggVertex *egg_vtx = vpool->create_unique_vertex(temp_vtx); - egg_poly->add_vertex(egg_vtx); - } - - // And apply the material for the polygon. - int material_index = face->_material_index; - if (material_index >= 0 && material_index < (int)_materials.size()) { - XFileMaterial *material = _materials[material_index]; - material->apply_to_egg(egg_poly, converter); - } - } - - // Now go through all of the vertices and skin them up. - EggVertexPool::iterator vi; - for (vi = vpool->begin(); vi != vpool->end(); ++vi) { - EggVertex *egg_vtx = (*vi); - int vertex_index = egg_vtx->get_external_index(); - - SkinWeights::const_iterator swi; - for (swi = _skin_weights.begin(); swi != _skin_weights.end(); ++swi) { - const SkinWeightsData &data = (*swi); - WeightMap::const_iterator wmi = data._weight_map.find(vertex_index); - if (wmi != data._weight_map.end()) { - EggGroup *joint = converter->find_joint(data._joint_name); - if (joint != nullptr) { - double weight = (*wmi).second; - joint->ref_vertex(egg_vtx, weight); - } - } - } - } - - if (!has_normals()) { - // If we don't have explicit normals, make some up, per the DX spec. - // Since the DX spec doesn't mention anything about a crease angle, we - // should be as generous as possible. - _egg_parent->recompute_vertex_normals(180.0, _cs); - } - - return true; -} - -/** - * Returns true if any of the vertices or faces added to this mesh used a - * normal, false otherwise. - */ -bool XFileMesh:: -has_normals() const { - return _has_normals; -} - -/** - * Returns true if any of the vertices or faces added to this mesh used a - * color, false otherwise. - */ -bool XFileMesh:: -has_colors() const { - return _has_colors; -} - -/** - * Returns true if any of the vertices added to this mesh used a texture - * coordinate, false otherwise. - */ -bool XFileMesh:: -has_uvs() const { - return _has_uvs; -} - -/** - * Returns true if any of the faces added to this mesh used a real material, - * false otherwise. - */ -bool XFileMesh:: -has_materials() const { - return _has_materials; -} - -/** - * Returns the number of distinct materials associated with the mesh. - */ -int XFileMesh:: -get_num_materials() const { - return _materials.size(); -} - -/** - * Returns a pointer to the nth materials associated with the mesh. - */ -XFileMaterial *XFileMesh:: -get_material(int n) const { - nassertr(n >= 0 && n < (int)_materials.size(), nullptr); - return _materials[n]; -} - -/** - * Creates an X structure corresponding to the mesh. - */ -XFileDataNode *XFileMesh:: -make_x_mesh(XFileNode *x_parent, const string &suffix) { - XFileDataNode *x_mesh = x_parent->add_Mesh("mesh" + suffix); - - // First, fill in the table of vertices. - XFileDataObject &x_vertices = (*x_mesh)["vertices"]; - - Vertices::const_iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - XFileVertex *vertex = (*vi); - x_vertices.add_Vector(x_mesh->get_x_file(), vertex->_point); - } - (*x_mesh)["nVertices"] = x_vertices.size(); - - // Then, create the list of faces that index into the above vertices. - XFileDataObject &x_faces = (*x_mesh)["faces"]; - Faces::const_iterator fi; - for (fi = _faces.begin(); fi != _faces.end(); ++fi) { - XFileFace *face = (*fi); - - XFileDataObject &x_mesh_face = x_faces.add_MeshFace(x_mesh->get_x_file()); - XFileDataObject &x_faceVertexIndices = x_mesh_face["faceVertexIndices"]; - XFileFace::Vertices::const_iterator fvi; - for (fvi = face->_vertices.begin(); - fvi != face->_vertices.end(); - ++fvi) { - x_faceVertexIndices.add_int((*fvi)._vertex_index); - } - x_mesh_face["nFaceVertexIndices"] = x_faceVertexIndices.size(); - } - (*x_mesh)["nFaces"] = x_faces.size(); - - // Now, add in any supplemental data. - - if (has_normals()) { - // Tack on normals. - make_x_normals(x_mesh, suffix); - } - if (has_colors()) { - // Tack on colors. - make_x_colors(x_mesh, suffix); - } - if (has_uvs()) { - // Tack on uvs. - make_x_uvs(x_mesh, suffix); - } - if (has_materials()) { - // Tack on materials. - make_x_material_list(x_mesh, suffix); - } - - return x_mesh; -} - -/** - * Creates a MeshNormals table for the mesh. - */ -XFileDataNode *XFileMesh:: -make_x_normals(XFileNode *x_mesh, const string &suffix) { - XFileDataNode *x_meshNormals = x_mesh->add_MeshNormals("norms" + suffix); - - XFileDataObject &x_normals = (*x_meshNormals)["normals"]; - - Normals::const_iterator ni; - for (ni = _normals.begin(); ni != _normals.end(); ++ni) { - XFileNormal *normal = (*ni); - x_normals.add_Vector(x_mesh->get_x_file(), normal->_normal); - } - (*x_meshNormals)["nNormals"] = x_normals.size(); - - // Then, create the list of faces that index into the above normals. - XFileDataObject &x_faces = (*x_meshNormals)["faceNormals"]; - Faces::const_iterator fi; - for (fi = _faces.begin(); fi != _faces.end(); ++fi) { - XFileFace *face = (*fi); - - XFileDataObject &x_normals_face = x_faces.add_MeshFace(x_mesh->get_x_file()); - XFileDataObject &x_faceVertexIndices = x_normals_face["faceVertexIndices"]; - XFileFace::Vertices::const_iterator fvi; - for (fvi = face->_vertices.begin(); - fvi != face->_vertices.end(); - ++fvi) { - x_faceVertexIndices.add_int((*fvi)._normal_index); - } - x_normals_face["nFaceVertexIndices"] = x_faceVertexIndices.size(); - } - (*x_meshNormals)["nFaceNormals"] = x_faces.size(); - - return x_meshNormals; -} - -/** - * Creates a MeshVertexColors table for the mesh. - */ -XFileDataNode *XFileMesh:: -make_x_colors(XFileNode *x_mesh, const string &suffix) { - XFileDataNode *x_meshColors = x_mesh->add_MeshVertexColors("colors" + suffix); - - XFileDataObject &x_colors = (*x_meshColors)["vertexColors"]; - - Vertices::const_iterator vi; - int i = 0; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - XFileVertex *vertex = (*vi); - const LColor &color = vertex->_color; - x_colors.add_IndexedColor(x_mesh->get_x_file(), i, color); - i++; - } - - (*x_meshColors)["nVertexColors"] = x_colors.size(); - - return x_meshColors; -} - -/** - * Creates a MeshTextureCoords table for the mesh. - */ -XFileDataNode *XFileMesh:: -make_x_uvs(XFileNode *x_mesh, const string &suffix) { - XFileDataNode *x_meshUvs = x_mesh->add_MeshTextureCoords("uvs" + suffix); - - XFileDataObject &x_uvs = (*x_meshUvs)["textureCoords"]; - - Vertices::const_iterator vi; - for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) { - XFileVertex *vertex = (*vi); - x_uvs.add_Coords2d(x_mesh->get_x_file(), vertex->_uv); - } - - (*x_meshUvs)["nTextureCoords"] = x_uvs.size(); - - return x_meshUvs; -} - -/** - * Creates a MeshMaterialList table for the mesh. - */ -XFileDataNode *XFileMesh:: -make_x_material_list(XFileNode *x_mesh, const string &suffix) { - XFileDataNode *x_meshMaterials = - x_mesh->add_MeshMaterialList("materials" + suffix); - - // First, build up the list of faces the reference the materials. - XFileDataObject &x_indexes = (*x_meshMaterials)["faceIndexes"]; - - Faces::const_iterator fi; - for (fi = _faces.begin(); fi != _faces.end(); ++fi) { - XFileFace *face = (*fi); - x_indexes.add_int(face->_material_index); - } - - (*x_meshMaterials)["nFaceIndexes"] = x_indexes.size(); - - // Now, build up the list of materials themselves. Each material is a child - // of the MeshMaterialList node, rather than an element of an array. - for (size_t i = 0; i < _materials.size(); i++) { - XFileMaterial *material = _materials[i]; - - material->make_x_material(x_meshMaterials, - suffix + "_" + format_string(i)); - } - - (*x_meshMaterials)["nMaterials"] = (int)_materials.size(); - - return x_meshMaterials; -} - -/** - * Fills the structure based on the raw data from the X file's Mesh object. - */ -bool XFileMesh:: -fill_mesh(XFileDataNode *obj) { - clear(); - - int i, j; - - const XFileDataObject &vertices = (*obj)["vertices"]; - for (i = 0; i < vertices.size(); i++) { - XFileVertex *vertex = new XFileVertex; - vertex->_point = vertices[i].vec3(); - add_vertex(vertex); - } - - const XFileDataObject &faces = (*obj)["faces"]; - for (i = 0; i < faces.size(); i++) { - XFileFace *face = new XFileFace; - - const XFileDataObject &faceIndices = faces[i]["faceVertexIndices"]; - - for (j = 0; j < faceIndices.size(); j++) { - XFileFace::Vertex vertex; - vertex._vertex_index = faceIndices[j].i(); - vertex._normal_index = -1; - - face->_vertices.push_back(vertex); - } - _faces.push_back(face); - } - - // Some properties are stored as children of the mesh. - int num_objects = obj->get_num_objects(); - for (i = 0; i < num_objects; i++) { - if (!fill_mesh_child(obj->get_object(i))) { - return false; - } - } - - return true; -} - -/** - * Fills the structure based on one of the children of the Mesh object. - */ -bool XFileMesh:: -fill_mesh_child(XFileDataNode *obj) { - if (obj->is_standard_object("MeshNormals")) { - if (!fill_normals(obj)) { - return false; - } - - } else if (obj->is_standard_object("MeshVertexColors")) { - if (!fill_colors(obj)) { - return false; - } - - } else if (obj->is_standard_object("MeshTextureCoords")) { - if (!fill_uvs(obj)) { - return false; - } - - } else if (obj->is_standard_object("MeshMaterialList")) { - if (!fill_material_list(obj)) { - return false; - } - - } else if (obj->is_standard_object("XSkinMeshHeader")) { - // Quietly ignore a skin mesh header. - - } else if (obj->is_standard_object("SkinWeights")) { - if (!fill_skin_weights(obj)) { - return false; - } - - } else { - if (xfile_cat.is_debug()) { - xfile_cat.debug() - << "Ignoring mesh data object of unknown type: " - << obj->get_template_name() << "\n"; - } - } - - return true; -} - -/** - * Fills the structure based on the raw data from the MeshNormals template. - */ -bool XFileMesh:: -fill_normals(XFileDataNode *obj) { - int i, j; - - const XFileDataObject &normals = (*obj)["normals"]; - for (i = 0; i < normals.size(); i++) { - XFileNormal *normal = new XFileNormal; - normal->_normal = normals[i].vec3(); - normal->_has_normal = true; - add_normal(normal); - } - - const XFileDataObject &faceNormals = (*obj)["faceNormals"]; - if (faceNormals.size() != (int)_faces.size()) { - xfile_cat.warning() - << "Incorrect number of faces in MeshNormals within " - << get_name() << "\n"; - } - - int num_normals = min(faceNormals.size(), (int)_faces.size()); - for (i = 0; i < num_normals; i++) { - XFileFace *face = _faces[i]; - - const XFileDataObject &faceIndices = faceNormals[i]["faceVertexIndices"]; - - if (faceIndices.size() != (int)face->_vertices.size()) { - xfile_cat.warning() - << "Incorrect number of vertices for face in MeshNormals within " - << get_name() << "\n"; - } - - int num_vertices = min(faceIndices.size(), (int)face->_vertices.size()); - for (j = 0; j < num_vertices; j++) { - face->_vertices[j]._normal_index = faceIndices[j].i(); - } - } - - return true; -} - -/** - * Fills the structure based on the raw data from the MeshVertexColors - * template. - */ -bool XFileMesh:: -fill_colors(XFileDataNode *obj) { - const XFileDataObject &vertexColors = (*obj)["vertexColors"]; - for (int i = 0; i < vertexColors.size(); i++) { - int vertex_index = vertexColors[i]["index"].i(); - if (vertex_index < 0 || vertex_index >= (int)_vertices.size()) { - xfile_cat.warning() - << "Vertex index out of range in MeshVertexColors within " - << get_name() << "\n"; - continue; - } - - XFileVertex *vertex = _vertices[vertex_index]; - vertex->_color = LCAST(PN_stdfloat, vertexColors[i]["indexColor"].vec4()); - vertex->_has_color = true; - } - - return true; -} - -/** - * Fills the structure based on the raw data from the MeshTextureCoords - * template. - */ -bool XFileMesh:: -fill_uvs(XFileDataNode *obj) { - const XFileDataObject &textureCoords = (*obj)["textureCoords"]; - if (textureCoords.size() != (int)_vertices.size()) { - xfile_cat.warning() - << "Wrong number of vertices in MeshTextureCoords within " - << get_name() << "\n"; - } - - int num_texcoords = min(textureCoords.size(), (int)_vertices.size()); - for (int i = 0; i < num_texcoords; i++) { - XFileVertex *vertex = _vertices[i]; - vertex->_uv = textureCoords[i].vec2(); - vertex->_has_uv = true; - } - - return true; -} - -/** - * Fills the structure based on the raw data from the SkinWeights template. - */ -bool XFileMesh:: -fill_skin_weights(XFileDataNode *obj) { - // Create a new SkinWeightsData record for the table. We'll need this data - // later when we create the vertices. - _skin_weights.push_back(SkinWeightsData()); - SkinWeightsData &data = _skin_weights.back(); - - data._joint_name = (*obj)["transformNodeName"].s(); - - const XFileDataObject &vertexIndices = (*obj)["vertexIndices"]; - const XFileDataObject &weights = (*obj)["weights"]; - - if (weights.size() != vertexIndices.size()) { - xfile_cat.warning() - << "Inconsistent number of vertices in SkinWeights within " << get_name() << "\n"; - } - - // Unpack the weight for each vertex. - size_t num_weights = min(weights.size(), vertexIndices.size()); - for (size_t i = 0; i < num_weights; i++) { - int vindex = vertexIndices[i].i(); - double weight = weights[i].d(); - - if (vindex < 0 || vindex > (int)_vertices.size()) { - xfile_cat.warning() - << "Illegal vertex index " << vindex << " in SkinWeights.\n"; - continue; - } - data._weight_map[vindex] = weight; - } - - // Also retrieve the matrix offset. - data._matrix_offset = (*obj)["matrixOffset"]["matrix"].mat4(); - - return true; -} - -/** - * Fills the structure based on the raw data from the MeshMaterialList - * template. - */ -bool XFileMesh:: -fill_material_list(XFileDataNode *obj) { - const XFileDataObject &faceIndexes = (*obj)["faceIndexes"]; - if (faceIndexes.size() > (int)_faces.size()) { - xfile_cat.warning() - << "Too many faces in MeshMaterialList within " << get_name() << "\n"; - } - - int material_index = -1; - int i = 0; - while (i < faceIndexes.size() && i < (int)_faces.size()) { - XFileFace *face = _faces[i]; - material_index = faceIndexes[i].i(); - face->_material_index = material_index; - i++; - } - - // The rest of the faces get the same material index as the last one in the - // list. - while (i < (int)_faces.size()) { - XFileFace *face = _faces[i]; - face->_material_index = material_index; - i++; - } - - // Now look for children of the MaterialList object. These should all be - // Material objects. - int num_objects = obj->get_num_objects(); - for (i = 0; i < num_objects; i++) { - XFileDataNode *child = obj->get_object(i); - if (child->is_standard_object("Material")) { - XFileMaterial *material = new XFileMaterial; - if (!material->fill_material(child)) { - delete material; - return false; - } - add_material(material); - - } else { - if (xfile_cat.is_debug()) { - xfile_cat.debug() - << "Ignoring material list object of unknown type: " - << child->get_template_name() << "\n"; - } - } - } - - return true; -} diff --git a/pandatool/src/xfileegg/xFileMesh.h b/pandatool/src/xfileegg/xFileMesh.h deleted file mode 100644 index 339ba203..00000000 --- a/pandatool/src/xfileegg/xFileMesh.h +++ /dev/null @@ -1,126 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileMesh.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef XFILEMESH_H -#define XFILEMESH_H - -#include "pandatoolbase.h" -#include "pvector.h" -#include "epvector.h" -#include "pmap.h" -#include "indirectCompareTo.h" -#include "namable.h" -#include "coordinateSystem.h" - -#include "luse.h" - -class XFileNode; -class XFileDataNode; -class XFileMesh; -class XFileVertex; -class XFileNormal; -class XFileMaterial; -class XFileFace; -class XFileToEggConverter; -class XFileDataNode; -class EggGroupNode; -class EggVertex; -class EggPolygon; -class EggPrimitive; -class Datagram; - -/** - * This is a collection of polygons; i.e. a polyset. - */ -class XFileMesh : public Namable { -public: - XFileMesh(CoordinateSystem cs = CS_yup_left); - ~XFileMesh(); - - void clear(); - - void add_polygon(EggPolygon *egg_poly); - int add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim); - int add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim); - int add_material(EggPrimitive *egg_prim); - - int add_vertex(XFileVertex *vertex); - int add_normal(XFileNormal *normal); - int add_material(XFileMaterial *material); - - void set_egg_parent(EggGroupNode *egg_parent); - - bool create_polygons(XFileToEggConverter *converter); - - bool has_normals() const; - bool has_colors() const; - bool has_uvs() const; - bool has_materials() const; - - int get_num_materials() const; - XFileMaterial *get_material(int n) const; - - XFileDataNode *make_x_mesh(XFileNode *x_parent, const std::string &suffix); - XFileDataNode *make_x_normals(XFileNode *x_mesh, const std::string &suffix); - XFileDataNode *make_x_colors(XFileNode *x_mesh, const std::string &suffix); - XFileDataNode *make_x_uvs(XFileNode *x_mesh, const std::string &suffix); - XFileDataNode *make_x_material_list(XFileNode *x_mesh, const std::string &suffix); - - bool fill_mesh(XFileDataNode *obj); - bool fill_mesh_child(XFileDataNode *obj); - bool fill_normals(XFileDataNode *obj); - bool fill_colors(XFileDataNode *obj); - bool fill_uvs(XFileDataNode *obj); - bool fill_skin_weights(XFileDataNode *obj); - bool fill_material_list(XFileDataNode *obj); - -private: - typedef pvector Vertices; - typedef pvector Normals; - typedef pvector Materials; - typedef pvector Faces; - - CoordinateSystem _cs; - - Vertices _vertices; - Normals _normals; - Materials _materials; - Faces _faces; - - typedef pmap WeightMap; - - class SkinWeightsData { - public: - LMatrix4d _matrix_offset; - std::string _joint_name; - WeightMap _weight_map; - }; - typedef epvector SkinWeights; - SkinWeights _skin_weights; - - typedef pmap > UniqueVertices; - typedef pmap > UniqueNormals; - typedef pmap > UniqueMaterials; - UniqueVertices _unique_vertices; - UniqueNormals _unique_normals; - UniqueMaterials _unique_materials; - - bool _has_normals; - bool _has_colors; - bool _has_uvs; - bool _has_materials; - - EggGroupNode *_egg_parent; -}; - -#endif diff --git a/pandatool/src/xfileegg/xFileNormal.cxx b/pandatool/src/xfileegg/xFileNormal.cxx deleted file mode 100644 index 748cdd8c..00000000 --- a/pandatool/src/xfileegg/xFileNormal.cxx +++ /dev/null @@ -1,63 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileNormal.cxx - * @author drose - * @date 2001-06-19 - */ - -#include "xFileNormal.h" -#include "eggVertex.h" -#include "eggPrimitive.h" -#include "config_xfile.h" - -/** - * - */ -XFileNormal:: -XFileNormal() { - _normal.set(0.0, 0.0, 0.0); - _has_normal = false; -} - -/** - * Sets the structure up from the indicated egg data. - */ -void XFileNormal:: -set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim) { - if (egg_vertex->has_normal() || egg_prim->has_normal()) { - LNormald norm; - if (egg_vertex->has_normal()) { - norm = egg_vertex->get_normal(); - } else { - norm = egg_prim->get_normal(); - } - - if (xfile_one_mesh) { - // If this is going into one big mesh, we must ensure every vertex is in - // world coordinates. - norm = norm * egg_prim->get_vertex_frame(); - } else { - // Otherwise, we ensure the vertex is in local coordinates. - norm = norm * egg_prim->get_vertex_to_node(); - } - - _normal = norm; - _has_normal = true; - } -} - -/** - * - */ -int XFileNormal:: -compare_to(const XFileNormal &other) const { - int ct; - ct = _normal.compare_to(other._normal); - return ct; -} diff --git a/pandatool/src/xfileegg/xFileNormal.h b/pandatool/src/xfileegg/xFileNormal.h deleted file mode 100644 index f8719936..00000000 --- a/pandatool/src/xfileegg/xFileNormal.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileNormal.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef XFILENORMAL_H -#define XFILENORMAL_H - -#include "pandatoolbase.h" -#include "luse.h" - -class EggVertex; -class EggPrimitive; - -/** - * This represents a single normal associated with an XFileFace. It is - * separate from XFileVertex, because the X syntax supports a different table - * of normals than that of vertices. - */ -class XFileNormal { -public: - XFileNormal(); - void set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim); - int compare_to(const XFileNormal &other) const; - - LNormald _normal; - bool _has_normal; -}; - -#endif diff --git a/pandatool/src/xfileegg/xFileToEggConverter.cxx b/pandatool/src/xfileegg/xFileToEggConverter.cxx deleted file mode 100644 index 91ba21ba..00000000 --- a/pandatool/src/xfileegg/xFileToEggConverter.cxx +++ /dev/null @@ -1,745 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileToEggConverter.cxx - * @author drose - * @date 2001-06-21 - */ - -#include "xFileToEggConverter.h" -#include "xFileMesh.h" -#include "xFileMaterial.h" -#include "xFileAnimationSet.h" -#include "config_xfile.h" - -#include "eggData.h" -#include "eggGroup.h" -#include "eggTable.h" -#include "eggXfmSAnim.h" -#include "eggGroupUniquifier.h" -#include "datagram.h" -#include "eggMaterialCollection.h" -#include "eggTextureCollection.h" -#include "dcast.h" - -using std::string; - -/** - * - */ -XFileToEggConverter:: -XFileToEggConverter() { - _make_char = false; - _frame_rate = 0.0; - _x_file = new XFile(true); - _dart_node = nullptr; -} - -/** - * - */ -XFileToEggConverter:: -XFileToEggConverter(const XFileToEggConverter ©) : - SomethingToEggConverter(copy), - _make_char(copy._make_char) -{ - _x_file = new XFile(true); - _dart_node = nullptr; -} - -/** - * - */ -XFileToEggConverter:: -~XFileToEggConverter() { - close(); -} - -/** - * Allocates and returns a new copy of the converter. - */ -SomethingToEggConverter *XFileToEggConverter:: -make_copy() { - return new XFileToEggConverter(*this); -} - - -/** - * Returns the English name of the file type this converter supports. - */ -string XFileToEggConverter:: -get_name() const { - return "DirectX"; -} - -/** - * Returns the common extension of the file type this converter supports. - */ -string XFileToEggConverter:: -get_extension() const { - return "x"; -} - -/** - * Returns true if this file type can transparently load compressed files - * (with a .pz extension), false otherwise. - */ -bool XFileToEggConverter:: -supports_compressed() const { - return true; -} - -/** - * Handles the reading of the input file and converting it to egg. Returns - * true if successful, false otherwise. - * - * This is designed to be as generic as possible, generally in support of run- - * time loading. Command-line converters may choose to use convert_flt() - * instead, as it provides more control. - */ -bool XFileToEggConverter:: -convert_file(const Filename &filename) { - close(); - clear_error(); - - if (!_x_file->read(filename)) { - nout << "Unable to open X file: " << filename << "\n"; - return false; - } - - if (_char_name.empty()) { - _char_name = filename.get_basename_wo_extension(); - } - - if (_egg_data->get_coordinate_system() == CS_default) { - _egg_data->set_coordinate_system(CS_yup_left); - } - - if (!get_toplevel()) { - return false; - } - - if (!create_polygons()) { - return false; - } - - if (_make_char) { - // Now make sure that each joint has a unique name. - EggGroupUniquifier uniquifier(false); - uniquifier.uniquify(_dart_node); - } - - if (!create_hierarchy()) { - return false; - } - - if (_keep_model && !_keep_animation) { - strip_nodes(EggTable::get_class_type()); - } - - if (_keep_animation && !_keep_model) { - strip_nodes(EggGroup::get_class_type()); - } - - return !had_error(); -} - -/** - * Finalizes and closes the file previously opened via convert_file(). - */ -void XFileToEggConverter:: -close() { - _x_file->clear(); - - // Clean up all the other stuff. - Meshes::const_iterator mi; - for (mi = _meshes.begin(); mi != _meshes.end(); ++mi) { - delete (*mi); - } - _meshes.clear(); - - AnimationSets::const_iterator asi; - for (asi = _animation_sets.begin(); asi != _animation_sets.end(); ++asi) { - delete (*asi); - } - _animation_sets.clear(); - - _joints.clear(); -} - -/** - * Removes all groups of the given type. This is used to implement the -anim - * and -model options. - */ -void XFileToEggConverter:: -strip_nodes(TypeHandle t) { - pvector garbage; - EggGroupNode::iterator i; - for (i=_egg_data->begin(); i!=_egg_data->end(); ++i) { - EggNode *node = (*i); - if (node->is_of_type(t)) { - garbage.push_back(node); - } - } - for (int n=0; n<(int)garbage.size(); n++) { - _egg_data->remove_child(garbage[n]); - } -} - -/** - * Returns the root of the joint hierarchy, if _make_char is true, or NULL - * otherwise. - */ -EggGroup *XFileToEggConverter:: -get_dart_node() const { - return _dart_node; -} - -/** - * Returns an EggTexture pointer whose properties match that of the the given - * EggTexture, except for the tref name. - */ -EggTexture *XFileToEggConverter:: -create_unique_texture(const EggTexture ©) { - return _textures.create_unique_texture(copy, ~EggTexture::E_tref_name); -} - -/** - * Returns an EggMaterial pointer whose properties match that of the the given - * EggMaterial, except for the mref name. - */ -EggMaterial *XFileToEggConverter:: -create_unique_material(const EggMaterial ©) { - return _materials.create_unique_material(copy, ~EggMaterial::E_mref_name); -} - -/** - * This is called by set_animation_frame, for the purposes of building the - * frame data for the animation--it needs to know the original rest frame - * transform. - */ -EggGroup *XFileToEggConverter:: -find_joint(const string &joint_name) { - Joints::iterator ji; - ji = _joints.find(joint_name); - if (ji != _joints.end()) { - EggGroup *joint = (*ji).second; - if (joint == nullptr) { - // An invalid joint detected earlier. - return nullptr; - } - - return joint; - } - - // Joint name is unknown. Issue a warning, then insert NULL into the table - // so we don't get the same warning again with the next polygon. - if (_make_char) { - xfile_cat.warning() - << "Joint name " << joint_name << " in animation data is undefined.\n"; - } - _joints[joint_name] = nullptr; - - return nullptr; -} - -/** - * Pulls off all of the top-level objects in the .x file and converts them, - * and their descendents, to the appropriate egg structures. - */ -bool XFileToEggConverter:: -get_toplevel() { - int num_objects = _x_file->get_num_objects(); - int i; - - _ticks_per_second = 4800; // X File default. - - // First, make a pass through the toplevel objects and see if we have frames - // andor animation. - _any_frames = false; - _any_animation = false; - for (i = 0; i < num_objects; i++) { - XFileDataNode *child = _x_file->get_object(i); - if (child->is_standard_object("Frame")) { - _any_frames = true; - } else if (child->is_standard_object("AnimationSet")) { - _any_animation = true; - } - } - - // If we have animation, assume we want to convert it as a character. - if (_any_animation) { - _make_char = true; - } - - EggGroupNode *egg_parent = _egg_data; - - // If we are converting an animatable model, make an extra node to represent - // the root of the hierarchy. - if (_make_char) { - _dart_node = new EggGroup(_char_name); - egg_parent->add_child(_dart_node); - _dart_node->set_dart_type(EggGroup::DT_default); - egg_parent = _dart_node; - } - - // Now go back through and convert the objects. - for (i = 0; i < num_objects; i++) { - if (!convert_toplevel_object(_x_file->get_object(i), egg_parent)) { - return false; - } - } - - return true; -} - -/** - * Converts the indicated object, encountered outside of any Frames, to the - * appropriate egg structures. - */ -bool XFileToEggConverter:: -convert_toplevel_object(XFileDataNode *obj, EggGroupNode *egg_parent) { - if (obj->is_standard_object("Header")) { - // Quietly ignore headers. - - } else if (obj->is_standard_object("Material")) { - // Quietly ignore toplevel materials. These will presumably be referenced - // below. - - } else if (obj->is_standard_object("Frame")) { - if (!convert_frame(obj, egg_parent)) { - return false; - } - - } else if (obj->is_standard_object("AnimationSet")) { - if (!convert_animation_set(obj)) { - return false; - } - - } else if (obj->is_standard_object("AnimTicksPerSecond")) { - _ticks_per_second = (*obj)[0].i(); - - } else if (obj->is_standard_object("Mesh")) { - // If there are any Frames at all in the file, then assume a Mesh at the - // toplevel is just present to define a reference that will be included - // below--so we ignore it here. On the other hand, if the file has no - // Frames, then a Mesh at the toplevel must be actual geometry, so convert - // it now. - if (!_any_frames) { - if (!convert_mesh(obj, egg_parent)) { - return false; - } - } - - } else { - if (xfile_cat.is_debug()) { - xfile_cat.debug() - << "Ignoring toplevel object of unknown type: " - << obj->get_template_name() << "\n"; - } - } - - return true; -} - -/** - * Converts the indicated object to the appropriate egg structures. - */ -bool XFileToEggConverter:: -convert_object(XFileDataNode *obj, EggGroupNode *egg_parent) { - if (obj->is_standard_object("Header")) { - // Quietly ignore headers. - - } else if (obj->is_standard_object("Frame")) { - if (!convert_frame(obj, egg_parent)) { - return false; - } - - } else if (obj->is_standard_object("FrameTransformMatrix")) { - if (!convert_transform(obj, egg_parent)) { - return false; - } - - } else if (obj->is_standard_object("Mesh")) { - if (!convert_mesh(obj, egg_parent)) { - return false; - } - - } else { - if (xfile_cat.is_debug()) { - xfile_cat.debug() - << "Ignoring object of unknown type: " - << obj->get_template_name() << "\n"; - } - } - - return true; -} - -/** - * Converts the indicated frame to the appropriate egg structures. - */ -bool XFileToEggConverter:: -convert_frame(XFileDataNode *obj, EggGroupNode *egg_parent) { - - string name = obj->get_name(); - EggGroup *group = new EggGroup(name); - egg_parent->add_child(group); - - if (_make_char) { - group->set_group_type(EggGroup::GT_joint); - if (name.empty()) { - // Make up a name for this unnamed joint. - group->set_name("unnamed"); - - } else { - bool inserted = _joints.insert(Joints::value_type(name, group)).second; - if (!inserted) { - xfile_cat.warning() - << "Nonunique Frame name " << name - << " encountered; animation will be ambiguous.\n"; - } - } - } - - // Now walk through the children of the frame. - int num_objects = obj->get_num_objects(); - for (int i = 0; i < num_objects; i++) { - if (!convert_object(obj->get_object(i), group)) { - return false; - } - } - - return true; -} - -/** - * Reads a transform matrix, a child of a given frame, and applies it to the - * node. Normally this can only be done if the node in question is an - * EggGroup, which should be the case if the transform was a child of a frame. - */ -bool XFileToEggConverter:: -convert_transform(XFileDataNode *obj, EggGroupNode *egg_parent) { - LMatrix4d mat = (*obj)["frameMatrix"]["matrix"].mat4(); - - if (egg_parent->is_of_type(EggGroup::get_class_type())) { - EggGroup *egg_group = DCAST(EggGroup, egg_parent); - egg_group->set_transform3d(mat); - - } else { - xfile_cat.error() - << "Transform " << obj->get_name() - << " encountered without frame!\n"; - } - - return true; -} - -/** - * Begins an AnimationSet. This is the root of one particular animation - * (table of frames per joint) to be applied to the model within this file. - */ -bool XFileToEggConverter:: -convert_animation_set(XFileDataNode *obj) { - XFileAnimationSet *animation_set = new XFileAnimationSet(); - animation_set->set_name(obj->get_name()); - - _total_tick_deltas = 0; - _num_ticks = 0; - - // Now walk through the children of the set; each one animates a different - // joint. - int num_objects = obj->get_num_objects(); - for (int i = 0; i < num_objects; i++) { - if (!convert_animation_set_object(obj->get_object(i), *animation_set)) { - return false; - } - } - - animation_set->_frame_rate = _frame_rate; - if (_num_ticks != 0 && _frame_rate == 0.0) { - // Compute the frame rate from the timing information. - double delta = (double)_total_tick_deltas / (double)_num_ticks; - if (delta != 0.0) { - animation_set->_frame_rate = (double)_ticks_per_second / delta; - } - } - - _animation_sets.push_back(animation_set); - - return true; -} - -/** - * Converts the indicated object, a child of a AnimationSet. - */ -bool XFileToEggConverter:: -convert_animation_set_object(XFileDataNode *obj, - XFileAnimationSet &animation_set) { - if (obj->is_standard_object("Animation")) { - if (!convert_animation(obj, animation_set)) { - return false; - } - - } else { - if (xfile_cat.is_debug()) { - xfile_cat.debug() - << "Ignoring animation set object of unknown type: " - << obj->get_template_name() << "\n"; - } - } - - return true; -} - -/** - * Converts the indicated Animation template object. - */ -bool XFileToEggConverter:: -convert_animation(XFileDataNode *obj, XFileAnimationSet &animation_set) { - // Within an Animation template, we expect to find a reference to a frame, - // possibly an AnimationOptions object, and one or more AnimationKey - // objects. - - // First, walk through the list of children, to find the one that is the - // frame reference. We need to know this up front so we know which table we - // should be building up. - string frame_name; - bool got_frame_name = false; - - int num_objects = obj->get_num_objects(); - int i; - for (i = 0; i < num_objects; i++) { - XFileDataNode *child = obj->get_object(i); - if (child->is_reference() && child->is_standard_object("Frame")) { - frame_name = child->get_name(); - got_frame_name = true; - } - } - - if (!got_frame_name) { - xfile_cat.error() - << "Animation " << obj->get_name() - << " includes no reference to a frame.\n"; - return false; - } - - FrameData &table = animation_set.create_frame_data(frame_name); - - // Now go back again and get the actual data. - for (i = 0; i < num_objects; i++) { - if (!convert_animation_object(obj->get_object(i), frame_name, table)) { - return false; - } - } - - return true; -} - -/** - * Converts the indicated object, a child of a Animation. - */ -bool XFileToEggConverter:: -convert_animation_object(XFileDataNode *obj, const string &joint_name, - XFileToEggConverter::FrameData &table) { - if (obj->is_standard_object("AnimationOptions")) { - // Quietly ignore AnimationOptions. - - } else if (obj->is_standard_object("Frame")) { - // Quietly ignore frames, since we already got the frame name. - - } else if (obj->is_standard_object("AnimationKey")) { - if (!convert_animation_key(obj, joint_name, table)) { - return false; - } - - } else { - if (xfile_cat.is_debug()) { - xfile_cat.debug() - << "Ignoring animation object of unknown type: " - << obj->get_template_name() << "\n"; - } - } - - return true; -} - -/** - * Converts the indicated AnimationKey template object. - */ -bool XFileToEggConverter:: -convert_animation_key(XFileDataNode *obj, const string &joint_name, - XFileToEggConverter::FrameData &table) { - int key_type = (*obj)["keyType"].i(); - - const XFileDataObject &keys = (*obj)["keys"]; - - int last_time = 0; - for (int i = 0; i < keys.size(); i++) { - // The time value is problematic, since it allows x files to specify - // keyframes of arbitrary duration. Panda doesn't support this; all - // frames in Panda must be of a constant duration. Thus, we largely - // ignore the time value, but we take the average of all deltas as the - // duration. This will correctly handle .x files with uniform keyframes, - // at least. - - int this_time = keys[i]["time"].i(); - if (i != 0) { - int delta = this_time - last_time; - _total_tick_deltas += delta; - ++_num_ticks; - } - last_time = this_time; - - const XFileDataObject &values = keys[i]["tfkeys"]["values"]; - if (!set_animation_frame(joint_name, table, i, key_type, values)) { - return false; - } - } - - return true; -} - -/** - * Sets a single frame of the animation data. - */ -bool XFileToEggConverter:: -set_animation_frame(const string &joint_name, - XFileToEggConverter::FrameData &table, int frame, - int key_type, const XFileDataObject &values) { - if ((int)table._entries.size() <= frame) { - nassertr((int)table._entries.size() == frame, false); - table._entries.push_back(XFileAnimationSet::FrameEntry()); - } - - XFileAnimationSet::FrameEntry &frame_entry = table._entries[frame]; - - // Now modify the last row in the table. - switch (key_type) { - case 0: - // Key type 0: rotation. This appears to be a quaternion. Hope we get - // the coordinate system right. - if (values.size() != 4) { - xfile_cat.error() - << "Incorrect number of values in animation table: " - << values.size() << " for rotation data.\n"; - return false; - } - frame_entry._rot.invert_from(LQuaterniond(values.vec4())); - table._flags |= XFileAnimationSet::FDF_rot; - break; - - case 1: - if (values.size() != 3) { - xfile_cat.error() - << "Incorrect number of values in animation table: " - << values.size() << " for scale data.\n"; - return false; - } - frame_entry._scale = values.vec3(); - table._flags |= XFileAnimationSet::FDF_scale; - break; - - case 2: - // Key type 2: position - if (values.size() != 3) { - xfile_cat.error() - << "Incorrect number of values in animation table: " - << values.size() << " for position data.\n"; - return false; - } - frame_entry._trans = values.vec3(); - table._flags |= XFileAnimationSet::FDF_trans; - break; - - /* - case 3: - // Key type 3: ???? - break; - */ - - case 4: - // Key type 4: full matrix - if (values.size() != 16) { - xfile_cat.error() - << "Incorrect number of values in animation table: " - << values.size() << " for matrix data.\n"; - return false; - } - frame_entry._mat = values.mat4(); - table._flags |= XFileAnimationSet::FDF_mat; - break; - - default: - xfile_cat.error() - << "Unsupported key type " << key_type << " in animation table.\n"; - return false; - } - - return true; -} - -/** - * Converts the indicated mesh to the appropriate egg structures. - */ -bool XFileToEggConverter:: -convert_mesh(XFileDataNode *obj, EggGroupNode *egg_parent) { - XFileMesh *mesh = new XFileMesh(_egg_data->get_coordinate_system()); - mesh->set_name(obj->get_name()); - mesh->set_egg_parent(egg_parent); - - if (!mesh->fill_mesh(obj)) { - delete mesh; - return false; - } - - _meshes.push_back(mesh); - - return true; -} - -/** - * Creates all the polygons associated with previously-saved meshes. - */ -bool XFileToEggConverter:: -create_polygons() { - bool okflag = true; - - Meshes::const_iterator mi; - for (mi = _meshes.begin(); mi != _meshes.end(); ++mi) { - if (!(*mi)->create_polygons(this)) { - okflag = false; - } - delete (*mi); - } - _meshes.clear(); - - return okflag; -} - -/** - * Creates the animation table hierarchies for the previously-saved animation - * sets. - */ -bool XFileToEggConverter:: -create_hierarchy() { - bool okflag = true; - - AnimationSets::const_iterator asi; - for (asi = _animation_sets.begin(); asi != _animation_sets.end(); ++asi) { - if (_make_char) { - if (!(*asi)->create_hierarchy(this)) { - okflag = false; - } - } - delete (*asi); - } - _animation_sets.clear(); - - return okflag; -} diff --git a/pandatool/src/xfileegg/xFileToEggConverter.h b/pandatool/src/xfileegg/xFileToEggConverter.h deleted file mode 100644 index d92f4c23..00000000 --- a/pandatool/src/xfileegg/xFileToEggConverter.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileToEggConverter.h - * @author drose - * @date 2001-06-21 - */ - -#ifndef XFILETOEGGCONVERTER_H -#define XFILETOEGGCONVERTER_H - -#include "pandatoolbase.h" -#include "xFileAnimationSet.h" -#include "xFile.h" -#include "somethingToEggConverter.h" -#include "eggTextureCollection.h" -#include "eggMaterialCollection.h" -#include "pvector.h" -#include "pmap.h" -#include "luse.h" -#include "pointerTo.h" - -class Datagram; -class XFileMesh; -class XFileMaterial; -class EggGroup; -class EggGroupNode; -class EggTexture; -class EggMaterial; -class XFileDataObject; - -/** - * - */ -class XFileToEggConverter : public SomethingToEggConverter { -public: - XFileToEggConverter(); - XFileToEggConverter(const XFileToEggConverter ©); - ~XFileToEggConverter(); - - virtual SomethingToEggConverter *make_copy(); - - virtual std::string get_name() const; - virtual std::string get_extension() const; - virtual bool supports_compressed() const; - - virtual bool convert_file(const Filename &filename); - void close(); - - EggGroup *get_dart_node() const; - - EggTexture *create_unique_texture(const EggTexture ©); - EggMaterial *create_unique_material(const EggMaterial ©); - EggGroup *find_joint(const std::string &joint_name); - void strip_nodes(TypeHandle t); - -public: - bool _make_char; - std::string _char_name; - double _frame_rate; - bool _keep_model; - bool _keep_animation; - -private: - typedef XFileAnimationSet::FrameData FrameData; - - bool get_toplevel(); - bool convert_toplevel_object(XFileDataNode *obj, EggGroupNode *egg_parent); - bool convert_object(XFileDataNode *obj, EggGroupNode *egg_parent); - bool convert_frame(XFileDataNode *obj, EggGroupNode *egg_parent); - bool convert_transform(XFileDataNode *obj, EggGroupNode *egg_parent); - bool convert_animation_set(XFileDataNode *obj); - bool convert_animation_set_object(XFileDataNode *obj, - XFileAnimationSet &animation_set); - bool convert_animation(XFileDataNode *obj, - XFileAnimationSet &animation_set); - bool convert_animation_object(XFileDataNode *obj, - const std::string &joint_name, FrameData &table); - bool convert_animation_key(XFileDataNode *obj, const std::string &joint_name, - FrameData &table); - bool set_animation_frame(const std::string &joint_name, FrameData &table, - int frame, int key_type, - const XFileDataObject &values); - bool convert_mesh(XFileDataNode *obj, EggGroupNode *egg_parent); - - bool create_polygons(); - bool create_hierarchy(); - - PT(XFile) _x_file; - - bool _any_frames; - bool _any_animation; - int _ticks_per_second; - int _total_tick_deltas; - int _num_ticks; - - typedef pvector Meshes; - Meshes _meshes; - - typedef pvector AnimationSets; - AnimationSets _animation_sets; - - typedef pmap Joints; - Joints _joints; - - EggGroup *_dart_node; - - EggTextureCollection _textures; - EggMaterialCollection _materials; -}; - -#endif diff --git a/pandatool/src/xfileegg/xFileVertex.cxx b/pandatool/src/xfileegg/xFileVertex.cxx deleted file mode 100644 index 6fb3e105..00000000 --- a/pandatool/src/xfileegg/xFileVertex.cxx +++ /dev/null @@ -1,88 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileVertex.cxx - * @author drose - * @date 2001-06-19 - */ - -#include "xFileVertex.h" -#include "eggVertex.h" -#include "eggPrimitive.h" -#include "config_xfile.h" - -/** - * - */ -XFileVertex:: -XFileVertex() { - _has_color = false; - _has_uv = false; - _point.set(0.0, 0.0, 0.0); - _uv.set(0.0, 0.0); - _color.set(1.0f, 1.0f, 1.0f, 1.0f); -} - -/** - * Sets the structure up from the indicated egg data. - */ -void XFileVertex:: -set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim) { - LVertexd pos = egg_vertex->get_pos3(); - - if (xfile_one_mesh) { - // If this is going into one big mesh, we must ensure every vertex is in - // world coordinates. - pos = pos * egg_prim->get_vertex_frame(); - } else { - // Otherwise, we ensure the vertex is in local coordinates. - pos = pos * egg_prim->get_vertex_to_node(); - } - - _point = pos; - - if (egg_vertex->has_uv()) { - LTexCoordd uv = egg_vertex->get_uv(); - if (egg_prim->has_texture()) { - // Check if there's a texture matrix on the texture. - EggTexture *egg_tex = egg_prim->get_texture(); - if (egg_tex->has_transform2d()) { - uv = uv * egg_tex->get_transform2d(); - } - } - - _uv[0] = uv[0]; - // Windows draws the UV's upside-down. - _uv[1] = 1.0 - uv[1]; - _has_uv = true; - } - - if (egg_vertex->has_color()) { - _color = egg_vertex->get_color(); - _has_color = true; - } else if (egg_prim->has_color()) { - _color = egg_prim->get_color(); - _has_color = true; - } -} - -/** - * - */ -int XFileVertex:: -compare_to(const XFileVertex &other) const { - int ct; - ct = _point.compare_to(other._point); - if (ct == 0) { - ct = _uv.compare_to(other._uv); - } - if (ct == 0) { - ct = _color.compare_to(other._color); - } - return ct; -} diff --git a/pandatool/src/xfileegg/xFileVertex.h b/pandatool/src/xfileegg/xFileVertex.h deleted file mode 100644 index 2d88a361..00000000 --- a/pandatool/src/xfileegg/xFileVertex.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileVertex.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef XFILEVERTEX_H -#define XFILEVERTEX_H - -#include "pandatoolbase.h" -#include "luse.h" - -class EggVertex; -class EggPrimitive; - -/** - * This represents a single vertex associated with an XFileFace. - */ -class XFileVertex { -public: - XFileVertex(); - void set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_poly); - int compare_to(const XFileVertex &other) const; - - LVertexd _point; - LTexCoordd _uv; - LColor _color; - bool _has_color; - bool _has_uv; -}; - -#endif diff --git a/pandatool/src/xfileegg/xFileVertexPool.h b/pandatool/src/xfileegg/xFileVertexPool.h deleted file mode 100644 index 3c99836c..00000000 --- a/pandatool/src/xfileegg/xFileVertexPool.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileVertexPool.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef XFILEVERTEXPOOL_H -#define XFILEVERTEXPOOL_H - -#include "pandatoolbase.h" - -/** - * This is a collection of unique vertices as extracted out of a Geom or a - * series of Geoms. - */ -class XFileVertexPool { -public: - XFileVertexPool(); - ~XFileVertexPool(); - - int add_vertex(const XFileVertex &vertex); - - int get_num_vertices(); - const LVertex *get_vertices(); - const LNormal *get_normals(); - const LTexCoord *get_uvs(); - const LColor *get_colors(); - - - - void set_normal(const LNormal &normal); - void set_uv(const LTexCoord &uv); - void set_color(const LColor &color); - - bool operator < (const XFileVertexPool &other) const; - -private: - LVertex _point; - LNormal _normal; - LTexCoord _uv; - LColor _color; -}; - -#endif diff --git a/pandatool/src/xfileprogs/CMakeLists.txt b/pandatool/src/xfileprogs/CMakeLists.txt deleted file mode 100644 index 9d3acc89..00000000 --- a/pandatool/src/xfileprogs/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -if(NOT BUILD_TOOLS) - return() -endif() - -add_executable(x-trans xFileTrans.cxx xFileTrans.h) -target_link_libraries(x-trans p3progbase p3xfile) -install(TARGETS x-trans EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -if(HAVE_EGG) - - add_executable(egg2x eggToX.cxx eggToX.h) - target_link_libraries(egg2x p3xfileegg p3eggbase p3progbase) - install(TARGETS egg2x EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - - add_executable(x2egg xFileToEgg.cxx xFileToEgg.h) - target_link_libraries(x2egg p3xfileegg p3eggbase p3progbase) - install(TARGETS x2egg EXPORT Tools COMPONENT Tools DESTINATION ${CMAKE_INSTALL_BINDIR}) - -endif() diff --git a/pandatool/src/xfileprogs/eggToX.cxx b/pandatool/src/xfileprogs/eggToX.cxx deleted file mode 100644 index a677a381..00000000 --- a/pandatool/src/xfileprogs/eggToX.cxx +++ /dev/null @@ -1,77 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToX.cxx - * @author drose - * @date 2001-06-19 - */ - -#include "eggToX.h" -#include "config_xfile.h" - -/** - * - */ -EggToX:: -EggToX() : EggToSomething("DirectX", ".x", true, false) { - add_texture_options(); - add_delod_options(0.0); - - set_program_brief("convert an .egg file into a DirectX .x file"); - set_program_description - ("This program reads an Egg file and outputs an equivalent, " - "or nearly equivalent, DirectX-style .x file. Only simple " - "hierarchy and polygon meshes are supported; advanced features " - "like LOD's, decals, and animation or skinning are not supported."); - - add_option - ("m", "", 0, - "Convert all the objects in the egg file as one big mesh, instead of " - "preserving the normal egg hierarchy.", - &EggToX::dispatch_none, &xfile_one_mesh); - - // X files are always y-up-left. - remove_option("cs"); - _got_coordinate_system = true; - _coordinate_system = CS_yup_left; - - // We always have -f on: force complete load. X files don't support - // external references. - remove_option("f"); - _force_complete = true; -} - - -/** - * - */ -void EggToX:: -run() { - if (!do_reader_options()) { - exit(1); - } - - if (!_x.add_tree(_data)) { - nout << "Unable to define egg structure.\n"; - exit(1); - } - - if (!_x.write(get_output_filename())) { - nout << "Unable to write " << get_output_filename() << ".\n"; - exit(1); - } -} - - -int main(int argc, char *argv[]) { - init_libxfile(); - EggToX prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/xfileprogs/eggToX.h b/pandatool/src/xfileprogs/eggToX.h deleted file mode 100644 index 9abef225..00000000 --- a/pandatool/src/xfileprogs/eggToX.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file eggToX.h - * @author drose - * @date 2001-06-19 - */ - -#ifndef EGGTOX_H -#define EGGTOX_H - -#include "pandatoolbase.h" -#include "eggToSomething.h" -#include "xFileMaker.h" - -#include "programBase.h" -#include "withOutputFile.h" -#include "filename.h" - -class Node; - -/** - * A program to read in a egg file and write an equivalent, or nearly - * equivalent, DirectX-style "x" file. - */ -class EggToX : public EggToSomething { -public: - EggToX(); - - void run(); - -private: - void convert_scene_graph(Node *root); - - Filename _input_filename; - XFileMaker _x; -}; - -#endif diff --git a/pandatool/src/xfileprogs/xFileToEgg.cxx b/pandatool/src/xfileprogs/xFileToEgg.cxx deleted file mode 100644 index d3734fa8..00000000 --- a/pandatool/src/xfileprogs/xFileToEgg.cxx +++ /dev/null @@ -1,121 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileToEgg.cxx - * @author drose - * @date 2001-06-21 - */ - -#include "xFileToEgg.h" -#include "xFileToEggConverter.h" -#include "config_xfile.h" - -/** - * - */ -XFileToEgg:: -XFileToEgg() : - SomethingToEgg("DirectX", ".x") -{ - add_path_replace_options(); - add_path_store_options(); - add_units_options(); - add_normals_options(); - add_transform_options(); - - set_program_brief("convert a DirectX .x file to an .egg file"); - set_program_description - ("This program converts DirectX retained-mode (.x) files to egg. " - "Polygon meshes, materials, and textures, as well as skeleton " - "animation and skinning data, are supported. All animations " - "found in the source .x file are written together into the same " - "egg file."); - - add_option - ("a", "name", 0, - "Specify the name of the animated character to generate. This option " - "forces the model to be converted as an animatable character, even " - "if animation channels are not found in the file. Without this " - "option, the model is converted as a static model (which " - "is usually more efficient to load within Panda), unless animation " - "channels are present in the .x file.", - &XFileToEgg::dispatch_string, &_make_char, &_char_name); - - add_option - ("fr", "fps", 0, - "Specify the frame rate of the resulting animation. If this is " - "omitted or 0, the frame rate is inferred from the file itself; but " - "note that the file must contain evenly-spaced keyframes.", - &XFileToEgg::dispatch_double, nullptr, &_frame_rate); - - add_option - ("anim", "", 0, - "Generate animation data only (all geometry will be discarded).", - &XFileToEgg::dispatch_none, &_keep_animation); - - add_option - ("model", "", 0, - "Generate model data only (all animation data will be discarded).", - &XFileToEgg::dispatch_none, &_keep_model); - - redescribe_option - ("ui", - "Specify the units of the input " + _format_name + " file."); - - redescribe_option - ("uo", - "Specify the units of the resulting egg file. If both this and -ui are " - "specified, the vertices in the egg file will be scaled as " - "necessary to make the appropriate units conversion; otherwise, " - "the vertices will be left as they are."); - - redescribe_option - ("cs", - "Specify the coordinate system of the input " + _format_name + - " file. Normally, this is y-up-left."); - - _frame_rate = 0.0; - _coordinate_system = CS_yup_left; -} - -/** - * - */ -void XFileToEgg:: -run() { - _data->set_coordinate_system(_coordinate_system); - - XFileToEggConverter converter; - converter.set_egg_data(_data); - - converter._frame_rate = _frame_rate; - converter._make_char = _make_char; - converter._char_name = _char_name; - converter._keep_model = _keep_model; - converter._keep_animation = _keep_animation; - - // Copy in the path and animation parameters. - apply_parameters(converter); - - if (!converter.convert_file(_input_filename)) { - nout << "Unable to read " << _input_filename << "\n"; - exit(1); - } - - write_egg_file(); - nout << "\n"; -} - - -int main(int argc, char *argv[]) { - init_libxfile(); - XFileToEgg prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/xfileprogs/xFileToEgg.h b/pandatool/src/xfileprogs/xFileToEgg.h deleted file mode 100644 index c95815fe..00000000 --- a/pandatool/src/xfileprogs/xFileToEgg.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileToEgg.h - * @author drose - * @date 2001-06-21 - */ - -#ifndef XFILETOEGG_H -#define XFILETOEGG_H - -#include "pandatoolbase.h" -#include "somethingToEgg.h" -#include "xFileToEggConverter.h" - -#include "dSearchPath.h" - -/** - * A program to read a DirectX "x" file and generate an egg file. - */ -class XFileToEgg : public SomethingToEgg { -public: - XFileToEgg(); - - void run(); - -public: - bool _make_char; - std::string _char_name; - double _frame_rate; - bool _keep_model; - bool _keep_animation; -}; - -#endif diff --git a/pandatool/src/xfileprogs/xFileTrans.cxx b/pandatool/src/xfileprogs/xFileTrans.cxx deleted file mode 100644 index afe58b25..00000000 --- a/pandatool/src/xfileprogs/xFileTrans.cxx +++ /dev/null @@ -1,96 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileTrans.cxx - * @author drose - * @date 2004-10-03 - */ - -#include "xFileTrans.h" -#include "xFile.h" - -/** - * - */ -XFileTrans:: -XFileTrans() : - WithOutputFile(true, false, true) -{ - // Indicate the extension name we expect the user to supply for output - // files. - _preferred_extension = ".x"; - - set_program_brief("reads and writes DirectX .x files"); - 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] -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); -} - - -/** - * - */ -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); - } -} - - -/** - * - */ -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; -} diff --git a/pandatool/src/xfileprogs/xFileTrans.h b/pandatool/src/xfileprogs/xFileTrans.h deleted file mode 100644 index 85c77fd5..00000000 --- a/pandatool/src/xfileprogs/xFileTrans.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * PANDA 3D SOFTWARE - * Copyright (c) Carnegie Mellon University. All rights reserved. - * - * All use of this software is subject to the terms of the revised BSD - * license. You should have received a copy of this license along - * with this source code in a file named "LICENSE." - * - * @file xFileTrans.h - * @author drose - * @date 2004-10-03 - */ - -#ifndef XFILETRANS_H -#define XFILETRANS_H - -#include "pandatoolbase.h" - -#include "programBase.h" -#include "withOutputFile.h" - -/** - * 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 diff --git a/results.txt b/results.txt new file mode 100644 index 00000000..7ca1a01e --- /dev/null +++ b/results.txt @@ -0,0 +1,400 @@ + +统计的是文件夹: . + 100 files 200 files 300 files 400 files 500 files 600 files 700 files 800 files 900 files 1000 files 1100 files 1200 files 1300 files 1400 files 1500 files 1600 files 1700 files 1800 files 1900 files 2000 files 2100 files 2200 files 2300 files 2400 files 2500 files 2600 files 2700 files 2800 files 2900 files 3000 files 3100 files 3200 files 3300 files 3400 files 3500 files 3600 files 3700 files 3800 files 3900 files 4000 files 4100 files 4200 files 4300 files 4400 files 4500 files 4600 files 4700 files 4800 files 4900 files 5000 files 5100 files 5200 files 5300 files 5400 files 5500 files 5600 files 5700 files 5800 files 5900 files 6000 files 6100 files 6200 files 6300 files 6400 files 6500 files 6600 files 6700 files 6800 files 6900 files 7000 files 7100 files 7200 files 7300 files 7400 files 7500 files 7600 files 7700 files 7800 files 7900 files 8000 files 8100 files 8200 files 8300 files 8400 files 8500 files 8600 files 8700 files 8800 files 8900 files 9000 files 9100 files 9200 files 9300 files 9400 files 9500 files 9600 files 9700 files 9800 files 9900 files 10000 files 10100 files 10200 files 10300 files 10400 files 10500 files 10600 files 10700 files 10800 files 10900 files 11000 files 11100 files 11200 files 11300 files 11400 files 11500 files 11600 files 11700 files 11800 files 11900 files 12000 files 12100 files 12200 files 12300 files 12400 files 12500 files 12600 files 12700 files 12800 files 12900 files 13000 files 13100 files 13200 files 13300 files 13400 files 13495 text files. +classified 13481 files Duplicate file check 13481 files (7001 known unique) Unique: 100 files Unique: 200 files Unique: 300 files Unique: 400 files Unique: 500 files Unique: 600 files Unique: 700 files Unique: 800 files Unique: 900 files Unique: 1000 files Unique: 1100 files Unique: 1200 files Unique: 1300 files Unique: 1400 files Unique: 1500 files Unique: 1600 files Unique: 1700 files Unique: 1800 files Unique: 1900 files Unique: 2000 files Unique: 2100 files Unique: 2200 files Unique: 2300 files Unique: 2400 files Unique: 2500 files Unique: 2600 files Unique: 2700 files Unique: 2800 files Unique: 2900 files Unique: 3000 files Unique: 3100 files Unique: 3200 files Unique: 3300 files Unique: 3400 files Unique: 3500 files Unique: 3600 files Unique: 3700 files Unique: 3800 files Unique: 3900 files Unique: 4000 files Unique: 4100 files Unique: 4200 files Unique: 4300 files Unique: 4400 files Unique: 4500 files Unique: 4600 files Unique: 4700 files Unique: 4800 files Unique: 4900 files Unique: 5000 files Unique: 5100 files Unique: 5200 files Unique: 5300 files Unique: 5400 files Unique: 5500 files Unique: 5600 files Unique: 5700 files Unique: 5800 files Unique: 5900 files Unique: 6000 files Unique: 6100 files Unique: 6200 files Unique: 6300 files Unique: 6400 files Unique: 6500 files Unique: 6600 files Unique: 6700 files Unique: 6800 files Unique: 6900 files Unique: 7000 files 12850 unique files. +Counting: 100 Counting: 200 Counting: 300 Counting: 400 Counting: 500 Counting: 600 Counting: 700 Counting: 800 Counting: 900 Counting: 1000 Counting: 1100 Counting: 1200 Counting: 1300 Counting: 1400 Counting: 1500 Counting: 1600 Counting: 1700 Counting: 1800 Counting: 1900 Counting: 2000 Counting: 2100 Counting: 2200 Counting: 2300 Counting: 2400 Counting: 2500 Counting: 2600 Counting: 2700 Counting: 2800 Counting: 2900 Counting: 3000 Counting: 3100 Counting: 3200 Counting: 3300 Counting: 3400 Counting: 3500 Counting: 3600 Counting: 3700 Counting: 3800 Counting: 3900 Counting: 4000 Counting: 4100 Counting: 4200 Counting: 4300 Counting: 4400 Counting: 4500 Counting: 4600 Counting: 4700 Counting: 4800 Counting: 4900 Counting: 5000 Counting: 5100 Counting: 5200 Counting: 5300 Counting: 5400 Counting: 5500 Counting: 5600 Counting: 5700 Counting: 5800 Counting: 5900 Counting: 6000 Counting: 6100 Counting: 6200 Counting: 6300 Counting: 6400 Counting: 6500 Counting: 6600 Counting: 6700 Counting: 6800 Counting: 6900 Counting: 7000 Counting: 7100 Counting: 7200 Counting: 7300 Counting: 7400 Counting: 7500 Counting: 7600 Counting: 7700 Counting: 7800 Counting: 7900 Counting: 8000 Counting: 8100 Counting: 8200 Counting: 8300 Counting: 8400 Counting: 8500 Counting: 8600 Counting: 8700 Counting: 8800 Counting: 8900 Counting: 9000 Counting: 9100 Counting: 9200 Counting: 9300 Counting: 9400 Counting: 9500 Counting: 9600 Counting: 9700 Counting: 9800 Counting: 9900 Counting: 10000 Counting: 10100 Counting: 10200 Counting: 10300 Counting: 10400 Counting: 10500 Counting: 10600 Counting: 10700 Counting: 10800 Counting: 10900 Counting: 11000 Counting: 11100 Counting: 11200 Counting: 11300 Counting: 11400 Counting: 11500 Counting: 11600 Counting: 11700 Counting: 11800 Counting: 11900 Counting: 12000 Counting: 12100 Counting: 12200 Counting: 12300 Counting: 12400 Counting: 12500 Counting: 12600 Counting: 12700 Counting: 12800 3124 files ignored. + +github.com/AlDanial/cloc v 1.90 T=7.99 s (1323.0 files/s, 354425.3 lines/s) +--------------------------------------------------------------------------------------- +Language files blank comment code +--------------------------------------------------------------------------------------- +Python 6244 229180 324244 996200 +JSON 157 5 0 424470 +C/C++ Header 1096 37242 94299 182139 +QML 1533 23679 45784 113180 +XML 159 5698 2287 82978 +C++ 365 12118 21015 57289 +CSV 30 0 0 36702 +Tcl/Tk 143 4585 10091 30211 +GLSL 191 3174 6711 9703 +Markdown 43 1669 0 8417 +SVG 10 3 3 7149 +C 69 677 1204 6687 +Gencat NLS 147 15 0 5268 +Objective-C++ 17 966 1400 4438 +Cython 24 840 513 3965 +Qt 4 56 0 3827 +Bourne Shell 28 672 1115 3740 +Lisp 3 591 1115 3726 +YAML 58 522 291 2661 +make 2 240 279 1610 +CMake 52 264 151 1478 +SQL 4 0 0 1398 +HTML 5 69 2 1391 +Fortran 90 60 129 97 987 +diff 2 172 1015 874 +reStructuredText 9 255 128 638 +Perl 3 86 133 616 +Windows Module Definition 6 26 3 558 +JavaScript 9 88 237 504 +Oracle PL/SQL 4 150 8 423 +Fortran 77 24 29 55 400 +Logos 1 40 40 194 +TOML 34 34 34 136 +Meson 3 24 9 122 +Bourne Again Shell 2 18 28 114 +PowerShell 1 49 90 108 +DOS Batch 9 16 6 60 +INI 6 5 1 47 +Fish Shell 1 13 14 42 +IDL 1 11 0 40 +TNSDL 1 6 0 28 +Java 1 6 3 16 +C Shell 1 9 5 12 +Fortran 95 1 0 1 4 +Visual Basic Script 1 0 0 4 +CSS 1 2 4 0 +--------------------------------------------------------------------------------------- +SUM: 10565 323433 512415 1994554 +--------------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./.conda + 100 files 200 files 300 files 400 files 500 files 600 files 700 files 800 files 900 files 1000 files 1100 files 1200 files 1300 files 1400 files 1500 files 1600 files 1700 files 1800 files 1900 files 2000 files 2100 files 2200 files 2300 files 2400 files 2500 files 2600 files 2700 files 2800 files 2900 files 3000 files 3100 files 3200 files 3300 files 3400 files 3500 files 3600 files 3700 files 3800 files 3900 files 4000 files 4100 files 4200 files 4300 files 4400 files 4500 files 4600 files 4700 files 4800 files 4900 files 5000 files 5100 files 5200 files 5300 files 5400 files 5500 files 5600 files 5700 files 5800 files 5900 files 6000 files 6100 files 6200 files 6300 files 6400 files 6500 files 6600 files 6700 files 6800 files 6900 files 7000 files 7100 files 7200 files 7300 files 7400 files 7500 files 7600 files 7700 files 7800 files 7900 files 8000 files 8100 files 8200 files 8300 files 8400 files 8500 files 8600 files 8700 files 8800 files 8900 files 9000 files 9100 files 9200 files 9300 files 9400 files 9500 files 9600 files 9700 files 9800 files 9900 files 10000 files 10100 files 10200 files 10300 files 10400 files 10500 files 10600 files 10700 files 10800 files 10900 files 11000 files 11100 files 11200 files 11300 files 11400 files 11500 files 11600 files 11700 files 11800 files 11804 text files. +classified 11790 files Duplicate file check 11790 files (6423 known unique) Unique: 100 files Unique: 200 files Unique: 300 files Unique: 400 files Unique: 500 files Unique: 600 files Unique: 700 files Unique: 800 files Unique: 900 files Unique: 1000 files Unique: 1100 files Unique: 1200 files Unique: 1300 files Unique: 1400 files Unique: 1500 files Unique: 1600 files Unique: 1700 files Unique: 1800 files Unique: 1900 files Unique: 2000 files Unique: 2100 files Unique: 2200 files Unique: 2300 files Unique: 2400 files Unique: 2500 files Unique: 2600 files Unique: 2700 files Unique: 2800 files Unique: 2900 files Unique: 3000 files Unique: 3100 files Unique: 3200 files Unique: 3300 files Unique: 3400 files Unique: 3500 files Unique: 3600 files Unique: 3700 files Unique: 3800 files Unique: 3900 files Unique: 4000 files Unique: 4100 files Unique: 4200 files Unique: 4300 files Unique: 4400 files Unique: 4500 files Unique: 4600 files Unique: 4700 files Unique: 4800 files Unique: 4900 files Unique: 5000 files Unique: 5100 files Unique: 5200 files Unique: 5300 files Unique: 5400 files Unique: 5500 files Unique: 5600 files Unique: 5700 files Unique: 5800 files Unique: 5900 files Unique: 6000 files Unique: 6100 files Unique: 6200 files Unique: 6300 files Unique: 6400 files 11177 unique files. +Counting: 100 Counting: 200 Counting: 300 Counting: 400 Counting: 500 Counting: 600 Counting: 700 Counting: 800 Counting: 900 Counting: 1000 Counting: 1100 Counting: 1200 Counting: 1300 Counting: 1400 Counting: 1500 Counting: 1600 Counting: 1700 Counting: 1800 Counting: 1900 Counting: 2000 Counting: 2100 Counting: 2200 Counting: 2300 Counting: 2400 Counting: 2500 Counting: 2600 Counting: 2700 Counting: 2800 Counting: 2900 Counting: 3000 Counting: 3100 Counting: 3200 Counting: 3300 Counting: 3400 Counting: 3500 Counting: 3600 Counting: 3700 Counting: 3800 Counting: 3900 Counting: 4000 Counting: 4100 Counting: 4200 Counting: 4300 Counting: 4400 Counting: 4500 Counting: 4600 Counting: 4700 Counting: 4800 Counting: 4900 Counting: 5000 Counting: 5100 Counting: 5200 Counting: 5300 Counting: 5400 Counting: 5500 Counting: 5600 Counting: 5700 Counting: 5800 Counting: 5900 Counting: 6000 Counting: 6100 Counting: 6200 Counting: 6300 Counting: 6400 Counting: 6500 Counting: 6600 Counting: 6700 Counting: 6800 Counting: 6900 Counting: 7000 Counting: 7100 Counting: 7200 Counting: 7300 Counting: 7400 Counting: 7500 Counting: 7600 Counting: 7700 Counting: 7800 Counting: 7900 Counting: 8000 Counting: 8100 Counting: 8200 Counting: 8300 Counting: 8400 Counting: 8500 Counting: 8600 Counting: 8700 Counting: 8800 Counting: 8900 Counting: 9000 Counting: 9100 Counting: 9200 Counting: 9300 Counting: 9400 Counting: 9500 Counting: 9600 Counting: 9700 Counting: 9800 Counting: 9900 Counting: 10000 Counting: 10100 Counting: 10200 Counting: 10300 Counting: 10400 Counting: 10500 Counting: 10600 Counting: 10700 Counting: 10800 Counting: 10900 Counting: 11000 Counting: 11100 2835 files ignored. + +github.com/AlDanial/cloc v 1.90 T=7.27 s (1255.9 files/s, 350927.8 lines/s) +--------------------------------------------------------------------------------------- +Language files blank comment code +--------------------------------------------------------------------------------------- +Python 5886 209236 300696 922241 +JSON 150 5 0 423997 +C/C++ Header 751 32588 87955 168435 +QML 1533 23679 45784 113180 +XML 144 5577 2218 81859 +CSV 30 0 0 36702 +Tcl/Tk 143 4585 10091 30211 +SVG 10 3 3 7149 +Gencat NLS 147 15 0 5268 +Cython 24 840 513 3965 +C 62 535 1020 3745 +C++ 27 759 1268 3742 +Lisp 3 591 1115 3726 +Bourne Shell 26 663 1107 3702 +make 2 240 279 1610 +SQL 4 0 0 1398 +HTML 3 39 0 1146 +Fortran 90 60 129 97 987 +reStructuredText 9 255 128 638 +Perl 3 86 133 616 +Windows Module Definition 6 26 3 558 +JavaScript 9 88 237 504 +Fortran 77 24 29 55 400 +CMake 8 69 106 322 +Markdown 5 95 0 283 +Oracle PL/SQL 2 58 1 176 +TOML 34 34 34 136 +Meson 3 24 9 122 +Bourne Again Shell 2 18 28 114 +PowerShell 1 49 90 108 +Fish Shell 1 13 14 42 +IDL 1 11 0 40 +INI 3 5 1 36 +TNSDL 1 6 0 28 +GLSL 5 2 0 20 +C Shell 1 9 5 12 +DOS Batch 2 0 1 4 +Fortran 95 1 0 1 4 +Visual Basic Script 1 0 0 4 +CSS 1 2 4 0 +--------------------------------------------------------------------------------------- +SUM: 9128 280363 452996 1817230 +--------------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./config + 1 text file. + 1 unique file. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.00 s (283.8 files/s, 4256.4 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +JSON 1 0 0 15 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./core + 42 text files. +classified 42 files 42 unique files. + 2 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.09 s (459.8 files/s, 288494.6 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 37 4470 4940 15211 +Markdown 2 87 0 376 +JSON 1 0 0 15 +------------------------------------------------------------------------------- +SUM: 40 4557 4940 15602 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./demo + 78 text files. +classified 78 files 76 unique files. + 2 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.06 s (1327.3 files/s, 304453.2 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 59 2680 2242 8991 +Markdown 17 835 0 2685 +------------------------------------------------------------------------------- +SUM: 76 3515 2242 11676 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./.git + 28 text files. +classified 28 files 27 unique files. + 16 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.01 s (2025.6 files/s, 123091.5 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Bourne Shell 12 76 221 320 +Perl 1 31 42 100 +------------------------------------------------------------------------------- +SUM: 13 107 263 420 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./gui + 2 text files. +classified 2 files 2 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.02 s (114.8 files/s, 229371.1 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 2 611 792 2592 +------------------------------------------------------------------------------- +SUM: 2 611 792 2592 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./icons + 0 text files. + 0 unique files. + 0 files ignored. +---------------------------------------- +统计的是文件夹: ./.idea + 2 text files. +classified 2 files 2 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.00 s (559.4 files/s, 5874.0 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +XML 2 0 0 21 +------------------------------------------------------------------------------- +SUM: 2 0 0 21 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./new + 1 text file. + 1 unique file. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.00 s (317.4 files/s, 2538.9 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +JSON 1 0 0 8 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./pandatool + 100 files 200 files 300 files 400 files 500 files 600 files 700 files 800 files 813 text files. +classified 813 files Duplicate file check 813 files (741 known unique) Unique: 100 files Unique: 200 files Unique: 300 files Unique: 400 files Unique: 500 files Unique: 600 files Unique: 700 files 813 unique files. +Counting: 100 Counting: 200 Counting: 300 Counting: 400 Counting: 500 Counting: 600 Counting: 700 Counting: 800 94 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.19 s (3707.7 files/s, 599048.5 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +C++ 322 10974 18463 52386 +C/C++ Header 326 4228 5468 12834 +Objective-C++ 17 966 1400 4438 +C 7 142 184 2942 +CMake 44 195 45 1156 +Logos 1 40 40 194 +XML 1 0 0 47 +Java 1 6 3 16 +------------------------------------------------------------------------------- +SUM: 719 16551 25603 74013 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./project + 2 text files. +classified 2 files 2 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.01 s (226.3 files/s, 179492.4 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 2 207 678 701 +------------------------------------------------------------------------------- +SUM: 2 207 678 701 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./__pycache__ + 0 text files. + 0 unique files. + 0 files ignored. +---------------------------------------- +统计的是文件夹: ./QPanda3D + 11 text files. +classified 11 files 11 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.01 s (1241.1 files/s, 165632.9 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 11 164 302 1002 +------------------------------------------------------------------------------- +SUM: 11 164 302 1002 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./RenderPipelineFile + 100 files 200 files 300 files 400 files 500 files 600 files 680 text files. +classified 680 files Duplicate file check 680 files (556 known unique) Unique: 100 files Unique: 200 files Unique: 300 files Unique: 400 files Unique: 500 files 666 unique files. +Counting: 100 Counting: 200 Counting: 300 Counting: 400 Counting: 500 Counting: 600 173 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.23 s (2345.6 files/s, 323519.0 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 212 6403 6791 24544 +GLSL 186 3172 6711 9683 +Qt 4 56 0 3827 +YAML 57 522 291 2646 +C++ 16 385 1284 1161 +XML 12 121 69 1051 +diff 2 172 1015 874 +C/C++ Header 19 426 876 870 +Oracle PL/SQL 2 92 7 247 +Markdown 14 103 0 165 +DOS Batch 7 16 5 56 +INI 3 0 0 11 +------------------------------------------------------------------------------- +SUM: 534 11468 17049 45135 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./requirements + 5 text files. +classified 5 files 5 unique files. + 3 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.00 s (512.2 files/s, 26888.2 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Markdown 1 25 0 65 +YAML 1 0 0 15 +------------------------------------------------------------------------------- +SUM: 2 25 0 80 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./Resources + 0 text files. + 0 unique files. + 6 files ignored. +---------------------------------------- +统计的是文件夹: ./scene + 3 text files. +classified 3 files 3 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.02 s (149.3 files/s, 214977.7 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 3 716 718 2886 +------------------------------------------------------------------------------- +SUM: 3 716 718 2886 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./scripts + 18 text files. +classified 18 files 18 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.01 s (1698.9 files/s, 145633.6 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 18 286 369 888 +------------------------------------------------------------------------------- +SUM: 18 286 369 888 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./templates + 1 text file. + 1 unique file. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.01 s (115.1 files/s, 180384.1 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 1 288 155 1124 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./tex + 0 text files. + 0 unique files. + 0 files ignored. +---------------------------------------- +统计的是文件夹: ./ui + 11 text files. +classified 11 files 11 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.09 s (122.9 files/s, 283346.1 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Python 11 3852 6278 15225 +------------------------------------------------------------------------------- +SUM: 11 3852 6278 15225 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./vr_actions + 4 text files. +classified 4 files 4 unique files. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.00 s (964.3 files/s, 107521.5 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +JSON 4 0 0 446 +------------------------------------------------------------------------------- +SUM: 4 0 0 446 +------------------------------------------------------------------------------- +---------------------------------------- +统计的是文件夹: ./.vscode + 1 text file. + 1 unique file. + 0 files ignored. + +github.com/AlDanial/cloc v 1.90 T=0.00 s (284.9 files/s, 1139.6 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +JSON 1 0 0 4 +------------------------------------------------------------------------------- +---------------------------------------- diff --git a/功能与源代码对应关系清单.md b/功能与源代码对应关系清单.md new file mode 100644 index 00000000..583eda71 --- /dev/null +++ b/功能与源代码对应关系清单.md @@ -0,0 +1,3716 @@ +# 功能与源代码对应关系清单 + +## 2.1.1 core模块核心文件 + +### 1. `core/__init__.py` +- **功能**: Python包初始化文件,导出核心类 +- **类**: + - `CoreWorld`: 核心世界类 + - `SelectionSystem`: 选择系统类 + - `EventHandler`: 事件处理器类 + - `ToolManager`: 工具管理器类 + - `ScriptManager`: 脚本管理器类 + - `ScriptBase`: 脚本基类 + - `ScriptComponent`: 脚本组件类 + +### 2. `core/world.py` +- **功能**: 核心世界功能类,负责基础的3D世界设置和核心功能 +- **类**: + - `CoreWorld`: 核心世界类 +- **方法**: + - `_setupResourcePaths()`: 设置资源路径 + - `_setupCamera()`: 设置相机 + - `_setupLighting()`: 设置光照 + - `_setupGround()`: 设置地面网格 + - `getChineseFont()`: 获取中文字体 + - `setQtWidget()`: 设置Qt部件引用 + - `getWindowSize()`: 获取准确的窗口尺寸 + - `wheelForward()`: 处理滚轮向前滚动(前进) + - `wheelBackward()`: 处理滚轮向后滚动(后退) + - `moveCamera()`: 移动相机位置(垂直移动) + - `mousePressEventRight()`: 处理鼠标右键按下事件 + - `mouseReleaseEventRight()`: 处理鼠标右键释放事件 + - `mouseMoveEvent()`: 处理鼠标移动事件 + - `getGroundNode()`: 获取地板节点 + - `getAmbientLight()`: 获取环境光 + - `getDirectionalLight()`: 获取定向光 + - `start_day_night_cycle()`: 让天空盒在指定时间内过渡 + - `_day_night_cycle_task()`: 天空盒过渡任务 + - `set_daytime()`: 设置时间 + - `get_render_pipeline()`: 获取 RenderPipeline 实例 + - `_setupSkybox()`: 设置静态天空盒 + - `createDirectionalLight()`: 创建平行光 + - `check_material_editor_connection()`: 检查材质编辑器连接状态 + - `create_material_editor_widget()`: 创建材质编辑器组件 + - `_delayed_material_test()`: 延迟执行的材质编辑器连接测试 + - `launch_day_time_editor()`: 启动光照编辑器 + - `setup_material_editor_network()`: 设置材质编辑器网络通信 + - `export_materials_to_file()`: 导出材质列表到文件 + - `update_material_from_editor()`: 从编辑器更新材质 + - `launch_material_editor()`: 启动材质编辑器 + - `create_sample_materials()`: 创建一些示例材质供编辑器使用 + - `load_test_models_with_materials()`: 加载一些测试模型以提供更多材质供编辑 + - `launch_plugin_configurator()`: 启动插件配置器 + +### 3. `core/vr_manager.py` +- **功能**: VR管理器主文件,负责VR系统的初始化和管理 +- **类**: + - `VRManager`: VR管理器类 +- **方法**: + - `initialize_vr()`: 初始化VR系统 + - `enable_vr()`: 启用VR模式 + - `disable_vr()`: 禁用VR模式 + - `update_vr()`: 更新VR状态 + - `render_vr()`: VR渲染处理 + - `set_vr_render_mode()`: 切换VR渲染模式 + - `get_vr_render_mode()`: 获取当前VR渲染模式 + - `cleanup()`: 清理VR资源 + - `get_vr_status()`: 获取VR状态信息 + - `submit_texture()`: 优化的VR纹理提交 + - `_batch_submit_textures()`: 批量提交两眼纹理 + - `_disable_main_cam()`: 禁用主相机 + - `_enable_main_cam()`: 恢复主相机 + - `_initialize_controllers()`: 初始化VR手柄控制器 + - `_detect_controllers()`: 检测并连接VR控制器 + - `_create_tracked_device_anchor()`: 为跟踪设备创建锚点节点 + - `update_tracked_devices()`: 更新所有跟踪设备的姿态 + - `get_controller_by_role()`: 根据角色获取控制器 + - `are_controllers_connected()`: 检查是否有控制器连接 + - `get_connected_controllers()`: 获取所有连接的控制器列表 + - `trigger_controller_haptic()`: 触发控制器震动反馈 + - `is_trigger_pressed()`: 检查扳机是否被按下 + - `is_trigger_just_pressed()`: 检查扳机是否刚刚被按下 + - `is_grip_pressed()`: 检查握把是否被按下 + - `is_grip_just_pressed()`: 检查握把是否刚刚被按下 + - `is_menu_pressed()`: 检查菜单按钮是否被按下 + - `is_trackpad_touched()`: 检查触摸板是否被触摸 + - `get_trackpad_position()`: 获取触摸板位置 + - `get_selected_object()`: 获取指定手选中的对象 + - `get_grabbed_object()`: 获取指定手抓取的对象 + - `is_grabbing_object()`: 检查是否正在抓取对象 + - `force_release_all_grabs()`: 强制释放所有抓取的对象 + - `add_interactable_object()`: 将对象标记为可交互 + - `enable_gc_control()`: 启用垃圾回收控制 + - `disable_gc_control()`: 禁用垃圾回收控制 + - `set_manual_gc_interval()`: 设置手动垃圾回收间隔 + - `force_manual_gc()`: 强制执行一次垃圾回收 + - `get_object_pool_status()`: 获取对象池状态 + - `set_resolution_scale()`: 设置VR分辨率缩放系数 + - `set_quality_preset()`: 设置VR质量预设 + - `cycle_quality_preset()`: 循环切换质量预设 + - `get_resolution_info()`: 获取分辨率相关信息 + - `print_resolution_info()`: 输出分辨率信息 + - `enable_performance_mode()`: 手动启用性能模式 + - `disable_performance_mode()`: 禁用性能模式 + - `set_performance_mode_trigger_frame()`: 设置性能模式自动触发的帧数 + - `get_performance_mode_status()`: 获取性能模式状态 + - 其他VR系统管理方法 + +### 4. `core/selection.py` +- **功能**: 选择系统模块,实现3D场景中对象的选择功能 +- **类**: + - `SelectionSystem`: 选择系统类 +- **方法**: + - `createSelectionBox()`: 创建选择框 + - `updateSelectionBoxGeometry()`: 更新选择框的几何形状和位置 + - `updateSelectionBoxTask()`: 选择框更新任务 + - `clearSelectionBox()`: 清除选择框 + - `createGizmo()`: 创建变换控制器 + - `createGizmoGeometry()`: 创建坐标轴的几何体 + - `updateGizmoTask()`: 更新变换控制器任务 + - `clearGizmo()`: 清除坐标轴 + - `setGizmoAxisColor()`: 设置坐标轴颜色 + - `setGizmoRotAxisColor()`: 设置旋转坐标轴颜色 + - `checkGizmoClick()`: 检查是否点击了坐标轴 + - `updateGizmoHighlight()`: 更新坐标轴高亮状态 + - `startGizmoDrag()`: 开始坐标轴拖拽 + - `updateGizmoDrag()`: 更新坐标轴拖拽 + - `stopGizmoDrag()`: 停止坐标轴拖拽 + - `updateSelection()`: 更新选择状态 + - `_setCursor()`: 设置光标 + - `_resetCursor()`: 重置光标 + - `_setupGizmoRendering()`: 设置坐标轴渲染属性 + - `setupGizmoCollision()`: 设置坐标轴碰撞检测 + - `detectGizmoAxisAtMouse()`: 统一的坐标轴检测方法 + - `distanceToLine()`: 计算点到线段的距离 + - `_safeUpdatePropertyPanel()`: 安全地更新属性面板 + - 其他选择和变换相关方法 + +### 5. `core/tool_manager.py` +- **功能**: 工具管理器模块,管理各种编辑工具 +- **类**: + - `ToolManager`: 工具管理器类 +- **方法**: + - `setCurrentTool()`: 设置当前工具 + - `getCurrentTool()`: 获取当前工具 + - `isSelectionTool()`: 检查是否是选择工具 + - `isMoveTool()`: 检查是否是移动工具 + - `isRotateTool()`: 检查是否是旋转工具 + - `isScaleTool()`: 检查是否是缩放工具 + - `isDayTimeEditorTool()`: 检查是否是光照编辑工具 + - `isPlugincongiguratorTool()`: 检查是否是图形编辑工具 + - `launch_day_time_editor()`: 启动光照编辑器 + - `openSunLightingTool()`: 打开太阳光照系统工具的便捷方法 + - `launch_plugin_configurator()`: 启动插件配置器 + +### 6. `core/script_system.py` +- **功能**: 脚本系统模块,管理游戏对象的脚本挂载和执行 +- **类**: + - `ScriptBase`: 脚本基类 + - `ScriptComponent`: 脚本组件类 + - `ScriptManager`: 脚本管理器类 + - `ScriptEngine`: 脚本引擎类 + - `ScriptLoader`: 脚本加载器类 + - `ScriptAPI`: 脚本API类 +- **方法**: + - `attach_script()`: 为对象挂载脚本 + - `detach_script()`: 为对象卸载脚本 + - `reload_script()`: 重载脚本 + - `get_script_info()`: 获取脚本信息 + - `start_system()`: 启动脚本系统 + - `stop_system()`: 停止脚本系统 + - `load_script_from_file()`: 从文件加载脚本 + - `load_all_scripts_from_directory()`: 从目录加载所有脚本 + - `add_script_to_object()`: 为对象添加脚本 + - `remove_script_from_object()`: 从游戏对象移除脚本 + - `get_scripts_on_object()`: 获取对象上的所有脚本 + - `get_script_on_object()`: 获取对象上的特定脚本 + - `get_available_scripts()`: 获取所有可用的脚本名称 + - `list_all_scripts()`: 列出所有脚本信息 + - `save_object_scripts()`: 保存对象脚本 + - 其他脚本管理方法 + +### 7. `core/gui_manager.py` +- **功能**: GUI管理器模块,负责2D和3D GUI元素的创建和管理 +- **类**: + - `GUIManager`: GUI管理器类 +- **方法**: + - `createGUIButton()`: 创建GUI按钮 + - `createGUILabel()`: 创建GUI标签 + - `createGUIEntry()`: 创建GUI输入框 + - `createGUI2DImage()`: 创建2D图像 + - `createGUI3DText()`: 创建3D文本 + - `createGUI3DImage()`: 创建3D图像 + - `createVideoScreen()`: 创建视频屏幕 + - `createGUI2DVideoScreen()`: 创建2D视频屏幕 + - `createSphericalVideo()`: 创建球形视频 + - `createGUIVirtualScreen()`: 创建虚拟屏幕 + - `findClickedGUI()`: 查找被点击的GUI元素 + - `selectGUIInTree()`: 在树形控件中选中GUI元素 + - `createGUIAtPosition()`: 在指定位置创建GUI元素 + - `editGUIElement()`: 编辑GUI元素属性 + - `deleteGUIElement()`: 删除GUI元素 + - `duplicateGUIElement()`: 复制GUI元素 + - `editGUIElementDialog()`: 显示GUI元素编辑对话框 + - `onGUIButtonClick()`: GUI按钮点击事件处理 + - `onGUIEntrySubmit()`: GUI输入框提交事件处理 + - `toggleGUIEditMode()`: 切换GUI编辑模式 + - `enterGUIEditMode()`: 进入GUI编辑模式 + - `exitGUIEditMode()`: 退出GUI编辑模式 + - `createGUIEditPanel()`: 创建GUI编辑面板 + - `openGUIPreviewWindow()`: 打开独立的GUI预览窗口 + - `closeGUIPreviewWindow()`: 关闭GUI预览窗口 + - `setGUICreateTool()`: 设置GUI创建工具 + - `deleteSelectedGUI()`: 删除选中的GUI元素 + - `copySelectedGUI()`: 复制选中的GUI元素 + - `handleGUIEditClick()`: 处理GUI编辑模式下的点击 + - `createGUIAtPosition()`: 在指定位置创建GUI元素 + - `findClickedGUI()`: 查找被点击的GUI元素 + - `selectGUIInTree()`: 在树形控件中选中GUI元素 + - `updateGUISelection()`: 更新GUI元素选择状态 + - `updateGUIPropertyPanel()`: 更新GUI元素属性面板 + - `selectGUIColor()`: 选择GUI元素颜色 + - `update3DImageTexture()`: 更新3D图像纹理 + - `update2DImageTexture()`: 更新2D图片纹理 + - `editGUI2DPosition()`: 编辑2D GUI元素位置 + - `editGUI3DPosition()`: 编辑3D GUI元素位置 + - `editGUIScale()`: 编辑GUI元素缩放 + - `createCesiumView()`: 创建 Cesium 视图窗口 + - `toggleCesiumView()`: 切换 Cesium 视图显示状态 + - `refreshCesiumView()`: 刷新 Cesium 视图 + - `updateCesiumURL()`: 更新 Cesium 视图的 URL + - `addModelToCesium()`: 向 Cesium 添加模型 + - `addCesiumTilesetToScene()`: 在 Panda3D 场景中添加 Cesium 3D Tiles + - `removeModelFromCesium()`: 从 Cesium 移除模型 + - `updateCesiumModelPosition()`: 更新 Cesium 中模型的位置 + - `getAllCesiumModels()`: 获取 Cesium 中所有模型的列表 + - `addLocalModelToCesium()`: 向 Cesium 添加本地模型文件 + - `_create_screen_text()`: 为虚拟屏幕创建文本节点 + - `_get_tree_widget()`: 安全获取树形控件 + - `_resizeButtonToText()`: 根据文本内容调整按钮大小 + - `constrain2DPosition()`: 限制2D GUI元素位置在屏幕范围内 + - `_ensureVideoScreenMaterial()`: 确保视频屏幕有正确的材质设置 + - `_debugVideoScreenTextures()`: 调试视频屏幕的纹理状态 + - `playVideo()`: 播放视频 + - `_getMovieTextureFromScreen()`: 从视频屏幕获取视频纹理 + - `pauseVideo()`: 暂停视频 + - `stopVideo()`: 停止视频 + - `setVideoTime()`: 设置视频播放时间 + - `loadVideoFile()`: 为视频屏幕加载新的视频文件 + - `_loadMovieTexture()`: 加载视频纹理的兼容方法 + - `_configureVideoTexture()`: 配置视频纹理属性 + - `load2DVideoFile()`: 为2D视频屏幕加载新的视频文件 + - `play2DVideo()`: 播放2D视频 + - `pause2DVideo()`: 暂停2D视频 + - `stop2DVideo()`: 停止2D视频 + - `createSphericalVideo()`: 创建球形视频 + - `_createSphereGeometry()`: 创建球形几何体 + - `playSphericalVideo()`: 播放球形视频 + - `pauseSphericalVideo()`: 暂停球形视频 + - `setSphericalVideoTime()`: 设置球形视频时间 + - 其他GUI元素创建和管理方法 + +### 8. `core/terrain_manager.py` +- **功能**: 地形管理器模块,处理3D地形的创建、编辑和渲染 +- **类**: + - `TerrainManager`: 地形管理器类 +- **方法**: + - `createTerrainFromHeightMap()`: 从高度图创建地形 + - `createFlatTerrain()`: 创建平面地形 + - `_applyTerrainMaterial()`: 为地形应用材质 + - `updateTerrain()`: 更新所有地形的LOD + - `setTerrainLODThreshold()`: 设置地形LOD阈值 + - `getTerrainHeight()`: 获取地形上指定点的高度 + - `modifyTerrainHeight()`: 修改地形高度 + - `deleteTerrain()`: 删除地形 + - `getTerrainByName()`: 根据名称查找地形 + - `getAllTerrainNames()`: 获取所有地形名称 + - `setTerrainColor()`: 设置地形颜色 + - `setTerrainTexture()`: 为地形设置纹理 + - `saveTerrainData()`: 保存地形数据到文件 + - `_recreateTerrain()`: 重新创建地形 + - `_get_tree_widget()`: 安全获取树形控件 + +### 9. `core/collision_manager.py` +- **功能**: 碰撞管理器模块,管理场景中的碰撞检测和响应 +- **类**: + - `CollisionManager`: 碰撞管理器类 + - `CollisionPerformanceMonitor`: 碰撞检测性能监控器 + - `OctreeNode`: 八叉树节点 +- **方法**: + - `enableModelCollisionDetection()`: 启用/禁用模型间碰撞检测 + - `detectModelCollisions()`: 检测模型间碰撞 + - `_checkModelPairCollision()`: 检查两个模型是否碰撞 + - `_findCollisionNode()`: 查找模型的碰撞节点 + - `_logCollisionInfo()`: 输出碰撞信息日志 + - `getCollisionHistory()`: 获取碰撞历史记录 + - `clearCollisionHistory()`: 清除碰撞历史记录 + - `getCollisionStatistics()`: 获取碰撞统计信息 + - `createCollisionShape()`: 为模型创建指定类型的碰撞体 + - `_determineOptimalShape()`: 根据模型特征自动确定最适合的碰撞体形状 + - `_getTransformedModelInfo()`: 获取考虑变换后的模型信息 + - `createMouseRay()`: 创建鼠标射线 + - `performRaycast()`: 执行射线检测 + - `getCollisionMask()`: 获取碰撞掩码 + - `createCollisionGroup()`: 创建碰撞分组 + - `addToCollisionGroup()`: 将模型添加到碰撞分组 + - `enableCollisionGroup()`: 启用/禁用碰撞分组 + - `registerCollisionCallback()`: 注册碰撞回调函数 + - `_executeCollisionCallbacks()`: 执行碰撞回调 + - `_getModelMaskType()`: 获取模型的掩码类型 + - `enableSpatialPartitioning()`: 启用空间分割优化 + - `_buildOctree()`: 构建八叉树 + - `detectModelCollisionsOptimized()`: 使用空间分割优化的碰撞检测 + - `cleanup()`: 清理碰撞管理器资源 + - `setupAdvancedCollision()`: 高级碰撞设置方法 + - `example_usage()`: 碰撞系统使用示例 + - `recordDetection()`: 记录射线检测性能 + - `recordModelCollisionDetection()`: 记录模型间碰撞检测性能 + - `getAverageTime()`: 获取平均射线检测时间 + - `getAverageModelCollisionTime()`: 获取平均模型间碰撞检测时间 + - `getPerformanceReport()`: 获取完整性能报告 + - `insert()`: 插入模型到八叉树 + - `query()`: 查询可能与指定模型碰撞的模型列表 + - `_contains()`: 检查模型是否在此节点范围内 + - `_subdivide()`: 分割节点为8个子节点 + +### 10. `core/event_handler.py` +- **功能**: 事件处理器模块,处理用户输入事件和系统事件 +- **类**: + - `EventHandler`: 事件处理器类 +- **方法**: + - `showClickRay()`: 显示鼠标点击的射线 + - `_addHitMarker()`: 在碰撞点添加标记 + - `clearRay()`: 清除当前显示的射线 + - `clearRayTask()`: 清除射线的任务回调 + - `toggleRayDisplay()`: 切换射线显示状态 + - `mousePressEventLeft()`: 鼠标左键按下事件 + - `mousePressEventRight()`: 鼠标右键按下事件 + - `_handleTerrainEdit()`: 处理地形编辑 + - `_handleSelectionClick()`: 处理选择工具的点击事件 + - `mouseReleaseEventLeft()`: 鼠标左键释放事件 + - `wheelForward()`: 处理滚轮向前滚动(前进) + - `wheelBackward()`: 处理滚轮向后滚动(后退) + - `mousePressEventMiddle()`: 处理鼠标中键按下事件 + - `mouseReleaseEventMiddle()`: 处理鼠标中键释放事件 + - `mouseMoveEvent()`: 处理鼠标移动事件 + +### 11. `core/Command_System.py` +- **功能**: 命令系统模块,实现命令模式,支持撤销/重做功能 +- **类**: + - `Command`: 命令基类 + - `CommandManager`: 命令管理器类 + - `MoveNodeCommand`: 节点移动命令类 + - `DeleteNodeCommand`: 节点删除命令类 + - `RotateNodeCommand`: 节点旋转命令类 + - `ScaleNodeCommand`: 节点缩放命令类 + - `CreateNodeCommand`: 节点创建命令类 + - `ReparentNodeCommand`: 节点重新父化命令类 + - `CompositeCommand`: 组合命令类 + - `MoveLightCommand`: 灯光移动命令类 +- **方法**: + - `execute()`: 执行命令 + - `undo()`: 撤销命令 + - `redo()`: 重做命令 + - `execute_command()`: 执行命令 + - `can_undo()`: 检查是否可以撤销 + - `can_redo()`: 检查是否可以重做 + - `clear_history()`: 清空所有历史记录 + - `get_undo_count()`: 获取可撤销的命令数量 + - `get_redo_count()`: 获取可重做的命令数量 + +### 12. `core/InfoPanelManager.py` +- **功能**: 信息面板管理器模块,管理场景中信息面板的显示和更新 +- **类**: + - `InfoPanelManager`: 信息面板管理器类 +- **方法**: + - `createInfoPanel()`: 创建信息面板 + - `setPanelBackgroundImage()`: 为指定面板设置背景图片 + - `_getPanelContent()`: 根据面板ID获取固定的标题和内容 + - `updatePanelContent()`: 更新面板内容 + - `registerDataSource()`: 注册数据源,定期更新面板内容 + - `_updateDataThread()`: 数据更新线程 + - `_is3DPanel()`: 判断面板是否为3D面板 + - `_is2DPanel()`: 判断面板是否为2D面板 + - `unregisterDataSource()`: 注销数据源 + - `updatePanelProperties()`: 更新面板属性 + - `showPanel()`: 显示指定面板 + - `hidePanel()`: 隐藏指定面板 + - `togglePanel()`: 切换面板显示/隐藏状态 + - `getPanelNode()`: 获取面板的节点 + - `removePanel()`: 移除指定面板 + - `removeAllPanels()`: 移除所有面板 + - `createHTTPInfoPanel()`: 创建HTTP信息面板 + - `updateHTTPInfoPanel()`: 更新HTTP信息面板的请求参数 + - `create3DInfoPanel()`: 创建简化版3D信息面板 + - `update3DPanelContent()`: 更新3D面板内容 + - `update3DPanelProperties()`: 更新3D面板属性 + - `create3DHTTPInfoPanel()`: 创建3D HTTP信息面板 + - `serializePanelData()`: 序列化面板数据用于保存 + - `getAllPanelData()`: 获取所有面板的序列化数据 + - `recreatePanelFromData()`: 从序列化数据重新创建面板 + - `onCreateSampleInfoPanel()`: 创建示例天气信息面板 + - `getRealWeatherData()`: 获取真实天气数据 + - 其他信息面板管理方法 + +### 13. `core/patrol_system.py` +- **功能**: 巡检系统模块,实现自动化巡检路径和逻辑 +- **类**: + - `PatrolSystem`: 巡检系统类 +- **方法**: + - `add_patrol_point()`: 添加巡检点 + - `add_auto_heading_patrol_point()`: 添加自动计算朝向的巡检点 + - `add_patrol_point_looking_at()`: 添加朝向指定位置的巡检点 + - `clear_patrol_points()`: 清空巡检点 + - `set_patrol_speed()`: 设置巡检速度 + - `start_patrol()`: 开始巡检 + - `stop_patrol()`: 停止巡检 + - `pause_patrol()`: 暂停巡检 + - `resume_patrol()`: 恢复巡检 + - `reset_to_original_position()`: 重置相机到原始位置 + - `_patrol_task()`: 巡检主任务 + - `_handle_moving_state()`: 处理移动状态 + - `_handle_turning_to_target_state()`: 处理转向目标状态 + - `_handle_waiting_state()`: 处理等待状态 + - `_handle_turning_back_state()`: 处理转回原朝向状态 + - `_normalize_angle()`: 规范化角度到-180到180度之间 + - `_look_at_to_hpr()`: 将方向向量转换为HPR角度 + - `get_patrol_status()`: 获取巡检状态信息 + - `list_patrol_points()`: 列出所有巡检点 + - `remove_patrol_point()`: 移除指定索引的巡检点 + - `insert_patrol_point()`: 在指定位置插入巡检点 + - `update_patrol_point()`: 更新指定巡检点的信息 + - `goto_patrol_point()`: 直接跳转到指定巡检点 + - `cleanup()`: 清理巡检系统资源 + +### 14. `core/assembly_interaction.py` +- **功能**: 装配交互模块,处理复杂装配体的交互逻辑 +- **类**: + - `AssemblyInteractionManager`: 装配交互管理器类 + - `StepGuideDialog`: 步骤指引对话框类 +- **方法**: + - `init_exam_mode()`: 初始化考核模式 + - `play_step_audio()`: 播放步骤音频 + - `play_audio_with_pygame()`: 使用pygame播放音频 + - `play_audio_fallback()`: 备用音频播放方法 + - `set_operation_enabled()`: 设置操作是否启用 + - `check_operation_permission()`: 检查操作权限 + - `check_tool_match()`: 检查工具是否匹配 + - `record_tool_error()`: 记录工具错误 + - `start_interaction_mode()`: 启动交互模式 + - `load_configuration()`: 加载配置文件 + - `load_original_positions_from_config()`: 从配置文件中加载模型的原始位置信息 + - `check_step_completeness()`: 检查配置文件的步骤完整性 + - `setup_picking()`: 设置用于鼠标拾取的碰撞检测系统 + - `show_step_dialog()`: 显示步骤指引对话框 + - `start_current_step()`: 开始当前步骤 + - `prepare_interaction()`: 准备交互 + - `find_model_node()`: 在场景中查找指定名称的模型节点 + - `list_scene_models()`: 列出场景中的所有模型 + - `show_models_status()`: 显示所有模型的当前状态 + - `record_current_positions()`: 将当前所有模型的位置记录为原始位置 + - `normalize_step_type()`: 标准化步骤类型 + - `normalize_operation_type()`: 标准化操作类型 + - `analyze_final_state()`: 分析最终状态 + - `qt_mouse_press_event()`: Qt鼠标按下事件处理 + - `is_click_in_gui_area()`: 检查鼠标点击是否在GUI区域 + - `handle_gui_button_click()`: 直接处理GUI按钮点击 + - `qt_mouse_release_event()`: Qt鼠标释放事件处理 + - `handle_qt_mouse_click()`: 处理Qt鼠标点击 + - `perform_ray_cast()`: 执行射线检测 + - `is_target_model_hit()`: 检查击中的节点是否是目标模型 + - `on_mouse_down()`: 鼠标按下事件 + - `start_dragging()`: 开始拖拽模型 + - `drag_task()`: 拖拽任务 + - `stop_dragging()`: 停止拖拽 + - `on_mouse_up()`: 鼠标抬起事件 + - `check_step_completion()`: 检查步骤是否完成 + - `complete_current_step()`: 完成当前步骤 + - `finish_interaction()`: 完成所有交互 + - `stop_interaction()`: 用户主动停止交互 + - `show_exam_results()`: 显示考核结果 + - `save_exam_results()`: 保存考核结果到文件 + - `stop_interaction_mode()`: 停止交互模式 + - `trigger_drag_by_keyboard()`: 通过键盘触发拖拽 + - `trigger_click_movement()`: 触发点击位移动画 + - `perform_disassemble_click_movement()`: 执行拆卸点击位移 + - `perform_assemble_click_movement()`: 执行安装点击位移 + +### 15. `core/CustomMouseController.py` +- **功能**: 自定义鼠标控制器模块,提供定制化的鼠标操作控制 +- **类**: + - `CustomMouseController`: 自定义鼠标控制器类 +- **方法**: + - `__init__()`: 初始化鼠标控制器 + - `setUp()`: 设置控制器参数 + - `setKey()`: 设置按键状态 + - `move()`: 处理相机移动和旋转 + +### 16. `core/maintenance_gui.py` +- **功能**: 维护GUI模块,提供设备维护相关的GUI界面 +- **类**: + - `MaintenanceGUI`: 维护GUI管理器类 +- **方法**: + - `__init__()`: 初始化维护GUI + - `setup_gui()`: 设置GUI界面 + - `start_mouse_monitor()`: 启动鼠标监控任务 + - `test_mouse_monitor()`: 测试鼠标监控功能 + - `monitor_mouse_clicks()`: 监控鼠标点击并手动检测按钮 + - `check_button_click()`: 检查鼠标点击是否在按钮区域 + - `handle_mouse_click()`: 直接处理鼠标点击 + - `get_aspect2d_reference()`: 获取aspect2d引用 + - `create_step_text()`: 创建步骤显示文本 + - `create_tool_buttons()`: 创建工具选择按钮 + - `create_current_tool_text()`: 创建当前工具显示文本 + - `create_stop_button()`: 创建停止按钮 + - `create_warning_text()`: 创建警告文本 + - `button_press_handler()`: 按钮按下事件处理 + - `button_release_handler()`: 按钮释放事件处理 + - `on_tool_selected()`: 工具选择回调 + - `on_stop_clicked()`: 停止按钮点击回调 + - `update_tool_button_styles()`: 更新工具按钮样式 + - `update_step_info()`: 更新步骤信息 + - `show_warning()`: 显示警告信息 + - `hide_warning()`: 隐藏警告信息 + - `test_tool_selection()`: 测试工具选择功能 + - `test_specific_button()`: 测试特定按钮 + - `print_button_positions()`: 打印所有按钮的位置信息 + - `show_exam_results()`: 显示考核结果 + - `create_exam_result_gui()`: 创建考核结果GUI界面 + - `close_exam_results()`: 关闭考核结果界面 + - `start_countdown_timer()`: 启动10秒倒计时 + - `update_countdown()`: 更新倒计时显示 + - `get_current_tool()`: 获取当前选择的工具 + - `set_mode()`: 设置模式 + - `cleanup_gui()`: 清理GUI元素 + - `show_gui()`: 显示GUI + - `hide_gui()`: 隐藏GUI + +## 2.1.2 VR子模块 + +### 1. VR配置管理 (core/vr/config/) + +**文件**: vr_config.py +- **功能**: VR基础配置管理,负责VR设置的保存、加载和管理 +- **类**: VRConfigManager + - `__init__(self, config_dir=None)` - 初始化配置管理器 + - `load_config(self)` - 加载VR配置 + - `save_config(self, config)` - 保存VR配置 + - `get_render_mode(self)` - 获取渲染模式配置 + - `set_render_mode(self, mode)` - 设置渲染模式并保存 + - `get_resolution_scale(self)` - 获取分辨率缩放配置 + - `set_resolution_scale(self, scale)` - 设置分辨率缩放并保存 + - `get_quality_preset(self)` - 获取质量预设 + - `set_quality_preset(self, preset)` - 设置质量预设并保存 + - `get_pipeline_config(self)` - 获取RenderPipeline VR配置 + - `update_pipeline_config(self, pipeline_config)` - 更新RenderPipeline VR配置 + - `reset_to_defaults(self)` - 重置为默认配置 + - `apply_config_to_vr_manager(self, vr_manager)` - 将配置应用到VR管理器 + - `save_from_vr_manager(self, vr_manager)` - 从VR管理器保存当前配置 + +**文件**: joystick_config.py +- **功能**: VR摇杆配置管理,提供摇杆交互的配置选项和预设 +- **枚举**: TurnMode + - SMOOTH - 平滑转向 + - SNAP - 分段转向 +- **枚举**: JoystickProfile + - COMFORTABLE - 舒适模式 + - STANDARD - 标准模式 + - GAMING - 游戏模式 + - ACCESSIBLE - 无障碍模式 +- **类**: VRJoystickConfig + - `__init__(self)` - 初始化默认配置 + - `apply_profile(self, profile)` - 应用预设配置 + - `_apply_comfortable_profile(self)` - 舒适模式配置 + - `_apply_standard_profile(self)` - 标准模式配置 + - `_apply_gaming_profile(self)` - 游戏模式配置 + - `_apply_accessible_profile(self)` - 无障碍模式配置 + - `set_turn_mode(self, mode)` - 设置转向模式 + - `set_turn_sensitivity(self, sensitivity)` - 设置转向灵敏度 + - `set_deadzone(self, deadzone)` - 设置摇杆死区 + - `set_teleport_range(self, range_meters)` - 设置传送范围 + - `set_player_height(self, height_meters)` - 设置玩家站立高度偏移 + - `enable_haptic_feedback(self, enabled)` - 启用或禁用震动反馈 + - `get_config_dict(self)` - 获取配置字典 + - `apply_to_joystick_manager(self, joystick_manager)` - 将配置应用到摇杆管理器 +- **变量**: COMFORTABLE_CONFIG - 舒适模式预设配置实例 +- **变量**: STANDARD_CONFIG - 标准模式预设配置实例 +- **变量**: GAMING_CONFIG - 游戏模式预设配置实例 +- **变量**: ACCESSIBLE_CONFIG - 无障碍模式预设配置实例 +- **函数**: create_custom_config(**kwargs) - 创建自定义配置 +- **函数**: print_usage_guide() - 打印使用指南 + +**文件**: shadow_stage.py +- **功能**: VR专用阴影Stage,为VR渲染管线提供阴影支持 +- **类**: VRShadowStage + - `__init__(self, name, pipeline, use_shared_atlas=True)` - 初始化VR阴影Stage + - `create(self, width, height)` - 创建阴影Stage + - `_create_shared_shadow_atlas(self)` - 复用主Pipeline的ShadowAtlas + - `_create_independent_shadow_atlas(self, width, height)` - 为VR创建独立的ShadowAtlas + - `_make_pcf_state(self)` - 创建PCF采样器状态 + - `get_shadow_atlas_tex(self)` - 获取阴影Atlas纹理 + - `get_shadow_atlas_pcf(self)` - 获取带PCF的阴影Atlas + - `bind_to_stage(self, target_stage)` - 将阴影数据绑定到目标stage + - `cleanup(self)` - 清理资源 + +**文件**: __init__.py +- **功能**: VR配置子系统初始化文件 +- **变量**: __all__ - 导出模块列表 + +### 2. VR交互系统 (core/vr/interaction/) + +**文件**: actions.py +- **类**: VRActionManager + - `__init__(self, vr_manager)` - 初始化VR动作管理器 + - `initialize(self)` - 初始化VR动作系统 + - `_create_action_manifest(self)` - 创建VR动作清单文件 + - `_create_default_bindings(self, manifest_dir)` - 创建默认的控制器绑定文件 + - `_load_action_handles(self)` - 加载动作句柄 + - `_setup_action_sets(self)` - 设置动作集 + - `update_actions(self)` - 更新动作状态 + - `is_digital_action_pressed(self, action_name, device_path=None)` - 检查数字动作是否被按下 + - `is_digital_action_just_pressed(self, action_name, device_path=None)` - 检查数字动作是否刚刚被按下 + - `is_digital_action_just_released(self, action_name, device_path=None)` - 检查数字动作是否刚刚被释放 + - `get_analog_action_value(self, action_name, device_path=None)` - 获取模拟动作值 + - `get_pose_action_data(self, action_name, device_path=None)` - 获取姿态动作数据 + - `trigger_haptic_pulse(self, action_name, duration=0.001, frequency=1.0, amplitude=1.0, device_path=None)` - 触发震动反馈 + - `cleanup(self)` - 清理资源 + +**文件**: grab.py +- **类**: VRInteractionManager + - `__init__(self, vr_manager)` - 初始化VR交互管理器 + - `initialize(self)` - 初始化交互系统 + - `_create_ray_casters(self)` - 创建射线投射节点 + - `_create_controller_ray(self, controller_name, anchor_node)` - 为控制器创建射线投射节点 + - `_setup_collision_detection(self)` - 设置碰撞检测系统 + - `_setup_scene_collision_objects(self)` - 为场景对象设置碰撞体 + - `_add_collision_to_object(self, node_path)` - 为对象添加碰撞体 + - `update(self)` - 更新交互系统 + - `_perform_collision_detection(self)` - 执行碰撞检测 + - `_update_selections(self)` - 更新对象选择状态 + - `_get_closest_hit_object(self, controller_name)` - 获取指定控制器射线最近的碰撞对象 + - `_update_grabbing(self)` - 更新对象抓取状态 + - `_start_grab(self, controller, obj)` - 开始抓取对象 + - `_update_grabbed_object(self, controller)` - 更新被抓取对象的位置 + - `_release_grab(self, controller)` - 释放抓取的对象 + - `_highlight_object(self, obj, color)` - 高亮显示对象 + - `_restore_object_color(self, obj)` - 恢复对象原始颜色 + - `_clear_selection_highlights(self)` - 清除所有选择高亮 + - `get_selected_object(self, controller_name)` - 获取指定控制器选中的对象 + - `get_grabbed_object(self, controller_name)` - 获取指定控制器抓取的对象 + - `is_grabbing(self, controller_name)` - 检查指定控制器是否正在抓取对象 + - `force_release_all(self)` - 强制释放所有抓取的对象 + - `cleanup(self)` - 清理资源 + +**文件**: joystick.py +- **类**: JoystickState + - `__init__(self)` - 初始化摇杆状态 + - `update(self, new_input)` - 更新摇杆状态 + - `is_input_changed(self, threshold=0.01)` - 检查输入是否发生变化 +- **类**: VRJoystickManager + - `__init__(self, vr_manager)` - 初始化VR摇杆管理器 + - `initialize(self, teleport_system)` - 初始化摇杆系统 + - `update(self, dt)` - 更新摇杆系统 + - `_update_controller_joystick(self, controller, joystick_state, hand, dt)` - 更新单个控制器的摇杆状态 + - `_update_interaction_modes(self, dt)` - 更新互斥交互模式状态 + - `_set_controller_mode(self, hand, mode)` - 设置控制器交互模式 + - `_can_use_mode(self, hand, requested_mode)` - 检查是否可以使用指定的交互模式 + - `_get_joystick_input(self, controller, hand)` - 获取摇杆输入 + - `_apply_deadzone(self, input_vec)` - 应用摇杆死区 + - `_handle_turning(self, input_vec, hand, dt)` - 处理摇杆转向 + - `_apply_rotation(self, angle_degrees)` - 应用旋转到VR跟踪空间 + - `_handle_teleport(self, controller, input_vec, joystick_state, hand)` - 处理摇杆传送 + - `_calculate_teleport_direction(self, controller, input_vec)` - 计算传送方向向量 + - `_execute_teleport(self, controller)` - 执行传送 + - `set_turning_mode(self, smooth=True)` - 设置转向模式 + - `set_turn_sensitivity(self, sensitivity)` - 设置转向灵敏度 + - `apply_config(self, config)` - 应用配置 + - `get_current_config(self)` - 获取当前配置 + - `_print_debug_status(self)` - 打印调试状态信息 + - `cleanup(self)` - 清理摇杆系统资源 + +**文件**: teleport.py +- **类**: VRTeleportSystem + - `__init__(self, vr_manager)` - 初始化VR传送系统 + - `initialize(self)` - 初始化传送系统 + - `_create_teleport_visuals(self)` - 创建传送可视化元素 + - `_create_target_marker(self)` - 创建传送目标标记 + - `_create_invalid_marker(self)` - 创建无效位置标记 + - `_setup_ground_detection(self)` - 设置地面检测 + - `start_teleport_preview(self, controller, direction)` - 开始传送预览 + - `_calculate_teleport_trajectory(self, start_pos, direction)` - 计算传送抛物线轨迹 + - `_calculate_ground_intersection(self, p1, p2)` - 计算与地面的精确交点 + - `_create_arc_geometry(self, points)` - 创建抛物线几何体 + - `_show_teleport_visuals(self)` - 显示传送可视化 + - `stop_teleport_preview(self)` - 停止传送预览 + - `execute_teleport(self)` - 执行传送 + - `update_teleport_preview(self, controller, direction)` - 更新传送预览 + - `cleanup(self)` - 清理传送系统资源 + +### 3. VR性能优化 (core/vr/performance/) + +**文件**: monitoring.py +- **类**: VRPerformanceMonitor + - `__init__(self, vr_manager)` - 初始化性能监控系统 + - `_init_performance_monitoring(self)` - 初始化性能监控库 + - `_update_performance_metrics(self)` - 更新系统性能指标 + - `_update_gpu_metrics(self)` - 更新GPU相关指标 + - `_track_frame_time(self)` - 记录帧时间 + - `_get_gpu_frame_timing(self, frames_ago=0)` - 获取GPU渲染时间统计 + - `enable_gpu_timing_monitoring(self)` - 启用GPU时间监控 + - `disable_gpu_timing_monitoring(self)` - 禁用GPU时间监控 + - `_start_timing(self, operation_name)` - 开始计时操作 + - `_end_timing(self, timing_data)` - 结束计时并记录结果 + - `_get_pipeline_stats(self)` - 获取渲染管线统计信息 + - `test_pipeline_monitoring(self)` - 测试管线监控功能 + - `set_prediction_time(self, prediction_time_ms)` - 设置预测时间 + - `_print_render_callback_diagnostics(self)` - 输出渲染回调诊断信息 + - `_check_rendering_optimizations(self)` - 检查渲染优化状态 + - `_diagnose_opengl_state(self)` - 诊断OpenGL渲染状态 + - `enable_debug_output(self)` - 启用调试输出 + - `disable_debug_output(self)` - 禁用调试输出 + - `set_debug_mode(self, mode)` - 设置调试模式 + - `toggle_debug_output(self)` - 切换调试输出状态 + - `get_debug_status(self)` - 获取调试状态 + - `set_performance_check_interval(self, interval)` - 设置性能检查间隔 + - `set_frame_time_history_size(self, size)` - 设置帧时间历史记录大小 + - `set_performance_report_interval(self, frames)` - 设置性能报告输出间隔 + - `get_performance_stats(self)` - 获取详细的性能统计信息 + - `get_current_performance_summary(self)` - 获取当前性能摘要 + - `get_performance_monitoring_config(self)` - 获取当前性能监控配置 + - `print_performance_monitoring_status(self)` - 输出性能监控状态 + - `enable_performance_monitoring(self)` - 启用性能监控 + - `disable_performance_monitoring(self)` - 禁用性能监控 + - `force_performance_report(self)` - 强制输出一次性能报告 + - `reset_performance_counters(self)` - 重置性能计数器 + +**文件**: optimization.py +- **类**: VROptimization + - `__init__(self, vr_manager)` - 初始化VR优化系统 + - `_initialize_object_pools(self)` - 初始化对象池 + - `_get_pooled_matrix(self)` - 从对象池获取Mat4对象 + - `_return_pooled_matrix(self, matrix)` - 将Mat4对象返回对象池 + - `_manual_gc_control(self)` - 手动垃圾回收控制 + - `enable_gc_control(self)` - 启用垃圾回收控制 + - `disable_gc_control(self)` - 禁用垃圾回收控制 + - `set_manual_gc_interval(self, frames)` - 设置手动垃圾回收间隔 + - `force_manual_gc(self)` - 强制执行一次垃圾回收 + - `get_object_pool_status(self)` - 获取对象池状态 + - `set_resolution_scale(self, scale)` - 设置VR分辨率缩放系数 + - `set_quality_preset(self, preset_name)` - 设置VR质量预设 + - `cycle_quality_preset(self)` - 循环切换质量预设 + - `_apply_resolution_scale(self)` - 应用分辨率缩放,重新创建VR缓冲区 + - `get_resolution_info(self)` - 获取分辨率相关信息 + - `print_resolution_info(self)` - 输出分辨率信息 + - `enable_performance_mode(self)` - 手动启用性能模式 + - `disable_performance_mode(self)` - 禁用性能模式 + - `set_performance_mode_trigger_frame(self, frame_count)` - 设置性能模式自动触发的帧数 + - `get_performance_mode_status(self)` - 获取性能模式状态 + +### 4. VR渲染系统 (core/vr/rendering/) + +**文件**: stages.py +- **函数**: _load_rp_shader(shader_name) - 加载RenderPipeline shader +- **类**: VRGBufferStage + - `__init__(self, name, pipeline)` - 初始化VR GBuffer Stage + - `create(self, width, height, vr_camera)` - 创建GBuffer渲染目标 + - `get_gbuffer_textures(self)` - 获取GBuffer纹理字典 + - `make_gbuffer_ubo(self)` - 创建GBuffer UBO + - `get_internal_buffer(self)` - 获取内部GraphicsOutput + - `cleanup(self)` - 清理资源 +- **类**: VRLightingStage + - `__init__(self, name, pipeline)` - 初始化VR光照Stage + - `create(self, width, height, gbuffer_stage)` - 创建光照渲染目标 + - `_bind_pipeline_inputs(self)` - 从主Pipeline获取光照相关shader inputs + - `_bind_pipeline_pipes(self)` - 从主Pipeline获取光照相关pipes + - `_set_vr_scene_data(self)` - 创建VR专用的MainSceneData UBO + - `get_shaded_texture(self)` - 获取光照计算后的纹理 + - `cleanup(self)` - 清理资源 +- **类**: VRAmbientStage + - `__init__(self, name, pipeline)` - 初始化VR环境光Stage + - `create(self, width, height, lighting_stage, gbuffer_stage)` - 创建环境光渲染目标 + - `_bind_environment_inputs(self)` - 从主Pipeline获取环境相关shader inputs + - `_set_vr_scene_data(self)` - 创建VR专用的MainSceneData UBO + - `get_ambient_scene_texture(self)` - 获取带环境光的场景纹理 + - `cleanup(self)` - 清理资源 +- **类**: VRFinalStage + - `__init__(self, name, pipeline)` - 初始化VR最终合成Stage + - `create(self, width, height, ambient_stage)` - 创建最终合成目标 + - `_set_vr_scene_data(self)` - 创建VR专用的MainSceneData UBO + - `get_final_texture(self)` - 获取最终输出纹理 + - `get_internal_buffer(self)` - 获取内部GraphicsOutput + - `cleanup(self)` - 清理资源 +- **类**: VRPipelineController + - `__init__(self, pipeline)` - 初始化VR Pipeline控制器 + - `create_eye_pipeline(self, eye_name, width, height, vr_camera)` - 为单个眼睛创建完整的渲染管线 + - `create_stereo_pipeline(self, width, height, left_camera, right_camera)` - 创建立体渲染管线 + - `get_left_textures(self)` - 获取左眼的所有纹理 + - `get_right_textures(self)` - 获取右眼的所有纹理 + - `get_left_buffer(self)` - 获取左眼Final stage的内部buffer + - `get_right_buffer(self)` - 获取右眼Final stage的内部buffer + - `cleanup_left(self)` - 清理左眼资源 + - `cleanup_right(self)` - 清理右眼资源 + - `cleanup_all(self)` - 清理所有VR渲染资源 + +### 5. VR测试调试 (core/vr/testing/) + +**文件**: test_mode.py +- **类**: VRTestMode + - `__init__(self, vr_manager)` - 初始化VR测试模式系统 + - `enable_vr_test_mode(self, display_mode='stereo')` - 启用VR测试模式 + - `disable_vr_test_mode(self)` - 禁用VR测试模式 + - `switch_test_display_mode(self, display_mode)` - 切换测试显示模式 + - `_ensure_test_mode_textures(self)` - 确保VR测试模式的纹理资源已正确初始化 + - `_create_cached_ovr_textures(self)` - 创建缓存的OpenVR Texture对象 + - `_initialize_test_display(self)` - 初始化测试显示系统 + - `_update_test_display(self)` - 更新测试显示内容 + - `_create_stereo_display(self)` - 创建左右眼并排显示 + - `_cleanup_test_display(self)` - 清理测试显示 + - `_initialize_test_performance_hud(self)` - 初始化性能HUD + - `_update_test_performance_hud(self)` - 更新性能HUD显示 + - `_cleanup_test_performance_hud(self)` - 清理性能HUD + - `get_test_mode_status(self)` - 获取测试模式状态 + - `get_test_mode_features(self)` - 获取当前测试模式功能设置 + - `set_test_mode_features(self, submit_texture=None, wait_poses=None)` - 设置测试模式功能开关 + - `run_vr_performance_test(self, duration_seconds=30, display_mode='stereo')` - 运行VR性能测试 + +### 6. VR跟踪系统 (core/vr/tracking/) + +**文件**: controllers.py +- **类**: VRController + - `__init__(self, vr_manager, name, hand_path, device_index=None)` - 初始化VR手柄 + - `_create_anchor(self)` - 创建手柄锚点节点 + - `_create_visualizer(self)` - 创建手柄可视化器 + - `set_device_index(self, device_index)` - 设置OpenVR设备索引 + - `update_pose(self, pose_data)` - 更新手柄姿态 + - `update_input_state(self, vr_system)` - 更新输入状态 + - `is_button_pressed(self, button_id)` - 检查按钮是否被按下 + - `is_button_just_pressed(self, button_id)` - 检查按钮是否刚刚被按下 + - `is_button_just_released(self, button_id)` - 检查按钮是否刚刚被释放 + - `is_trigger_pressed(self, threshold=0.1)` - 检查扳机是否被按下 + - `is_grip_pressed(self, threshold=0.1)` - 检查握把是否被按下 + - `show_ray(self, show=True)` - 显示或隐藏交互射线 + - `set_ray_color(self, color)` - 设置射线颜色 + - `trigger_haptic_feedback(self, duration=0.001, strength=1.0)` - 触发震动反馈 + - `get_world_position(self)` - 获取手柄在世界坐标系中的位置 + - `get_world_rotation(self)` - 获取手柄在世界坐标系中的旋转 + - `get_forward_direction(self)` - 获取手柄指向的方向向量 + - `is_joystick_touched(self)` - 检查摇杆是否被触摸 + - `is_joystick_pressed(self)` - 检查摇杆是否被按下 + - `get_joystick_position(self)` - 获取摇杆位置 + - `get_joystick_delta(self)` - 获取摇杆位置变化 + - `is_joystick_moved(self, threshold=0.01)` - 检查摇杆是否移动 + - `_debug_axis_data(self, axis_data)` - 调试输出轴数据 + - `recreate_visualizer(self)` - 重新创建visualizer + - `cleanup(self)` - 清理资源 +- **类**: LeftController - 左手控制器 +- **类**: RightController - 右手控制器 + +### 7. VR可视化系统 (core/vr/visualization/) + +**文件**: controllers.py +- **类**: VRControllerVisualizer + - `__init__(self, controller, render_node)` - 初始化手柄可视化器 + - `_create_visual_components(self)` - 创建可视化组件 + - `_create_controller_model(self)` - 创建手柄3D模型 + - `_load_steamvr_model(self)` - 加载SteamVR官方手柄模型 + - `_fix_model_material(self, model)` - 修复模型材质 + - `_apply_controller_identity_marker(self, model)` - 为控制器添加身份标记 + - `_apply_steamvr_textures(self, model, base_path)` - 为SteamVR模型应用纹理 + - `_load_combined_steamvr_model(self, base_path)` - 尝试组合加载多个SteamVR模型部件 + - `_create_fallback_model(self)` - 创建改进的程序化手柄模型作为后备方案 + - `_create_box_geometry(self, width, length, height)` - 创建立方体几何体 + - `_create_disc_geometry(self, radius, thickness)` - 创建圆盘几何体 + - `_create_interaction_ray(self)` - 创建交互射线 + - `_create_sphere_geometry(self, radius)` - 创建球体几何体 + - `_create_button_indicators(self)` - 创建按钮状态指示器 + - `update(self)` - 更新可视化状态 + - `_update_button_indicators(self)` - 更新按钮指示器状态 + - `_update_ray_display(self)` - 更新射线显示 + - `show(self)` - 显示手柄可视化 + - `hide(self)` - 隐藏手柄可视化 + - `show_ray(self)` - 显示交互射线 + - `hide_ray(self)` - 隐藏交互射线 + - `set_ray_color(self, color)` - 设置射线颜色 + - `set_ray_length(self, length)` - 设置射线长度 + - `_apply_render_mode_settings(self, model_node)` - 根据当前渲染模式应用渲染设置 + - `_set_always_on_top(self, model_node)` - 设置手柄模型始终显示在上层 + - `cleanup(self)` - 清理资源 + +**文件**: effects.py +- **类**: VREffectsManager + - `__init__(self, pipeline)` - 初始化VR Effects Manager + - `apply_effects_to_scene(self, scene_root)` - 为场景根节点下的所有模型应用effects + - `apply_effect_to_model(self, model_node, effect_config=None)` - 为单个模型节点应用RenderPipeline effect + - `apply_effect_to_model_simple(self, model_node)` - 为模型应用简化版effect + - `_should_apply_effect(self, node)` - 判断是否应该为节点应用effect + - `apply_effects_to_new_models(self, model_list)` - 为新添加的模型列表批量应用effects + - `update_effect_config(self, new_config)` - 更新默认effect配置 + - `get_applied_models_count(self)` - 获取已应用effects的模型数量 + - `clear_applied_models_cache(self)` - 清空已应用模型的缓存 +- **函数**: setup_vr_model_effects(world, vr_root=None) - 便捷函数:为VR场景设置RenderPipeline Effects + +### 8. VR主管理器 (core/vr_manager.py) + +**枚举**: VRRenderMode +- NORMAL - 普通渲染模式 +- RENDER_PIPELINE - RenderPipeline高级渲染模式 + +**类**: VRManager +- `__init__(self, world)` - 初始化VR管理器 +- `convert_mat(self, mat)` - 将OpenVR矩阵转换为Panda3D矩阵 +- `is_vr_available(self)` - 检查VR系统是否可用 +- `initialize_vr(self)` - 初始化VR系统 +- `_create_vr_buffers(self)` - 创建VR渲染缓冲区 +- `_create_vr_texture(self, name)` - 创建VR纹理对象 +- `_prepare_and_cache_textures(self)` - 准备纹理并缓存OpenGL ID +- `_create_vr_buffer(self, name, texture, width, height)` - 创建VR渲染缓冲区 +- `_diagnose_buffer_performance(self, buffer, name, width, height)` - 诊断VR缓冲区性能特性 +- `_create_vr_buffers_with_pipeline(self)` - 创建带RenderPipeline的VR渲染缓冲区 +- `_apply_pipeline_vr_effects(self)` - 为VR场景应用RenderPipeline效果配置 +- `_check_skybox_status(self)` - 检查并报告天空盒状态 +- `_create_vr_skybox(self)` - 为VR创建天空盒 +- `_setup_vr_cameras(self)` - 设置VR相机 +- `_get_eye_offset(self, eye)` - 获取眼睛相对于头显的偏移 +- `_optimize_vr_rendering(self)` - 优化VR模式下的渲染管线 +- `_apply_lightweight_rendering(self, buffer, eye_name)` - 为VR缓冲区应用轻量级渲染设置 +- `_disable_vr_buffer_extras(self)` - 禁用VR缓冲区的额外功能以提升性能 +- `_start_vr_task(self)` - 启动VR更新任务 +- `_update_vr(self, task)` - VR更新任务 +- `_sync_gpu_if_needed(self)` - 可选的GPU同步 +- `simple_left_cb(self, cbdata)` - 简化的左眼渲染回调 +- `simple_right_cb(self, cbdata)` - 简化的右眼渲染回调 +- `_wait_get_poses(self)` - 调用VRCompositor的waitGetPoses来获取焦点和姿态数据 +- `_wait_get_poses_immediate(self)` - 立即获取VR姿态 +- `_wait_get_poses_with_prediction(self)` - 使用预测时间获取VR姿态 +- `_cache_poses_for_next_frame(self)` - 缓存当前姿态供下一帧渲染使用 +- `_reset_waitgetposes_flag(self, task)` - 重置WaitGetPoses标记 +- `_update_tracking_data(self)` - 更新VR追踪数据 +- `_convert_openvr_matrix_to_panda(self, ovr_matrix)` - 将OpenVR矩阵转换为Panda3D矩阵 +- `update_hmd(self, pose)` - 更新HMD锚点 +- `_update_camera_poses(self)` - 更新相机姿态 +- `_update_camera_poses_with_cache(self)` - 使用缓存姿态更新相机 +- `enable_vr(self)` - 启用VR模式 +- `disable_vr(self)` - 禁用VR模式 +- `set_vr_render_mode(self, mode)` - 切换VR渲染模式 +- `get_vr_render_mode(self)` - 获取当前VR渲染模式 +- `_cleanup_vr_buffers(self)` - 清理VR渲染缓冲区 +- `cleanup(self)` - 清理VR资源 +- `get_vr_status(self)` - 获取VR状态信息 +- `submit_texture(self, eye, texture)` - 优化的VR纹理提交 +- `_smart_gpu_sync(self)` - 智能GPU同步策略 +- `_disable_main_cam(self)` - 禁用主相机 +- `_enable_main_cam(self)` - 恢复主相机 +- `_initialize_controllers(self)` - 初始化VR手柄控制器 +- `_detect_controllers(self)` - 检测并连接VR控制器 +- `_create_tracked_device_anchor(self, device_index, name)` - 为跟踪设备创建锚点节点 +- `update_tracked_devices(self)` - 更新所有跟踪设备的姿态 +- `get_controller_by_role(self, role)` - 根据角色获取控制器 +- `are_controllers_connected(self)` - 检查是否有控制器连接 +- `get_connected_controllers(self)` - 获取所有连接的控制器列表 +- `trigger_controller_haptic(self, role, duration=0.001, strength=1.0)` - 触发控制器震动反馈 +- `is_trigger_pressed(self, hand='any')` - 检查扳机是否被按下 +- `is_trigger_just_pressed(self, hand='any')` - 检查扳机是否刚刚被按下 +- `is_grip_pressed(self, hand='any')` - 检查握把是否被按下 +- `is_grip_just_pressed(self, hand='any')` - 检查握把是否刚刚被按下 +- `is_menu_pressed(self, hand='any')` - 检查菜单按钮是否被按下 +- `is_trackpad_touched(self, hand='any')` - 检查触摸板是否被触摸 +- `get_trackpad_position(self, hand='any')` - 获取触摸板位置 +- `get_selected_object(self, hand='any')` - 获取指定手选中的对象 +- `get_grabbed_object(self, hand='any')` - 获取指定手抓取的对象 +- `is_grabbing_object(self, hand='any')` - 检查是否正在抓取对象 +- `force_release_all_grabs(self)` - 强制释放所有抓取的对象 +- `add_interactable_object(self, object_node)` - 将对象标记为可交互 +- `_disable_async_reprojection(self)` - 禁用异步重投影 +- `enable_async_reprojection_disable(self)` - 启用异步重投影禁用选项 +- `disable_async_reprojection_disable(self)` - 禁用异步重投影禁用选项 +- `_batch_submit_textures(self)` - 批量提交两眼纹理 + +## 2.2 gui模块 + +### 1. `gui/__init__.py` +- **功能**: GUI模块初始化文件,导出GUI管理器类 +- **类**: + - `GUIManager`: GUI管理器类 + +### 2. `gui/gui_manager.py` +- **功能**: GUI管理器模块,负责2D和3D GUI元素的创建和管理 +- **类**: + - `GUIManager`: GUI管理器类 +- **方法**: + - `__init__()`: 初始化GUI管理系统 + - `createGUIButton()`: 创建2D GUI按钮 + - `createGUILabel()`: 创建2D GUI标签 + - `createGUIEntry()`: 创建2D GUI文本输入框 + - `createGUI2DImage()`: 创建2D GUI图片 + - `constrain2DPosition()`: 限制2dGUI元素位置在屏幕范围内 + - `createGUI3DText()`: 创建3D空间文本 + - `createGUI3DImage()`: 创建3D空间图片 + - `createVideoScreen()`: 创建3D视频播放屏幕 + - `_ensureVideoScreenMaterial()`: 确保视频屏幕有正确的材质设置 + - `_debugVideoScreenTextures()`: 调试视频屏幕的纹理状态 + - `playVideo()`: 播放视频 + - `_getMovieTextureFromScreen()`: 从视频屏幕获取视频纹理 + - `pauseVideo()`: 暂停视频 + - `stopVideo()`: 停止视频 + - `setVideoTime()`: 设置视频播放时间 + - `loadVideoFile()`: 为视频屏幕加载新的视频文件 + - `_loadMovieTexture()`: 加载视频纹理的兼容方法 + - `_configureVideoTexture()`: 配置视频纹理属性 + - `createGUI2DVideoScreen()`: 创建2D视频播放屏幕 + - `load2DVideoFile()`: 为2D视频屏幕加载新的视频文件 + - `play2DVideo()`: 播放2D视频 + - `pause2DVideo()`: 暂停2D视频 + - `stop2DVideo()`: 停止2D视频 + - `createSphericalVideo()`: 创建球形视频(360度视频) + - `_createSphereGeometry()`: 创建球形几何体 + - `playSphericalVideo()`: 播放球形视频 + - `pauseSphericalVideo()`: 暂停球形视频 + - `setSphericalVideoTime()`: 设置球形视频播放时间 + - `createGUIVirtualScreen()`: 创建3D虚拟屏幕 + - `_create_screen_text()`: 为虚拟屏幕创建文本节点 + - `_get_tree_widget()`: 安全获取树形控件 + - `createGUISlider()`: 创建2D GUI滑块 + - `deleteGUIElement()`: 删除GUI元素 + - `editGUIElement()`: 编辑GUI元素属性 + - `_resizeButtonToText()`: 根据文本内容调整按钮大小 + - `duplicateGUIElement()`: 复制GUI元素 + - `editGUIElementDialog()`: 显示GUI元素编辑对话框 + - `onGUIButtonClick()`: GUI按钮点击事件处理 + - `onGUIEntrySubmit()`: GUI输入框提交事件处理 + - `toggleGUIEditMode()`: 切换GUI编辑模式 + - `enterGUIEditMode()`: 进入GUI编辑模式 + - `exitGUIEditMode()`: 退出GUI编辑模式 + - `createGUIEditPanel()`: 创建GUI编辑面板 + - `openGUIPreviewWindow()`: 打开独立的GUI预览窗口 + - `closeGUIPreviewWindow()`: 关闭GUI预览窗口 + - `setGUICreateTool()`: 设置GUI创建工具 + - `deleteSelectedGUI()`: 删除选中的GUI元素 + - `copySelectedGUI()`: 复制选中的GUI元素 + - `handleGUIEditClick()`: 处理GUI编辑模式下的点击 + - `createGUIAtPosition()`: 在指定位置创建GUI元素 + - `findClickedGUI()`: 查找被点击的GUI元素 + - `selectGUIInTree()`: 在树形控件中选中GUI元素 + - `updateGUISelection()`: 更新GUI元素选择状态 + - `updateGUIPropertyPanel()`: 更新GUI元素属性面板 + - `selectGUIColor()`: 选择GUI元素颜色 + - `update3DImageTexture()`: 更新3D图像纹理 + - `_preserveChildNodeTextures()`: 保护子节点的纹理不被父节点纹理影响 + - `_is3DTextElement()`: 检查节点是否为3D文本元素 + - `_isOtherSpecialElement()`: 检查节点是否为其他需要特殊处理的元素 + - `_restore3DTextTexture()`: 恢复3D文本的纹理设置 + - `update2DImageTexture()`: 更新2D图片纹理 + - `editGUI2DPosition()`: 编辑2D GUI元素位置并应用边界约束 + - `editGUI3DPosition()`: 编辑3D GUI元素位置 + - `editGUIScale()`: 编辑GUI元素缩放 + - `createCesiumView()`: 创建 Cesium 视图窗口(离线版本) + - `toggleCesiumView()`: 切换 Cesium 视图显示状态 + - `refreshCesiumView()`: 刷新 Cesium 视图 + - `updateCesiumURL()`: 更新 Cesium 视图的 URL + - `addModelToCesium()`: 向 Cesium 添加模型 + - `addCesiumTilesetToScene()`: 在 Panda3D 场景中添加 Cesium 3D Tiles + - `removeModelFromCesium()`: 从 Cesium 移除模型 + - `updateCesiumModelPosition()`: 更新 Cesium 中模型的位置 + - `getAllCesiumModels()`: 获取 Cesium 中所有模型的列表 + - `addLocalModelToCesium()`: 向 Cesium 添加本地模型文件 + +## 2.3 project模块 + +### 1. `project/__init__.py` +- **功能**: 项目管理模块初始化文件,导出项目管理器类和新建项目对话框 +- **类**: + - `ProjectManager`: 项目管理器类 + - `NewProjectDialog`: 新建项目对话框类 + +### 2. `project/project_manager.py` +- **功能**: 项目管理器模块,负责项目的生命周期管理,处理项目创建、打开、保存、打包等功能 +- **类**: + - `ProjectManager`: 项目管理器类 +- **方法**: + - `__init__()`: 初始化项目管理器 + - `createNewProject()`: 创建新项目 + - `openProject()`: 打开项目 + - `openProjectForPath()`: 通过路径打开项目 + - `saveProject()`: 保存项目 + - `buildPackage()`: 打包项目为可执行文件 + - `_createStandardBuildFiles()`: 创建标准的Panda3D打包文件 + - `_copyScriptsToBuild()`: 复制脚本文件到构建目录的scripts文件夹 + - `_copyScriptSystemToBuild()`: 复制脚本系统文件到构建目录 + - `_saveGUIElementsToJSON()`: 保存GUI元素到JSON文件 + - `_updateResourcePaths()`: 更新资源路径 + - `_createRequirementsFile()`: 创建requirements.txt文件 + - `copy_folder()`: 将一个文件夹从源路径复制到目标路径下的resources文件夹中 + - `_copyResourcesToBuild()`: 复制GUI资源到构建目录的resources文件夹 + - `_collectResourceFiles()`: 收集项目中GUI使用的资源文件 + - `_extractResourcesFromScene()`: 从场景文件中提取资源引用 + - `_isMediaFile()`: 判断是否为媒体文件(图片或视频) + - `_createAppFile()`: 创建应用程序主文件 + - `_createStandardSetupFile()`: 创建优化的标准setup.py文件 + - `_executeStandardBuild()`: 执行标准的Panda3D打包命令 + - `_tryBuildAppsThreaded()`: 尝试使用 build_apps 命令(线程安全版本) + - `_tryBuildApps()`: 尝试使用 build_apps 命令 + - `updateWindowTitle()`: 更新窗口标题 + - `_clearCurrentScene()`: 清空当前场景 + - `getCurrentProjectPath()`: 获取当前项目路径 + - `getCurrentProjectConfig()`: 获取当前项目配置 + - `isProjectOpen()`: 检查是否有项目打开 + - `getProjectName()`: 获取当前项目名称 + - `getProjectInfo()`: 获取项目信息 + +## 2.4 QPanda3D模块 + +### 1. `QPanda3D/__init__.py` +- **功能**: QPanda3D模块初始化文件,导出核心类 +- **类**: + - 无 +- **方法**: + - 无 +- **导出项**: + - `QPanda3DWidget`: QPanda3D部件类 + - `Panda3DWorld`: Panda3D世界类 + - `QPanda3D_Keys_Translation`: 键盘事件翻译类 + +### 2. `QPanda3D/Panda3DWorld.py` +- **功能**: Panda3D世界类,处理Panda3D环境设置和渲染管理 +- **类**: + - `Panda3DWorld`: Panda3D世界类,继承自ShowBase +- **方法**: + - `__init__(self, width=1380, height=750, is_fullscreen=False, size=1.0, clear_color=LVecBase4f(0, 0.5, 0, 1), name="qpanda3D")`: 初始化Panda3D世界 + - `_handle_transform_error(self)`: 处理TransformState相关的错误 + - `render_pipeline(self)`: 获取RenderPipeline实例 + - `set_parent(self, parent: QWidget)`: 设置父部件 + - `getAspectRatio(self, win = None)`: 获取宽高比 + - `resize_buffer(self, width: int, height: int)`: 根据新窗口尺寸调整Panda3D渲染输出尺寸 + +### 3. `QPanda3D/QPanda3DWidget.py` +- **功能**: QPanda3D部件类,作为Panda3D内容在Qt应用程序中的容器 +- **类**: + - `QPanda3DSynchronizer`: Panda3D同步器类,继承自QTimer + - `QPanda3DWidget`: QPanda3D部件类,继承自QWidget +- **方法**: + - `QPanda3DSynchronizer.__init__(self, qPanda3DWidget, FPS=60)`: 初始化同步器 + - `QPanda3DSynchronizer.tick(self)`: 同步器定时更新方法 + - `get_panda_key_modifiers(evt)`: 获取Panda3D按键修饰符 + - `get_panda_key_modifiers_prefix(evt)`: 获取Panda3D按键修饰符前缀 + - `QPanda3DWidget.__init__(self, panda3DWorld, parent=None, FPS=60, debug=False)`: 初始化QPanda3D部件 + - `QPanda3DWidget.mousePressEvent(self, evt)`: 鼠标按下事件处理 + - `QPanda3DWidget.mouseMoveEvent(self, evt:QtGui.QMouseEvent)`: 鼠标移动事件处理 + - `QPanda3DWidget.mouseReleaseEvent(self, evt)`: 鼠标释放事件处理 + - `QPanda3DWidget.wheelEvent(self, evt)`: 鼠标滚轮事件处理 + - `QPanda3DWidget.keyPressEvent(self, evt)`: 键盘按下事件处理 + - `QPanda3DWidget.keyReleaseEvent(self, evt)`: 键盘释放事件处理 + - `QPanda3DWidget.resizeEvent(self, evt)`: 窗口大小调整事件处理 + - `QPanda3DWidget.minimumSizeHint(self)`: 最小尺寸提示 + - `QPanda3DWidget.paintEvent(self, event)`: 绘制事件处理 + - `QPanda3DWidget.sync_panda3d_window_size(self, width, height)`: 同步Panda3D窗口尺寸到Qt窗口尺寸 + +### 4. `QPanda3D/QMouseWatcherNode.py` +- **功能**: 鼠标观察节点类,通过父级QWidget访问鼠标位置和按钮状态 +- **类**: + - `QMouseWatcherNode`: 鼠标观察节点类,继承自MouseWatcher +- **方法**: + - `__init__(self, parent)`: 初始化鼠标观察节点 + - `getMouse(self, *args, **kwargs)`: 获取鼠标位置 + - `hasMouse(self)`: 检查是否有鼠标 + +### 5. `QPanda3D/QPanda3D_Keys_Translation.py` +- **功能**: 键盘事件翻译字典,将Qt键盘事件翻译为Panda3D键盘事件 +- **类**: + - 无 +- **方法**: + - 无 +- **变量**: + - `QPanda3D_Key_translation`: Qt到Panda3D键盘事件的翻译字典 + +### 6. `QPanda3D/QPanda3D_Buttons_Translation.py` +- **功能**: 鼠标事件翻译字典,将Qt鼠标事件翻译为Panda3D鼠标事件 +- **类**: + - 无 +- **方法**: + - 无 +- **变量**: + - `QPanda3D_Button_translation`: Qt到Panda3D鼠标事件的翻译字典 + +### 7. `QPanda3D/QPanda3D_Modifiers_Translation.py` +- **功能**: 键盘修饰符翻译字典,将Qt键盘事件翻译为Panda3D键盘事件 +- **类**: + - 无 +- **方法**: + - 无 +- **变量**: + - `QPanda3D_Modifier_translation`: Qt到Panda3D键盘修饰符的翻译字典 + +### 8. `QPanda3D/Helpers/__init__.py` +- **功能**: QPanda3D辅助模块初始化文件,导出辅助类 +- **类**: + - 无 +- **方法**: + - 无 +- **导出项**: + - `Env_Grid_Maker`: 环境网格生成器类 + +### 9. `QPanda3D/Helpers/Env_Grid_Maker.py` +- **功能**: 环境网格生成器,创建3D网格实现以显示坐标轴 +- **类**: + - `Env_Grid_Maker`: 环境网格生成器类 +- **方法**: + - `__init__(self, XYPlaneShow = True, XZPlaneShow = False, YZPlaneShow = False, endCapLinesShow = True, XSize = 50, YSize = 50, ZSize = 50, gridStep = 10, subdiv = 10)`: 初始化环境网格生成器 + - `create(self)`: 创建网格 + - `myfrange(self, start, stop=None, step=None)`: 浮点数范围生成器 + +### 10. `QPanda3D/Tools/__init__.py` +- **功能**: QPanda3D工具模块初始化文件,导出工具类 +- **类**: + - 无 +- **方法**: + - 无 +- **导出项**: + - `generate_qt_to_pd3d_translator`: Qt到Panda3D翻译生成器 + +### 11. `QPanda3D/Tools/generate_qt_to_pd3d_translator.py` +- **功能**: 生成Qt到Panda3D事件翻译的工具脚本 +- **类**: + - 无 +- **方法**: + - 无 +- **变量**: + - `H`: Qt模块字典 + - `lst`: 以"Key_"开头的Qt键列表 + - `QPanda3D_Key_translation`: 生成的Qt到Panda3D键盘事件翻译字符串 + +## 2.5 scene模块 + +### 1. `scene/__init__.py` +- **功能**: scene模块初始化文件,导出场景管理器类 +- **类**: + - `SceneManager`: 场景管理器类 +- **方法**: + - 无 + +### 2. `scene/scene_manager.py` +- **功能**: 场景管理器模块,负责场景和模型管理的核心功能,处理模型导入、场景树构建、材质系统、碰撞设置等 +- **类**: + - `SceneManager`: 场景管理器类 + - `CesiumIntegration`: Cesium集成类 +- **方法**: + - `__init__(self, world)`: 初始化场景管理器 + - `importModel(self, filepath, apply_unit_conversion=False, normalize_scales=True, auto_convert_to_glb=True)`: 导入模型 + - `_fixModelStructure(self, model)`: 修复模型结构 + - `_validateAndFixAllTransforms(self, model)`: 验证并修复模型中所有节点的变换矩阵 + - `_validateAndFixTransform(self, node_path)`: 验证并修复单个节点的变换矩阵 + - `_applyModelScale(self, model, scale_factor)`: 应用模型特定缩放 + - `_applyMaterialsToModel(self, model)`: 递归应用材质到模型的所有GeomNode + - `_adjustModelToGround(self, model)`: 智能调整模型到地面,但保持原有缩放结构 + - `_normalizeModelScales(self, model)`: 智能标准化模型缩放层级 + - `_collectScaleInfo(self, node, scale_info, depth=0)`: 递归收集节点缩放信息 + - `_findCommonLargeScale(self, large_scales)`: 找到最常见的大缩放值 + - `_applyScaleNormalization(self, node, normalize_factor, depth=0)`: 安全地应用缩放标准化 + - `importModelAsync(self, filepath)`: 异步导入模型 + - `processMaterials(self, model)`: 处理模型材质 + - `processModelGeometry(self, model)`: 处理模型几何体 + - `setupCollision(self, model)`: 为模型设置碰撞检测(增强版本) + - `updateSceneTree(self)`: 更新场景树显示 - 代理到interface_manager + - `_collectGUIElementInfo(self, gui_node)`: 收集GUI元素的信息用于保存 + - `_get_script_file_path(self, script_class, script_name)`: 获取脚本文件路径的可靠方法 + - `saveScene(self, filename, project_path)`: 保存场景到BAM文件 - 完整版,支持GUI元素,地形 + - `take_screenshot(self, projectpath)`: 截图并保存到指定的完整路径 + - `loadScene(self, filename)`: 从BAM文件加载场景 + - `_rebuildParentChildRelationships(self, loaded_nodes)`: 重建父子关系 + - `_inferParentChildRelationships(self, loaded_nodes)`: 从场景结构推断父子关系 + - `_shouldSkipNodeInTree(self, nodePath)`: 判断节点是否应该在场景树中跳过显示 + - `_recreateGUIElementsFromData(self, gui_data)`: 根据保存的GUI数据重新创建GUI元素 + - `_findOrCreateQtTreeItem(self, tree_widget, target_element, element_name)`: 在Qt树中查找或创建指定元素对应的项 + - `_findQtTreeItem(self, tree_widget, target_element)`: 在Qt树中查找指定元素对应的项 + - `_find_script_in_directory(self, script_name)`: 在脚本目录中查找脚本文件 + - `_recreateSpotLight(self, light_node)`: 重新创建聚光灯 + - `_recreatePointLight(self, light_node)`: 重新创建点光源 + - `_cleanupAuxiliaryNodes(self)`: 清理场景中可能存在的辅助节点 + - `deleteModel(self, model)`: 删除模型 + - `clearAllModels(self)`: 清除所有模型 + - `getModels(self)`: 获取模型列表 + - `getModelCount(self)`: 获取模型数量 + - `findModelByName(self, name)`: 根据名称查找模型 + - `processLoadedModel(self, model)`: 处理加载完成的模型(用于异步加载回调) + - `createSpotLight(self, pos=(0, 0, 0))`: 创建聚光灯 - 支持多选创建,优化版本 + - `createPointLight(self, pos=(0, 0, 0))`: 创建点光源 - 支持多选创建,优化版本 + - `_get_tree_widget(self)`: 安全获取树形控件 + - `_shouldConvertToGLB(self, filepath)`: 判断是否应该转换为GLB格式 + - `_convertToGLBWithProgress(self, filepath)`: 带进度显示的GLB转换 + - `_convertToGLB(self, filepath, progress=None)`: 将模型文件转换为GLB格式 + - `_convertWithBlender(self, input_path, output_path, progress=None)`: 使用 Blender 进行转换 + - `_convertWithFBX2glTF(self, input_path, output_path, progress=None)`: 使用 FBX2glTF 进行转换(仅支持FBX) + - `_convertWithAssimp(self, input_path, output_path, progress=None)`: 使用 PyAssimp 进行转换 + - `load_cesium_tileset(self, tileset_url, position=(0, 0, 0))`: 加载 Cesium 3D Tileset - 采用新的创建逻辑,支持多选和更完善的UI交互 + - `_load_tileset_async(self, tileset_url, tileset_info)`: 异步加载 tileset 数据 + - `_check_async_task(self, panda3d_task)`: 检查 asyncio 任务是否完成 + - `_parse_tileset(self, tileset_data, tileset_info)`: 解析 tileset 数据 + - `_parse_tile(self, tile_data, parent_node, tileset_info)`: 解析 tile 数据 + - `_create_tile_geometry(self, parent_node)`: 为 tile 创建占位几何体 + - `_create_placeholder_geometry(self, parent_node)`: 创建一个简单的占位符几何体,让用户能看到节点 + - `serializeNode(self, node)`: 序列化节点为字典数据 + - `deserializeNode(self, node_data, parent_node)`: 从字典数据反序列化节点 + - `serializeNodeForCopy(self, node)`: 序列化节点用于复制操作,完整保存视觉属性 + - `_serializeGUIData(self, node)`: 序列化GUI元素数据 + - `_serializeModelData(self, node)`: 序列化模型数据,包括材质信息 + - `recreateNodeFromData(self, node_data, parent_node)`: 根据数据重建节点,并确保在场景树中显示 + - `_findTreeItemForNode(self, node)`: 根据节点查找对应的场景树项 + - `_findTreeItemForNodeRecursive(self, item, target_node)`: 递归查找场景树项 + - `_recreateLightFromData(self, node_data, parent_node, name)`: 根据数据重建光源 + - `_recreateTilesetFromData(self, node_data, parent_node, name)`: 根据数据重建Tileset + - `_recreateGUIFromData(self, node_data, parent_node, name)`: 根据数据重建GUI元素 + - `_recreateModelFromData(self, node_data, parent_node, name)`: 根据数据重建模型,保持材质 + - `_restoreModelMaterial(self, model, model_data)`: 恢复模型材质 + - `_createBasicNodeFromData(self, node_data, parent_node, name)`: 创建基本节点,保持视觉属性 + - `_generateUniqueName(self, base_name, parent_node)`: 生成唯一节点名称 + +### 3. `scene/util.py` +- **功能**: 跨平台路径处理工具,提供标准化模型文件路径的功能 +- **类**: + - `CrossPlatformPathHandler`: 跨平台路径处理器 +- **方法**: + - `__init__(self)`: 初始化路径处理器 + - `normalize_model_path(self, filepath)`: 标准化模型文件路径 + - `_check_file_exists(self, filepath)`: 检查文件是否存在 + - `_panda3d_normalize(self, filepath)`: 使用Panda3D标准化路径 + - `_attempt_path_fixes(self, filepath)`: 尝试各种路径修复方法 + - `_fix_path_separators(self, filepath)`: 修复路径分隔符 + - `_convert_to_relative_path(self, filepath)`: 转换绝对路径为相对路径 + - `_clean_special_characters(self, filepath)`: 清理路径中的特殊字符 + - `_smart_file_search(self, filepath)`: 智能文件搜索 + - `_search_in_common_directories(self, filename)`: 在常见目录中搜索 + - `_recursive_search(self, filename, max_depth=3)`: 递归搜索文件 + - `_search_user_directories(self, filename)`: 搜索用户常用目录 + - `_handle_path_not_found(self, filepath)`: 处理路径未找到的情况 + - `suggest_file_placement(self, filename)`: 建议文件放置位置 +- **函数**: + - `normalize_model_path(filepath)`: 便捷函数:标准化模型路径 + - `suggest_file_placement(filename)`: 便捷函数:建议文件放置位置 + +## 2.6 scripts模块 + +### 1. `scripts/a.py` +- **功能**: 自定义脚本示例 +- **类**: + - `A`: 自定义脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化脚本 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新 + - `on_destroy(self)`: 脚本销毁时调用 + +### 2. `scripts/BouncerScript.py` +- **功能**: 跳跃脚本,让对象产生上下跳跃效果 +- **类**: + - `BouncerScript`: 跳跃脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化脚本参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现跳跃效果 + - `set_bounce_parameters(self, height=None, speed=None, bounce_type=None)`: 设置跳跃参数 + - `toggle_bouncing(self)`: 切换跳跃状态 + - `reverse_direction(self)`: 反转跳跃方向 + - `reset_position(self)`: 重置到原始高度 + - `jump_once(self)`: 执行一次跳跃 + - `on_destroy(self)`: 脚本销毁时调用 + +### 3. `scripts/ColorChangerScript.py` +- **功能**: 颜色变化脚本,让对象颜色产生循环变化 +- **类**: + - `ColorChangerScript`: 颜色变化脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化颜色参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现颜色变化效果 + - `_calculate_rainbow_color(self)`: 计算彩虹颜色 + - `_calculate_pulse_color(self)`: 计算脉冲颜色 + - `_calculate_fade_color(self)`: 计算淡入淡出颜色 + - `_calculate_strobe_color(self)`: 计算闪烁颜色 + - `set_color_parameters(self, speed=None, mode=None, base_color=None, intensity=None)`: 设置颜色参数 + - `toggle_color_change(self)`: 切换颜色变化状态 + - `reset_color(self)`: 重置到原始颜色 + - `set_solid_color(self, r=1.0, g=1.0, b=1.0, a=1.0)`: 设置固定颜色 + - `on_destroy(self)`: 脚本销毁时调用 + +### 4. `scripts/ComboAnimatorScript.py` +- **功能**: 复合动画脚本,结合旋转和跳跃效果 +- **类**: + - `ComboAnimatorScript`: 复合动画脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化脚本 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现旋转和跳跃效果 + - `on_destroy(self)`: 脚本销毁时调用 + +### 5. `scripts/example_script.py` +- **功能**: 示例脚本,演示如何编写脚本 +- **类**: + - `ExampleScript`: 示例脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化脚本 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新 + - `on_destroy(self)`: 脚本销毁时调用 + - `on_enable(self)`: 脚本启用时调用 + - `on_disable(self)`: 脚本禁用时调用 + +### 6. `scripts/FollowerScript.py` +- **功能**: 跟随脚本,让对象跟随指定的目标对象 +- **类**: + - `FollowerScript`: 跟随脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化跟随参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现跟随效果 + - `set_target(self, target)`: 设置跟随目标 + - `on_destroy(self)`: 脚本销毁时调用 + +### 7. `scripts/MoverScript.py` +- **功能**: 移动脚本,让对象在指定方向上来回移动 +- **类**: + - `MoverScript`: 移动脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化移动参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现移动效果 + - `set_move_parameters(self, distance=None, speed=None, axis=None)`: 设置移动参数 + - `toggle_movement(self)`: 切换移动状态 + - `reset_position(self)`: 重置到起始位置 + - `on_destroy(self)`: 脚本销毁时调用 + +### 8. `scripts/R_P.py` +- **功能**: 旋转脚本,让对象持续旋转(围绕P轴) +- **类**: + - `RotatorScript`: 旋转脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化旋转参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现旋转效果 + - `set_max_angle(self, new_max_angle)`: 设置新的最大旋转角度 + - `set_rotation_speed(self, new_speed)`: 设置新的旋转速度 + - `pause_rotation(self)`: 暂停旋转 + - `resume_rotation(self)`: 恢复旋转 + - `reset_to_initial_angle(self)`: 重置到初始角度 + - `get_current_info(self)`: 获取当前旋转信息 + - `on_destroy(self)`: 脚本销毁时调用 + +### 9. `scripts/R_R.py` +- **功能**: 旋转脚本,让对象持续旋转(围绕R轴) +- **类**: + - `RotatorScript`: 旋转脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化旋转参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现旋转效果 + - `set_max_angle(self, new_max_angle)`: 设置新的最大旋转角度 + - `set_rotation_speed(self, new_speed)`: 设置新的旋转速度 + - `pause_rotation(self)`: 暂停旋转 + - `resume_rotation(self)`: 恢复旋转 + - `reset_to_initial_angle(self)`: 重置到初始角度 + - `get_current_info(self)`: 获取当前旋转信息 + - `on_destroy(self)`: 脚本销毁时调用 + +### 10. `scripts/Rotate_H_Script.py` +- **功能**: 机器人式旋转脚本,让对象围绕H轴旋转并带有停顿效果 +- **类**: + - `RotatorScript`: 旋转脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化旋转参数和机器人模式参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现机器人式旋转效果 + - `set_robot_mode(self, enabled=True)`: 启用或禁用机器人模式 + - `set_pause_duration(self, duration)`: 设置停顿时间 + - `set_max_angle(self, new_max_angle)`: 设置新的最大旋转角度 + - `set_rotation_speed(self, new_speed)`: 设置新的旋转速度 + - `pause_rotation(self)`: 暂停旋转 + - `resume_rotation(self)`: 恢复旋转 + - `reset_to_initial_angle(self)`: 重置到初始角度 + - `get_current_info(self)`: 获取当前旋转信息 + - `set_slow_robot_mode(self)`: 预设:慢速机器人模式 + - `set_fast_robot_mode(self)`: 预设:快速机器人模式 + - `set_smooth_mode(self)`: 预设:平滑模式(非机器人) + - `on_destroy(self)`: 脚本销毁时调用 + +### 11. `scripts/Rotate_P_Script.py` +- **功能**: 机器人式旋转脚本,让对象围绕P轴旋转并带有停顿效果 +- **类**: + - `RotatorScript`: 旋转脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化旋转参数和机器人模式参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现机器人式旋转效果 + - `set_robot_mode(self, enabled=True)`: 启用或禁用机器人模式 + - `set_pause_duration(self, duration)`: 设置停顿时间 + - `set_max_angle(self, new_max_angle)`: 设置新的最大旋转角度 + - `set_rotation_speed(self, new_speed)`: 设置新的旋转速度 + - `pause_rotation(self)`: 暂停旋转 + - `resume_rotation(self)`: 恢复旋转 + - `reset_to_initial_angle(self)`: 重置到初始角度 + - `get_current_info(self)`: 获取当前旋转信息 + - `set_slow_robot_mode(self)`: 预设:慢速机器人模式 + - `set_fast_robot_mode(self)`: 预设:快速机器人模式 + - `set_smooth_mode(self)`: 预设:平滑模式(非机器人) + - `on_destroy(self)`: 脚本销毁时调用 + +### 12. `scripts/Rotate_R_Script.py` +- **功能**: 旋转脚本,让对象围绕R轴旋转 +- **类**: + - `RotatorScript`: 旋转脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化旋转参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现旋转效果 + - `on_destroy(self)`: 脚本销毁时调用 + +### 13. `scripts/RotatorScript.py` +- **功能**: 旋转脚本,让对象持续旋转 +- **类**: + - `RotatorScript`: 旋转脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化旋转参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现旋转效果 + - `on_destroy(self)`: 脚本销毁时调用 + +### 14. `scripts/ScalerScript.py` +- **功能**: 缩放脚本,让对象产生呼吸般的缩放效果 +- **类**: + - `ScalerScript`: 缩放脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化缩放参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现缩放效果 + - `set_scale_parameters(self, base=None, amplitude=None, speed=None, uniform=None)`: 设置缩放参数 + - `toggle_scaling(self)`: 切换缩放状态 + - `reset_scale(self)`: 重置到原始缩放 + - `pulse_once(self)`: 执行一次脉冲缩放 + - `on_destroy(self)`: 脚本销毁时调用 + +### 15. `scripts/test_quick_script.py` +- **功能**: 测试快速脚本示例 +- **类**: + - `TestQuickScript`: 测试快速脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化脚本 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新 + - `on_destroy(self)`: 脚本销毁时调用 + +### 16. `scripts/TestMover.py` +- **功能**: 测试移动脚本 +- **类**: + - `Testmover`: 测试移动脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化移动参数 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新,实现移动效果 + - `on_destroy(self)`: 脚本销毁时调用 + +### 17. `scripts/TestRotator.py` +- **功能**: 测试旋转脚本 +- **类**: + - `Testrotator`: 测试旋转脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化脚本 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新 + - `on_destroy(self)`: 脚本销毁时调用 + +### 18. `scripts/TestScaler.py` +- **功能**: 测试缩放脚本 +- **类**: + - `Testscaler`: 测试缩放脚本类,继承自ScriptBase +- **方法**: + - `__init__(self)`: 初始化脚本 + - `start(self)`: 脚本开始时调用 + - `update(self, dt)`: 每帧更新 + - `on_destroy(self)`: 脚本销毁时调用 + +## 2.7 RenderPipelineFile模块 + +### 1. RenderPipelineFile根目录文件 + +**文件**: __init__.py +- **功能**: Python包初始化文件 +- **类**: + - 无 +- **方法**: + - 无 + +**文件**: README.md +- **功能**: 项目说明文档,包含项目介绍、特性列表和使用说明 +- **类**: + - 无 +- **方法**: + - 无 + +**文件**: setup.py +- **功能**: 安装和配置脚本,负责编译原生模块、生成必要的资源文件和配置渲染管线环境 +- **类**: + - 无 +- **方法**: + - `parse_cmd_args()`: 解析命令行参数 + - `color()`: 为字符串着色 + - `error()`: 打印错误信息并退出程序 + - `print_step()`: 打印新章节 + - `ask_for_troubleshoot()`: 询问是否打开故障排除页面 + - `exec_python_file()`: 执行Python文件并检查返回值 + - `extract_gz_files()`: 递归解压给定路径中的所有gz文件 + - `check_file_exists()`: 检查给定文件是否存在 + - `ask_download_samples()`: 询问用户是否要下载示例 + - `get_user_choice()`: 向用户提出布尔问题 + - `write_flag()`: 写入二进制标志 + - `check_cmake()`: 检查是否安装了cmake + - `check_panda_version()`: 检查Panda3D版本是否是最新的 + - `check_panda_rplight()`: 检查Panda3D是否提供rpcore原生模块 + - `setup()`: 主设置例程 + +**文件**: start_daytime_editor.py +- **功能**: 启动日间编辑器脚本,用于运行时间ofday编辑器 +- **类**: + - 无 +- **方法**: + - 无 + +**文件**: start_plugin_configurator.py +- **功能**: 启动插件配置器脚本,用于运行插件配置工具 +- **类**: + - 无 +- **方法**: + - 无 + +### 2. RenderPipelineFile/config目录 + +**文件**: pipeline.yaml +- **功能**: 渲染管线基础配置文件,包含管线内部组件的基本设置 +- **配置项**: + - `pipeline.display_debugger`: 控制是否显示屏幕调试器 + - `pipeline.advanced_debugging_info`: 控制显示的调试信息详细程度 + - `pipeline.use_r11_g11_b10`: 是否使用GL_R11F_G11F_B10F纹理格式节省内存和带宽 + - `pipeline.resolution_scale`: 渲染分辨率缩放因子 + - `pipeline.reference_mode`: 是否以参考模式渲染 + - `lighting.culling_grid_size_x/y`: 光照剔除网格大小 + - `lighting.culling_grid_slices`: 视锥体分割片数 + - `lighting.culling_max_distance`: 光照剔除最大距离 + - `lighting.culling_slice_width`: 剔除切片宽度 + - `lighting.max_lights_per_cell`: 每个单元格最大光源数 + - `shadows.atlas_size`: 全局阴影图集大小 + - `shadows.max_updates`: 每帧最大阴影更新数 + - `shadows.max_update_distance`: 阴影更新最大距离 + +**文件**: plugins.yaml +- **功能**: 渲染管线插件配置文件,包含启用的插件列表和各插件的配置参数 +- **配置项**: + - `enabled`: 启用的插件列表 + - `overrides`: 各插件的具体配置参数 + +**文件**: stages.yaml +- **功能**: 控制所有渲染阶段的执行顺序 +- **配置项**: + - `global_stage_order`: 全局渲染阶段执行顺序列表 + +**文件**: debugging.yaml +- **功能**: 调试模式配置文件,包含所有可用的调试模式 +- **配置项**: + - `render_modes`: 渲染模式列表 + +**文件**: panda3d-config.prc +- **功能**: Panda3D基础配置文件,用于配置Panda3D的基本设置 +- **配置项**: + - 开发选项 + - 生产选项 + - 杂项设置 + - OpenGL/性能设置 + +**文件**: task-scheduler.yaml +- **功能**: 任务调度配置文件,控制每帧允许运行的任务 +- **配置项**: + - `frame_cycles`: 帧循环任务调度配置 + +### 3. RenderPipelineFile/data目录 + +**目录**: builtin_models/ +- **功能**: 内置模型资源目录 +- **子目录**: + - `skybox/`: 天空盒模型 + +**目录**: default_cubemap/ +- **功能**: 默认立方体贴图资源目录 +- **子目录**: + - `source/`: 源文件目录 + - `cubemap.txo.pz`: 立方体贴图文件 + - `source_2/`: 源文件目录2 +- **文件**: + - `cubemap.txo.pz`: 立方体贴图文件 + - `filter.compute.glsl`: 过滤计算着色器 + - `filter.py`: 过滤脚本,用于过滤立方体贴图 + - **类**: + - `CubeMapFilter`: 立方体贴图过滤器类 + - `__init__()`: 初始化立方体贴图过滤器 + - `load_settings()`: 加载设置 + - `filter()`: 执行过滤操作 + - `_make_temp_buffer()`: 创建临时缓冲区 + - `_make_temp_target()`: 创建临时目标 + - `_make_copy_target()`: 创建复制目标 + +**目录**: empty_textures/ +- **功能**: 空纹理资源目录 +- **文件**: + - `empty_basecolor.png`: 空基础颜色纹理 + - `empty_normal.png`: 空法线纹理 + - `empty_roughness.png`: 空粗糙度纹理 + - `empty_specular.png`: 空镜面反射纹理 + - `README.md`: 说明文档 + +**目录**: environment_brdf/ +- **功能**: 环境BRDF资源目录 +- **子目录**: + - `res/`: 资源目录 + - `slices/`: 切片目录 + - `slices_coat/`: 涂层切片目录 + - `slices_metal/`: 金属切片目录 +- **文件**: + - `generate_reference.py`: 生成参考脚本 + - **函数**: + - `main()`: 主函数 + - `generate_reference()`: 生成参考函数 + - `run_mitsuba.bat`: Mitsuba运行脚本 + +**目录**: film_grain/ +- **功能**: 胶片颗粒资源目录 +- **文件**: + - `generate.py`: 生成脚本 + - **函数**: + - `main()`: 主函数 + - `generate_grain_texture()`: 生成颗粒纹理函数 + - `grain.compute.glsl`: 颗粒计算着色器 + - `grain.txo.pz`: 颗粒纹理文件 + +**目录**: font/ +- **功能**: 字体资源目录 +- **文件**: 包含Roboto字体系列的各种样式和粗细版本 + - `roboto-LICENSE.txt`: 字体许可证 + +**目录**: gui/ +- **功能**: GUI资源目录 +- **文件**: 包含各种GUI元素的纹理和图标资源 + +**目录**: ies_profiles/ +- **功能**: IES光照配置文件目录 +- **文件**: 包含多种光照配置文件,如area_light.ies、bollard.ies等 + - `PREVIEWS.jpg`: 预览图片 + - `README.md`: 说明文档 + +**目录**: Materials/ +- **功能**: 材质资源目录 +- **文件**: + - `GroundMaterial.yaml`: 地面材质配置 + +**目录**: panda3d_patches/ +- **功能**: Panda3D补丁目录 +- **文件**: + - `prev-model-view-matrix-part2.diff`: 模型视图矩阵补丁2 + - `prev-model-view-matrix.diff`: 模型视图矩阵补丁 + - `README.md`: 说明文档 + +**目录**: scripts/ +- **功能**: 脚本资源目录 +- **文件**: + - `example_script.py`: 示例脚本 + - **函数**: + - `main()`: 主函数 + +**目录**: setup/ +- **功能**: 安装设置资源目录 +- **文件**: + - `check_requirements.py`: 检查依赖脚本 + - **函数**: + - `check_requirements()`: 检查依赖函数 + - `main()`: 主函数 + +**文件**: generate_txo_files.py +- **功能**: TXO文件生成脚本,将管线资源转换为TXO文件以加速加载 +- **类**: + - 无 +- **方法**: + - 无 + +**文件**: install.flag +- **功能**: 安装标志文件,标识渲染管线是否已安装 + +### 4. RenderPipelineFile/effects目录 + +**文件**: basic_instancing.yaml +- **功能**: 基础实例化效果定义文件 + +**文件**: debug_metallic.yaml +- **功能**: 金属度调试效果定义文件 + +**文件**: debug_roughness.yaml +- **功能**: 粗糙度调试效果定义文件 + +**文件**: default.yaml +- **功能**: 默认效果定义文件,用于所有未覆盖的对象 + +**文件**: material_blend4.yaml +- **功能**: 四材质混合效果定义文件 + +**文件**: metallic_only.yaml +- **功能**: 仅金属度效果定义文件 + +**文件**: pbr_additive_metallic.yaml +- **功能**: PBR附加金属度效果定义文件 + +**文件**: pbr_direct_metallic.yaml +- **功能**: PBR直接金属度效果定义文件 + +**文件**: pbr_direct_roughness.yaml +- **功能**: PBR直接粗糙度效果定义文件 + +**文件**: pbr_extended.yaml +- **功能**: 扩展PBR效果定义文件,支持额外的纹理类型 + +**文件**: pbr_with_emission.yaml +- **功能**: 带自发光的PBR效果定义文件 + +**文件**: pbr_with_metallic.yaml +- **功能**: 带金属度的PBR效果定义文件 + +**文件**: pbr_with_normal.yaml +- **功能**: 带法线贴图的PBR效果定义文件 + +**文件**: pbr_with_roughness.yaml +- **功能**: 带粗糙度的PBR效果定义文件 + +**文件**: pbr_with_textures.yaml +- **功能**: 带纹理的PBR效果定义文件 + +**文件**: roughness_only.yaml +- **功能**: 仅粗糙度效果定义文件 + +**文件**: simple_texture_test.yaml +- **功能**: 简单纹理测试效果定义文件 + +**文件**: simple_transparent.yaml +- **功能**: 简单透明效果定义文件 + +**文件**: skybox.yaml +- **功能**: 天空盒效果定义文件 + +**文件**: terrain-effect.yaml +- **功能**: 地形效果定义文件 + +**文件**: test_metallic_debug.yaml +- **功能**: 金属度调试测试效果定义文件 + +**文件**: test_roughness_debug.yaml +- **功能**: 粗糙度调试测试效果定义文件 + +### 5. RenderPipelineFile/rpcore目录 + +**文件**: __init__.py +- **功能**: rpcore模块初始化文件,导出核心类 +- **类**: + - `RenderPipeline`: 渲染管线主类 + - `SpotLight`: 聚光灯类 + - `PointLight`: 点光源类 +- **方法**: + - `set_shader_inputs()`: 为较旧版本的Panda3D添加set_shader_inputs函数 + +**文件**: render_pipeline.py +- **功能**: 渲染管线主类,组合所有组件形成工作系统 +- **类**: + - `RenderPipeline`: 渲染管线主类 + - **属性**: + - `pipeline`: 管线实例 + - `mount_mgr`: 挂载管理器 + - `settings`: 管线设置 + - `tag_mgr`: 标签状态管理器 + - `plugin_mgr`: 插件管理器 + - `stage_mgr`: 阶段管理器 + - `light_mgr`: 光源管理器 + - `daytime_mgr`: 日间管理器 + - `common_resources`: 常用资源 + - **方法**: + - `__init__()`: 创建新的管线实例 + - `load_settings()`: 从给定文件名加载管线配置 + - `reload_shaders()`: 重新加载所有着色器 + - `_apply_custom_shaders()`: 重新应用用户自定义的着色器 + - `pre_showbase_init()`: 设置所有需要在showbase初始化前设置的管线设置和配置 + - `create()`: 创建管线并设置所有缓冲区 + - `set_loading_screen_image()`: 设置使用默认加载屏幕 + - `add_light()`: 添加新光源到渲染光源中 + - `remove_light()`: 移除之前附加的光源 + - `load_ies_profile()`: 从给定文件名加载IES配置文件 + - `_internal_set_effect()`: 为给定对象设置效果 + - `set_effect()`: 设置效果(内部_set_effect的包装) + - `add_environment_probe()`: 构造新环境探针并返回句柄 + - `prepare_scene()`: 准备给定场景,转换panda灯光为渲染管线灯光 + - `_create_managers()`: 创建所有管理器和实例 + - `_analyze_system()`: 打印系统使用信息 + - `_initialize_managers()`: 初始化所有管理器 + - `_init_debugger()`: 初始化基于GUI的调试器 + - `_init_globals()`: 初始化所有全局绑定 + - `_set_default_effect()`: 设置默认效果 + - `_adjust_camera_settings()`: 设置默认相机设置 + - `_compute_render_resolution()`: 计算内部使用的渲染分辨率 + - `_init_showbase()`: 初始化给定的showbase对象 + - `_init_bindings()`: 初始化任务和按键绑定 + - `_handle_window_event()`: 检查窗口事件 + - `_clear_state_cache()`: 清除状态缓存任务 + - `_manager_update_task()`: 更新任务,在渲染前更新所有管理器 + - `_update_inputs_and_stages()`: 每帧更新常用输入 + - `_plugin_pre_render_update()`: 渲染前更新插件的任务 + - `_plugin_post_render_update()`: 渲染后更新插件的任务 + - `_create_common_defines()`: 创建常用着色器配置定义 + - `_create_default_skybox()`: 返回默认天空盒 + - `_check_version()`: 检查所需Panda3D版本是否满足 + - `_init_common_stages()`: 初始化常用阶段 + - `_get_serialized_material_name()`: 返回可序列化的材质名称 + - `export_materials()`: 导出当前场景中所有材质的列表 + - `update_serialized_material()`: 从给定序列化材质更新材质 + +**文件**: light_manager.py +- **功能**: 光源管理器,InternalLightManager的包装器,提供额外功能 +- **类**: + - `LightManager`: 光源管理器类 + - **属性**: + - `pipeline`: 管线实例 + - `internal_mgr`: 内部光源管理器 + - `cmd_queue`: GPU命令队列 + - `shadow_manager`: 阴影管理器 + - `tile_size`: 瓦片大小 + - `num_tiles`: 瓦片数量 + - `total_tiles`: 总瓦片数 + - `num_lights`: 光源数量 + - `num_shadow_sources`: 阴影源数量 + - `shadow_atlas_coverage`: 阴影图集覆盖率 + - `img_light_data`: 光源数据图像 + - `img_source_data`: 阴影源数据图像 + - `pta_max_light_index`: 最大光源索引PTA + - **方法**: + - `__init__()`: 构造光源管理器 + - `add_light()`: 添加新光源 + - `remove_light()`: 移除光源 + - `update()`: 主更新方法处理GPU命令 + - `reload_shaders()`: 重新加载所有分配的着色器 + - `compute_tile_size()`: 计算屏幕上 tile 数量 + - `init_command_queue()`: 初始化命令队列 + - `init_shadow_manager()`: 初始化阴影管理器 + - `init_shadows()`: 初始化阴影 + - `init_internal_manager()`: 创建光源存储管理器和光源数据缓冲区 + - `init_stages()`: 初始化光照所需的所有阶段 + - `init_defines()`: 初始化常用定义 + +**文件**: effect.py +- **功能**: 表示已编译效果的实例,可以从文件加载 +- **类**: + - `Effect`: 效果类 + - **属性**: + - `effect_id`: 效果ID + - `filename`: 文件名 + - `effect_name`: 效果名称 + - `effect_hash`: 效果哈希 + - **方法**: + - `load()`: 从给定文件名加载具有指定选项的效果 + - `_generate_hash()`: 为效果生成唯一哈希 + - `__init__()`: 构造新的空效果 + - `get_option()`: 通过名称返回给定选项值 + - `set_options()`: 设置效果选项,覆盖默认选项 + - `do_load()`: 从给定文件名加载效果的内部方法 + - `get_shader_obj()`: 返回给定渲染通道的编译着色器对象句柄 + - `_convert_filename_to_name()`: 从文件名构造效果名称 + - `_parse_content()`: 从yaml对象构造效果的内部方法 + - `_parse_shader_template()`: 解析片段模板 + - `_construct_shader_from_data()`: 从给定数据集构造着色器 + - `_process_shader_template()`: 从给定着色器源位置和代码注入定义生成编译着色器对象 + +**文件**: render_target.py +- **功能**: 渲染目标库,提供在Panda3D中轻松设置缓冲区的函数 +- **类**: + - `RenderTarget`: 渲染目标类 + - **属性**: + - `engine`: 图形引擎 + - `debug_name`: 调试名称 + - `support_transparency`: 支持透明度 + - `create_default_region`: 创建默认区域 + - `sort`: 排序值 + - `_targets`: 目标字典 + - `_color_bits`: 颜色位数 + - `_aux_bits`: 辅助位数 + - `_aux_count`: 辅助计数 + - `_depth_bits`: 深度位数 + - `_size`: 尺寸 + - `_size_constraint`: 尺寸约束 + - `_source_window`: 源窗口 + - `_source_region`: 源区域 + - `_active`: 活动状态 + - `_internal_buffer`: 内部缓冲区 + - **方法**: + - `__init__()`: 初始化渲染目标 + - `add_color_attachment()`: 添加新的颜色附件 + - `add_depth_attachment()`: 添加深度附件 + - `add_aux_attachment()`: 添加新的辅助附件 + - `add_aux_attachments()`: 添加n个新的辅助附件 + - `size`: 设置渲染目标大小的setter属性 + - `active`: 返回目标是否当前处于活动状态的属性 + - `active.setter`: 设置目标是否处于活动状态 + - `color_tex`: 返回颜色附件(如果存在) + - `depth_tex`: 返回深度附件(如果存在) + - `aux_tex`: 返回辅助纹理列表 + - `set_shader_input()`: 设置目标可用的着色器输入 + - `set_shader_inputs()`: 设置目标可用的着色器输入 + - `shader`: 设置目标上的着色器的setter属性 + - `internal_buffer`: 返回内部GraphicsBuffer对象句柄的属性 + - `targets`: 返回附件字典的属性 + - `region`: 返回内部使用的PostProcessRegion的属性 + - `prepare_render()`: 准备渲染场景 + - `prepare_buffer()`: 准备目标以渲染到离屏缓冲区 + - `present_on_screen()`: 准备目标以在主窗口上渲染 + - `remove()`: 删除此缓冲区,恢复之前的状态 + - `set_clear_color()`: 设置清除颜色 + - `instance_count`: 设置实例计数的setter属性 + - `_create_buffer()`: 创建缓冲区对象的内部方法 + - `_compute_size_from_constraint()`: 从目标大小约束计算实际大小(以像素为单位) + - `_setup_textures()`: 准备所有绑定的纹理 + - `_make_properties()`: 创建窗口和缓冲区属性 + - `_create()`: 创建内部使用的缓冲区 + - `consider_resize()`: 检查目标是否需要调整大小,如果需要则执行调整大小 + - `setter`: 仅设置属性的装饰器类 + +**文件**: rpobject.py +- **功能**: 渲染管线中每个对象的基类,提供调试、警告、错误和致命函数 +- **类**: + - `RPObject`: 渲染管线对象基类 + - **属性**: + - `_debug_name`: 调试名称 + - `_debug_color`: 调试颜色 + - **方法**: + - `set_output_level()`: 设置输出级别 + - `global_debug()`: 从静态上下文打印调试消息 + - `global_warn()`: 从静态上下文打印警告 + - `global_error()`: 从静态上下文打印错误 + - `__init__()`: 用给定名称初始化RPObject + - `_set_debug_color()`: 设置用于输出调试消息的颜色 + - `debug()`: 输出调试消息 + - `warn()`: 输出警告消息 + - `error()`: 输出错误消息 + - `fatal()`: 输出致命错误消息并退出程序 + - `__repr__()`: 表示此对象 + +**文件**: render_stage.py +- **功能**: 所有渲染阶段的抽象基类 +- **类**: + - `RenderStage`: 渲染阶段基类 + - **属性**: + - `stage_id`: 阶段ID + - `required_inputs`: 必需的输入 + - `required_pipes`: 必需的管道 + - `produced_inputs`: 生成的输入 + - `produced_pipes`: 生成的管道 + - `produced_defines`: 生成的定义 + - `disabled`: 禁用状态 + - `_pipeline`: 管线实例 + - `_active`: 活动状态 + - `_targets`: 目标字典 + - **方法**: + - `__init__()`: 创建新的渲染阶段 + - `create()`: 设置阶段并创建管道 + - `reload_shaders()`: 设置所有需要的着色器 + - `set_shader_input()`: 在所有阶段设置着色器输入 + - `set_shader_inputs()`: 在所有阶段设置着色器输入 + - `update()`: 每帧调用的更新方法 + - `active`: 属性,返回所有目标是否处于活动状态 + - `active.setter`: 启用或禁用此阶段 + - `create_target()`: 创建新的渲染目标并绑定到此阶段 + - `remove_target()`: 移除之前注册的目标 + - `load_shader()`: 从给定参数加载着色器 + - `load_plugin_shader()`: 从插件目录加载着色器 + - `handle_window_resize()`: 处理窗口大小调整 + - `set_dimensions()`: 设置所有目标的尺寸 + - `_get_shader_handle()`: 返回着色器对象句柄 + - `_get_plugin_id()`: 返回创建此阶段的插件ID + +**文件**: loader.py +- **功能**: 管线使用的通用加载器类,所有资产加载都在这里进行 +- **类**: + - `RPLoader`: 资产加载器类 + - **方法**: + - `load_texture()`: 从磁盘加载2D纹理 + - `load_cube_map()`: 从磁盘加载立方体贴图 + - `load_3d_texture()`: 从磁盘加载3D纹理 + - `load_font()`: 从磁盘加载字体 + - `load_shader()`: 从磁盘加载着色器 + - `load_model()`: 从磁盘加载模型 + - `load_sliced_3d_texture()`: 从给定文件名和尺寸加载纹理 + - `timed_loading_operation`: 同步加载操作的上下文管理器类 + - **方法**: + - `__init__()`: 初始化加载操作 + - `__enter__()`: 进入上下文 + - `__exit__()`: 退出上下文 + +**文件**: globals.py +- **功能**: 存储应用程序广泛使用的全局变量的单例类 +- **类**: + - `Globals`: 全局变量类 + - **属性**: + - `base`: ShowBase实例 + - `render`: 渲染节点 + - `clock`: 全局时钟 + - `font`: 字体 + - `resolution`: 分辨率 + - `native_resolution`: 原生分辨率 + - **方法**: + - `load()`: 从给定的showbase加载全局变量 + +**文件**: mount_manager.py +- **功能**: 挂载管线运行所需的目录 +- **类**: + - `MountManager`: 挂载管理器类 + - **属性**: + - `_pipeline`: 管线实例 + - `_base_path`: 基础路径 + - `_lock_file`: 锁文件 + - `_model_paths`: 模型路径 + - `_write_path`: 写入路径 + - `_mounted`: 挂载状态 + - `_do_cleanup`: 清理标志 + - `_config_dir`: 配置目录 + - **方法**: + - `__init__()`: 创建新的挂载管理器 + - `write_path`: 返回先前设置的写入路径或None + - `write_path.setter`: 设置生成文件的可写目录 + - `base_path`: 返回管线的基本路径 + - `base_path.setter`: 设置基本着色器和模型所在路径 + - `config_dir`: 返回先前设置的配置目录或None + - `config_dir.setter`: 设置配置目录路径 + - `do_cleanup`: 返回挂载管理器是否会在应用程序停止运行后尝试清理生成的文件 + - `do_cleanup.setter`: 设置是否在应用程序停止后清理临时文件夹 + - `get_lock()`: 检查是否是唯一运行的实例 + - `_find_basepath()`: 尝试通过查看此文件的位置找到管线基本路径 + - `_is_pid_running()`: 检查pid是否仍在运行 + - `_write_lock()`: 将当前进程id写入instance.pid锁文件 + - `_try_remove()`: 尝试删除指定文件名 + - `_on_exit_cleanup()`: 应用程序退出时调用 + - `is_mounted`: 返回挂载管理器是否已通过调用mount()挂载 + - `mount()`: 初始化VFS挂载 + - `unmount()`: 卸载VFS + +**文件**: stage_manager.py +- **功能**: 管理所有渲染阶段的顺序,同时连接不同的管道、输入、UBO和定义 +- **类**: + - `StageManager`: 阶段管理器类 + - **属性**: + - `stages`: 阶段列表 + - `inputs`: 输入字典 + - `pipes`: 管道字典 + - `input_blocks`: 输入块列表 + - `previous_pipes`: 前一帧管道字典 + - `future_bindings`: 未来绑定列表 + - `defines`: 定义字典 + - `pipeline`: 管线实例 + - `created`: 创建状态 + - **方法**: + - `__init__()`: 构造阶段管理器 + - `_load_stage_order()`: 从stages.yaml配置文件加载所有阶段的顺序 + - `add_stage()`: 添加新阶段 + - `get_stage()`: 返回实例化阶段的句柄 + - `_prepare_stages()`: 通过删除禁用的阶段和排序阶段来准备所有阶段 + - `_bind_pipes_to_stage()`: 在阶段上设置所有需要的管道 + - `_bind_inputs_to_stage()`: 将所有输入包括通用输入绑定到给定阶段 + - `_register_stage_result()`: 注册给定阶段生成的所有管道、输入和定义 + - `_create_previous_pipes()`: 为每个上一帧的管道创建目标 + - `_apply_future_bindings()`: 应用所有未来绑定 + - `setup()`: 设置阶段 + - `reload_shaders()`: 将着色器设置为所有阶段并生成着色器配置 + - `update()`: 调用每个已注册阶段的更新方法 + - `handle_window_resize()`: 窗口调整大小时调用的方法 + - `write_autoconfig()`: 基于不同阶段指定的定义编写着色器自动配置 + +**文件**: image.py +- **功能**: Panda3D的Texture类的包装器,跟踪所有图像并注册/注销它们以及计算使用的内存 +- **类**: + - `ImageFormatTypes`: 防止pylint错误的辅助类 + - `Image`: 图像类 + - **属性**: + - `REGISTERED_IMAGES`: 注册的图像列表 + - `FORMAT_MAPPINGS`: 格式映射字典 + - **方法**: + - `create_buffer()`: 创建新的缓冲区纹理 + - `create_counter()`: 创建新的1x1 R32I纹理用作原子计数器 + - `create_2d()`: 创建新的2D纹理 + - `create_2d_array()`: 创建新的2D数组纹理 + - `create_3d()`: 创建新的3D纹理 + - `create_cube()`: 创建新的立方体贴图 + - `create_cube_array()`: 创建新的立方体贴图数组 + - `convert_texture_format()`: 将"RGBA8"等字符串转换为纹理类型和格式 + - `__init__()`: 创建新图像的内部方法 + - `__del__()`: 销毁图像 + - `write()`: 将图像写入磁盘 + +**文件**: gpu_command_queue.py +- **功能**: GPU命令队列,用于将命令排队到GPU进行处理 +- **类**: + - `GPUCommandQueue`: GPU命令队列类 + - **属性**: + - `_pipeline`: 管线实例 + - `_commands_per_frame`: 每帧命令数 + - `_command_list`: 命令列表 + - `_pta_num_commands`: 命令数量PTA + - `_data_texture`: 数据纹理 + - `_command_target`: 命令目标 + - `_commands`: 命令列表 + - **方法**: + - `__init__()`: 构造GPU命令队列 + - `clear_queue()`: 清除队列中的所有命令 + - `command_list`: 返回命令列表句柄的属性 + - `num_queued_commands`: 返回队列中命令数量的属性 + - `num_processed_commands`: 返回已处理命令数量的属性 + - `process_queue()`: 处理队列中的命令 + - `reload_shaders()`: 重新加载着色器 + - `register_input()`: 注册新的输入 + - `_register_defines()`: 注册命令类型定义 + - `_create_data_storage()`: 创建数据存储缓冲区 + - `_create_command_target()`: 创建命令处理目标 + +**文件**: common_resources.py +- **功能**: 存储管线常用资源的类 +- **类**: + - `CommonResources`: 常用资源类 + - **属性**: + - `_pipeline`: 管线实例 + - `_showbase`: ShowBase实例 + - `_ptas`: PTA字典 + - `_input_ubo`: 输入UBO + - **方法**: + - `__init__()`: 初始化常用资源 + - `_load_fonts()`: 加载默认字体 + - `_setup_inputs()`: 设置常用着色器输入 + - `_load_textures()`: 加载常用纹理 + - `_load_environment_cubemap()`: 加载环境立方体贴图 + - `_load_prefilter_brdf()`: 加载预过滤BRDF + - `_load_skydome()`: 加载天空穹顶 + - `load_default_skybox()`: 加载默认天空盒 + - `write_config()`: 生成着色器配置 + - `update()`: 更新常用资源 + +**目录**: gui/ +- **功能**: GUI相关组件 +- **文件**: + - `__init__.py`: 初始化文件 + - `buffer_viewer.py`: 缓冲区查看器 + - `checkbox_collection.py`: 复选框集合 + - `checkbox.py`: 复选框组件 + - `debugger.py`: 调试器 + - `draggable_window.py`: 可拖拽窗口 + - `error_message_display.py`: 错误信息显示 + - `exposure_widget.py`: 曝光控件 + - `fps_chart.py`: FPS图表 + - `labeled_checkbox.py`: 带标签的复选框 + - `loading_screen.py`: 加载屏幕 + - `pipe_viewer.py`: 管道查看器 + - `pixel_inspector.py`: 像素检查器 + - `README.md`: 说明文档 + - `render_mode_selector.py`: 渲染模式选择器 + - `slider.py`: 滑块控件 + - `sprite.py`: 精灵组件 + - `text_node.py`: 文本节点 + - `text.py`: 文本组件 + - `texture_preview.py`: 纹理预览器 + +**目录**: native/ +- **功能**: 原生C++模块接口 +- **文件**: + - `__init__.py`: 初始化文件 + - `source/`: C++源代码目录 + - `.gitignore`: Git忽略文件 + - `config.ini`: 配置文件 + - `update_module_builder.py`: 模块构建器更新脚本 + - `use_cxx.flag`: C++使用标志文件 + +**目录**: pluginbase/ +- **功能**: 插件基础类 +- **文件**: + - `__init__.py`: 初始化文件 + - `base_plugin.py`: 插件基类 + - `day_manager.py`: 日间管理器 + - `day_setting_types.py`: 日间设置类型 + - `manager.py`: 管理器 + - `setting_types.py`: 设置类型 + +**目录**: pynative/ +- **功能**: Python原生接口 +- **文件**: + - `__init__.py`: 初始化文件 + - `gpu_command_list.py`: GPU命令列表Python接口 + - `gpu_command.py`: GPU命令Python接口 + - `ies_dataset.py`: IES数据集Python接口 + - `internal_light_manager.py`: 内部光源管理器Python接口 + - `pointer_slot_storage.py`: 指针槽存储Python接口 + - `pssm_camera_rig.py`: PSSM相机支架Python接口 + - `README.md`: 说明文档 + - `rp_light.py`: RP光源Python接口 + - `rp_point_light.py`: RP点光源Python接口 + - `rp_spot_light.py`: RP聚光灯Python接口 + - `shadow_atlas.py`: 阴影图集Python接口 + - `shadow_manager.py`: 阴影管理器Python接口 + - `shadow_source.py`: 阴影源Python接口 + - `tag_state_manager.py`: 标签状态管理器Python接口 + +**目录**: shader/ +- **功能**: 着色器管理 +- **子目录**: + - `ibl/`: 基于图像的光照着色器 + - `includes/`: 包含文件 + - `templates/`: 模板文件 + +**目录**: stages/ +- **功能**: 渲染阶段实现 +- **文件**: + - `__init__.py`: 初始化文件 + - `ambient_stage.py`: 环境阶段 + - `apply_lights_stage.py`: 应用光源阶段 + - `collect_used_cells_stage.py`: 收集使用单元阶段 + - `combine_velocity_stage.py`: 合并速度阶段 + - `cull_lights_stage.py`: 剔除光源阶段 + - `downscale_z_stage.py`: Z缓冲下采样阶段 + - `final_stage.py`: 最终阶段 + - `flag_used_cells_stage.py`: 标记使用单元阶段 + - `gbuffer_stage.py`: G缓冲阶段 + - `render_stage.py`: 渲染阶段基类 + - **类**: `RenderStage` + - **方法**: + - `__init__()`: 创建新的渲染阶段 + - `create()`: 设置阶段并创建管道 + - `reload_shaders()`: 设置所有需要的着色器 + - `set_shader_input()`: 在所有阶段设置着色器输入 + - `set_shader_inputs()`: 在所有阶段设置着色器输入 + - `update()`: 每帧调用的更新方法 + - `create_target()`: 创建新的渲染目标并绑定到此阶段 + - `remove_target()`: 移除之前注册的目标 + - `load_shader()`: 从给定参数加载着色器 + - `load_plugin_shader()`: 从插件目录加载着色器 + - `handle_window_resize()`: 处理窗口大小调整 + - `set_dimensions()`: 设置所有目标的尺寸 + - `_get_shader_handle()`: 返回着色器对象句柄 + - `_get_plugin_id()`: 返回创建此阶段的插件ID + - `active`: 属性,返回所有目标是否处于活动状态 + - `active.setter`: 启用或禁用此阶段 + - `shadow_stage.py`: 阴影阶段 + - `update_previous_pipes_stage.py`: 更新前一管道阶段 + - `upscale_stage.py`: 上采样阶段 + +**目录**: util/ +- **功能**: 工具函数 +- **文件**: + - `__init__.py`: 初始化文件 + - `cubemap_filter.py`: 立方体贴图过滤器 + - `display_shader_builder.py`: 显示着色器构建器 + - `generic.py`: 通用工具函数 + - `ies_profile_loader.py`: IES配置文件加载器 + - `movement_controller.py`: 移动控制器 + - `network_communication.py`: 网络通信 + - `post_process_region.py`: 后期处理区域 + - `shader_input_blocks.py`: 着色器输入块 + - `smooth_connected_curve.py`: 平滑连接曲线 + - `submodule_downloader.py`: 子模块下载器 + - `task_scheduler.py`: 任务调度器 + +### 6. RenderPipelineFile/rpplugins目录 + +**文件**: __init__.py +- **功能**: rpplugins模块初始化文件 +- **类**: + - 无 +- **方法**: + - 无 + +**文件**: README.md +- **功能**: 插件目录说明文档 +- **类**: + - 无 +- **方法**: + - 无 + +**目录**: ao/ +- **功能**: 环境光遮蔽插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `ao_stage.py`: AO阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: bloom/ +- **功能**: 泛光效果插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `bloom_stage.py`: 泛光阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `on_pipeline_created()`: 管线创建回调 + +**目录**: clouds/ +- **功能**: 云渲染插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `apply_clouds_stage.py`: 应用云阶段 + - `cloud_voxel_stage.py`: 云体素阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - `required_plugins`: 必需插件 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: color_correction/ +- **功能**: 颜色校正插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `auto_exposure_stage.py`: 自动曝光阶段 + - `color_correction_stage.py`: 颜色校正阶段 + - `config.yaml`: 配置文件 + - `manual_exposure_stage.py`: 手动曝光阶段 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: dof/ +- **功能**: 景深效果插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `dof_stage.py`: 景深阶段 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `on_pipeline_created()`: 管线创建回调 + - `update_some_setting()`: 设置更新回调 + +**目录**: env_probes/ +- **功能**: 环境探针插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `apply_envprobes_stage.py`: 应用环境探针阶段 + - `config.yaml`: 配置文件 + - `cull_probes_stage.py`: 剔除探针阶段 + - `environment_capture_stage.py`: 环境捕捉阶段 + - `environment_probe.py`: 环境探针类 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: forward_shading/ +- **功能**: 前向渲染插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `forward_stage.py`: 前向渲染阶段 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `on_pipeline_created()`: 管线创建回调 + +**目录**: fxaa/ +- **功能**: FXAA抗锯齿插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `fxaa_stage.py`: FXAA阶段 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: motion_blur/ +- **功能**: 运动模糊插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `motion_blur_stage.py`: 运动模糊阶段 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: plugin_prefab/ +- **功能**: 插件预制件 +- **文件**: + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `demo_stage.py`: 演示阶段 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: pssm/ +- **功能**: 平行分割阴影贴图插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - `required_plugins`: 必需插件 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `pssm_dist_shadow_stage.py`: PSSM距离阴影阶段 + - `pssm_scene_shadow_stage.py`: PSSM场景阴影阶段 + - `pssm_shadow_stage.py`: PSSM阴影阶段 + - `pssm_stage.py`: PSSM阶段 + +**目录**: scattering/ +- **功能**: 散射效果插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `godray_stage.py`: 光线阶段 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_pipeline_created()`: 管线创建回调 + - `on_stage_setup()`: 阶段设置回调 + - `scattering_envmap_stage.py`: 散射环境贴图阶段 + - `scattering_methods.py`: 散射方法 + - `scattering_stage.py`: 散射阶段 + +**目录**: skin_shading/ +- **功能**: 皮肤着色插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `skin_shading_stage.py`: 皮肤着色阶段 + +**目录**: sky_ao/ +- **功能**: 天空AO插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `ao_stage.py`: AO阶段 + - `capture_stage.py`: 捕捉阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + +**目录**: smaa/ +- **功能**: SMAA抗锯齿插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `jitters.py`: 抖动工具 + - `LICENSE.txt`: 许可证文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `smaa_stage.py`: SMAA阶段 + +**目录**: ssr/ +- **功能**: 屏幕空间反射插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `reload_shaders()`: 重载着色器回调 + - `ssr_stage.py`: SSR阶段 + +**目录**: volumetrics/ +- **功能**: 体积渲染插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - `required_plugins`: 必需插件 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `volumetrics_stage.py`: 体积渲染阶段 + +**目录**: vxgi/ +- **功能**: VXGI全局光照插件 +- **文件**: + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - **类**: `Plugin` + - **属性**: + - `name`: 插件名称 + - `author`: 插件作者 + - `description`: 插件描述 + - `version`: 插件版本 + - **方法**: + - `on_stage_setup()`: 阶段设置回调 + - `voxelization_stage.py`: 体素化阶段 + - `vxgi_stage.py`: VXGI阶段 + +### 7. RenderPipelineFile/toolkit目录 + +**目录**: bake_gi/ +- **功能**: GI烘焙工具 +- **文件**: + - `resources/`: 资源目录 + - `bake.py`: 烘焙脚本 + - **功能**: GI光照烘焙工具主程序 + - **类**: + - 无 + - **方法**: + - 主函数入口 + - `display.py`: 显示脚本 + - **功能**: 显示烘焙结果工具 + - **类**: + - 无 + - **方法**: + - 主函数入口 + +**目录**: day_time_editor/ +- **功能**: 日间时间编辑器 +- **文件**: + - `ui/`: UI目录 + - **功能**: 用户界面资源文件 + - `curve_widget.py`: 曲线控件 + - **功能**: 时间曲线编辑控件 + - **类**: + - `CurveWidget`: 曲线编辑控件类 + - **方法**: + - 控件绘制和交互方法 + - `main.py`: 主程序 + - **功能**: 日间时间编辑器主程序 + - **类**: + - `PointDialog`: 点插入对话框类 + - `DayTimeEditor`: 日间时间编辑器主类 + - **方法**: + - `setupUi()`: UI设置 + - `_on_time_changed()`: 时间变化处理 + - `_on_setting_selected()`: 设置选择处理 + - `_insert_point()`: 插入点处理 + - `_reset_settings()`: 重置设置处理 + - `_update_tree_widgets()`: 更新树控件 + - `_on_curve_edited()`: 曲线编辑处理 + +**目录**: import_sun_data/ +- **功能**: 导入太阳数据工具 +- **文件**: + - `import_data.py`: 导入数据脚本 + - **功能**: 太阳数据导入工具 + - **类**: + - 无 + - **方法**: + - 数据解析和导入方法 + - `README.md`: 说明文档 + - **功能**: 工具使用说明 + +**目录**: material_editor/ +- **功能**: 材质编辑器 +- **文件**: + - `ui/`: UI目录 + - **功能**: 用户界面资源文件 + - `main.py`: 主程序 + - **功能**: 材质编辑器主程序 + - **类**: + - 无 + - **方法**: + - 主程序入口和UI初始化 + +**目录**: pathtracing_reference/ +- **功能**: 路径追踪参考 +- **文件**: + - `config/`: 配置目录 + - **功能**: 配置文件目录 + - `res/`: 资源目录 + - **功能**: 资源文件目录 + - `batch_compare.py`: 批量比较脚本 + - **功能**: 批量比较渲染结果 + - **类**: + - 无 + - **方法**: + - 批量比较处理方法 + - `generate_difference.py`: 生成差异脚本 + - **功能**: 生成渲染结果差异图像 + - **类**: + - 无 + - **方法**: + - 差异图像生成方法 + - `get_brightness.py`: 获取亮度脚本 + - **功能**: 获取图像亮度信息 + - **类**: + - 无 + - **方法**: + - 亮度计算方法 + - `README.md`: 说明文档 + - **功能**: 工具使用说明 + - `run_mitsuba.bat`: Mitsuba运行脚本 + - **功能**: 运行Mitsuba渲染器 + - `run_renderpipeline.py`: 运行渲染管线脚本 + - **功能**: 运行渲染管线进行对比测试 + - **类**: + - 无 + - **方法**: + - 渲染管线运行方法 + +**目录**: plugin_configurator/ +- **功能**: 插件配置器 +- **文件**: + - `ui/`: UI目录 + - **功能**: 用户界面资源文件 + - `main.py`: 主程序 + - **功能**: 插件配置器主程序 + - **类**: + - 无 + - **方法**: + - 主程序入口和UI初始化 + +**目录**: poisson_disk_generator/ +- **功能**: 泊松圆盘生成器 +- **文件**: + - `source/`: 源代码目录 + - **功能**: C++源代码目录 + - `.gitignore`: Git忽略文件 + - **功能**: Git忽略配置 + - `config.ini`: 配置文件 + - **功能**: 生成器配置文件 + - `generate_poisson_disk.py`: 生成泊松圆盘脚本 + - **功能**: 泊松圆盘生成工具 + - **类**: + - 无 + - **方法**: + - 圆盘生成方法 + - `update_module_builder.py`: 更新模块构建器脚本 + - **功能**: 更新模块构建器 + - **类**: + - 无 + - **方法**: + - 构建器更新方法 + +**目录**: render_service/ +- **功能**: 渲染服务 +- **文件**: + - `config/`: 配置目录 + - **功能**: 服务配置文件目录 + - `resources/`: 资源目录 + - **功能**: 服务资源文件目录 + - `example_usage.py`: 使用示例 + - **功能**: 渲染服务使用示例 + - **类**: + - 无 + - **方法**: + - 示例使用方法 + - `README.md`: 说明文档 + - **功能**: 服务使用说明 + - `service.py`: 服务脚本 + - **功能**: 渲染服务主程序 + - **类**: + - 无 + - **方法**: + - 服务启动和管理方法 + +**目录**: rp_distributor/ +- **功能**: RP分发器 +- **文件**: + - `launch.templ.bat`: 启动模板脚本 + - **功能**: 启动脚本模板 + - `main.py`: 主程序 + - **功能**: 分发器主程序 + - **类**: + - 无 + - **方法**: + - 分发器主逻辑 + - `README.md`: 说明文档 + - **功能**: 分发器使用说明 + +### 8. RenderPipelineFile/rplibs目录 + +**目录**: colorama/ +- **功能**: 终端颜色库 + - **功能**: 为终端输出提供颜色支持 + +**目录**: progressbar/ +- **功能**: 进度条库 + - **功能**: 提供进度条显示功能 + +**目录**: yaml/ +- **功能**: YAML解析库 + - **功能**: 提供YAML文件解析功能 + +**文件**: __init__.py +- **功能**: rplibs模块初始化文件 +- **类**: + - 无 +- **方法**: + - 无 + +**文件**: pyqt_imports.py +- **功能**: 导入所有qt类的包装脚本 +- **类**: + - 无 +- **方法**: + - `qt_connect()`: 连接Qt对象的信号和槽 + - `qt_register_fonts()`: 注册字体 + +**文件**: six-source.txt +- **功能**: Six库源信息 + - **功能**: Six库的源信息记录 + +**文件**: six.py +- **功能**: Six库兼容工具 + - **功能**: Python 2/3兼容性工具库 + +## 2.8 ui模块 + +### 1. `ui/__init__.py` +- **功能**: ui模块初始化文件,导出UI组件类 +- **类**: + - 无 +- **方法**: + - 无 +- **导出项**: + - `CustomPanda3DWidget`: 自定义Panda3D部件类 + - `CustomFileView`: 自定义文件视图类 + - `CustomTreeWidget`: 自定义树形控件类 + - `MainWindow`: 主窗口类 + - `setup_main_window`: 设置主窗口函数 + +### 2. `ui/assembly_disassembly_config_simple.py` +- **功能**: 拆装交互配置界面 - 简化版本,实现模型的分步拆装交互功能配置 +- **类**: + - `AssemblyDisassemblyConfigDialog`: 拆装配置主对话框 - 简化版本 +- **方法**: + - `__init__(self, parent=None, world=None)`: 初始化拆装配置对话框 + - `setupUI(self)`: 设置界面 + - `createModelsTab(self)`: 创建模型选择标签页 + - `createStepsTab(self)`: 创建步骤配置标签页 + - `createToolsTab(self)`: 创建工具配置标签页 + - `createSettingsTab(self)`: 创建全局设置标签页 + - `connectSignals(self)`: 连接信号槽 + - `loadSceneModels(self)`: 加载场景中的模型 + - `_addNodeToTree(self, node, parent_item)`: 递归添加节点到树形控件 + - `filterSceneModels(self, search_text)`: 根据搜索文本过滤场景模型 + - `addModelsToConfig(self)`: 添加选中的模型到配置 + - `removeModelsFromConfig(self)`: 从配置中移除选中的模型 + - `addStep(self)`: 添加步骤 + - `removeStep(self)`: 删除步骤 + - `moveStepUp(self)`: 上移步骤 + - `moveStepDown(self)`: 下移步骤 + - `renumberSteps(self)`: 重新编号步骤 + - `onStepSelectionChanged(self)`: 步骤选择改变 + - `_clearStepConfigurationUI(self)`: 清空步骤配置界面 + - `loadStepConfiguration(self, step_data)`: 加载步骤配置到界面 + - `disconnectStepConfigSignals(self)`: 断开步骤配置的信号连接 + - `connectStepConfigSignals(self)`: 连接步骤配置的信号 + - `saveCurrentStepConfig(self)`: 保存当前步骤的配置到list_item的UserRole数据中 + - `addTool(self)`: 添加工具 + - `editTool(self)`: 编辑工具 + - `deleteTool(self)`: 删除工具 + - `browseAudioFile(self)`: 浏览音频文件 + - `saveConfiguration(self)`: 保存配置 + - `loadConfiguration(self)`: 加载配置 + - `loadConfigurationData(self, data)`: 加载配置数据到界面 + - `_loadModelConfiguration(self, saved_models)`: 加载模型配置,通过路径精确匹配场景中的模型节点 + - `_buildSceneModelMap(self, node, model_map)`: 递归构建场景模型名称到节点的映射 + - `_getNodePath(self, node)`: 获取节点的完整路径,用于精确定位 + - `_findNodeByPath(self, root_node, node_path)`: 根据路径在场景中查找节点 + - `_findNodeByNameAndParent(self, root_node, node_name, parent_name)`: 根据节点名称和父节点名称查找节点 + - `previewConfiguration(self)`: 预览配置效果 + - `applyConfiguration(self)`: 应用配置 + +### 3. `ui/assembly_disassembly_config.py` +- **功能**: 拆装交互配置界面,实现模型的分步拆装交互功能配置 +- **类**: + - `AssemblyDisassemblyConfigDialog`: 拆装配置主对话框 +- **方法**: + - `__init__(self, parent=None, world=None)`: 初始化拆装配置对话框 + - `setupUI(self)`: 设置界面 + - `createLeftPanel(self)`: 创建左侧面板 + - `createRightPanel(self)`: 创建右侧面板 + - `createStepsTab(self)`: 创建步骤配置标签页 + - `createStepConfigWidget(self)`: 创建步骤详细配置部件 + - `createSettingsTab(self)`: 创建全局设置标签页 + - `connectSignals(self)`: 连接信号槽 + - `loadSceneModels(self)`: 加载场景中的模型 + - `_addNodeToTree(self, node, parent_item)`: 递归添加节点到树形控件 + - `filterSceneModels(self, text)`: 过滤场景模型列表 + - `addModelsToConfig(self)`: 添加选中的模型到配置 + - `removeModelsFromConfig(self)`: 从配置中移除选中的模型 + - `addTool(self)`: 添加工具 + - `editTool(self)`: 编辑工具 + - `removeTool(self)`: 删除工具 + - `addStep(self)`: 添加步骤 + - `removeStep(self)`: 删除步骤 + - `moveStepUp(self)`: 上移步骤 + - `moveStepDown(self)`: 下移步骤 + - `renumberSteps(self)`: 重新编号步骤 + - `onStepSelectionChanged(self)`: 步骤选择改变 + - `loadStepConfiguration(self, step_data)`: 加载步骤配置到界面 + - `onInteractionTypeChanged(self, interaction_type)`: 交互方式改变 + - `updateCurrentStep(self)`: 更新当前步骤数据 + - `browseAudioFile(self)`: 浏览音频文件 + - `saveConfiguration(self)`: 保存配置 + - `loadConfiguration(self)`: 加载配置 + - `loadConfigurationData(self, data)`: 加载配置数据到界面 + - `previewConfiguration(self)`: 预览配置效果 + - `applyConfiguration(self)`: 应用配置 + +### 4. `ui/icon_manager_gui.py` +- **功能**: 图标管理器GUI工具,提供图形界面来管理和查看图标 +- **类**: + - `IconPreviewWidget`: 图标预览控件 + - `IconManagerDialog`: 图标管理器对话框 +- **方法**: + - `IconPreviewWidget.__init__(self)`: 初始化图标预览控件 + - `IconPreviewWidget.setupUI(self)`: 设置UI + - `IconPreviewWidget.showIcon(self, icon_name: str, icon: QIcon)`: 显示图标 + - `IconManagerDialog.__init__(self, parent=None)`: 初始化图标管理器对话框 + - `IconManagerDialog.setupUI(self)`: 设置UI + - `IconManagerDialog.loadIcons(self)`: 加载图标列表 + - `IconManagerDialog.onIconSelected(self)`: 当选择图标时 + - `IconManagerDialog.refreshIcons(self)`: 刷新图标 + - `IconManagerDialog.addIcon(self)`: 添加新图标 + - `IconManagerDialog.showDebugInfo(self)`: 显示调试信息 + - `show_icon_manager(parent=None)`: 显示图标管理器对话框 + +### 5. `ui/icon_manager.py` +- **功能**: 图标管理工具,负责统一管理应用程序中的所有图标 +- **类**: + - `IconManager`: 图标管理器类 +- **方法**: + - `__init__(self)`: 初始化图标管理器 + - `_get_icon_directory(self)`: 获取图标目录的绝对路径 + - `_create_default_icon(self)`: 创建默认图标 + - `_preload_icons(self)`: 预加载常用图标 + - `get_icon(self, icon_name: str, size: Optional[QSize] = None)`: 获取图标 + - `get_icon_path(self, icon_name: str)`: 获取图标文件的完整路径 + - `has_icon(self, icon_name: str)`: 检查图标是否存在 + - `add_icon(self, icon_name: str, icon_path: str)`: 添加新图标到缓存 + - `refresh_cache(self)`: 刷新图标缓存 + - `get_available_icons(self)`: 获取所有可用的图标列表 + - `get_cache_info(self)`: 获取缓存信息 + - `debug_info(self)`: 打印调试信息 + - `get_icon_manager()`: 获取全局图标管理器实例 + - `get_icon(icon_name: str, size: Optional[QSize] = None)`: 便捷函数:获取图标 + - `get_icon_path(icon_name: str)`: 便捷函数:获取图标路径 + - `has_icon(icon_name: str)`: 便捷函数:检查图标是否存在 + +### 6. `ui/interface_manager.py` +- **功能**: 界面管理器,处理树形控件和UI交互 +- **类**: + - `InterfaceManager`: 界面管理器类 +- **方法**: + - `__init__(self, world)`: 初始化界面管理器 + - `setTreeWidget(self, treeWidget)`: 设置树形控件引用并更新场景树 + - `onTreeWidgetClicked(self, index)`: 处理树形控件点击事件(包括空白区域) + - `onTreeCurrentItemChanged(self, current, previous)`: 处理树形控件当前选中项改变事件 + - `onTreeItemClicked(self, item, column)`: 处理树形控件项目点击事件 + - `isModelOrChild(self, item)`: 检查是否是模型节点或其子节点 + - `deleteNode(self, nodePath, item)`: 删除节点 + - `_cleanupAllLightsInSubtree(self, parentNode)`: 清理节点树中的灯光 + - `updateSceneTree(self)`: 更新场景树显示 - 实际实现 + - `findTreeItem(self, node, parentItem)`: 在树形控件中查找指定的节点项 + - `_collect_expanded(self, item=None, prefix="")`: 收集展开的节点路径 + - `_restore_expanded(self, item=None, prefix="")`: 恢复展开的节点状态 + - `syncVisibilityDownward(self)`: 向下同步可见性 + +### 7. `ui/main_window.py` + +#### 类: StyledTerrainDialog +- **功能**: 与新建项目对话框风格一致的参数输入对话框 +- **方法**: + - `__init__(self, parent, title, fields, primary_text="确认", secondary_text="取消")`: 初始化对话框 + - `createTitleBar(self)`: 创建标题栏 + - `_applyTitleBarIcons(self)`: 应用标题栏图标 + - `setWindowTitle(self, title)`: 设置窗口标题 + - `mousePressEvent(self, event)`: 鼠标按下事件 + - `mouseMoveEvent(self, event)`: 鼠标移动事件 + - `mouseReleaseEvent(self, event)`: 鼠标释放事件 + - `get_value(self, name)`: 获取字段值 + +#### 类: MainWindow +- **功能**: 主窗口类,负责创建和管理应用程序的主界面 +- **方法**: + - `__init__(self, world)`: 初始化主窗口 + - `setupMessageBoxStyles(self)`: 设置消息框样式 + - `createStyledInputDialog(self, parent, title, label, mode=QLineEdit.Normal, text="")`: 创建带样式的输入对话框 + - `createStyledFileDialog(self, parent, caption, directory="", filter="")`: 创建带样式的文件对话框 + - `setupCenterWidget(self)`: 设置窗口中央部件 + - `move_center(self)`: 将窗口移动到屏幕中央 + - `get_icon_path(self, icon_name)`: 获取图标文件路径 + - `setupEmbeddedToolbar(self)`: 创建内嵌工具栏 + - `toolbarMousePressEvent(self, event)`: 工具栏鼠标按下事件 + - `toolbarMouseMoveEvent(self, event)`: 工具栏鼠标移动事件 + - `toolbarMouseReleaseEvent(self, event)`: 工具栏鼠标释放事件 + - `snapToNearestPosition(self)`: 自动吸附到最近的预设位置 + - `setupMenus(self)`: 创建菜单栏 + - `refreshAssetsView(self)`: 刷新资源视图 + - `setupCreateMenuActions(self)`: 设置创建菜单动作 + - `setupViewMenuActions(self)`: 设置视图菜单动作 + - `onViewPerspective(self)`: 切换到透视视图 + - `onViewOrthographic(self)`: 切换到正交视图 + - `onViewTop(self)`: 切换到俯视图 + - `onViewFront(self)`: 切换到前视图 + - `onViewGrid(self)`: 切换网格显示 + - `_createGridView(self)`: 创建网格视图 + - `_saveCurrentCameraSettings(self)`: 保存当前相机设置 + - `_setupOrthographicLens(self)`: 设置正交镜头 + - `_updateViewMenuText(self)`: 更新视图菜单文本 + - `_onWindowResized(self)`: 窗口大小改变时的处理 + - `connectCreateMenuActions(self)`: 连接创建菜单动作 + - `getCreateMenuActions(self)`: 获取所有创建菜单动作 + - `setupDockWindows(self)`: 创建停靠窗口 + - `setupToolbar(self)`: 创建工具栏 + - `setupScriptPanel(self, layout)`: 创建脚本管理面板 + - `connectEvents(self)`: 连接事件信号 + - `onCopy(self)`: 复制操作 + - `onCut(self)`: 剪切操作 + - `onPaste(self)`: 粘贴操作 + - `_serializeNode(self, node)`: 序列化节点 + - `_deserializeNode(self, node_data, parent_node)`: 反序列化节点 + - `_deleteNode(self, node, tree_item)`: 删除节点 + - `onUndo(self)`: 撤销操作 + - `onRedo(self)`: 重做操作 + - `onCreateCesiumView(self)`: 创建 Cesium 视图 + - `onToggleCesiumView(self)`: 切换 Cesium 视图 + - `onRefreshCesiumView(self)`: 刷新 Cesium 视图 + - `onUpdateCesiumURL(self)`: 更新 Cesium URL + - `onAddModelClicked(self)`: 处理添加模型按钮点击 + - `showAddModelDialog(self)`: 显示添加模型对话框 + - `getModelCoordinates(self)`: 获取模型坐标信息 + - `onLoadCesiumTileset(self)`: 加载 Cesium 3D Tiles + - `onToolChanged(self, button)`: 工具切换事件处理 + - `openWebBrowser(self)`: 打开网页浏览器 + - `getSampleWeatherData(self)`: 获取示例天气数据 + - `onCreate3DSampleInfoPanel(self)`: 创建3D示例信息面板 + - `addInfoPanelToTree(self, panel, panel_name)`: 将信息面板添加到场景树 + - `onCreateSystemStatusPanel(self)`: 创建系统状态信息面板 + - `getSystemStatusData(self)`: 获取系统状态数据 + - `onCreateSensorDataPanel(self)`: 创建传感器数据信息面板 + - `getSensorData(self)`: 获取传感器数据 + - `onCreateSceneInfoPanel(self)`: 创建场景信息面板 + - `getSceneInfoData(self)`: 获取场景信息数据 + - `refreshScriptsList(self)`: 刷新脚本列表 + - `updateScriptPanel(self)`: 更新脚本面板状态 + - `updateMountedScriptsList(self, game_object)`: 更新已挂载脚本列表 + - `onCreateScript(self)`: 创建脚本按钮事件 + - `onCreateScriptDialog(self)`: 菜单创建脚本事件 + - `onLoadScript(self)`: 加载脚本按钮事件 + - `onLoadScriptFile(self)`: 加载脚本文件菜单事件 + - `onReloadAllScripts(self)`: 重新加载所有脚本事件 + - `onToggleHotReload(self)`: 切换热更新状态 + - `onOpenScriptsManager(self)`: 打开脚本管理器 + - `onScriptDoubleClick(self, item)`: 脚本列表双击事件 + - `onMountScript(self)`: 挂载脚本事件 + - `onUnmountScript(self)`: 卸载脚本事件 + - `onOpenIconManager(self)`: 打开图标管理器 + - `closeEvent(self, event)`: 处理窗口关闭事件 + - `onCreateFlatTerrain(self)`: 创建平面地形 + - `onCreateHeightmapTerrain(self)`: 从高度图创建地形 + - `onOpenAssemblyDisassemblyConfig(self)`: 打开拆装配置界面 + - `onStartAssemblyInteraction(self)`: 开始拆装交互 + - `onOpenMaintenanceSystem(self)`: 打开维修系统 + - `onEnterVR(self)`: 进入VR模式 + - `onExitVR(self)`: 退出VR模式 + - `onShowVRStatus(self)`: 显示VR状态 + - `onShowVRSettings(self)`: 显示VR设置对话框 + - `createVRSettingsDialog(self)`: 创建VR设置对话框 + - `onVRSettingsOK(self, dialog)`: 确定VR设置 + - `applyVRSettings(self, dialog)`: 应用VR设置 + - `onToggleVRDebug(self)`: 切换VR调试输出 + - `onShowVRPerformance(self)`: 显示VR性能报告 + - `onSetVRDebugMode(self, mode)`: 设置VR调试模式 + - `onToggleVRPerformanceMonitor(self)`: 切换VR性能监控 + - `onToggleVRGpuTiming(self)`: 切换VR GPU时间监控 + - `onToggleVRPipelineMonitor(self)`: 切换VR管线监控 + - `onSetVRPoseStrategy(self, strategy)`: 设置VR姿态策略 + - `onTestVRPipeline(self)`: 测试VR管线监控功能 + - `onShowVRDebugSettings(self)`: 显示VR调试设置对话框 + - `createVRDebugSettingsDialog(self)`: 创建VR调试设置对话框 + - `onToggleVRTestMode(self)`: 切换VR测试模式 + - `onToggleVRTestSubmitTexture(self)`: 切换VR测试模式纹理提交功能 + - `onToggleVRTestWaitPoses(self)`: 切换VR测试模式姿态等待功能 + - `onSetVRTestStep(self, step)`: 设置VR测试步骤 + +#### 函数: setup_main_window +- **功能**: 设置主窗口的便利函数 +- **方法**: + - `setup_main_window(world, path=None)`: 设置主窗口 + +#### 类: AssemblyModeSelectionDialog +- **功能**: 拆装模式选择对话框 +- **方法**: + - `__init__(self, parent=None)`: 初始化对话框 + - `setupUI(self)`: 设置界面 + - `on_mode_changed(self)`: 模式改变时的处理 + - `get_selected_mode(self)`: 获取选中的模式 + +### 8. `ui/maintenance_system.py` + +#### 类: MaintenanceLoginDialog +- **功能**: 维修系统登录对话框 +- **信号**: + - `login_success`: 登录成功信号 +- **方法**: + - `__init__(self, parent=None)`: 初始化登录对话框 + - `setupUI(self)`: 设置用户界面,包括标题、登录表单、提示信息和按钮,应用样式和布局 + - `on_login(self)`: 处理登录,验证账号密码,成功时发射login_success信号 + +#### 类: MaintenanceSubjectDialog +- **功能**: 维修系统科目选择对话框 +- **信号**: + - `subject_selected`: 科目选择信号,传递科目路径和模式参数 +- **方法**: + - `__init__(self, project_path, parent=None)`: 初始化科目选择对话框,设置项目路径和科目路径 + - `setupUI(self)`: 设置用户界面,包括标题、科目列表、科目详情、模式选择和底部按钮,应用样式和布局 + - `load_subjects(self)`: 加载科目列表,扫描Subjects目录中的JSON文件并显示在列表中 + - `on_subject_selected(self, item)`: 处理科目选择,更新科目详情显示和开始按钮状态 + - `format_subject_description(self, subject_data, filename)`: 格式化科目描述,显示科目基本信息、描述、步骤数量、总分和工具列表 + - `on_start(self)`: 开始科目,获取选择的模式并发射subject_selected信号 + +#### 类: MaintenanceSystemManager +- **功能**: 维修系统管理器 +- **方法**: + - `__init__(self, world)`: 初始化维修系统管理器,保存world引用 + - `show_maintenance_system(self, parent_window)`: 显示维修系统,创建登录对话框并连接登录成功信号 + - `show_subject_selection(self, parent_window)`: 显示科目选择界面,获取当前项目路径并创建科目选择对话框 + - `start_maintenance_subject(self, subject_path, mode)`: 开始维修科目,加载科目配置并启动拆装交互系统 + +### 9. `ui/property_panel.py` + +#### 类: PropertyPanelManager +- **功能**: 属性面板管理器,负责显示和编辑场景中各种对象的属性 +- **方法**: + - `__init__(self, world)`: 初始化属性面板管理器 + - `createStatusBadge(self, text, badge_type="green")`: 创建现代化状态徽章 + - `createFixedStatusBadge(self, text, badge_type="green")`: 创建固定宽度的状态徽章 + - `createModernButton(self, text, button_type="default")`: 创建现代化按钮 + - `_collision_button_style(self)`: 返回碰撞检测面板按钮统一样式 + - `createModernGroupBox(self, title, parent_layout)`: 创建现代化的分组框 + - `_getFigmaSpinBoxStyle(self)`: 获取符合Figma设计的SpinBox样式 + - `createPropertyRow(self, label_text, widget, layout, tooltip=None)`: 创建属性行 + - `setPropertyLayout(self, layout)`: 设置属性面板布局引用 + - `clearPropertyPanel(self)`: 清空属性面板 + - `updateNodeVisibilityAfterDrag(self, item)`: 拖拽结束后更新节点的可见性状态 + - `_syncSceneVisibility(self)`: 同步场景可见性 + - `updatePropertyPanel(self, item)`: 更新属性面板显示 + - `_isTerrainNode(self, node, item)`: 检查是否是地形节点 + - `_showTerrainProperties(self, terrain_node, item)`: 显示地形属性面板 + - `_updateTerrainTransformPanel(self, terrain_node)`: 更新地形变化属性面板 + - `_createTerrainEditPanel(self, terrain_info)`: 创建地形编辑控制面板 + - `_onTerrainRadiusChanged(self, value)`: 地形编辑半径改变 + - `_onTerrainStrengthChanged(self, value)`: 地形编辑强度改变 + - `_onTerrainOperationChanged(self, text)`: 地形编辑操作类型改变 + - `_updateTerrainMaterialPanel(self, terrain_node, terrain_info)`: 更新地形材质属性面板 + - `_selectTerrainColor(self, terrain_info)`: 选择地形颜色 + - `_selectTerrainTexture(self, terrain_info)`: 选择地形纹理 + - `_deleteTerrain(self, terrain_info, item)`: 删除地形 + - `_cleanupAllReferences(self)`: 清理所有控件引用 + - `_setUserVisible(self, node, visible)`: 设置用户可见性 + - `_syncEffectiveVisibility(self, start_node)`: 同步有效可见性 + - `_toggleModelVisibility(self, model, state)`: 切换模型可见性状态 + - `refreshModelValues(self, nodePath)`: 刷新模型值显示 + - `_refreshGUIElementValues(self, gui_element)`: 刷新GUI元素值显示 + - `_refreshModelValues(self, nodePath)`: 刷新普通模型值显示 + - `_isPropertyPanelValid(self)`: 检查属性面板是否仍然有效 + - `_safeUpdateSpinBox(self, attr_name, value)`: 安全地更新数值框 + - `_createTransformControls(self, nodePath)`: 创建变换控制控件 + - `_onPositionEditFinished(self, nodePath, axis)`: 位置编辑完成时的处理 + - `_createSafeSpinBox(self, min_val, max_val, read_only=False)`: 创建安全的数值框 + - `_cleanupTransformControls(self)`: 清理变换控件引用 + - `_refreshWorldPos(self, model)`: 刷新世界位置 + - `_showCesiumTilesetProperties(self, nodePath, item)`: 显示 Cesium tileset 属性 + - `_createPositionControl(self, label, nodePath, axis)`: 创建位置控制控件 + - `_createScaleControl(self, nodePath)`: 创建缩放控制控件 + - `_updateTilesetPosition(self, nodePath, axis, value)`: 更新 tileset 位置 + - `_updateTilesetScale(self, nodePath, value)`: 更新 tileset 缩放 + - `_deleteCesiumTileset(self, nodePath, item)`: 删除 Cesium tileset + - `_updateModelPropertyPanel(self, model)`: 更新模型属性面板 + - `_onScaleValueChanged(self, scale_widget, value)`: 缩放值改变 + - `_updateXScale(self, model, value)`: 更新X轴缩放值 + - `_updateYScale(self, model, value)`: 更新Y轴缩放值 + - `_updateZScale(self, model, value)`: 更新Z轴缩放值 + - `updateGUIPropertyPanel(self, gui_element, item)`: 更新GUI元素属性面板 + - `_addInfoPanelProperties(self, info_panel)`: 为信息面板添加属性控制面板 + - `_applyInfoPanel3DTitleProperties(self, info_panel, r, g, b, a, size)`: 应用3D信息面板标题属性 + - `_applyInfoPanel3DContentProperties(self, info_panel, r, g, b, a, size)`: 应用3D信息面板内容属性 + - `_adjustContentWordwrap(self, panel_id, panel_width, font_size)`: 调整信息面板内容的换行设置 + - `_startInfoPanelMonitoring(self, info_panel, panel_id)`: 启动信息面板内容监控 + - `_checkInfoPanelUpdates(self, panel_id)`: 检查信息面板内容更新 + - `_selectInfoPanelBorderColor(self, info_panel, r_spin, g_spin, b_spin, a_spin)`: 选择信息面板边框颜色 + - `updateInfoPanelBackgroundImage(self, info_panel, image_path)`: 更新信息面板背景图片 + - `_applyInfoPanelBackgroundImage(self, panel_node, image_path, panel_data)`: 应用信息面板背景图片 + - `_update3DInfoPanelBackgroundImage(self, panel_id, info_panel, image_path)`: 更新3D信息面板背景图片 + - `_selectInfoPanelBackgroundColor(self, info_panel, r_spin, g_spin, b_spin, a_spin)`: 选择信息面板背景颜色 + - `_applyInfoPanelBackgroundColor(self, info_panel, r, g, b, a)`: 应用信息面板背景颜色 + - `_selectInfoPanelTitleColor(self, info_panel, r_spin, g_spin, b_spin, a_spin)`: 选择信息面板标题颜色 + - `_selectInfoPanelContentColor(self, info_panel, r_spin, g_spin, b_spin, a_spin)`: 选择信息面板内容颜色 + - `_applyInfoPanelTitleProperties(self, info_panel, r, g, b, a, size)`: 应用信息面板标题属性 + - `_applyInfoPanelContentProperties(self, info_panel, r, g, b, a, size)`: 应用信息面板内容属性 + - `_addSphericalVideoProperties(self, spherical_video)`: 为球形视频添加属性控制面板 + - `_toggleSphericalVideoPlayback(self, spherical_video)`: 切换球形视频播放状态 + - `_stopSphericalVideo(self, spherical_video)`: 停止球形视频 + - `_seekSphericalVideo(self, spherical_video, slider_value)`: 跳转到指定时间位置 + - `_updateSphericalVideoRadius(self, spherical_video, new_radius)`: 更新球形视频半径 + - `loadSphericalVideoFile(self, spherical_video, video_path)`: 为球形视频加载新的视频文件 + - `_selectSphericalVideoFile(self, spherical_video)`: 选择球形视频文件 + - `_addVideoScreenProperties(self, video_screen, item)`: 添加视频屏幕属性面板 + - `_add2DVideoScreenProperties(self, video_screen, item)`: 为2D视频屏幕添加属性控制面板 + - `_loadVideoFromURLWithOpenCV(self, video_screen, url)`: 使用OpenCV从URL加载视频流并在2D视频屏幕上显示 + - `play2DVideo(self, video_screen)`: 播放2D视频 + - `pause2DVideo(self, video_screen)`: 暂停2D视频 + - `_stop2DVideo(self, video_screen)`: 停止2D视频 + - `_loadNew2DVideo(self, video_screen, item)`: 为2D视频屏幕加载新视频文件 + - `_loadVideoFromURLWithOpenCV_3D(self, video_screen, url)`: 使用OpenCV从URL加载视频流并在3D视频屏幕上显示 + - `_verifyVideoDisplay(self, video_screen, texture)`: 验证视频显示 + - `_retryLoadVideoFromURLWithOpenCV_3D(self, video_screen, url)`: 重新加载3D视频流 + - `_stop3DVideo(self, video_screen)`: 停止3D视频 + - `_loadNewVideo(self, video_screen, item)`: 加载新视频 + - `editGUI2DPosition(self, gui_element, axis, value)`: 编辑2D GUI元素位置 + - `editGUIScale(self, gui_element, axis, value)`: 编辑GUI元素缩放 + - `_update2DImageWidth(self, gui_element, width)`: 更新2D图片宽度 + - `_update2DImageHeight(self, gui_element, height)`: 更新2D图片高度 + - `_update2DImageScale(self, gui_element, scale)`: 更新2D图片缩放 + - `_update3DImageScale(self, gui_element, axis, scale)`: 更新3D元素缩放 + - `_selectGUIColor(self, gui_element)`: 选择GUI元素的字体颜色 + - `_updateGUITextColor(self, gui_element, color)`: 更新GUI元素的字体颜色 + - `_updateGUIScaleY(self, gui_element, scale_y)`: 更新GUI元素Y轴缩放 + - `_updateGUIScaleZ(self, gui_element, scale_z)`: 更新GUI元素Z轴缩放 + - `update2DImageTexture(self, image_element, texture_path)`: 更新2D图片纹理 + - `_updateScriptPropertyPanel(self, game_object)`: 更新脚本属性面板 + - `_toggleScriptEnabled(self, script_component)`: 切换脚本启用状态 + - `updateLightPropertyPanel(self, model)`: 更新光源属性面板 + - `_updateLightPosition(self, light_object, node_path, axis, value)`: 更新光源位置 + - `_updateLightRotation(self, light_object, node_path, axis, value)`: 更新光源旋转 + - `_updateLightEnergy(self, light_object, value)`: 更新光源强度 + - `_updateLightRadius(self, light_object, value)`: 更新光源半径 + - `_updateLightFOV(self, light_Object, value)`: 更新聚光灯视野角度 + - `_updateLightTemperature(self, light_object, value)`: 更新光源色温 + - `_updateLightInnerRadius(self, light_object, value)`: 更新点光源内半径 + - `_updateLightShaowResolution(self, light_object, value)`: 更新阴影分辨率 + - `_updateLightNearPlane(self, light_object, value)`: 更新近平面距离 + - `_updateLightCastsShadows(self, light_object, casts_shadows)`: 更新光源是否投射阴影 + - `_updateLightScale(self, node_path, axis, value)`: 更新光源节点缩放 + - `_generateUniqueMaterialNames(self, materials, model_name)`: 生成唯一的材质名称 + - `_updateModelMaterialPanel(self, model)`: 模型材质属性 + - `_updateMaterialBaseColor(self, material, component, value)`: 更新材质基础颜色 + - `_updateMaterialTransparency(self, material, alpha_value)`: 更新材质透明度 + - `_updateMaterialRoughness(self, material, value)`: 更新材质粗糙度 + - `_updateMaterialMetallic(self, material, value)`: 更新材质金属性 + - `_updateMaterialIOR(self, material, value)`: 更新材质折射率 + - `_getMaterialStatus(self, material)`: 获取材质状态描述 + - `_getTextureModeString(self, mode)`: 获取纹理模式的字符串表示 + - `_checkAndAdjustMaterialProperty(self, material, property_name, current_value, texture_type)`: 检查并智能调整材质属性值 + - `_getOrCreateMaterialBaseColor(self, material)`: 智能获取或创建材质的基础颜色 + - `_selectDiffuseTexture(self, material_title)`: 漫反射贴图 + - `_selectNormalTexture(self, material)`: 选择法线贴图 + - `_selectRoughnessTexture(self, material)`: 选择粗糙度贴图 + - `_selectMetallicTexture(self, material)`: 选择金属性贴图 + - `_selectIORTexture(self, material)`: 选择IOR贴图 + - `_selectParallaxTexture(self, material)`: 选择视差贴图 + - `_selectEmissionTexture(self, material)`: 选择自发光贴图 + - `_selectAOTexture(self, material)`: 选择环境光遮蔽贴图 + - `_selectAlphaTexture(self, material)`: 选择透明度贴图 + - `_selectDetailTexture(self, material)`: 选择细节贴图 + - `_selectGlossTexture(self, material)`: 选择光泽贴图 + - `_applyDiffuseTexture(self, material_title, texture_path)`: 应用漫反射贴图 + - `_applyNormalTexture(self, material, texture_path)`: 应用法线贴图 + - `_applyRoughnessTexture_FINAL(self, material, texture_path)`: 应用粗糙度贴图 + - `_hasNormalTexture(self, node)`: 检查节点是否有法线贴图 + - `_applySmartPBREffect(self, node, effect_file="effects/default.yaml")`: 智能应用PBR效果 + - `_verifyTextureInShader(self, node, texture_type, expected_sort)`: 验证纹理是否在shader中正确处理 + - `_ensureEnhancedPBREffect(self, node)`: 确保节点使用增强的PBR效果 + - `_createWhiteDiffuseTexture(self, node)`: 创建白色漫反射纹理 + - `_applyMetallicTexture(self, material, texture_path)`: 应用金属性贴图 + - `_applyIORTexture(self, material, texture_path)`: 应用IOR贴图 + - `_applyParallaxTexture(self, material, texture_path)`: 应用视差贴图 + - `_ensureNormalMappingEnabled(self, model)`: 确保模型启用了法线映射功能 + - `_ensurePBREffectEnabled(self, model)`: 确保模型启用了完整的PBR效果 + - `_ensurePBREffectEnabledWithParallax(self, model)`: 确保模型启用了完整的PBR效果,包括视差映射 + - `_ensurePBREffectEnabledWithMetallic(self, model)`: 确保模型启用了支持金属性贴图的PBR效果 + - `_ensurePBREffectEnabledWithDirectMetallic(self, model)`: 确保模型启用了支持金属性贴图直接控制的PBR效果 + - `_onMetallicModeChanged(self, material, mode_index)`: 处理金属性控制模式变化 + - `_ensurePBREffectEnabledWithAdditiveMetallic(self, model)`: 确保模型启用了支持金属性贴图叠加控制的PBR效果 + - `_ensurePBREffectEnabledWithEmission(self, model)`: 确保模型启用了支持自发光贴图的PBR效果 + - `_ensurePBREffectEnabledWithAlpha(self, model)`: 确保模型启用了支持透明度的PBR效果 + - `_ensurePBREffectEnabledWithRoughness(self, model)`: 确保模型启用了支持粗糙度贴图的PBR效果 + - `_ensurePBREffectEnabledStable(self, model)`: 确保模型启用了稳定的PBR效果 + - `_applyEmissionTexture(self, material, texture_path)`: 应用自发光贴图 + - `_applyAOTexture(self, material, texture_path)`: 应用环境光遮蔽贴图 + - `_applyAlphaTexture(self, material, texture_path)`: 应用透明度贴图 + - `_applyDetailTexture(self, material, texture_path)`: 应用细节贴图 + - `_applyGlossTexture(self, material, texture_path)`: 应用光泽贴图 + - `_clearConflictingTextureStages(self, node)`: 清理可能冲突的纹理阶段 + - `_findNodeWithMaterial(self, target_material)`: 查找使用指定材质的节点 + - `_findMaterialAndNodeByTitle(self, material_title)`: 根据材质标题查找对应的材质和节点 + - `_findSpecificGeomNodeWithMaterial(self, model, target_material)`: 查找使用指定材质的具体几何节点 + - `_findSpecificGeomNodeForMaterial(self, target_material)`: 查找使用指定材质的具体几何节点 + - `_findGeomNodeWithMaterial(self, model, target_material)`: 查找使用指定材质的具体几何节点 + - `_displayCurrentTextures(self, material, material_layout, current_row)`: 显示当前材质的贴图信息 + - `_applyToAllMaterials(self, model, property_name, value)`: 将属性应用到模型的所有材质 + - `_addShadingModelPanel(self, material, material_layout, current_row)`: 添加着色模型选择面板 + - `_onShadingModelChanged(self, material, model_index)`: 处理着色模型变化 + - `_updateShadingModel(self, material, model_index)`: 更新着色模型 + - `_addTransparencyPanel(self, material, material_layout, current_row)`: 添加透明度控制面板 + - `_updateTransparency(self, material, opacity_value)`: 更新不透明度值 + - `_updateMaterialAlphaForTransparency(self, material, opacity_slider)`: 为透明度更新材质Alpha + - `_applyTransparentRenderingEffect(self)`: 为当前选中的模型应用透明渲染效果 + - `_addEmissionPanel(self, material, material_layout, current_row)`: 添加自发光控制面板 + - `_updateEmissionStrength(self, material, strength)`: 更新自发光强度 + - `_addMaterialPresetPanel(self, material, material_layout, current_row)`: 添加材质预设面板 + - `_detectCurrentPreset(self, material)`: 检测当前材质最接近的预设 + - `_applyMaterialPreset(self, material, preset_name)`: 应用材质预设 + - `_apply_transparent_effect(self)`: 为当前选中的模型应用透明渲染效果 + - `_refreshMaterialUI(self)`: 刷新材质 UI 显示 + - `_addBatchOperationsPanel(self, model)`: 添加批量操作面板 + - `_batchSetRoughness(self, model)`: 批量设置粗糙度 + - `_applyMetallicTexture_NEW(self, material, texture_path)`: 应用金属性贴图 + - `_hasMetallicTexture(self, node)`: 检查节点是否有金属性贴图 + - `_applyDefaultNormalTexture(self, node)`: 应用RenderPipeline的默认法线贴图 + - `_needsAlphaTesting(self, node)`: 检查节点是否需要透明度测试 + - `_addSunAzimuthPanel(self)`: 添加太阳方位角控制面板 + - `_onSunAzimuthSliderChanged(self, value)`: 滑块值改变时的回调 + - `_onSunAzimuthSpinboxChanged(self, value)`: 数值框值改变时的回调 + - `_onSunAltitudeSliderChanged(self, value)`: 太阳高度角滑块值改变时的回调 + - `_onSunAltitudeSpinboxChanged(self, value)`: 太阳高度角数值框值改变时的回调 + - `_setSunPreset(self, preset_name)`: 设置太阳预设位置 + - `_applySunAzimuth_new(self, azimuth_value)`: 应用太阳方位角 + - `_applySunAltitude(self, altitude_value)`: 应用太阳高度角 + - `_updateDayTimeEditorSetting(self, plugin_name, setting_name, value)`: 直接更新Day Time Editor中的设置节点值 + - `_applySunAzimuth(self, azimuth_degrees)`: 应用太阳方位角到Day Time Editor中的Sun Azimuth节点 + - `_sendSunAzimuthViaFile(self, azimuth_degrees)`: 通过文件通信发送Sun Azimuth值到Day Time Editor + - `_addAnimationPanel(self, origin_model)`: 添加动画面板 + - `_buildSkeletalUI(self, origin_model, actor, layout)`: 构建骨骼动画UI + - `_getModelFormat(self, origin_model)`: 获取模型格式信息 + - `_processAnimationNames(self, origin_model, anim_names)`: 处理和分析动画名称 + - `_isLikelyBoneGroup(self, name)`: 判断动画名称是否更像骨骼组而不是动画序列 + - `_analyzeAnimationQuality(self, actor, anim_names, format_info)`: 分析动画质量和类型 + - `_getActor(self, origin_model)`: 获取Actor + - `_createFBXActor(self, origin_model, filepath)`: 专门为 FBX 文件创建 Actor + - `_convertFBXToActor(self, fbx_path)`: 将 FBX 转换为可用的 Actor + - `_fixFBXAnimations(self, actor, fbx_path)`: 修复 FBX Actor 的动画数据 + - `_deepAnalyzeFBX(self, fbx_path)`: 深度分析 FBX 文件并尝试提取动画 + - `_convertFBXManually(self, origin_model)`: 手动转换 FBX 动画 + - `_systemConvertFBX(self, fbx_path, progress=None)`: 使用系统工具转换 FBX + - `_playAnimation(self, origin_model)`: 播放动画 + - `_pauseAnimation(self, origin_model)`: 暂停动画 + - `_stopAnimation(self, origin_model)`: 停止动画 + - `_loopAnimation(self, origin_model)`: 循环动画 + - `_setAnimationSpeed(self, origin_model, speed)`: 设置动画播放倍速 + - `_dispatchAnimCommand(self, origin_model, cmd)`: 分发动画命令 + - `removeActorForModel(self, model)`: 删除 model 对应的 Actor + - `_addCollisionPanel(self, model)`: 添加碰撞检测面板 + - `_addCollisionParameterControls(self, model, layout, start_row, shape_type)`: 添加碰撞参数调整控件 + - `_createCollisionSpinBox(self, min_val, max_val, decimals=2)`: 创建碰撞参数调整用的SpinBox + - `_addSphereParameters(self, model, layout, start_row)`: 添加球形碰撞参数 + - `_addBoxParameters(self, model, layout, start_row)`: 添加盒型碰撞参数 + - `_addCapsuleParameters(self, model, layout, start_row)`: 添加胶囊体碰撞参数 + - `_addPlaneParameters(self, model, layout, start_row)`: 添加平面碰撞参数 + - `_hasCollision(self, model)`: 检查模型是否已有碰撞体 + - `_isCollisionVisible(self, model)`: 检查碰撞是否可见 + - `_toggleCollisionVisibility(self, model)`: 切换碰撞可见性 + - `_updateCollisionVisibilityButton(self, model)`: 更新碰撞可见性按钮状态 + - `_getCurrentCollisionShape(self, model)`: 获取当前模型的碰撞形状类型 + - `_setComboToShape(self, shape_type)`: 根据形状类型设置下拉框选择 + - `_getSelectedCollisionShape(self)`: 获取选中的碰撞形状类型 + - `_addCollisionAndUpdate(self, model)`: 添加指定形状的碰撞体并更新界面 + - `_removeCollisionAndUpdate(self, model)`: 移除模型的碰撞体并更新界面 + - `_findButtonRow(self, layout)`: 查找按钮应该在的行数 + - `_updateCollisionPanelState(self, model)`: 更新碰撞面板状态 + - `_loadCurrentCollisionParameters(self, model, shape_type)`: 加载当前碰撞参数到界面 + - `_getCollisionShapeCenter(self, solid)`: 从碰撞体形状中获取中心点 + - `_loadSphereParameters(self, solid)`: 加载球形参数 + - `_loadBoxParameters(self, solid)`: 加载盒型参数 + - `_loadCapsuleParameters(self, solid)`: 加载胶囊体参数 + - `_loadPlaneParameters(self, solid)`: 加载平面参数 + - `_updateCollisionPosition(self, model, axis, value)`: 更新碰撞位置偏移 + - `_updateSphereRadius(self, model, radius)`: 更新球形半径 + - `_updateBoxSize(self, model, dimension, value)`: 更新盒型尺寸 + - `_updateCapsuleRadius(self, model, radius)`: 更新胶囊体半径 + - `_updateCapsuleHeight(self, model, height)`: 更新胶囊体高度 + - `_updatePlaneNormal(self, model, axis, value)`: 更新平面法向量 + - `_recreateCollisionShape(self, model, shape_type, **kwargs)`: 重新创建碰撞形状 + - `_clearCollisionParameterControls(self)`: 清理碰撞参数控件 + - `_refreshCollisionPanel(self, model)`: 刷新整个碰撞面板 + - `_addParameterControlsToExistingPanel(self, model, shape_type)`: 向现有面板添加参数控件 + - `_addSphereParametersToExisting(self, model, layout, start_row)`: 向现有面板添加球形参数 + - `_addBoxParametersToExisting(self, model, layout, start_row)`: 向现有面板添加盒型参数 + - `_addCapsuleParametersToExisting(self, model, layout, start_row)`: 向现有面板添加胶囊体参数 + - `_addPlaneParametersToExisting(self, model, layout, start_row)`: 向现有面板添加平面参数 + - `_addVisibilityButtonToExistingPanel(self, model)`: 向现有面板添加可见性按钮 + - `_repositionButtons(self, new_row)`: 重新定位按钮位置 + - `_hideCollisionParameterControls(self)`: 隐藏碰撞参数控件 + +### 10. `ui/simple_maintenance_login.py` + +#### 类: SimpleMaintenanceLoginDialog +- **功能**: 简化的维修系统登录对话框 +- **信号**: + - `login_success`: 登录成功信号 +- **方法**: + - `__init__(self, parent=None)`: 初始化登录对话框 + - `setupUI(self)`: 设置用户界面,包括标题、登录表单、提示信息和按钮,应用样式和布局 + - `handle_login(self)`: 处理登录,验证账号密码,成功时发射login_success信号 + +#### 函数: test_simple_login +- **功能**: 测试简化登录界面 +- **方法**: + - `test_simple_login()`: 测试简化登录界面功能 + +### 11. `ui/widgets.py` + +#### 类: NewProjectDialog +- **功能**: 新建项目对话框 +- **方法**: + - `__init__(self, parent=None)`: 初始化新建项目对话框 + - `createTitleBar(self)`: 创建自定义标题栏 + - `_applyTitleBarIcons(self)`: 为标题栏按钮应用图标 + - `toggleMaximize(self)`: 切换窗口最大化/还原 + - `setWindowTitle(self, title)`: 设置窗口标题 + - `mousePressEvent(self, event)`: 鼠标按下事件 - 用于拖拽窗口 + - `mouseDoubleClickEvent(self, event)`: 双击标题栏切换最大化 + - `mouseMoveEvent(self, event)`: 鼠标移动事件 - 用于拖拽窗口 + - `mouseReleaseEvent(self, event)`: 鼠标释放事件 - 停止拖拽 + - `browsePath(self)`: 浏览选择项目路径 + - `validate(self)`: 验证输入并关闭对话框 + +#### 类: CustomPanda3DWidget +- **功能**: 自定义Panda3D显示部件 +- **方法**: + - `__init__(self, world, parent=None)`: 初始化自定义Panda3D显示部件 + - `getActualSize(self)`: 获取Qt部件的实际渲染尺寸 + - `dragEnterEvent(self, event)`: 处理拖拽进入事件 + - `dragMoveEvent(self, event)`: 处理拖拽移动事件 + - `dropEvent(self, event)`: 处理拖放事件 + - `wheelEvent(self, event)`: 处理滚轮事件 + - `mousePressEvent(self, event)`: 处理 Qt 鼠标按下事件 + - `mouseReleaseEvent(self, event)`: 处理 Qt 鼠标释放事件 + - `mouseMoveEvent(self, event)`: 处理 Qt 鼠标移动事件 + - `cleanup(self)`: 清理Panda3D资源 + +#### 类: CustomFileView +- **功能**: 自定义文件浏览器 +- **方法**: + - `__init__(self, world, parent=None)`: 初始化自定义文件浏览器 + - `setupUI(self)`: 初始化UI设置 + - `setupDragDrop(self)`: 设置拖拽功能 + - `startDrag(self, supportedActions)`: 开始拖拽操作 + - `mouseDoubleClickEvent(self, event)`: 双击标题栏切换最大化 + +#### 类: CustomAssetsTreeWidget +- **功能**: 自定义资源树形控件 +- **方法**: + - `__init__(self, world, parent=None)`: 初始化自定义资源树形控件 + - `showContextMenu(self, position)`: 显示右键菜单 + - `_saveExpandedState(self)`: 保存展开状态 + - `_restoreExpandedState(self, expanded_paths)`: 恢复展开状态 + - `_refreshWithStatePreservation(self)`: 刷新树形视图并保持状态 + - `createNewFolder(self, parent_item)`: 新建文件夹 + - `createNewFile(self, parent_item)`: 新建文件 + - `renameItem(self, item)`: 重命名文件或文件夹 + - `deleteItem(self, item)`: 删除文件或文件夹 + - `copyPath(self, filepath)`: 复制路径到剪贴板 + - `openFile(self, filepath)`: 打开文件 + - `showProperties(self, item)`: 显示属性面板 + - `setupUI(self)`: 初始化UI设置 + - `setupDragDrop(self)`: 设置拖拽功能 + - `getProjectRootPath(self)`: 获取项目根路径下的Resources文件夹,考虑跨平台 + - `load_file_tree(self)`: 加载树形视图 + - `addWatchedDirectory(self, directory)`: 添加监控目录 + - `removeWatchedDirectory(self, directory)`: 移除监控目录 + - `onDirectoryChanged(self, path)`: 目录发生变化时处理 + - `onFileChanged(self, path)`: 目录发生变化时的处理 + - `refreshView(self)`: 刷新视图 + - `load_directory_tree(self, path, parent_item, max_depth=3, current_depth=0)`: 递归加载目录树 + - `create_simple_tree_item(self, name, path, is_folder)`: 创建简单的树形项目 + - `get_file_icon(self, filename)`: 根据文件扩展名获取图标 + - `startDrag(self, supportedActions)`: 开始拖拽操作 + - `dragEnterEvent(self, event)`: 处理拖拽进入事件 + - `dragMoveEvent(self, event)`: 处理拖拽移动事件 + - `dropEvent(self, event)`: 处理拖放事件 + - `_moveFiles(self, source_paths, target_dir)`: 移动文件到目标目录 + - `_isChildOf(self, potential_child, potential_parent)`: 检查 potential_child 是否是 potential_parent 的子级 + +#### 类: CustomConsoleDockWidget +- **功能**: 自定义控制台停靠部件 +- **方法**: + - `__init__(self, world, parent=None)`: 初始化控制台UI + - `setupUI(self)`: 初始化控制台UI + - `updateFPS(self)`: 更新FPS显示 + - `setupConsoleRedirect(self)`: 设置控制台重定向 + - `addMessage(self, message, msg_type="INFO")`: 添加消息到控制台 + - `clearConsole(self)`: 清空控制台 + - `executeCommand(self)`: 执行命令 + - `cleanup(self)`: 清理资源 + +#### 类: ConsoleRedirect +- **功能**: 控制台重定向类 +- **方法**: + - `__init__(self, console_widget, stream_type)`: 初始化控制台重定向 + - `write(self, text)`: 重定向写入 + - `flush(self)`: 刷新缓冲区 + +#### 类: StyledMessageBox +- **功能**: 统一样式的消息框辅助类 +- **变量**: + - `MESSAGEBOX_STYLE`: 消息框样式 + - `INPUTDIALOG_STYLE`: 输入对话框样式 + - `BUTTON_STYLE`: 按钮样式 +- **方法**: + - `information(parent, title, message)`: 显示信息提示框 + - `question(parent, title, message, buttons=QMessageBox.Yes | QMessageBox.No, defaultButton=QMessageBox.No)`: 显示确认对话框 + - `warning(parent, title, message)`: 显示警告对话框 + - `critical(parent, title, message)`: 显示错误对话框 + - `getText(parent, title, label, text="")`: 显示样式统一的文本输入对话框 + +#### 类: UniversalMessageDialog +- **功能**: 通用消息对话框类 - 支持不同图标和按钮配置 +- **枚举**: + - `SUCCESS`: 成功图标 + - `WARNING`: 警告图标 + - `ERROR`: 错误图标 + - `INFO`: 信息图标 +- **方法**: + - `__init__(self, parent, title, message, message_type=INFO, show_cancel=True, confirm_text="确认", cancel_text="取消", icon_size=QSize(20, 20))`: 初始化通用消息对话框 + - `_get_message_icon(self)`: 根据消息类型获取对应图标 + - `_setup_styles(self)`: 设置对话框样式 + - `_create_ui(self, message)`: 构建用户界面 + - `_create_title_bar(self)`: 创建自定义标题栏 + - `_apply_title_bar_icons(self)`: 应用标题栏图标 + - `setWindowTitle(self, title)`: 设置窗口标题 + - `mousePressEvent(self, event)`: 鼠标按下事件 - 用于拖拽窗口 + - `mouseMoveEvent(self, event)`: 鼠标移动事件 - 用于拖拽窗口 + - `mouseReleaseEvent(self, event)`: 鼠标释放事件 - 停止拖拽 + - `show_success(parent, title, message, show_cancel=False, confirm_text="确认")`: 显示成功消息对话框 + - `show_warning(parent, title, message, show_cancel=True, confirm_text="确认", cancel_text="取消")`: 显示警告消息对话框 + - `show_error(parent, title, message, show_cancel=False, confirm_text="确认")`: 显示错误消息对话框 + - `show_info(parent, title, message, show_cancel=True, confirm_text="确认", cancel_text="取消")`: 显示信息消息对话框 + +#### 类: StyledTextInputDialog +- **功能**: 与新建项目样式一致的文本输入对话框 +- **方法**: + - `__init__(self, parent, title, label_text="", placeholder="", default_text="")`: 初始化文本输入对话框 + - `_createTitleBar(self)`: 创建标题栏 + - `_applyTitleBarIcons(self)`: 应用标题栏图标 + - `setWindowTitle(self, title)`: 设置窗口标题 + - `_onAccept(self)`: 确认按钮点击事件 + - `text(self)`: 获取输入文本 + - `mousePressEvent(self, event)`: 鼠标按下事件 + - `mouseMoveEvent(self, event)`: 鼠标移动事件 + - `mouseReleaseEvent(self, event)`: 鼠标释放事件 + +#### 类: CustomTreeWidget +- **功能**: 自定义场景树部件 +- **方法**: + - `__init__(self, world, parent=None)`: 初始化自定义场景树部件 + - `initData(self)`: 初始化变量 + - `setupUI(self)`: 初始化UI设置 + - `setupDragDrop(self)`: 设置拖拽功能 + - `setupContextMenu(self)`: 设置右键菜单 + - `showContextMenu(self, position)`: 显示右键菜单 + - `dropEvent(self, event)`: 处理拖放事件 + - `_ensureUnderSceneRoot(self, item)`: 确保节点在场景根节点下 + - `isValidParentChild(self, dragged_item, target_item)`: 检查是否是有效的父子关系 + - `_validateGUITypeCompatibility(self, dragged_item, target_item)`: 验证GUI元素类型兼容性 + - `_getRootNode(self, item)`: 获取树中节点的根节点项 + - `dragEnterEvent(self, event)`: 处理拖入事件 + - `dragMoveEvent(self, event)`: 处理拖动事件 + - `keyPressEvent(self, event)`: 处理键盘按键事件 + - `_preprocess_light_items_for_deletion(self, selected_items)`: 预处理灯光节点删除 + - `delete_items(self, selected_items)`: 删除选中的item + - `delete_item(self, panda_node)`: 删除指定节点 panda3D + - `clear_tree(self)`: 清空UI树 + - `_apply_font_to_item(self, item)`: 根据节点层级设置字体大小 + - `_apply_font_recursively(self, item)`: 递归应用字体样式 + - `_handle_rows_inserted(self, parent_index, first, last)`: 在插入新节点时自动调整字体 + - `_cleanup_panda_node_resources(self, panda_node)`: 清理与Panda3D节点相关的所有资源 + - `update_item_name(self, text, item)`: 树节点名字 + - `_findSceneRoot(self)`: 查找场景根节点 + - `create_model_items(self, model: NodePath)`: 创建模型项 + - `_add_all_children_unconditionally(self, parent_item: QTreeWidgetItem, node_path: NodePath)`: 无条件地、递归地添加一个节点下的所有子节点 + - `_generateUniqueNodeName(self, base_name, parent_node)`: 生成唯一的节点名称 + - `add_node_to_tree_widget(self, node, parent_item, node_type)`: 将node元素添加到树形控件 + - `update_selection_and_properties(self, node, qt_item)`: 更新选择状态和属性面板 + - `get_target_parents_for_creation(self)`: 获取创建目标的父节点列表 + - `_isValidParentForNewNode(self, item)`: 检查节点是否适合作为新节点的父节点 + - `get_target_parents_for_gui_creation(self)`: 获取GUI创建目标的父节点列表 + - `isValidParentForGUI(self, item)`: 检查节点是否适合作为GUI元素的父节点 + - `is_gui_element(self, node)`: 判断节点是否是GUI元素 + - `calculate_relative_gui_position(self, pos, parent_gui)`: 计算相对于GUI父节点的位置 + - `add_existing_node(self, panda_node, node_type="SCENE_NODE", parent_item=None)`: 将已存在的Panda3D节点添加到Qt树形控件中 + - `_findRenderItem(self)`: 查找render根节点项目 + - `create_item(self, node_type="empty", selected_items=None)`: 创建不同类型的场景节点 + - `_determineParentItems(self, selected_items)`: 确定父节点项目列表 + - `_setupNewNodeDefaults(self, node)`: 设置新节点的默认属性 + - `_createEmptyNode(self, parent_node, parent_item)`: 创建空节点 + - `_createSpotLightNode(self, parent_node, parent_item)`: 创建聚光灯节点 + - `_createPointLightNode(self, parent_node, parent_item)`: 创建点光源节点 \ No newline at end of file diff --git a/源代码架构说明.md b/源代码架构说明.md new file mode 100644 index 00000000..318bfaf0 --- /dev/null +++ b/源代码架构说明.md @@ -0,0 +1,1026 @@ +# 源代码整体架构说明 + +## 1. 项目整体结构 + +项目根目录包含以下主要目录和文件: + +- `core/`: 核心模块,包含世界类、VR系统、选择系统、工具管理器、脚本系统等核心功能。 +- `gui/`: GUI管理模块,负责2D和3D GUI元素的创建与管理。 +- `project/`: 项目管理模块,处理项目文件的加载、保存等操作。 +- `scene/`: 场景管理模块,负责场景中模型的管理。 +- `QPanda3D/`: Panda3D与PyQt5集成库,提供Panda3D渲染窗口的Qt部件封装。 +- `scripts/`: 脚本文件目录,包含各种可挂载到对象的Python脚本。 +- `core/vr/`: VR子系统,包含VR相关的配置、交互、性能、渲染、测试、跟踪和可视化模块。 +- `render_pipeline/` 渲染管线模块 +- `config/`: 配置文件目录,包含VR设置等配置文件。 +- `Resources/`: 资源文件目录,包含模型、纹理等资源。 +- `requirements/`: 依赖管理文件目录。 +- `ui/`: UI组件和主窗口定义。 +- `icons/`: 图标资源文件。 +- `templates/`: 模板文件。 +- `tex/`: 纹理资源文件。 +- `vr_actions/`: VR动作相关文件。 +- `main.py`: 程序主入口文件。 +- `Start_Run.py`: 启动脚本。 + +## 2. 各模块详细说明 + +接下来将详细说明每个模块及其包含的文件。 + +### 2.1 core模块 + +`core/`目录包含了应用程序的核心功能模块,是整个系统的基础。 + +#### 2.1.1 核心文件 + +1. `__init__.py`: Python包初始化文件。 + +2. `world.py`: + - 定义了`CoreWorld`类,是整个3D世界的基础类。 + - 负责基本的场景设置,如相机、光照、坐标轴、地面网格等。 + - 提供资源路径管理和中文字体支持。 + +3. `vr_manager.py`: + - VR管理器主文件,负责VR系统的初始化和管理。 + - 集成了OpenVR/SteamVR支持,处理HMD和控制器的跟踪。 + - 管理VR渲染系统,支持普通渲染和RenderPipeline高级渲染。 + - 包含VR交互系统(抓取、传送、摇杆控制等)。 + +4. `selection.py`: + - 选择系统模块。 + - 实现了3D场景中对象的选择功能。 + - 提供选择历史管理和选择对象的可视化。 + +5. `tool_manager.py`: + - 工具管理器模块。 + - 管理各种编辑工具(选择、移动、旋转、缩放等)。 + - 处理工具状态和工具切换逻辑。 + +6. `script_system.py`: + - 脚本系统模块。 + - 管理游戏对象的脚本挂载和执行。 + - 提供脚本的热重载功能。 + +7. `gui_manager.py`: + - GUI管理器模块。 + - 负责2D和3D GUI元素的创建和管理。 + - 提供GUI编辑模式和属性面板集成。 + +8. `terrain_manager.py`: + - 地形管理器模块。 + - 处理3D地形的创建、编辑和渲染。 + - 支持高度图导入和LOD更新。 + +9. `collision_manager.py`: + - 碰撞管理器模块。 + - 管理场景中的碰撞检测和响应。 + - 提供碰撞历史和统计功能。 + +10. `event_handler.py`: + - 事件处理器模块。 + - 处理用户输入事件和系统事件。 + - 提供事件分发和处理机制。 + +11. `Command_System.py`: + - 命令系统模块。 + - 实现命令模式,支持撤销/重做功能。 + - 管理命令的执行和历史记录。 + +12. `InfoPanelManager.py`: + - 信息面板管理器模块。 + - 管理场景中信息面板的显示和更新。 + - 提供性能监控和调试信息显示。 + +13. `patrol_system.py`: + - 巡检系统模块。 + - 实现自动化巡检路径和逻辑。 + - 支持巡检点设置和巡检过程监控。 + +14. `assembly_interaction.py`: + - 装配交互模块。 + - 处理复杂装配体的交互逻辑。 + - 支持装配和拆卸操作。 + +15. `CustomMouseController.py`: + - 自定义鼠标控制器模块。 + - 提供定制化的鼠标操作控制。 + - 支持不同的鼠标交互模式。 + +16. `maintenance_gui.py`: + - 维护GUI模块。 + - 提供设备维护相关的GUI界面。 + - 支持维护任务管理和状态显示。 + +#### 2.1.2 VR子模块 + +`core/vr/`目录包含了VR系统的各个子模块: + +1. `config/`: VR配置管理模块。 + - `__init__.py`: Python包初始化文件。 + - `vr_config.py`: VR配置管理器模块,负责VR设置的保存、加载和管理,包括渲染模式、分辨率缩放、质量预设等参数的配置和管理。 + - `joystick_config.py`: VR摇杆配置模块,提供摇杆交互的配置选项和预设,包括不同的转向模式和灵敏度设置、传送参数调整等。 + - `shadow_stage.py`: VR专用阴影Stage模块,为VR渲染管线提供阴影支持,采用智能复用策略,可选择复用主Pipeline的ShadowAtlas或创建独立的ShadowAtlas。 + - `vr_settings.json`: VR配置文件,存储VR系统的各种设置参数。 + +2. `interaction/`: VR交互系统模块。 + - `__init__.py`: Python包初始化文件。 + - `actions.py`: VR动作系统模块,基于OpenVR Action系统,提供高级的输入处理和动作映射,包括VR动作清单管理、按钮和轴输入处理、触觉反馈、动作集管理等。 + - `grab.py`: VR抓取交互模块,提供VR手柄与3D场景的交互功能,包括射线投射和碰撞检测、对象选择和高亮、对象抓取和移动、UI交互、距离抓取等。 + - `joystick.py`: VR摇杆交互系统模块,提供类似SteamVR的摇杆交互功能,包括摇杆左右转向(旋转视角)、摇杆向前传送预览(抛物线轨迹)、松开摇杆执行传送、死区处理和平滑控制等。 + - `teleport.py`: VR传送系统模块,提供VR传送功能,包括抛物线轨迹计算和可视化、传送点有效性检测、传送执行、可视化反馈(抛物线、落点标记)等。 + +3. `performance/`: VR性能监控模块。 + - `__init__.py`: Python包初始化文件,导出VRPerformanceMonitor类。 + - `monitoring.py`: VR性能监控子系统,负责VR应用的性能监控、GPU计时、管线统计和性能诊断,包含完整的性能报告、监控核心、GPU计时、管线统计、诊断工具、调试控制、配置、查询和控制方法。 + - `optimization.py`: VR对象池和优化系统,负责VR系统中的对象池管理、垃圾回收控制、分辨率缩放和性能模式控制。 + - `MIGRATION_REPORT.md`: VR性能监控子系统迁移完成报告,详细记录了性能监控功能的迁移过程和验证结果。 + +4. `rendering/`: VR渲染模块。 + - `__init__.py`: Python包初始化文件。 + - `stages.py`: VR专用渲染Stages模块,为VR创建简化但完整的渲染管线,支持GBuffer生成(延迟渲染基础)、光照计算(复用主Pipeline的LightManager)、最终合成(tone mapping + gamma校正),包含VRGBufferStage、VRLightingStage、VRAmbientStage、VRFinalStage和VRPipelineController类。 + +5. `testing/`: VR测试模块。 + - `__init__.py`: Python包初始化文件,导出VRTestMode类。 + - `test_mode.py`: VR测试调试子系统,负责VR测试模式、HUD显示和性能测试功能,包含测试模式控制、纹理管理、显示系统、HUD系统、状态查询和性能测试方法,支持VR内容直接显示在屏幕上、实时性能监控HUD、左眼/右眼/立体三种显示模式、渐进式测试功能和性能测试工具。 + +6. `tracking/`: VR跟踪模块。 + - `__init__.py`: Python包初始化文件。 + - `controllers.py`: VR手柄管理模块,基于panda3d-openvr参考实现,提供完整的VR手柄追踪和交互功能,包括手柄位置和姿态追踪、按钮和触摸板输入处理、手柄可视化和射线显示、震动反馈支持,包含VRController基类和LeftController、RightController子类。 + +7. `visualization/`: VR可视化模块。 + - `__init__.py`: Python包初始化文件。 + - `controllers.py`: VR可视化模块,提供VR手柄和交互元素的高级可视化功能,包括手柄3D模型渲染、交互射线显示、按钮状态可视化、触摸板和扳机反馈,包含VRControllerVisualizer类。 + - `effects.py`: VR Effects管理器模块,为VR场景中的模型自动应用RenderPipeline Effects,包含VREffectsManager类和setup_vr_model_effects便捷函数。 + +#### 2.1.3 资源文件 + +- `RotationHandleFull.fbx`, `RotationHandleQuarter.fbx`, `TranslateArrowHandle.fbx`, `UniformScaleHandle.fbx`: 工具控制器的3D模型文件。 + +### 2.2 gui模块 + +`gui/`目录包含了GUI管理系统,负责2D和3D GUI元素的创建和管理。 + +#### 2.2.1 核心文件 + +1. `__init__.py`: Python包初始化文件,导出`GUIManager`类。 + +2. `gui_manager.py`: + - GUI管理器主文件,定义了`GUIManager`类。 + - 负责各种GUI元素的创建,包括: + - 2D GUI元素:按钮、标签、输入框、2D图像、2D视频屏幕等 + - 3D GUI元素:3D文本、3D图像、视频屏幕、球形视频、虚拟屏幕等 + - 提供GUI编辑模式,支持在独立预览窗口中查看和编辑GUI元素。 + - 支持GUI元素的属性编辑、复制、删除等操作。 + - 集成Cesium地图视图功能,支持在GUI中嵌入地图显示。 + - 提供GUI元素在场景树中的管理与属性面板集成。 + - 支持视频播放控制功能,包括播放、暂停、停止和时间控制。 + - 支持2D和3D图像纹理更新功能。 + +### 2.3 project模块 + +`project/`目录包含了项目管理系统,负责项目的生命周期管理。 + +#### 2.3.1 核心文件 + +1. `__init__.py`: Python包初始化文件,导出`ProjectManager`和`NewProjectDialog`类。 + +2. `project_manager.py`: + - 项目管理器主文件,定义了`ProjectManager`类。 + - 负责项目的完整生命周期管理,包括: + - 创建新项目:提供项目创建向导,生成标准项目结构 + - 打开项目:加载项目配置和场景文件 + - 保存项目:保存场景数据和项目配置 + - 打包项目:将项目打包为可执行文件,支持多平台发布 + - 提供项目配置管理,维护项目元数据(创建时间、修改时间、版本等)。 + - 集成文件浏览器,支持项目文件的可视化管理。 + - 提供窗口标题更新等辅助功能。 + - 支持通过路径直接打开项目功能。 + - 在打包过程中复制Resources、scripts和RenderPipelineFile目录。 + - 保存GUI元素信息到JSON文件供打包后使用。 + +### 2.4 QPanda3D模块 + +`QPanda3D/`目录包含了Panda3D与PyQt5集成的库,实现了在Qt应用程序中嵌入Panda3D渲染窗口的功能。 + +#### 2.4.1 核心文件 + +1. `__init__.py`: Python包初始化文件,导出主要的类。 + +2. `QPanda3DWidget.py`: + - 定义了`QPanda3DWidget`类,这是一个继承自`QWidget`的自定义Qt控件。 + - 负责在Qt界面中显示Panda3D渲染内容。 + - 处理用户输入事件(鼠标、键盘)并将其转换为Panda3D事件。 + - 集成定时器系统,定期更新Panda3D场景和重绘Qt控件。 + - 提供窗口尺寸调整功能,保持渲染内容与窗口尺寸同步。 + - 实现了保持宽高比的图像缩放和居中显示功能。 + - 添加了异常处理机制,静默处理TransformState断言错误和其他异常。 + +3. `Panda3DWorld.py`: + - 定义了`Panda3DWorld`类,继承自`ShowBase`。 + - 负责初始化Panda3D环境,设置离屏渲染模式。 + - 集成RenderPipeline渲染管线,提供高质量的渲染效果。 + - 创建用于Qt显示的纹理输出接口。 + - 提供鼠标控制器集成。 + - 添加了VR性能优化配置,包括单缓冲、禁用VSync等设置。 + - 实现了窗口尺寸调整功能,支持同步Panda3D窗口尺寸到Qt窗口尺寸。 + +4. `QMouseWatcherNode.py`: + - 定义了`QMouseWatcherNode`类,继承自`MouseWatcher`。 + - 实现了通过父级QWidget获取鼠标位置和状态的功能。 + - 为Panda3D提供鼠标输入数据。 + +5. `QPanda3D_Keys_Translation.py`: + - 定义了`QPanda3D_Key_translation`字典。 + - 实现了Qt键盘按键到Panda3D键盘事件的映射。 + +6. `QPanda3D_Buttons_Translation.py`: + - 定义了`QPanda3D_Button_translation`字典。 + - 实现了Qt鼠标按键到Panda3D鼠标事件的映射。 + +7. `QPanda3D_Modifiers_Translation.py`: + - 定义了`QPanda3D_Modifier_translation`字典。 + - 实现了Qt修饰键(如Shift、Ctrl、Alt)到Panda3D修饰键的映射。 + +### 2.5 scene模块 + +`scene/`目录包含了场景管理系统,负责场景中模型、光源、地形等元素的管理。 + +#### 2.5.1 核心文件 + +1. `__init__.py`: Python包初始化文件,导出`SceneManager`类。 + +2. `scene_manager.py`: + - 场景管理器主文件,定义了`SceneManager`类。 + - 负责场景中各种元素的管理,包括: + - 模型导入:支持多种3D模型格式(FBX、GLB等),提供模型转换和优化功能 + - 光源管理:创建和管理聚光灯、点光源等不同类型的光源 + - 场景保存和加载:支持将整个场景保存为BAM文件格式,并能完整加载恢复 + - 碰撞检测:为模型设置碰撞体,支持选择和交互功能 + - Cesium 3D Tiles集成:支持加载和显示地理空间数据 + - GUI元素管理:与GUI系统集成,管理场景中的GUI元素 + - 提供模型处理功能,包括材质应用、缩放标准化、位置调整等。 + - 支持异步模型加载,提升用户体验。 + - 集成脚本系统,支持为场景元素挂载和管理脚本。 + +3. `util.py`: + - 工具模块,提供跨平台路径处理功能。 + - 定义了`CrossPlatformPathHandler`类,用于处理不同操作系统的路径问题。 + - 提供路径标准化、文件搜索、错误处理等辅助功能。 + +### 2.6 scripts模块 + +`scripts/`目录包含了各种可挂载到场景对象的脚本文件,用于实现对象的动态行为。 + +#### 2.6.1 核心概念 + +脚本系统基于组件化设计,每个脚本都是一个继承自`ScriptBase`的Python类。脚本可以被挂载到场景中的任何对象上,为对象添加动态行为。 + +#### 2.6.2 脚本文件说明 + +1. `example_script.py`: + - 示例脚本,演示了脚本的基本结构和生命周期方法。 + - 实现了简单的旋转功能。 + +2. `Rotate_H_Script.py`: + - H轴(偏航)旋转脚本,实现对象绕Y轴的机器人式旋转。 + - 支持设置旋转角度范围、速度、停顿时间等参数。 + - 提供多种预设模式(慢速、快速、平滑)。 + +3. `Rotate_P_Script.py`: + - P轴(俯仰)旋转脚本,实现对象绕X轴的机器人式旋转。 + - 支持设置旋转角度范围、速度、停顿时间等参数。 + - 提供多种预设模式(慢速、快速、平滑)。 + +4. `Rotate_R_Script.py`: + - R轴(滚动)旋转脚本,实现对象绕Z轴的旋转。 + - 简化版旋转脚本,适用于基本的旋转需求。 + +5. `MoverScript.py`: + - 移动脚本,实现对象在指定轴向上的来回移动。 + - 支持设置移动距离、速度和移动轴(X/Y/Z)。 + +6. `ScalerScript.py`: + - 缩放脚本,实现对象的呼吸式缩放效果。 + - 支持设置基础缩放、缩放幅度、缩放速度等参数。 + - 提供统一缩放和非统一缩放选项。 + +7. `ColorChangerScript.py`: + - 颜色变化脚本,实现对象颜色的动态变化。 + - 支持多种颜色模式:彩虹、脉冲、淡入淡出、闪烁。 + - 可调整颜色变化速度和强度。 + +8. `BouncerScript.py`: + - 跳跃脚本,实现对象的上下跳跃效果。 + - 支持多种跳跃类型:正弦波、绝对值正弦波、方波。 + - 可设置跳跃高度和速度。 + +9. `ComboAnimatorScript.py`: + - 组合动画脚本,可以同时控制对象的多个属性(位置、旋转、缩放)。 + - 支持复杂的动画序列和时间控制。 + +10. `FollowerScript.py`: + - 跟随脚本,使对象跟随另一个对象或鼠标位置移动。 + - 支持平滑跟随和延迟跟随效果。 + +11. `TestMover.py`、`TestRotator.py`、`TestScaler.py`: + - 测试脚本,用于验证脚本系统的基本功能。 + +12. `a.py`、`R_P.py`、`R_R.py`、`Rotate_H_Script.py`: + - 其他功能脚本,实现特定的动画或交互效果。 + +### 2.7 RenderPipelineFile模块 + +`RenderPipelineFile/`目录包含了Panda3D的高级渲染管线实现,提供了基于物理的着色、延迟渲染和后处理效果。 + +#### 2.7.1 核心特性 + +- 基于物理的着色(Physically Based Shading) +- 延迟渲染(Deferred Rendering) +- 高级后处理效果和框架 +- 时间ofday系统 +- 插件系统 + +#### 2.7.2 目录结构 + +1. `config/`: 配置文件目录 + - `debugging.yaml`: 调试配置 + - `panda3d-config.prc`: Panda3D配置 + - `pipeline.yaml`: 渲染管线配置 + - `plugins.yaml`: 插件配置 + - `stages.yaml`: 渲染阶段配置 + - `task-scheduler.yaml`: 任务调度配置 + +2. `data/`: 数据资源目录 + - `builtin_models/`: 内置模型资源 + - `skybox/`: 天空盒模型 + - `default_cubemap/`: 默认立方体贴图资源 + - `source/`: 源文件目录 + - `source_2/`: 源文件目录2 + - `cubemap.txo.pz`: 立方体贴图文件 + - `filter.compute.glsl`: 过滤计算着色器 + - `filter.py`: 过滤脚本 + - `empty_textures/`: 空纹理资源 + - `empty_basecolor.png`: 空基础颜色纹理 + - `empty_normal.png`: 空法线纹理 + - `empty_roughness.png`: 空粗糙度纹理 + - `empty_specular.png`: 空镜面反射纹理 + - `README.md`: 说明文档 + - `environment_brdf/`: 环境BRDF资源 + - `res/`: 资源目录 + - `slices/`: 切片目录 + - `slices_coat/`: 涂层切片目录 + - `slices_metal/`: 金属切片目录 + - `generate_reference.py`: 生成参考脚本 + - `run_mitsuba.bat`: Mitsuba运行脚本 + - `film_grain/`: 胶片颗粒资源 + - `generate.py`: 生成脚本 + - `grain.compute.glsl`: 颗粒计算着色器 + - `grain.txo.pz`: 颗粒纹理文件 + - `font/`: 字体资源 + - 包含Roboto字体系列的各种样式和粗细版本 + - `roboto-LICENSE.txt`: 字体许可证 + - `gui/`: GUI资源 + - 包含各种GUI元素的纹理和图标资源 + - `ies_profiles/`: IES光照配置文件 + - 包含多种光照配置文件,如area_light.ies、bollard.ies等 + - `PREVIEWS.jpg`: 预览图片 + - `README.md`: 说明文档 + - `Materials/`: 材质资源 + - `GroundMaterial.yaml`: 地面材质配置 + - `panda3d_patches/`: Panda3D补丁 + - `prev-model-view-matrix-part2.diff`: 模型视图矩阵补丁2 + - `prev-model-view-matrix.diff`: 模型视图矩阵补丁 + - `README.md`: 说明文档 + - `scripts/`: 脚本资源 + - `example_script.py`: 示例脚本 + - `setup/`: 安装设置资源 + - `check_requirements.py`: 检查依赖脚本 + - `generate_txo_files.py`: TXO文件生成脚本 + - `install.flag`: 安装标志文件 + +3. `effects/`: 效果定义目录 + - `basic_instancing.yaml`: 基础实例化效果 + - `debug_metallic.yaml`: 金属度调试效果 + - `debug_roughness.yaml`: 粗糙度调试效果 + - `default.yaml`: 默认效果 + - `material_blend4.yaml`: 四材质混合效果 + - `metallic_only.yaml`: 仅金属度效果 + - `pbr_additive_metallic.yaml`: PBR附加金属度效果 + - `pbr_direct_metallic.yaml`: PBR直接金属度效果 + - `pbr_direct_roughness.yaml`: PBR直接粗糙度效果 + - `pbr_extended.yaml`: 扩展PBR效果 + - `pbr_with_emission.yaml`: 带自发光的PBR效果 + - `pbr_with_metallic.yaml`: 带金属度的PBR效果 + - `pbr_with_normal.yaml`: 带法线贴图的PBR效果 + - `pbr_with_roughness.yaml`: 带粗糙度的PBR效果 + - `pbr_with_textures.yaml`: 带纹理的PBR效果 + - `roughness_only.yaml`: 仅粗糙度效果 + - `simple_texture_test.yaml`: 简单纹理测试效果 + - `simple_transparent.yaml`: 简单透明效果 + - `skybox.yaml`: 天空盒效果 + - `terrain-effect.yaml`: 地形效果 + - `test_metallic_debug.yaml`: 金属度调试测试效果 + - `test_roughness_debug.yaml`: 粗糙度调试测试效果 + +4. `rpcore/`: 核心渲染管线模块 + - `__init__.py`: Python包初始化文件 + - `common_resources.py`: 通用资源管理 + - `effect.py`: 效果管理 + - `globals.py`: 全局变量和设置 + - `gpu_command_queue.py`: GPU命令队列 + - `image.py`: 图像处理 + - `light_manager.py`: 光源管理器 + - `loader.py`: 资源加载器 + - `mount_manager.py`: 挂载管理器 + - `render_pipeline.py`: 渲染管线主类 + - `render_stage.py`: 渲染阶段基类 + - `render_target.py`: 渲染目标管理 + - `rpobject.py`: RP对象基类 + - `stage_manager.py`: 阶段管理器 + + - `gui/`: GUI相关组件 + - `__init__.py`: 初始化文件 + - `buffer_viewer.py`: 缓冲区查看器 + - `checkbox_collection.py`: 复选框集合 + - `checkbox.py`: 复选框组件 + - `debugger.py`: 调试器 + - `draggable_window.py`: 可拖拽窗口 + - `error_message_display.py`: 错误信息显示 + - `exposure_widget.py`: 曝光控件 + - `fps_chart.py`: FPS图表 + - `labeled_checkbox.py`: 带标签的复选框 + - `loading_screen.py`: 加载屏幕 + - `pipe_viewer.py`: 管道查看器 + - `pixel_inspector.py`: 像素检查器 + - `README.md`: 说明文档 + - `render_mode_selector.py`: 渲染模式选择器 + - `slider.py`: 滑块控件 + - `sprite.py`: 精灵组件 + - `text_node.py`: 文本节点 + - `text.py`: 文本组件 + - `texture_preview.py`: 纹理预览器 + + - `native/`: 原生C++模块接口 + - `__init__.py`: 初始化文件 + - `source/`: C++源代码目录 + - `config_rsnative.cpp/h/N`: 原生配置模块 + - `gpu_command_list.cpp/h`: GPU命令列表 + - `gpu_command.cpp/h/I`: GPU命令 + - `ies_dataset.cpp/h`: IES数据集 + - `internal_light_manager.cpp/h/I`: 内部光源管理器 + - `pointer_slot_storage.h`: 指针槽存储 + - `pssm_camera_rig.cpp/h/I`: PSSM相机支架 + - `pssm_helper.cpp/h`: PSSM辅助函数 + - `README.md`: 说明文档 + - `rp_light.cpp/h/I`: RP光源基类 + - `rp_point_light.cpp/h/I`: RP点光源 + - `rp_spot_light.cpp/h/I`: RP聚光灯 + - `shadow_atlas.cpp/h/I`: 阴影图集 + - `shadow_manager.cpp/h/I`: 阴影管理器 + - `shadow_source.cpp/h/I`: 阴影源 + - `tag_state_manager.cpp/h/I`: 标签状态管理器 + - `.gitignore`: Git忽略文件 + - `config.ini`: 配置文件 + - `update_module_builder.py`: 模块构建器更新脚本 + - `use_cxx.flag`: C++使用标志文件 + + - `pluginbase/`: 插件基础类 + - `__init__.py`: 初始化文件 + - `base_plugin.py`: 插件基类 + - `day_manager.py`: 日间管理器 + - `day_setting_types.py`: 日间设置类型 + - `manager.py`: 管理器 + - `setting_types.py`: 设置类型 + + - `pynative/`: Python原生接口 + - `__init__.py`: 初始化文件 + - `gpu_command_list.py`: GPU命令列表Python接口 + - `gpu_command.py`: GPU命令Python接口 + - `ies_dataset.py`: IES数据集Python接口 + - `internal_light_manager.py`: 内部光源管理器Python接口 + - `pointer_slot_storage.py`: 指针槽存储Python接口 + - `pssm_camera_rig.py`: PSSM相机支架Python接口 + - `README.md`: 说明文档 + - `rp_light.py`: RP光源Python接口 + - `rp_point_light.py`: RP点光源Python接口 + - `rp_spot_light.py`: RP聚光灯Python接口 + - `shadow_atlas.py`: 阴影图集Python接口 + - `shadow_manager.py`: 阴影管理器Python接口 + - `shadow_source.py`: 阴影源Python接口 + - `tag_state_manager.py`: 标签状态管理器Python接口 + + - `shader/`: 着色器管理 + - `ibl/`: 基于图像的光照着色器 + - `cubemap_diffuse_filter.frag.glsl`: 立方体贴图漫反射过滤片段着色器 + - `cubemap_diffuse.frag.glsl`: 立方体贴图漫反射片段着色器 + - `cubemap_specular_filter_first.frag.glsl`: 立方体贴图镜面反射过滤第一阶段片段着色器 + - `cubemap_specular_filter.frag.glsl`: 立方体贴图镜面反射过滤片段着色器 + - `cubemap_specular_prefilter_first.frag.glsl`: 立方体贴图镜面反射预过滤第一阶段片段着色器 + - `cubemap_specular_prefilter.frag.glsl`: 立方体贴图镜面反射预过滤片段着色器 + - `includes/`: 包含文件 + - `brdf.inc.glsl`: BRDF函数包含文件 + - `color_spaces.inc.glsl`: 颜色空间包含文件 + - `common_functions.inc.glsl`: 通用函数包含文件 + - `envprobes.inc.glsl`: 环境探针包含文件 + - `forward_shading.inc.glsl`: 前向渲染包含文件 + - `gaussian_weights.inc.glsl`: 高斯权重包含文件 + - `gbuffer.inc.glsl`: G缓冲包含文件 + - `halton_sequences.inc.glsl`: Halton序列包含文件 + - `ies_lighting.inc.glsl`: IES光照包含文件 + - `importance_sampling.inc.glsl`: 重要性采样包含文件 + - `light_classification.inc.glsl`: 光源分类包含文件 + - `light_culling.inc.glsl`: 光源剔除包含文件 + - `light_data.inc.glsl`: 光源数据包含文件 + - `light_data.struct.glsl`: 光源数据结构包含文件 + - `lighting_pipeline.inc.glsl`: 光照管线包含文件 + - `lights.inc.glsl`: 光源包含文件 + - `material.inc.glsl`: 材质包含文件 + - `noise.inc.glsl`: 噪声包含文件 + - `nonviewspace_shading_pipeline.inc.glsl`: 非视图空间着色管线包含文件 + - `normal_mapping.inc.glsl`: 法线映射包含文件 + - `normal_packing.inc.glsl`: 法线打包包含文件 + - `poisson_disk.inc.glsl`: 泊松圆盘包含文件 + - `sampling_sequences.inc.glsl`: 采样序列包含文件 + - `shadows.inc.glsl`: 阴影包含文件 + - `skin_shading.inc.glsl`: 皮肤着色包含文件 + - `source_data.struct.glsl`: 源数据结构包含文件 + - `temporal_resolve.inc.glsl`: 时间解析包含文件 + - `tonemapping.inc.glsl`: 色调映射包含文件 + - `transforms.inc.glsl`: 变换包含文件 + - `upsampling.inc.glsl`: 上采样包含文件 + - `vertex_output.struct.glsl`: 顶点输出结构包含文件 + - `templates/`: 模板文件 + - `envmap.frag.glsl`: 环境贴图片段着色器模板 + - `forward.frag.glsl`: 前向渲染片段着色器模板 + - `gbuffer.frag.glsl`: G缓冲片段着色器模板 + - `shadow.frag.glsl`: 阴影片段着色器模板 + - `vertex.vert.glsl`: 顶点着色器模板 + - `voxelize.frag.glsl`: 体素化片段着色器模板 + - `ambient_stage.frag.glsl`: 环境阶段片段着色器 + - `apply_lights.frag.glsl`: 应用光照片段着色器 + - `bilateral_blur.frag.glsl`: 双边模糊片段着色器 + - `bilateral_halfres_blur.frag.glsl`: 半分辨率双边模糊片段着色器 + - `bilateral_upscale.frag.glsl`: 双边上采样片段着色器 + - `collect_used_cells.frag.glsl`: 收集使用单元片段着色器 + - `combine_velocity.frag.glsl`: 合并速度片段着色器 + - `cull_lights.frag.glsl`: 剔除光源片段着色器 + - `default_gui_shader.vert.glsl`: 默认GUI顶点着色器 + - `default_post_process_instanced.vert.glsl`: 默认后期处理实例化顶点着色器 + - `default_post_process.vert.glsl`: 默认后期处理顶点着色器 + - `downscale_depth.frag.glsl`: 深度下采样片段着色器 + - `final_present_stage.frag.glsl`: 最终呈现阶段片段着色器 + - `final_stage.frag.glsl`: 最终阶段片段着色器 + - `flag_used_cells.frag.glsl`: 标记使用单元片段着色器 + - `fps_chart_update.compute.glsl`: FPS图表更新计算着色器 + - `fps_chart.compute.glsl`: FPS图表计算着色器 + - `group_lights.frag.glsl`: 分组光源片段着色器 + - `pixel_inspector.frag.glsl`: 像素检查器片段着色器 + - `process_command_queue.frag.glsl`: 处理命令队列片段着色器 + - `render_pipeline_base.inc.glsl`: 渲染管线基础包含文件 + - `tiled_culling.vert.glsl`: 平铺剔除顶点着色器 + - `upscale_stage.frag.glsl`: 上采样阶段片段着色器 + - `view_frustum_cull.frag.glsl`: 视锥剔除片段着色器 + - `visualize_exposure.compute.glsl`: 可视化曝光计算着色器 + + - `stages/`: 渲染阶段实现 + - `__init__.py`: 初始化文件 + - `ambient_stage.py`: 环境阶段 + - `apply_lights_stage.py`: 应用光源阶段 + - `collect_used_cells_stage.py`: 收集使用单元阶段 + - `combine_velocity_stage.py`: 合并速度阶段 + - `cull_lights_stage.py`: 剔除光源阶段 + - `downscale_z_stage.py`: Z缓冲下采样阶段 + - `final_stage.py`: 最终阶段 + - `flag_used_cells_stage.py`: 标记使用单元阶段 + - `gbuffer_stage.py`: G缓冲阶段 + - `shadow_stage.py`: 阴影阶段 + - `update_previous_pipes_stage.py`: 更新前一管道阶段 + - `upscale_stage.py`: 上采样阶段 + + - `util/`: 工具函数 + - `__init__.py`: 初始化文件 + - `cubemap_filter.py`: 立方体贴图过滤器 + - `display_shader_builder.py`: 显示着色器构建器 + - `generic.py`: 通用工具函数 + - `ies_profile_loader.py`: IES配置文件加载器 + - `movement_controller.py`: 移动控制器 + - `network_communication.py`: 网络通信 + - `post_process_region.py`: 后期处理区域 + - `shader_input_blocks.py`: 着色器输入块 + - `smooth_connected_curve.py`: 平滑连接曲线 + - `submodule_downloader.py`: 子模块下载器 + - `task_scheduler.py`: 任务调度器 + +5. `rpplugins/`: 插件目录 + - `__init__.py`: 初始化文件 + - `ao/`: 环境光遮蔽插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `ao_stage.py`: AO阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `bloom/`: 泛光效果插件 + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `bloom_stage.py`: 泛光阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `clouds/`: 云渲染插件 + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `apply_clouds_stage.py`: 应用云阶段 + - `cloud_voxel_stage.py`: 云体素阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `color_correction/`: 颜色校正插件 + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `auto_exposure_stage.py`: 自动曝光阶段 + - `color_correction_stage.py`: 颜色校正阶段 + - `config.yaml`: 配置文件 + - `manual_exposure_stage.py`: 手动曝光阶段 + - `plugin.py`: 插件主文件 + - `sharpen_stage.py`: 锐化阶段 + - `tonemapping_stage.py`: 色调映射阶段 + - `dof/`: 景深效果插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `dof_stage.py`: 景深阶段 + - `plugin.py`: 插件主文件 + - `env_probes/`: 环境探针插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `apply_envprobes_stage.py`: 应用环境探针阶段 + - `config.yaml`: 配置文件 + - `cull_probes_stage.py`: 剔除探针阶段 + - `environment_capture_stage.py`: 环境捕捉阶段 + - `environment_probe.py`: 环境探针类 + - `plugin.py`: 插件主文件 + - `probe_manager.py`: 探针管理器 + - `forward_shading/`: 前向渲染插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `forward_stage.py`: 前向渲染阶段 + - `plugin.py`: 插件主文件 + - `fxaa/`: FXAA抗锯齿插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `fxaa_stage.py`: FXAA阶段 + - `plugin.py`: 插件主文件 + - `motion_blur/`: 运动模糊插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `motion_blur_stage.py`: 运动模糊阶段 + - `plugin.py`: 插件主文件 + - `plugin_prefab/`: 插件预制件 + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `demo_stage.py`: 演示阶段 + - `plugin.py`: 插件主文件 + - `pssm/`: 平行分割阴影贴图插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `pssm_dist_shadow_stage.py`: PSSM距离阴影阶段 + - `pssm_scene_shadow_stage.py`: PSSM场景阴影阶段 + - `pssm_shadow_stage.py`: PSSM阴影阶段 + - `pssm_stage.py`: PSSM阶段 + - `scattering/`: 散射效果插件 + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `godray_stage.py`: 光线阶段 + - `plugin.py`: 插件主文件 + - `scattering_envmap_stage.py`: 散射环境贴图阶段 + - `scattering_methods.py`: 散射方法 + - `scattering_stage.py`: 散射阶段 + - `skin_shading/`: 皮肤着色插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `skin_shading_stage.py`: 皮肤着色阶段 + - `sky_ao/`: 天空AO插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `ao_stage.py`: AO阶段 + - `capture_stage.py`: 捕捉阶段 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `smaa/`: SMAA抗锯齿插件 + - `__init__.py`: 初始化文件 + - `resources/`: 资源目录 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `jitters.py`: 抖动工具 + - `LICENSE.txt`: 许可证文件 + - `plugin.py`: 插件主文件 + - `smaa_stage.py`: SMAA阶段 + - `ssr/`: 屏幕空间反射插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `ssr_stage.py`: SSR阶段 + - `volumetrics/`: 体积渲染插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `volumetrics_stage.py`: 体积渲染阶段 + - `vxgi/`: VXGI全局光照插件 + - `__init__.py`: 初始化文件 + - `shader/`: 着色器目录 + - `config.yaml`: 配置文件 + - `plugin.py`: 插件主文件 + - `voxelization_stage.py`: 体素化阶段 + - `vxgi_stage.py`: VXGI阶段 + +6. `toolkit/`: 工具集 + - `bake_gi/`: GI烘焙工具 + - `resources/`: 资源目录 + - `bake.py`: 烘焙脚本 + - `display.py`: 显示脚本 + - `day_time_editor/`: 日间时间编辑器 + - `ui/`: UI目录 + - `curve_widget.py`: 曲线控件 + - `main.py`: 主程序 + - `import_sun_data/`: 导入太阳数据工具 + - `import_data.py`: 导入数据脚本 + - `README.md`: 说明文档 + - `material_editor/`: 材质编辑器 + - `ui/`: UI目录 + - `main.py`: 主程序 + - `pathtracing_reference/`: 路径追踪参考 + - `config/`: 配置目录 + - `res/`: 资源目录 + - `batch_compare.py`: 批量比较脚本 + - `generate_difference.py`: 生成差异脚本 + - `get_brightness.py`: 获取亮度脚本 + - `README.md`: 说明文档 + - `run_mitsuba.bat`: Mitsuba运行脚本 + - `run_renderpipeline.py`: 运行渲染管线脚本 + - `plugin_configurator/`: 插件配置器 + - `ui/`: UI目录 + - `main.py`: 主程序 + - `poisson_disk_generator/`: 泊松圆盘生成器 + - `source/`: 源代码目录 + - `.gitignore`: Git忽略文件 + - `config.ini`: 配置文件 + - `generate_poisson_disk.py`: 生成泊松圆盘脚本 + - `update_module_builder.py`: 更新模块构建器脚本 + - `render_service/`: 渲染服务 + - `config/`: 配置目录 + - `resources/`: 资源目录 + - `example_usage.py`: 使用示例 + - `README.md`: 说明文档 + - `service.py`: 服务脚本 + - `rp_distributor/`: RP分发器 + - `launch.templ.bat`: 启动模板脚本 + - `main.py`: 主程序 + - `README.md`: 说明文档 + +7. `rplibs/`: 第三方库 + - `colorama/`: 终端颜色库 + - `progressbar/`: 进度条库 + - `yaml/`: YAML解析库 + - `__init__.py`: 初始化文件 + - `pyqt_imports.py`: PyQt导入工具 + - `six-source.txt`: Six库源信息 + - `six.py`: Six库兼容工具 + +#### 2.7.3 根目录文件 + + 1. `__init__.py`: Python包初始化文件 + 2. `.flake8`: Flake8配置文件,用于代码风格检查 + 3. `.gitignore`: Git忽略文件,指定不纳入版本控制的文件和目录 + 4. `.pylintrc`: Pylint配置文件,用于代码质量检查 + 5. `.travis.yml`: Travis CI配置文件,用于持续集成 + 6. `Default_NRM_2K.png`: 默认法线贴图,2K分辨率 + 7. `Default_Rough.png`: 默认粗糙度贴图 + 8. `LICENSE.txt`: 许可证文件,采用MIT许可证 + 9. `README.md`: 项目说明文档,包含项目介绍、特性列表和使用说明 + 10. `setup.py`: 安装和配置脚本,负责编译原生模块、生成必要的资源文件和配置渲染管线环境 + 11. `start_daytime_editor.py`: 启动日间编辑器脚本,用于运行时间ofday编辑器 + 12. `start_plugin_configurator.py`: 启动插件配置器脚本,用于运行插件配置工具 + +### 2.8 ui模块 + +`ui/`目录包含了用户界面组件和主窗口定义。 + +#### 2.8.1 核心文件 + +1. `__init__.py`: Python包初始化文件。 + +2. `assembly_disassembly_config_simple.py`: + - 简化版装配拆卸配置界面模块,提供装配拆卸功能的简单配置界面。 + +3. `assembly_disassembly_config.py`: + - 装配拆卸配置界面模块,提供复杂的装配拆卸配置功能。 + +4. `icon_manager_gui.py`: + - 图标管理GUI模块,负责管理界面中的图标资源。 + +5. `icon_manager.py`: + - 图标管理器模块,提供图标资源的加载和管理功能。 + +6. `interface_manager.py`: + - 界面管理器模块,负责管理整个应用程序的界面组件。 + - 处理窗口布局、控件管理和用户交互。 + +7. `main_window.py`: + - 主窗口模块,定义了应用程序的主窗口结构和布局。 + - 负责创建和管理主界面的各种组件。 + +8. `maintenance_system.py`: + - 维护系统模块,提供设备维护相关的界面功能。 + +9. `property_panel.py`: + - 属性面板模块,负责对象属性的显示和编辑。 + - 提供对象属性的可视化编辑界面。 + +10. `simple_maintenance_login.py`: + - 简化版维护登录界面模块,提供维护功能的登录界面。 + +11. `widgets.py`: + - 自定义控件模块,包含各种自定义的UI控件。 + - 提供Panda3D控件和文件视图等特殊控件。 + +### 2.9 templates模块 + +`templates/`目录包含项目模板文件。 + +#### 2.9.1 核心文件 + +1. `main_template.py`: + - 主程序模板文件,提供了一个基础的Panda3D应用程序框架。 + - 包含场景加载、GUI元素处理、动画播放、脚本管理等功能的模板实现。 + - 提供了相机控制、鼠标点击处理、帧率显示等基础功能。 + +### 2.10 主程序文件 + +#### 2.10.1 核心文件 + +1. `main.py`: + - 程序主入口文件,定义了`MyWorld`类,继承自`CoreWorld`。 + - 集成了所有核心系统:选择系统、事件处理、工具管理、脚本管理、GUI管理、场景管理、项目管理、地形管理、属性面板、界面管理、VR管理、碰撞管理等。 + - 提供了兼容性属性和功能代理方法,将各种操作委托给相应的管理器。 + - 实现了键盘事件处理、巡检系统控制、模型导入等核心功能。 + - 包含了与UI模块的集成,通过`setup_main_window`函数创建主窗口。 + +2. `Start_Run.py`: + - 程序启动脚本,负责初始化Python路径和依赖。 + - 自动添加项目根目录、RenderPipeline、RenderPipelineFile和icons目录到Python路径。 + - 处理命令行参数并启动主程序。 + - 提供了项目路径参数的处理功能。 + + +## 3 非代码文件 +### 3.1 config模块 + + `config/`目录包含项目的配置文件,主要用于存储系统设置和参数。 + +#### 3.1.1 核心文件 + + 1. `vr_settings.json`: + - VR系统配置文件,定义了VR渲染模式和质量参数。 + - 包含渲染模式设置(render_pipeline)、分辨率缩放、管线分辨率缩放、质量预设等参数。 + - 包含Pipeline VR配置,如阴影、环境光遮蔽(AO)、泛光(Bloom)、运动模糊等效果的启用状态和质量设置。 + +### 3.2 Resources模块 + + `Resources/`目录包含了项目使用的各种资源文件。 + +#### 3.2.1 目录结构 + + 1. `animations/`: + - 动画资源目录,当前为空。 + + 2. `c/`: + - 测试/临时资源目录,包含一些测试文件和子目录。 + + 3. `icons/`: + - 图标资源目录,包含各种纹理图标: + - `heightmap.png`: 高度图纹理 + - `test_metallic_stripes.png`: 金属度测试纹理 + - `test_roughness_checkerboard.png`: 粗糙度棋盘纹理 + - `test_roughness_circle.png`: 粗糙度圆形纹理 + - `test_roughness_gradient.png`: 粗糙度渐变纹理 + + 4. `materials/`: + - 材质资源目录,当前为空。 + + 5. `models/`: + - 3D模型资源目录,包含示例模型文件: + - `DancingTwerk.glb`: 跳舞动画模型 + - `Haqijingzhu.glb`: 花旗镜柱模型 + - `JQB_auto_converted.glb`: 自动转换的JQB模型 + - `Women_2.glb`: 女性角色模型 + + 6. `textures/`: + - 纹理资源目录,当前为空。 + + 7. `a`: + - 根目录下的测试文件。 + +### 3.3 requirements模块 + + `requirements/`目录包含项目的依赖管理文件,用于环境配置和部署。 + +#### 3.3.1 核心文件 + + 1. `requirements.txt`: + - 项目的完整依赖列表文件,包含所有必要的Python包及其版本。 + - 包括Panda3D、PyQt5、PySide6、Pillow、pyassimp等核心依赖。 + - 还包含系统级包如apturl、bcrypt、dbus-python等。 + + 2. `clean-requirements.txt`: + - 精简的依赖列表文件,仅包含项目核心依赖。 + - 包括Panda3D、PyQt5、PySide6、Pillow、python-dotenv、pyassimp等。 + + 3. `environment.yml`: + - Conda环境配置文件,定义了项目环境的依赖。 + - 指定了Python版本为3.10,并包含了pip依赖项。 + + 4. `conda-requirements.txt`: + - Conda显式依赖文件,用于创建完全相同的环境。 + - 包含了系统级依赖如libgcc、openssl、ncurses等。 + + 5. `DEPLOYMENT_README.md`: + - 项目部署指南文档,提供详细的部署说明。 + - 包含使用Conda和virtualenv两种部署方法。 + - 提供了项目依赖说明和跨平台注意事项。 + - 包含常见问题解答。 + + +### 3.4 icons模块 + + `icons/`目录包含应用程序使用的各种图标资源文件。 + +#### 3.4.1 图标文件 + + 1. `close_icon.png`: 关闭按钮图标 + 2. `delete_fail_icon.png`: 删除失败图标 + 3. `down_arrows.png`: 向下箭头图标 + 4. `left_arrows.png`: 向左箭头图标 + 5. `logo.png`: 应用程序Logo图标 + 6. `minimize_icon.png`: 最小化按钮图标 + 7. `move_tool.png`: 移动工具图标 + 8. `property_select_image.png`: 属性选择图像 + 9. `right_arrows.png`: 向右箭头图标 + 10. `rotate_tool.png`: 旋转工具图标 + 11. `scale_tool.png`: 缩放工具图标 + 12. `select_tool.png`: 选择工具图标 + 13. `solid_down_arrows.png`: 实心向下箭头图标 + 14. `solid_right_arrows.png`: 实心向右箭头图标 + 15. `success_icon.png`: 成功图标 + 16. `up_arrows.png`: 向上箭头图标 + 17. `warning_icon.png`: 警告图标 + 18. `windowing_icon.png`: 窗口化图标 + +### 3.5 tex模块 + + `tex/`目录包含基础纹理资源文件。 + +#### 3.5.1 纹理文件 + + 1. `empty_basecolor.png`: 空白基础颜色纹理 + 2. `empty_normal.png`: 空白法线纹理 + 3. `empty_roughness.png`: 空白粗糙度纹理 + 4. `empty_specular.png`: 空白镜面反射纹理 + + 这些纹理通常用作默认或占位纹理,在材质系统中作为基础资源。 + +### 3.6 vr_actions模块 + + `vr_actions/`目录包含VR动作系统配置文件。 + +#### 3.6.1 核心文件 + + 1. `actions.json`: + - VR动作定义文件,定义了VR系统中所有可用的动作。 + - 包括姿态、触发器、握把、菜单、系统按钮、触摸板、操纵杆等动作。 + - 定义了动作集和默认绑定关系,支持多语言本地化。 + + 2. `bindings_index.json`: + - Valve Index控制器绑定配置文件。 + - 定义了Index控制器的按钮、操纵杆、触摸板等输入的映射关系。 + + 3. `bindings_oculus.json`: + - Oculus Touch控制器绑定配置文件。 + - 定义了Oculus Touch控制器的按钮、扳机、操纵杆等输入的映射关系。 + + 4. `bindings_vive.json`: + - HTC Vive控制器绑定配置文件。 + - 定义了Vive控制器的按钮、触控板等输入的映射关系。