diff --git a/common/MeshObjectT.cc b/common/MeshObjectT.cc index 4b949871f34906bc46ea743d8b0dbb1001158a7a..a6d13fcf86922e12c9d297139231a000b1191788 100644 --- a/common/MeshObjectT.cc +++ b/common/MeshObjectT.cc @@ -12,12 +12,12 @@ // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // OpenFlipper 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 Lesser General Public License for more details. -// +// // You should have received a copy of the GNU Lesser General Public License // along with OpenFlipper. If not, see . // @@ -37,69 +37,69 @@ // MyTypes // //============================================================================= - + #define MESHOBJECT_C - - + + //== INCLUDES ================================================================= - + #include "Types.hh" #include #include - - + + //== TYPEDEFS ================================================================= - + //== CLASS DEFINITION ========================================================= - - /** Constructor for Mesh Objects. This object class gets a Separator Node giving + + /** Constructor for Mesh Objects. This object class gets a Separator Node giving * the root node to which it should be connected. The mesh is generated internally * and all nodes for visualization will be added below the scenegraph node.\n - * You dont need to create an object of this type manually. Use - * PluginFunctions::addTriMesh or PluginFunctions::addPolyMesh instead. The + * You dont need to create an object of this type manually. Use + * PluginFunctions::addTriMesh or PluginFunctions::addPolyMesh instead. The * objectDataType has to match the one of MeshT ( see Types.hh::DataType ) */ template < class MeshT , DataType objectDataType > MeshObject< MeshT , objectDataType >::MeshObject( SeparatorNode* _rootNode ) : BaseObjectData(_rootNode ), - mesh_(0), + mesh_(0), statusNode_(0), areaNode_(0), - handleNode_(0), + handleNode_(0), meshNode_(0), textureNode_(0), shaderNode_(0), - triangle_bsp_(0) + triangle_bsp_(0) { setDataType(objectDataType); init(); } - + /** Destructor for Mesh Objects. The destructor deletes the mesh and all * Scenegraph nodes associated with the mesh or the object. */ template < class MeshT , DataType objectDataType > - MeshObject< MeshT , objectDataType >::~MeshObject() - { + MeshObject< MeshT , objectDataType >::~MeshObject() + { // Delete the data attached to this object ( this will remove all perObject data) // Not the best way to do it but it will work. // This is only necessary if people use references to the mesh below and // they do something with the mesh in the destructor of their // perObjectData. deleteData(); - + // Delete the Mesh only, if this object contains a mesh - if ( mesh_ != NULL) { + if ( mesh_ != NULL) { delete mesh_; mesh_ = NULL; } else { - std::cerr << "Destructor error : Mesh already deleted" << std::endl; + std::cerr << "Destructor error : Mesh already deleted" << std::endl; } - + if ( triangle_bsp_ != 0 ) delete triangle_bsp_; triangle_bsp_ = 0; - + // No need to delete the scenegraph Nodes as this will be managed by baseplugin areaNode_ = 0; handleNode_ = 0; @@ -107,46 +107,46 @@ textureNode_ = 0; shaderNode_ = 0; } - + /** Cleanup Function for Mesh Objects. Deletes the contents of the whole object and * calls MeshObject::init afterwards. */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::cleanup() { // Delete the Mesh only, if this object contains a mesh - if ( mesh_ != NULL) { + if ( mesh_ != NULL) { delete mesh_; mesh_ = NULL; } else { - std::cerr << "Cleanup error : Triangle Mesh already deleted" << std::endl; + std::cerr << "Cleanup error : Triangle Mesh already deleted" << std::endl; } - + if ( triangle_bsp_ != 0 ) delete triangle_bsp_; triangle_bsp_ = 0; - + BaseObjectData::cleanup(); - + statusNode_ = 0; areaNode_ = 0; handleNode_ = 0; textureNode_= 0; shaderNode_ = 0; meshNode_ = 0; - + setDataType(objectDataType); - + init(); - + } - + /** This function initalizes the mesh object. It creates the scenegraph nodes, * the mesh and requests all required properties for the mesh. */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::init() { mesh_ = new MeshT(); - + mesh_->request_vertex_normals(); mesh_->request_face_normals(); mesh_->request_vertex_status(); @@ -155,123 +155,123 @@ mesh_->request_edge_status(); mesh_->request_vertex_colors(); mesh_->request_face_colors(); - mesh_->request_vertex_texcoords2D(); - mesh_->request_halfedge_texcoords2D(); - + mesh_->request_vertex_texcoords2D(); + mesh_->request_halfedge_texcoords2D(); + if ( manipulatorNode() == NULL) std::cerr << "Error when creating Mesh Object! manipulatorNode is NULL!" << std::endl; statusNode_ = new ACG::SceneGraph::SelectionNodeT(*mesh_,manipulatorNode(),"NEW StatusNode for mesh " ); statusNode_->set_point_size(4.0); statusNode_->set_color(ACG::Vec4f(1.0,0.0,0.0,1.0)); - + areaNode_ = new ACG::SceneGraph::StatusNodeT >(*mesh_, manipulatorNode(), "NEW AreaNode for mesh "); areaNode_->set_round_points(true); areaNode_->enable_alpha_test(0.5); areaNode_->set_point_size(7.0); areaNode_->set_color(ACG::Vec4f(0.4, 0.4, 1.0, 1.0)); - + handleNode_ = new ACG::SceneGraph::StatusNodeT >(*mesh_, manipulatorNode(), "NEW HandleNode for mesh "); handleNode_->set_round_points(true); handleNode_->enable_alpha_test(0.5); handleNode_->set_line_width(2.0); handleNode_->set_point_size(7.0); handleNode_->set_color(ACG::Vec4f(0.2, 1.0, 0.2, 1.0)); - + if ( materialNode() == NULL) std::cerr << "Error when creating Mesh Object! materialNode is NULL!" << std::endl; textureNode_ = new TextureNode(materialNode(),"NEW TextureNode for "); - + shaderNode_ = new ACG::SceneGraph::ShaderNode(textureNode() , "NEW ShaderNode for "); - + meshNode_ = new ACG::SceneGraph::MeshNodeT(*mesh_, shaderNode_, "NEW MeshNode"); - + QString shaderDir = OpenFlipper::Options::shaderDirStr() + OpenFlipper::Options::dirSeparator(); - + std::string shaderDirectory = std::string( shaderDir.toUtf8() ); shaderNode_->setShaderDir( shaderDirectory ); - + if ( QFile( shaderDir + "Phong/Vertex.glsl").exists() && QFile( shaderDir + "Phong/Fragment.glsl" ).exists() ) { - shaderNode_->setShader(ACG::SceneGraph::DrawModes::SOLID_PHONG_SHADED, + shaderNode_->setShader(ACG::SceneGraph::DrawModes::SOLID_PHONG_SHADED, "Phong/Vertex.glsl" , "Phong/Fragment.glsl" ); } else std::cerr << "Shader Files for Phong not found!" << std::endl; - + if ( QFile( shaderDir + "Ward/Vertex.glsl").exists() && QFile( shaderDir + "Ward/Fragment.glsl" ).exists() ) { - - shaderNode_->setShader(ACG::SceneGraph::DrawModes::SOLID_SHADER, + + shaderNode_->setShader(ACG::SceneGraph::DrawModes::SOLID_SHADER, "Ward/Vertex.glsl" , "Ward/Fragment.glsl" ); - + // Ward shader uses 3 parameters so activate shader, set params and deactivate it again GLSL::PtrProgram shader = shaderNode_->getShader( ACG::SceneGraph::DrawModes::SOLID_SHADER ); if ( shader == 0 ) { - std::cerr << "Unable to get shader for shader mode" << std::endl; + std::cerr << "Unable to get shader for shader mode" << std::endl; } else { shader->use(); - + shader->setUniform("ward_specular" , 0.5f); shader->setUniform("ward_diffuse" , 1.0f); shader->setUniform("ward_alpha" , 0.1f); - - shader->disable(); + + shader->disable(); } - + } else std::cerr << "Shader Files for Ward not found!!" << std::endl; - - + + // Update all nodes update(); } - + // =============================================================================== // Name/Path Handling // =============================================================================== - - /** Set the name of an object. All Scenegraph nodes are renamed too. It also calls + + /** Set the name of an object. All Scenegraph nodes are renamed too. It also calls * BaseObjectData::setName. */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::setName( QString _name ) { BaseObjectData::setName(_name); - + std::string nodename = std::string("StatusNode for mesh " + _name.toUtf8() ); statusNode_->name( nodename ); - + nodename = std::string("AreaNode for mesh " + _name.toUtf8() ); areaNode_->name( nodename ); - + nodename = std::string("HandleNode for mesh " + _name.toUtf8() ); handleNode_->name( nodename ); - + nodename = std::string("TextureNode for mesh "+ _name.toUtf8() ); textureNode_->name( nodename ); - + nodename = std::string("ShaderNode for mesh "+ _name.toUtf8() ); shaderNode_->name( nodename ); - + nodename = std::string("MeshNode for mesh " + _name.toUtf8() ); meshNode_->name( nodename ); } - + // =============================================================================== // Content // =============================================================================== - + /** Get a pointer to the objects mesh. * @return Pointer to the mesh */ template < class MeshT , DataType objectDataType > MeshT* MeshObject< MeshT , objectDataType >::mesh() { - return mesh_; + return mesh_; } - - /** Updates the visualization of the object. Calls MeshObject::updateGeometry, - * MeshObject::updateTopology, MeshObject::updateSelection and + + /** Updates the visualization of the object. Calls MeshObject::updateGeometry, + * MeshObject::updateTopology, MeshObject::updateSelection and * MeshObject::updateModelingRegions. */ template < class MeshT , DataType objectDataType > @@ -281,32 +281,32 @@ updateSelection(); updateModelingRegions(); } - + /** Updates the selection scenegraph nodes */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::updateSelection() { - statusNode_->update_cache(); + statusNode_->update_cache(); } - + /** Updates the geometry information in the mesh scenegraph node */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::updateGeometry() { - meshNode_->update_geometry(); + meshNode_->update_geometry(); } - + /** Updates the topology information in the mesh scenegraph node */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::updateTopology() { - meshNode_->update_topology(); + meshNode_->update_topology(); } - + /** Updates the modeling regions scenegraph nodes */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::updateModelingRegions() { areaNode_->update_cache(); handleNode_->update_cache(); } - + // =============================================================================== // Visualization // =============================================================================== @@ -317,7 +317,7 @@ TextureNode* MeshObject< MeshT , objectDataType >::textureNode() { return textureNode_; } - + /** Returns a pointer to the shader node * @return Pointer to the shader node */ @@ -325,22 +325,58 @@ ACG::SceneGraph::ShaderNode* MeshObject< MeshT , objectDataType >::shaderNode() { return shaderNode_; } - + + /** Shows or hides the selections on the object + */ + template < class MeshT , DataType objectDataType > + void MeshObject< MeshT , objectDataType >::hideSelection( bool _hide ) { + + if ( _hide ) { + statusNode_->set_status( ACG::SceneGraph::BaseNode::HideNode ); + } else { + statusNode_->set_status( ACG::SceneGraph::BaseNode::Active ); + } + + } + + /** Shows or hides the areas on the object + */ + template < class MeshT , DataType objectDataType > + void MeshObject< MeshT , objectDataType >::hideAreaNodes( bool _hide ) { + if ( _hide ) { + areaNode_->set_status( ACG::SceneGraph::BaseNode::HideNode ); + handleNode_->set_status( ACG::SceneGraph::BaseNode::HideNode ); + } else { + areaNode_->set_status( ACG::SceneGraph::BaseNode::Active ); + handleNode_->set_status( ACG::SceneGraph::BaseNode::Active ); + } + } + + template < class MeshT , DataType objectDataType > + bool MeshObject< MeshT , objectDataType >::selectionVisible() { + return ( statusNode_->status() == ACG::SceneGraph::BaseNode::Active ); + } + + template < class MeshT , DataType objectDataType > + bool MeshObject< MeshT , objectDataType >::areasVisible() { + return ( areaNode_->status() == ACG::SceneGraph::BaseNode::Active ); + } + /** Returns a pointer to the mesh node * @return Pointer to the mesh node */ template < class MeshT , DataType objectDataType > ACG::SceneGraph::MeshNodeT* MeshObject< MeshT , objectDataType >::meshNode() { - return meshNode_; + return meshNode_; } - + /** Get the Bounding box size of this object */ template < class MeshT , DataType objectDataType > void MeshObject< MeshT , objectDataType >::boundingBox( ACG::Vec3f& _bbMin , ACG::Vec3f& _bbMax ) { - meshNode_->boundingBox(_bbMin,_bbMax); + meshNode_->boundingBox(_bbMin,_bbMax); } - + /** Add a texture to the object. * @param _property Name of the mesh property handle containing the texture. * @param _textureFile Name of the texturefile used (has to be in the Textures dir of OpenFlipper) @@ -350,84 +386,84 @@ { textures.push_back( std::pair(_property,_textureFile) ); } - - + + // =============================================================================== // Load/Save // =============================================================================== - + /** Load the mesh data from a file. The loader uses the OpenMesh object loaders and * therefore supports all mesh types supported by OpenMesh. - * + * * @param _filename Full path of the file to load. */ template < class MeshT , DataType objectDataType > bool MeshObject< MeshT , objectDataType >::loadMesh(QString _filename) { - + setFromFileName(_filename); - + // call the local function to update names setName( name() ); - + std::string filename = std::string( _filename.toUtf8() ); - + // load file bool ok = OpenMesh::IO::read_mesh( (*mesh()) , filename ); - if (!ok) + if (!ok) { if ( objectDataType == DATA_TRIANGLE_MESH ) std::cerr << "Main Application : Read error for Triangle Mesh at "<< filename << std::endl; if ( objectDataType == DATA_POLY_MESH ) std::cerr << "Main Application : Read error for Poly Mesh\n"; - return false; + return false; } - + mesh()->update_normals(); - + update(); - + show(); - + return true; } - + // =============================================================================== // Object information // =============================================================================== - + /** Returns a string containing all information about the current object. This also * includes the information provided by BaseObjectData::getObjectinfo - * + * * @return String containing the object information */ template < class MeshT , DataType objectDataType > QString MeshObject< MeshT , objectDataType >::getObjectinfo() { QString output; - + output += "========================================================================\n"; output += BaseObjectData::getObjectinfo(); - - if ( dataType( DATA_TRIANGLE_MESH ) ) + + if ( dataType( DATA_TRIANGLE_MESH ) ) output += "Object Contains Triangle Mesh : "; - - if ( dataType( DATA_POLY_MESH ) ) + + if ( dataType( DATA_POLY_MESH ) ) output += "Object Contains Poly Mesh : "; - + output += QString::number( mesh()->n_vertices() ) + " vertices, "; output += QString::number( mesh()->n_edges() ) += " edges "; output += QString::number( mesh()->n_faces() ) += " faces.\n"; - + output += "========================================================================\n"; return output; } - + // =============================================================================== // Picking // =============================================================================== - + /** Given an node index from PluginFunctions::scenegraph_pick this function can be used to * check if the meshNode of the object has been picked. - * + * * @param _node_idx Index of the picked mesh node * @return bool if the meshNode of this object is the picking target. */ @@ -450,32 +486,32 @@ bool MeshObject< MeshT , objectDataType >::pickingEnabled() { return meshNode_->pickingEnabled(); } - + // =============================================================================== // Octree - // =============================================================================== + // =============================================================================== template < class MeshT , DataType objectDataType > - typename MeshObject< MeshT , objectDataType >::OMTriangleBSP* + typename MeshObject< MeshT , objectDataType >::OMTriangleBSP* MeshObject< MeshT , objectDataType >::requestTriangleBsp() { - + if ( ! dataType( DATA_TRIANGLE_MESH) ) { std::cerr << "Bsps are only supported for triangle meshes." << std::endl; return 0; } - - // Create the tree if needed. - if ( triangle_bsp_ == 0 ) + + // Create the tree if needed. + if ( triangle_bsp_ == 0 ) { // create Triangle BSP triangle_bsp_ = new OMTriangleBSP( *mesh() ); // build Triangle BSP triangle_bsp_->reserve(mesh()->n_faces()); - + typename MeshT::FIter f_it = mesh()->faces_begin(); typename MeshT::FIter f_end = mesh()->faces_end(); - + for (; f_it!=f_end; ++f_it) triangle_bsp_->push_back(f_it.handle()); @@ -485,19 +521,19 @@ // return pointer to triangle bsp return triangle_bsp_; } - + template < class MeshT , DataType objectDataType > - typename MeshObject< MeshT , objectDataType >::OMTriangleBSP* + typename MeshObject< MeshT , objectDataType >::OMTriangleBSP* MeshObject< MeshT , objectDataType >::resetTriangleBsp() { if ( triangle_bsp_ != 0 ) { delete triangle_bsp_; triangle_bsp_ = 0; } - + return requestTriangleBsp(); } - - + + //============================================================================= - + diff --git a/common/MeshObjectT.hh b/common/MeshObjectT.hh index 1b15aa85545ef5d3453e3a3ddd2dbf3a43aa1506..59f119c7b10f6e797a1e2ed24a826b1b19842323 100644 --- a/common/MeshObjectT.hh +++ b/common/MeshObjectT.hh @@ -12,12 +12,12 @@ // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // OpenFlipper 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 Lesser General Public License for more details. -// +// // You should have received a copy of the GNU Lesser General Public License // along with OpenFlipper. If not, see . // @@ -39,7 +39,7 @@ //============================================================================= /** - * \file Types.hh + * \file Types.hh * This File contains the basic available datatypes in the Framework. */ @@ -47,7 +47,7 @@ #ifndef MESHOBJECT_HH #define MESHOBJECT_HH - + #ifdef WIN32 #define DLLEXPORT __declspec(dllexport) #else @@ -64,7 +64,7 @@ #include #include -/// Additional Node status Bits for Mesh +/// Additional Node status Bits for Mesh enum StatusBits { /// Modifyable area AREA = OpenMesh::Attributes::UNUSED << 1, @@ -75,148 +75,160 @@ enum StatusBits { #include "StatusNodeMods.hh" #include "TriangleMeshTypes.hh" #include "PolyMeshTypes.hh" - + // -------------------- BSP #include - -#include "BaseObjectData.hh" - - +#include "BaseObjectData.hh" + + + //== TYPEDEFS ================================================================= - + /// Texture Node -typedef ACG::SceneGraph::TextureNode TextureNode; +typedef ACG::SceneGraph::TextureNode TextureNode; //== CLASS DEFINITION ========================================================= /** This class provides the functionality for all kind of meshes for the framework */ -template < class MeshT, DataType objectDataType > +template < class MeshT, DataType objectDataType > class DLLEXPORT MeshObject : public BaseObjectData { - public: + public: /// constructor MeshObject(SeparatorNode* _rootNode); - + /// destructor virtual ~MeshObject(); - + /// Reset current object, including all related nodes. - virtual void cleanup(); + virtual void cleanup(); protected: - + /// Initialise current object, including all related nodes. - virtual void init(); - + virtual void init(); + //=========================================================================== /** @name Name and Path handling * @{ */ - //=========================================================================== + //=========================================================================== public: - + /// Set the name of the Object void setName( QString _name ); - - + + //=========================================================================== /** @name Content * @{ */ //=========================================================================== - + public: /// return a pointer to the mesh - MeshT* mesh(); - + MeshT* mesh(); + /// Update the whole Object (Selection,Topology,...) virtual void update(); - + /// Call this function to update the modeling regions void updateSelection(); - + /// Call this function to update the modeling regions void updateModelingRegions(); - + /// Update Geometry of all data structures void updateGeometry(); - + /// Update Topology of all data structures void updateTopology(); - + private: MeshT* mesh_; - - /** @} */ - + + /** @} */ + //=========================================================================== /** @name Visualization * @{ */ - //=========================================================================== - - public: - + //=========================================================================== + + public: + /// Get the TextureNode of the current mesh TextureNode* textureNode(); - + /// Return pointer to the shader node ACG::SceneGraph::ShaderNode* shaderNode(); - + + /// Hide or show the selection Node of the object + void hideSelection( bool _hide ); + + /// return if the selections are currently visible + bool selectionVisible(); + + /// Hide or show the area Nodes of the object + void hideAreaNodes( bool _hide ); + + /// return if the areas are currently visible + bool areasVisible(); + /// Get the Scenegraph Mesh Node ACG::SceneGraph::MeshNodeT* meshNode();; - + /// Get the BoundingBox of this object void boundingBox( ACG::Vec3f& _bbMin , typename ACG::Vec3f& _bbMax ); - + private : /// Status Node for a mesh, visualizing the selection state of a mesh ACG::SceneGraph::SelectionNodeT* statusNode_; - + /// Area selection Vis ACG::SceneGraph::StatusNodeT > * areaNode_; - + /// Handle selection Vis ACG::SceneGraph::StatusNodeT > * handleNode_; - + /// Scenegraph Mesh Node ACG::SceneGraph::MeshNodeT* meshNode_; - + /// Scenegraph TextureNode TextureNode* textureNode_; - + /// Scenegraph ShaderNode ACG::SceneGraph::ShaderNode* shaderNode_; - - /** @} */ - + + /** @} */ + //=========================================================================== /** @name Load/Save * @{ */ - //=========================================================================== - + //=========================================================================== + public: - + /// Load a mesh from the given file bool loadMesh(QString _filename); - - /** @} */ - + + /** @} */ + //=========================================================================== /** @name Object Information * @{ */ - //=========================================================================== + //=========================================================================== public: /// Get all Info for the Object as a string QString getObjectinfo(); - - /** @} */ - - + + /** @} */ + + //=========================================================================== /** @name Picking * @{ */ - //=========================================================================== + //=========================================================================== public: /// detect if the node has been picked bool picked( uint _node_idx ); @@ -226,17 +238,17 @@ class DLLEXPORT MeshObject : public BaseObjectData { /// Check if picking is enabled for this Node bool pickingEnabled(); - - /** @} */ - + + /** @} */ + //=========================================================================== /** @name Texture Handling * @{ */ - //=========================================================================== + //=========================================================================== public : - + void addTexture(QString _property, QString _textureFile ); - + /** This vector is used to store the available Textures, which will be handled * by the texture control plugin. For meshes the first String identifies the mesh * property used for the texture coordinates. The second String identifies the @@ -244,36 +256,36 @@ class DLLEXPORT MeshObject : public BaseObjectData { * nothing happens if you select it. */ std::vector< std::pair < QString , QString > > textures; - /** @} */ - + /** @} */ + //=========================================================================== /** @name BSP Extension ( Implements a BSP for the mesh used for fast searches ) * @{ */ - //=========================================================================== + //=========================================================================== public: - + typedef OpenMeshTriangleBSPT< MeshT > OMTriangleBSP; - + /** Get a bsp for this object. Only supported for Triangle Meshes at the moment. - * - * + * + * * @return Pointer to bsp or Null if unsupported for this type. */ OMTriangleBSP* requestTriangleBsp(); - + /** If something in the mesh changes, call this function to clear the octree. * You have to do a new request as the old one will be deleted. * @todo : Update the tree when the update function of this object is called. * @todo : dont recreate but update the old one. - * @return The new pointer to the bsp or Null if unsupported + * @return The new pointer to the bsp or Null if unsupported */ OMTriangleBSP* resetTriangleBsp(); - + private : /// If requested a bsp is created for this object OMTriangleBSP* triangle_bsp_; - - /** @} */ + + /** @} */ }; //============================================================================= @@ -282,8 +294,8 @@ class DLLEXPORT MeshObject : public BaseObjectData { #define TYPES_TEMPLATES #include "MeshObjectT.cc" #endif - - + + //============================================================================= #endif // MESHOBJECT_HH defined //=============================================================================