diff --git a/.idea/EG.iml b/.idea/EG.iml index c1574376..ba1e88cf 100644 --- a/.idea/EG.iml +++ b/.idea/EG.iml @@ -3,8 +3,9 @@ + - + diff --git a/.idea/misc.xml b/.idea/misc.xml index 51b9fc17..b4e62875 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/RenderPipelineFile/config/daytime.yaml b/RenderPipelineFile/config/daytime.yaml index 54447c55..84b58692 100644 --- a/RenderPipelineFile/config/daytime.yaml +++ b/RenderPipelineFile/config/daytime.yaml @@ -17,7 +17,7 @@ control_points: scattering: sun_intensity: [[[0.0000000000,0.0000000000],[0.0041666667,0.0000000000],[0.0083333333,0.0000000000],[0.0125000000,0.0000000000],[0.0166666667,0.0000000000],[0.0208333333,0.0000000000],[0.0250000000,0.0000000000],[0.0291666667,0.0000000000],[0.0333333333,0.0000000000],[0.0375000000,0.0000000000],[0.0416666667,0.0000000000],[0.0458333333,0.0000000000],[0.0500000000,0.0000000000],[0.0541666667,0.0000000000],[0.0583333333,0.0000000000],[0.0625000000,0.0000000000],[0.0666666667,0.0000000000],[0.0708333333,0.0000000000],[0.0750000000,0.0000000000],[0.0791666667,0.0000000000],[0.0833333333,0.0000000000],[0.0875000000,0.0000000000],[0.0916666667,0.0000000000],[0.0958333333,0.0000000000],[0.1000000000,0.0000000000],[0.1041666667,0.0000000000],[0.1083333333,0.0000000000],[0.1125000000,0.0000000000],[0.1166666667,0.0000000000],[0.1208333333,0.0000000000],[0.1250000000,0.0000000000],[0.1291666667,0.0000000000],[0.1333333333,0.0000000000],[0.1375000000,0.0000000000],[0.1416666667,0.0000000000],[0.1458333333,0.0000000000],[0.1500000000,0.0000000000],[0.1541666667,0.0000000000],[0.1583333333,0.0000028805],[0.1625000000,0.0003577724],[0.1666666667,0.0013331400],[0.1708333333,0.0029671803],[0.1750000000,0.0052963381],[0.1791666667,0.0083550556],[0.1833333333,0.0121755589],[0.1875000000,0.0167876159],[0.1916666667,0.0222183530],[0.1958333333,0.0284919947],[0.2000000000,0.0356297193],[0.2041666667,0.0436494349],[0.2083333333,0.0525656099],[0.2125000000,0.0623891610],[0.2166666667,0.0731272461],[0.2208333333,0.0847831708],[0.2250000000,0.0973563167],[0.2291666667,0.1108419698],[0.2333333333,0.1252313631],[0.2375000000,0.1405115250],[0.2416666667,0.1566653434],[0.2458333333,0.1736715009],[0.2500000000,0.1915046014],[0.2541666667,0.2101350464],[0.2583333333,0.2295292930],[0.2625000000,0.2496498145],[0.2666666667,0.2704552670],[0.2708333333,0.2919006662],[0.2750000000,0.3139375192],[0.2791666667,0.3365139497],[0.2833333333,0.3595750662],[0.2875000000,0.3830630359],[0.2916666667,0.4069173972],[0.2958333333,0.4310753462],[0.3000000000,0.4554720417],[0.3041666667,0.4800408236],[0.3083333333,0.5047136020],[0.3125000000,0.5294212108],[0.3166666667,0.5540936424],[0.3208333333,0.5786605298],[0.3250000000,0.6030514553],[0.3291666667,0.6271963182],[0.3333333333,0.6510256858],[0.3375000000,0.6744711982],[0.3416666667,0.6974659988],[0.3458333333,0.7199450163],[0.3500000000,0.7418453485],[0.3541666667,0.7631067095],[0.3583333333,0.7836717291],[0.3625000000,0.8034862953],[0.3666666667,0.8224999302],[0.3708333333,0.8406661079],[0.3750000000,0.8579425235],[0.3791666667,0.8742914270],[0.3833333333,0.8896799131],[0.3875000000,0.9040801386],[0.3916666667,0.9174695289],[0.3958333333,0.9298310650],[0.4000000000,0.9411533765],[0.4041666667,0.9514309312],[0.4083333333,0.9606641691],[0.4125000000,0.9688595571],[0.4166666667,0.9760296330],[0.4208333333,0.9821930708],[0.4250000000,0.9873746114],[0.4291666667,0.9916050060],[0.4333333333,0.9949209310],[0.4375000000,0.9973647924],[0.4416666667,0.9989845508],[0.4458333333,0.9998334497],[0.4500000000,0.9999696949],[0.4541666667,0.9994560801],[0.4583333333,0.9983595429],[0.4625000000,0.9967506613],[0.4666666667,0.9947030614],[0.4708333333,0.9922927758],[0.4750000000,0.9895975125],[0.4791666667,0.9866958610],[0.4833333333,0.9836664262],[0.4875000000,0.9805868867],[0.4916666667,0.9775330316],[0.4958333333,0.9745777179],[0.5000000000,0.9717898417],[0.5041666667,0.9692332877],[0.5083333333,0.9669658924],[0.5125000000,0.9650384806],[0.5089595376,0.9690650222],[0.5208333333,0.9623666659],[0.5250000000,0.9616814371],[0.5291666667,0.9614534423],[0.5333333333,0.9616877089],[0.5375000000,0.9623790807],[0.5416666667,0.9635123329],[0.5458333333,0.9650624244],[0.5500000000,0.9669949804],[0.5541666667,0.9692669864],[0.5583333333,0.9718275065],[0.5625000000,0.9746185969],[0.5666666667,0.9775762863],[0.5708333333,0.9806315864],[0.5750000000,0.9837115661],[0.5791666667,0.9867403433],[0.5833333333,0.9896401655],[0.5875000000,0.9923323562],[0.5916666667,0.9947382579],[0.5958333333,0.9967800977],[0.6000000000,0.9983817820],[0.6041666667,0.9994696263],[0.6083333333,0.9999730028],[0.6125000000,0.9998249266],[0.6166666667,0.9989625601],[0.6208333333,0.9973276624],[0.6250000000,0.9948669567],[0.6291666667,0.9915324664],[0.6333333333,0.9872817545],[0.6375000000,0.9820781426],[0.6416666667,0.9758908775],[0.6458333333,0.9686952146],[0.6500000000,0.9604725211],[0.6541666667,0.9512102537],[0.6583333333,0.9409019858],[0.6625000000,0.9295473441],[0.6666666667,0.9171518878],[0.6708333333,0.9037270619],[0.6750000000,0.8892899902],[0.6791666667,0.8738633008],[0.6833333333,0.8574749656],[0.6875000000,0.8401579787],[0.6916666667,0.8219502453],[0.6958333333,0.8028941798],[0.7000000000,0.7830364456],[0.7041666667,0.7624277344],[0.7083333333,0.7411222520],[0.7125000000,0.7191776044],[0.7166666667,0.6966542563],[0.7208333333,0.6736152714],[0.7250000000,0.6501259629],[0.7291666667,0.6262533880],[0.7333333333,0.6020661121],[0.7375000000,0.5776338043],[0.7416666667,0.5530267796],[0.7458333333,0.5283156992],[0.7500000000,0.5035711751],[0.7541666667,0.4788634341],[0.7583333333,0.4542618347],[0.7625000000,0.4298347613],[0.7666666667,0.4056490351],[0.7708333333,0.3817697830],[0.7750000000,0.3582600107],[0.7791666667,0.3351803495],[0.7833333333,0.3125888445],[0.7875000000,0.2905406366],[0.7916666667,0.2690876955],[0.7958333333,0.2482787388],[0.8000000000,0.2281588906],[0.8041666667,0.2087696425],[0.8083333333,0.1901486315],[0.8125000000,0.1723295359],[0.8166666667,0.1553419918],[0.8208333333,0.1392115328],[0.8250000000,0.1239595144],[0.8291666667,0.1096030703],[0.8333333333,0.0961551918],[0.8375000000,0.0836246599],[0.8416666667,0.0720161369],[0.8458333333,0.0613302273],[0.8500000000,0.0515635598],[0.8541666667,0.0427088803],[0.8583333333,0.0347551990],[0.8625000000,0.0276878920],[0.8666666667,0.0214889271],[0.8708333333,0.0161369711],[0.8750000000,0.0116076130],[0.8791666667,0.0078735477],[0.8833333333,0.0049047927],[0.8875000000,0.0026688977],[0.8916666667,0.0011311782],[0.8958333333,0.0002549473],[0.9000000000,0.0000000000],[0.9041666667,0.0000000000],[0.9083333333,0.0000000000],[0.9125000000,0.0000000000],[0.9166666667,0.0000000000],[0.9208333333,0.0000000000],[0.9250000000,0.0000000000],[0.9291666667,0.0000000000],[0.9333333333,0.0000000000],[0.9375000000,0.0000000000],[0.9416666667,0.0000000000],[0.9458333333,0.0000000000],[0.9500000000,0.0000000000],[0.9541666667,0.0000000000],[0.9583333333,0.0000000000],[0.9625000000,0.0000000000],[0.9666666667,0.0000000000],[0.9708333333,0.0000000000],[0.9750000000,0.0000000000],[0.9791666667,0.0000000000],[0.9833333333,0.0000000000],[0.9875000000,0.0000000000],[0.9916666667,0.0000000000],[0.9958333333,0.0000000000]]] sun_color: [[[0.5010435645,0.5818710306],[0.0433100000,0.8999700000],[0.8635787716,0.9130000000],[0.1785000000,0.8973600000],[0.8099800000,0.8651100000],[0.2360800000,0.7712700000],[0.6583432177,0.8485126184],[0.1266806142,0.9648102053],[0.9558541267,0.9090909091],[0.5568400771,0.7353760446]],[[0.5001318426,0.5160300000],[0.0572700000,0.6541600000],[0.2395000000,0.5976800000],[0.8104600000,0.6009000000],[0.6967400000,0.5483900000]],[[0.0862400000,0.4257800000],[0.4955600000,0.4033000000],[0.8234200000,0.4340200000]]] - sun_azimuth: [[[0.5000000000,0.6250000000]]] + sun_azimuth: [[[0.5000000000,0.4916666667]]] sun_altitude: [[[0.5000000000,0.9555555556]]] extinction: [[[0.4913294798,0.6378830084]]] volumetrics: 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/scene/scene_manager.py b/scene/scene_manager.py index ebac4a6b..28a3f3d4 100644 --- a/scene/scene_manager.py +++ b/scene/scene_manager.py @@ -3481,8 +3481,59 @@ except Exception as e: print(f"序列化GUI数据失败: {e}") return {} + def _serializeModelTextures(self, node): + """序列化模型纹理信息""" + try: + texture_data = {} + + # 获取节点的所有纹理阶段 + from panda3d.core import TextureStage + texture_stages = node.findAllTextureStages() + + if texture_stages.getNumTextureStages() > 0: + texture_data['textures'] = {} + + # 遍历所有纹理阶段 + for i in range(texture_stages.getNumTextureStages()): + stage = texture_stages.getTextureStage(i) + stage_name = stage.getName() + + # 获取该阶段的纹理 + texture = node.getTexture(stage) + if texture: + # 保存纹理信息 + texture_info = { + 'stage_name': stage_name, + 'stage_mode': stage.getMode(), + 'texture_path': texture.getFullpath().toOsSpecific() if texture.hasFullpath() else '', + 'texture_name': texture.getName(), + 'wrap_u': texture.getWrapU(), + 'wrap_v': texture.getWrapV(), + 'minfilter': texture.getMinfilter(), + 'magfilter': texture.getMagfilter(), + 'anisotropic_degree': texture.getAnisotropicDegree() + } + + # 保存颜色比例和偏移(使用安全的方法) + try: + texture_info['color_scale'] = tuple(node.getTextureScale(stage)) + except: + texture_info['color_scale'] = (1.0, 1.0, 1.0, 1.0) + + try: + texture_info['color_offset'] = tuple(node.getTextureOffset(stage)) + except: + texture_info['color_offset'] = (0.0, 0.0, 0.0, 0.0) + + texture_data['textures'][stage_name] = texture_info + + return texture_data + except Exception as e: + print(f"序列化模型纹理时出错: {e}") + return {} + def _serializeModelData(self, node): - """序列化模型数据,包括材质信息""" + """序列化模型数据,包括材质和纹理信息""" try: model_data = {} @@ -3498,15 +3549,16 @@ except Exception as e: if hasattr(node, 'getState'): state = node.getState() if state: - # 保存基础颜色信息 + # 保存基础颜色信息(使用正确的方法) from panda3d.core import ColorAttrib - color_attrib = state.getColor() - if color_attrib: + color_attrib = state.getAttrib(ColorAttrib) + if color_attrib and not color_attrib.isOff(): + color = color_attrib.getColor() model_data['base_color'] = ( - color_attrib.getColor().getX(), - color_attrib.getColor().getY(), - color_attrib.getColor().getZ(), - color_attrib.getColor().getW() + color.getX(), + color.getY(), + color.getZ(), + color.getW() ) # 保存其他材质属性 @@ -3544,10 +3596,34 @@ except Exception as e: # 保存粗糙度和金属度等参数 model_data['material_roughness'] = material.getRoughness() - model_data['material metallic'] = material.getMetallic() + model_data['material_metallic'] = material.getMetallic() + + # 保存自发光颜色 + emission_color = material.getEmission() + model_data['material_emission_color'] = ( + emission_color.getX(), emission_color.getY(), emission_color.getZ(), + emission_color.getW() + ) + + # 保存光泽度 + model_data['material_shininess'] = material.getShininess() + + # 保存透明度信息 + from panda3d.core import TransparencyAttrib + transparency_attrib = state.getAttrib(TransparencyAttrib.getClassType()) + if transparency_attrib: + model_data['transparency_mode'] = transparency_attrib.get_mode() except Exception as e: print(f"保存材质信息时出错: {e}") + + # 保存纹理信息 + try: + texture_data = self._serializeModelTextures(node) + if texture_data: + model_data['texture_data'] = texture_data + except Exception as e: + print(f"保存纹理信息时出错: {e}") return model_data except Exception as e: @@ -3847,7 +3923,7 @@ except Exception as e: model.setHpr(*hpr) model.setScale(*scale) - # 恢复材质信息 + # 恢复材质和纹理信息 try: self._restoreModelMaterial(model, model_data) except Exception as e: @@ -3869,8 +3945,59 @@ except Exception as e: # 出错时创建基本节点 return self._createBasicNodeFromData(node_data, parent_node, name) + def _restoreModelTextures(self, model, texture_data): + """恢复模型纹理""" + try: + if not texture_data or 'textures' not in texture_data: + return + + from panda3d.core import TextureStage, SamplerState + + textures_info = texture_data['textures'] + + # 为每个纹理阶段恢复纹理 + for stage_name, texture_info in textures_info.items(): + # 创建纹理阶段 + stage = TextureStage(stage_name) + stage.setMode(texture_info.get('stage_mode', TextureStage.M_modulate)) + + # 加载纹理 + texture_path = texture_info['texture_path'] + if texture_path and os.path.exists(texture_path): + texture = self.world.loader.loadTexture(texture_path) + if texture: + # 设置纹理属性 + texture.setWrapU(texture_info.get('wrap_u', SamplerState.WM_repeat)) + texture.setWrapV(texture_info.get('wrap_v', SamplerState.WM_repeat)) + texture.setMinfilter(texture_info.get('minfilter', SamplerState.FT_linear)) + texture.setMagfilter(texture_info.get('magfilter', SamplerState.FT_linear)) + texture.setAnisotropicDegree(texture_info.get('anisotropic_degree', 1)) + + # 应用纹理到模型 + model.setTexture(stage, texture, 1) # 1 表示强制应用 + + # 恢复颜色比例和偏移(使用安全的方法) + if 'color_scale' in texture_info: + try: + model.setTextureScale(stage, *texture_info['color_scale']) + except Exception as e: + print(f"恢复纹理比例失败: {e}") + + if 'color_offset' in texture_info: + try: + model.setTextureOffset(stage, *texture_info['color_offset']) + except Exception as e: + print(f"恢复纹理偏移失败: {e}") + + print(f"恢复纹理: {stage_name} <- {texture_path}") + else: + print(f"纹理文件不存在或路径为空: {texture_path}") + + except Exception as e: + print(f"恢复模型纹理时出错: {e}") + def _restoreModelMaterial(self, model, model_data): - """恢复模型材质""" + """恢复模型材质和纹理""" try: # 恢复基础颜色 if 'base_color' in model_data: @@ -3905,6 +4032,11 @@ except Exception as e: if 'material_specular_color' in model_data: specular_color = model_data['material_specular_color'] material.setSpecular((specular_color[0], specular_color[1], specular_color[2], specular_color[3])) + + # 恢复自发光颜色 + if 'material_emission_color' in model_data: + emission_color = model_data['material_emission_color'] + material.setEmission((emission_color[0], emission_color[1], emission_color[2], emission_color[3])) # 恢复粗糙度和金属度 if 'material_roughness' in model_data: @@ -3912,9 +4044,23 @@ except Exception as e: if 'material_metallic' in model_data: material.setMetallic(model_data['material_metallic']) + + # 恢复光泽度 + if 'material_shininess' in model_data: + material.setShininess(model_data['material_shininess']) # 应用材质到模型 model.setMaterial(material) + + # 恢复透明度设置 + if 'transparency_mode' in model_data: + from panda3d.core import TransparencyAttrib + transparency_mode = model_data['transparency_mode'] + model.setTransparency(transparency_mode) + + # 恢复纹理信息 + if 'texture_data' in model_data: + self._restoreModelTextures(model, model_data['texture_data']) except Exception as e: print(f"恢复材质失败: {e}") diff --git a/ui/property_panel.py b/ui/property_panel.py index a36f8a47..4893a719 100644 --- a/ui/property_panel.py +++ b/ui/property_panel.py @@ -6287,7 +6287,7 @@ class PropertyPanelManager: """应用漫反射贴图""" try: from RenderPipelineFile.rpcore.loader import RPLoader - from panda3d.core import TextureStage + from panda3d.core import TextureStage, TransparencyAttrib # 加载纹理 texture = RPLoader.load_texture(texture_path) @@ -6297,10 +6297,19 @@ class PropertyPanelManager: if node and material: print(f"正在为节点 {node.getName()} 应用漫反射贴图") + # 检查纹理是否包含透明度信息 + has_alpha = False + # 检查纹理格式 + format_name = str(texture.getFormat()) + if 'alpha' in format_name.lower() or 'rgba' in format_name.lower(): + has_alpha = True + + print(f"纹理格式: {texture.getFormat()}, 包含透明通道: {has_alpha}") + # 检查是否有金属性贴图,选择合适的PBR效果 print("🔧 检查金属性贴图并选择合适的PBR效果...") has_metallic = self._hasMetallicTexture(node) - needs_alpha = self._needsAlphaTesting(node) + needs_alpha = self._needsAlphaTesting(node) or has_alpha if has_metallic: print("✅ 检测到金属性贴图,使用支持金属性的PBR效果") @@ -6348,6 +6357,15 @@ class PropertyPanelManager: node.setTexture(diffuse_stage, texture) print("漫反射贴图已应用到p3d_Texture0槽") + # 如果纹理包含透明度,启用透明度渲染 + if has_alpha: + print("检测到透明纹理,启用透明度渲染") + node.setTransparency(TransparencyAttrib.MAlpha) + node.setDepthWrite(False) # 透明物体通常不写入深度缓冲区 + else: + # 确保关闭透明度(避免之前设置的影响) + node.setTransparency(TransparencyAttrib.MNone) + # 调试信息:显示当前纹理阶段 print("=== 漫反射贴图应用后的纹理阶段信息 ===") all_stages = node.findAllTextureStages() @@ -6400,6 +6418,7 @@ class PropertyPanelManager: has_diffuse_texture = True print(f" 🔍 发现现有漫反射贴图: {tex.getName()}") + # 如果没有漫反射贴图,必须创建白色纹理,否则法线映射会失效 if not has_diffuse_texture: print("⚠️ 没有漫反射贴图,创建白色纹理确保法线映射正常工作...")