<commit_before>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    void set_child_pointer(GLuint childID, void* child_pointer, std::vector<void*> &child_pointer_vector, std::queue<GLuint> &free_childID_queue);
    GLuint get_childID(std::vector<void*> &child_pointer_vector, std::queue<GLuint> &free_childID_queue);

    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

        private:
            // this method sets a shader pointer.
            void set_shader_pointer(GLuint childID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint childID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            void compute_matrices_from_inputs();

            void* world_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;

            friend class Shader;
            friend class Species;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all textures using this shader.
            void render();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `childID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

        private:
            // this method sets a texture pointer.
            void set_texture_pointer(GLuint childID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint childID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;

            void bind_to_world();

            void* world_species_pointer;          // pointer to world species (used in collision detection).

            GLuint childID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;

            friend class World;
            friend class Texture;
            friend class Species;
            friend class Object;
    };

    class Texture
    {
        public:
            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

            // this method renders all species using this texture.
            void render();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `childID` from the new shader.
            void switch_texture_to_new_shader(model::Shader *new_shader_pointer);

        private:
            // this method sets a species pointer.
            void set_species_pointer(GLuint childID, void* species_pointer);

            // this method sets a font pointer.
            void set_font_pointer(GLuint childID, void* font_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint childID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method gets a font ID and removes it from the `free_fontID_queue` if it was popped from the queue.
            GLuint get_fontID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

            void bind_to_shader();

            void* world_species_pointer;           // pointer to world species (used in collision detection).

            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint childID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;

            friend class Shader;
            friend class Species;
            friend class Object;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

        private:
            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;

            friend class Node;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

        private:
            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;

            friend class Graph;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `childID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            // this method sets a object pointer.
            void set_object_pointer(GLuint childID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint childID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint childID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Font
    {
        public:
            // constructor.
            Font(FontStruct font_struct);

            // destructor.
            ~Font();

            // this method renders all objects of this species.
            void render();

            // this method sets a glyph pointer.
            void set_glyph_pointer(GLuint childID, void* object_pointer);

            // this method gets a glyph pointer.
            void* get_glyph_pointer(GLuint childID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_glyphID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `childID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint childID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Glyph
    {
        public:
            // constructor.
            Glyph(GlyphStruct glyph_struct);

            // destructor.
            ~Glyph();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint childID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint childID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Font *font_pointer;             // pointer to the font.

        private:
            void bind_to_font();

            GLuint glyphID;                        // glyph ID, returned by `model::Font->get_glyphID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `childID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

        private:
            void bind_to_species();

            model::Species *species_pointer;       // pointer to the species.

            GLuint childID;                       // object ID, returned by `model::Species->get_objectID()`.
            bool has_entered;

            glm::vec3 coordinate_vector;           // coordinate vector.
            glm::vec3 original_scale_vector;       // original scale vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<commit_msg>`friend`-määritykset siirretty kunkin luokan `public:`-osan loppuun.<commit_after>#ifndef __MODEL_HPP_INCLUDED
#define __MODEL_HPP_INCLUDED

// Include GLEW
#ifndef __GL_GLEW_H_INCLUDED
#define __GL_GLEW_H_INCLUDED
#include <GL/glew.h>
#endif

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp>
#endif

#include <iostream>
#include <queue> // std::queue
#include <string.h>
#include "globals.hpp"
#include "shader.hpp"
#include "heightmap_loader.hpp"
#include "objloader.hpp"

namespace model
{
    void set_child_pointer(GLuint childID, void* child_pointer, std::vector<void*> &child_pointer_vector, std::queue<GLuint> &free_childID_queue);
    GLuint get_childID(std::vector<void*> &child_pointer_vector, std::queue<GLuint> &free_childID_queue);

    class World
    {
        public:
            // constructor.
            World();

            // destructor.
            ~World();

            // this method renders the entire world, one shader at a time.
            void render();

            friend class Shader;
            friend class Species;

        private:
            // this method sets a shader pointer.
            void set_shader_pointer(GLuint childID, void* shader_pointer);

            // this method gets a shader pointer.
            void* get_shader_pointer(GLuint childID);

            // this method gets a shader ID and removes it from the `free_shaderID_queue` if it was popped from the queue.
            GLuint get_shaderID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            void compute_matrices_from_inputs();

            void* world_species_pointer;              // pointer to world species (used in collision detection).

            std::vector<void*> shader_pointer_vector;
            std::queue<GLuint> free_shaderID_queue;
    };

    class Shader
    {
        public:
            // constructor.
            Shader(ShaderStruct shader_struct);

            // destructor.
            ~Shader();

            // this method renders all textures using this shader.
            void render();

            // this method sets pointer to this shader to NULL, sets `world_pointer` according to the input, and requests a new `childID` from the new world.
            void switch_to_new_world(model::World *new_world_pointer);

            friend class World;
            friend class Texture;
            friend class Species;
            friend class Object;

        private:
            // this method sets a texture pointer.
            void set_texture_pointer(GLuint childID, void* texture_pointer);

            // this method gets a texture pointer.
            void* get_texture_pointer(GLuint childID);

            // this method gets a texture ID and removes it from the `free_textureID_queue` if it was popped from the queue.
            GLuint get_textureID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::World *world_pointer;          // pointer to the world.

            GLuint programID;                     // shaders' programID, returned by `LoadShaders`.

            GLuint MatrixID;
            GLuint ViewMatrixID;
            GLuint ModelMatrixID;

            void bind_to_world();

            void* world_species_pointer;          // pointer to world species (used in collision detection).

            GLuint childID;                      // shader ID, returned by `model::World->get_shaderID()`.

            std::string vertex_shader;            // filename of vertex shader.
            std::string fragment_shader;          // filename of fragment shader.

            std::vector<void*> texture_pointer_vector;
            std::queue<GLuint> free_textureID_queue;

            const char *char_vertex_shader;
            const char *char_fragment_shader;
    };

    class Texture
    {
        public:
            // constructor.
            Texture(TextureStruct texture_struct);

            // destructor.
            ~Texture();

            // this method renders all species using this texture.
            void render();

            // this method sets pointer to this shader to NULL, sets `shader_pointer` according to the input, and requests a new `childID` from the new shader.
            void switch_texture_to_new_shader(model::Shader *new_shader_pointer);

            friend class Shader;
            friend class Species;
            friend class Object;

        private:
            // this method sets a species pointer.
            void set_species_pointer(GLuint childID, void* species_pointer);

            // this method sets a font pointer.
            void set_font_pointer(GLuint childID, void* font_pointer);

            // this method gets a species pointer.
            void* get_species_pointer(GLuint childID);

            // this method gets a species ID and removes it from the `free_speciesID_queue` if it was popped from the queue.
            GLuint get_speciesID();

            // this method gets a font ID and removes it from the `free_fontID_queue` if it was popped from the queue.
            GLuint get_fontID();

            // this method sets a world species pointer.
            void set_world_species_pointer(void* world_species_pointer);

            model::Shader *shader_pointer;         // pointer to the shader.

            void bind_to_shader();

            void* world_species_pointer;           // pointer to world species (used in collision detection).

            GLuint texture;                        // Texture, returned by `load_DDS_texture` or `load_BMP_texture`.
            GLuint openGL_textureID;               // texture ID, returned by `glGetUniformLocation(programID, "myTextureSampler");`.

            std::vector<void*> species_pointer_vector;
            std::queue<GLuint> free_speciesID_queue;

            std::string texture_file_format;       // type of the model file, eg. `"bmp"`.
            std::string texture_filename;          // filename of the model file.
            GLuint childID;                      // texture ID, returned by `Shader::get_textureID`.
            const char *char_texture_file_format;
            const char *char_texture_filename;
    };

    class Graph
    {
        public:
            // constructor.
            Graph();

            // destructor.
            ~Graph();

            friend class Node;

        private:
            // this method sets a node pointer.
            void set_node_pointer(GLuint nodeID, void* node_pointer);

            // this method gets a node pointer.
            void* get_node_pointer(GLuint nodeID);

            // this method gets a node ID and removes it from the `free_nodeID_queue` if it was popped from the queue.
            GLuint get_nodeID();

            std::vector<void*> node_pointer_vector;
            std::queue<GLuint> free_nodeID_queue;
    };

    // `Node` is not a subclass of `Graph` because if the graph splits, node may be transferred to an another graph.
    // Transferring a node to a new graph naturally requires appropriate reindexing of `nodeID`s.
    // The graph in which a node belongs is accessible through `void* graph_pointer` (must be cast to `model::Graph*`).
    class Node
    {
        public:
            // constructor.
            Node(NodeStruct node_struct);

            // destructor.
            ~Node();

            friend class Graph;

        private:
            // this method creates a bidirectional link.
            // creating of bidirectional links is not possible before all nodes are created.
            void create_bidirectional_link(GLuint nodeID);

            // this method deletes a bidirectional link.
            // deleting of links is not possible before all nodes are created.
            void delete_bidirectional_link(GLuint nodeID);

            // this method transfers this node to a new graph.
            // links will not be changed.
            // all nodes that are to be transferred must be transferred separately.
            // before transfering any node to a new graph,
            // all links to nodes that do not belong to the new graph of this node must be deleted with separate `delete_bidirectional_link` calls.
            void transfer_to_new_graph(model::Graph *new_graph_pointer);

            GLuint nodeID;
            model::Graph *graph_pointer;

            // nodes do not keep pointers to neighbor nodes, because all pointer values are not known yet before all nodes are created.
            std::vector<GLuint> neighbor_nodeIDs;

            // this method creates an unidirectional link.
            // in the constructor only unidirectional links can be created.
            void create_unidirectional_link(GLuint nodeID);

            // this method deletes an unidirectional link.
            void delete_unidirectional_link(GLuint nodeID);

            glm::vec3 coordinate_vector;
    };

    class Species
    {
        public:
            // constructor.
            Species(SpeciesStruct species_struct);

            // destructor.
            ~Species();

            // this method renders all objects of this species.
            void render();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `childID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            // this method sets a object pointer.
            void set_object_pointer(GLuint childID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint childID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            bool is_world;                           // worlds currently do not rotate nor translate.

            std::string color_channel;               // color channel in use: `"red"`, `"green"`, `"blue"`, `"mean"` or `"all"`.
            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint childID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Font
    {
        public:
            // constructor.
            Font(FontStruct font_struct);

            // destructor.
            ~Font();

            // this method renders all objects of this species.
            void render();

            // this method sets a glyph pointer.
            void set_glyph_pointer(GLuint childID, void* object_pointer);

            // this method gets a glyph pointer.
            void* get_glyph_pointer(GLuint childID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_glyphID();

            // this method sets pointer to this species to NULL, sets `texture_pointer` according to the input, and requests a new `childID` from the new texture.
            void switch_to_new_texture(model::Texture *new_texture_pointer);

            std::vector<ObjectStruct> object_vector; // vector of individual objects of this species.
            glm::vec3 lightPos;                      // light position.

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            model::Texture *texture_pointer;       // pointer to the texture.

        private:
            void bind_to_texture();

            std::string model_file_format;         // type of the model file, eg. `"bmp"`.
            std::string model_filename;            // filename of the model file.
            GLuint childID;                      // species ID, returned by `model::Texture->get_speciesID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.
            const char *char_model_file_format;
            const char *char_model_filename;
            const char *char_color_channel;

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Glyph
    {
        public:
            // constructor.
            Glyph(GlyphStruct glyph_struct);

            // destructor.
            ~Glyph();

            // this method renders all objects of this species.
            void render();

            // this method sets a object pointer.
            void set_object_pointer(GLuint childID, void* object_pointer);

            // this method gets a object pointer.
            void* get_object_pointer(GLuint childID);

            // this method gets a object ID and removes it from the `free_objectID_queue` if it was popped from the queue.
            GLuint get_objectID();

            // The rest fields are created in the constructor.
            GLuint image_width;
            GLuint image_height;

            GLuint vertexPosition_modelspaceID;
            GLuint vertexUVID;
            GLuint vertexNormal_modelspaceID;

            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object.

            std::vector<GLuint> indices;           // the deleted vertices will be reused (though it is not required, if there's enough memory).
            std::vector<glm::vec3> indexed_vertices;
            std::vector<glm::vec2> indexed_UVs;
            std::vector<glm::vec3> indexed_normals;

            GLuint vertexbuffer;
            GLuint uvbuffer;
            GLuint normalbuffer;
            GLuint elementbuffer;

            model::Font *font_pointer;             // pointer to the font.

        private:
            void bind_to_font();

            GLuint glyphID;                        // glyph ID, returned by `model::Font->get_glyphID()`.
            GLuint lightID;                        // light ID, returned by `glGetUniformLocation(programID, "LightPosition_worldspace");`.

            std::vector<void*> object_pointer_vector;
            std::queue<GLuint> free_objectID_queue;
    };

    class Object
    {
        public:
            // constructor.
            Object(ObjectStruct object_struct);

            // destructor.
            ~Object();

            // this method renders this object.
            void render();

            // this method sets pointer to this object to NULL, sets `species_pointer` according to the input, and requests a new `childID` from the new species.
            void switch_to_new_species(model::Species *new_species_pointer);

        private:
            void bind_to_species();

            model::Species *species_pointer;       // pointer to the species.

            GLuint childID;                       // object ID, returned by `model::Species->get_objectID()`.
            bool has_entered;

            glm::vec3 coordinate_vector;           // coordinate vector.
            glm::vec3 original_scale_vector;       // original scale vector.
            GLfloat rotate_angle;                  // rotate angle.
            glm::vec3 rotate_vector;               // rotate vector.
            glm::vec3 translate_vector;            // translate vector.

            // The rest fields are created in the constructor.
            glm::mat4 model_matrix;                // model matrix.
            std::vector<glm::vec3> vertices;       // vertices of the object.
            std::vector<glm::vec2> UVs;            // UVs of the object.
            std::vector<glm::vec3> normals;        // normals of the object. not used at the moment.

            glm::mat4 MVP_matrix;                  // model view projection matrix.
    };
}

#endif
<|endoftext|>


<commit_before>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "ut_selfcompositing.h"
#include "mimgraphicsview.h"
#include "mimwidget.h"
#include "mimxapplication.h"
#include "utils.h"

namespace
{
    const QSize windowSize(200, 200);

    QWidget *createGraphicsView(QWidget *parent)
    {
        MImGraphicsView *subject = new MImGraphicsView(new QGraphicsScene(parent), parent);
        subject->setSceneRect(QRect(QPoint(), windowSize));
        subject->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        subject->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        subject->setFrameStyle(0);
        subject->setAttribute(Qt::WA_OpaquePaintEvent);
        subject->setAttribute(Qt::WA_NoSystemBackground);
        subject->viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
        subject->viewport()->setAttribute(Qt::WA_NoSystemBackground);
        subject->resize(parent->size());
        subject->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        subject->setCacheMode(QGraphicsView::CacheNone);
        return subject;
    }

    QWidget *createWidget(QWidget *parent)
    {
        MImWidget *subject = new MImWidget(parent);
        subject->setAttribute(Qt::WA_OpaquePaintEvent);
        subject->setAttribute(Qt::WA_NoSystemBackground);
        subject->resize(parent->size());
        return subject;
    }
}

typedef QWidget * (* WidgetCreator)(QWidget *parent);
Q_DECLARE_METATYPE(WidgetCreator);

void Ut_SelfCompositing::initTestCase()
{
    static char *argv[2] = { (char *) "Ut_SelfCompositing",
                             (char *) "-use-self-composition" };
    static int argc = 2;

    // Enforcing raster GS to make test reliable:
    QApplication::setGraphicsSystem("raster");

    app = new MImXApplication(argc, argv);
    QVERIFY(app->selfComposited());
}

void Ut_SelfCompositing::cleanupTestCase()
{
    delete app;
}

void Ut_SelfCompositing::init()
{}

void Ut_SelfCompositing::cleanup()
{}

void Ut_SelfCompositing::testSelfCompositing_data()
{
    QTest::addColumn<WidgetCreator>("widgetCreator");
    QTest::newRow("MImWidget") << &createWidget;
    QTest::newRow("MImGraphicsView") << &createGraphicsView;
}

void Ut_SelfCompositing::testSelfCompositing()
{
    QFETCH(WidgetCreator, widgetCreator);

    MaliitTestUtils::RemoteWindow remote;
    remote.setGeometry(0, 0, windowSize.width(), windowSize.height());

    QWidget *passthru = app->passThruWindow();
    passthru->setGeometry(remote.geometry().right() + 10, 0,
                          windowSize.width(), windowSize.height());

    QWidget *subject = widgetCreator(passthru);

    remote.show();
    app->setTransientHint(remote.window()->effectiveWinId());

    passthru->show();
    QTest::qWaitForWindowShown(remote.window());

    subject->show();
    QTest::qWaitForWindowShown(passthru->window());
    passthru->raise();
    app->remoteWindow()->redirect();

    QApplication::setActiveWindow(passthru);

    remote.update(); // Not strictly required, due to our window attributes.
    QCoreApplication::processEvents();

    QGraphicsView *view = qobject_cast<QGraphicsView *>(subject);
    QImage subjectImage = QPixmap::grabWidget(view  ? view->viewport() : subject).toImage();
    QImage remoteImage = QPixmap::grabWidget(&remote).toImage();
    QCOMPARE(subjectImage, remoteImage);

    app->remoteWindow()->unredirect();
}

QTEST_APPLESS_MAIN(Ut_SelfCompositing)
<commit_msg>Changes: Skip selfcomposition test if no compositing WM is present<commit_after>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "ut_selfcompositing.h"
#include "mimgraphicsview.h"
#include "mimwidget.h"
#include "mimxapplication.h"
#include "utils.h"

#if defined(Q_WS_X11)
#include <QX11Info>
#endif

namespace
{
    const QSize windowSize(200, 200);

    QWidget *createGraphicsView(QWidget *parent)
    {
        MImGraphicsView *subject = new MImGraphicsView(new QGraphicsScene(parent), parent);
        subject->setSceneRect(QRect(QPoint(), windowSize));
        subject->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        subject->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        subject->setFrameStyle(0);
        subject->setAttribute(Qt::WA_OpaquePaintEvent);
        subject->setAttribute(Qt::WA_NoSystemBackground);
        subject->viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
        subject->viewport()->setAttribute(Qt::WA_NoSystemBackground);
        subject->resize(parent->size());
        subject->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        subject->setCacheMode(QGraphicsView::CacheNone);
        return subject;
    }

    QWidget *createWidget(QWidget *parent)
    {
        MImWidget *subject = new MImWidget(parent);
        subject->setAttribute(Qt::WA_OpaquePaintEvent);
        subject->setAttribute(Qt::WA_NoSystemBackground);
        subject->resize(parent->size());
        return subject;
    }
}

typedef QWidget * (* WidgetCreator)(QWidget *parent);
Q_DECLARE_METATYPE(WidgetCreator);

void Ut_SelfCompositing::initTestCase()
{
    static char *argv[2] = { (char *) "Ut_SelfCompositing",
                             (char *) "-use-self-composition" };
    static int argc = 2;

    // Enforcing raster GS to make test reliable:
    QApplication::setGraphicsSystem("raster");

    app = new MImXApplication(argc, argv);
    QVERIFY(app->selfComposited());
}

void Ut_SelfCompositing::cleanupTestCase()
{
    delete app;
}

void Ut_SelfCompositing::init()
{}

void Ut_SelfCompositing::cleanup()
{}

void Ut_SelfCompositing::testSelfCompositing_data()
{
    QTest::addColumn<WidgetCreator>("widgetCreator");
    QTest::newRow("MImWidget") << &createWidget;
    QTest::newRow("MImGraphicsView") << &createGraphicsView;
}

void Ut_SelfCompositing::testSelfCompositing()
{
#if defined(Q_WS_X11)
    if (not QX11Info::isCompositingManagerRunning()) {
        QSKIP("Not running a compositing windowmanager", SkipSingle);
    }
#endif

    QFETCH(WidgetCreator, widgetCreator);

    MaliitTestUtils::RemoteWindow remote;
    remote.setGeometry(0, 0, windowSize.width(), windowSize.height());

    QWidget *passthru = app->passThruWindow();
    passthru->setGeometry(remote.geometry().right() + 10, 0,
                          windowSize.width(), windowSize.height());

    QWidget *subject = widgetCreator(passthru);

    remote.show();
    app->setTransientHint(remote.window()->effectiveWinId());

    passthru->show();
    QTest::qWaitForWindowShown(remote.window());

    subject->show();
    QTest::qWaitForWindowShown(passthru->window());
    passthru->raise();
    app->remoteWindow()->redirect();

    QApplication::setActiveWindow(passthru);

    remote.update(); // Not strictly required, due to our window attributes.
    QCoreApplication::processEvents();

    QGraphicsView *view = qobject_cast<QGraphicsView *>(subject);
    QImage subjectImage = QPixmap::grabWidget(view  ? view->viewport() : subject).toImage();
    QImage remoteImage = QPixmap::grabWidget(&remote).toImage();
    QCOMPARE(subjectImage, remoteImage);

    app->remoteWindow()->unredirect();
}

QTEST_APPLESS_MAIN(Ut_SelfCompositing)
<|endoftext|>


<commit_before>/***************************************************************************
    copyright            : (C) 2002, 2003 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it  under the terms of the GNU Lesser General Public License version  *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library 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 this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
 *   USA                                                                   *
 ***************************************************************************/

#include <tbytevectorlist.h>
#include <id3v2tag.h>

#include "textidentificationframe.h"

using namespace TagLib;
using namespace ID3v2;

class TextIdentificationFrame::TextIdentificationFramePrivate
{
public:
  TextIdentificationFramePrivate() : textEncoding(String::Latin1) {}
  String::Type textEncoding;
  StringList fieldList;
};

////////////////////////////////////////////////////////////////////////////////
// TextIdentificationFrame public members
////////////////////////////////////////////////////////////////////////////////

TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) :
  Frame(type)
{
  d = new TextIdentificationFramePrivate;
  d->textEncoding = encoding;
}

TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) :
  Frame(data)
{
  d = new TextIdentificationFramePrivate;
  setData(data);
}

TextIdentificationFrame::~TextIdentificationFrame()
{
  delete d;
}

void TextIdentificationFrame::setText(const StringList &l)
{
  d->fieldList = l;
}

void TextIdentificationFrame::setText(const String &s)
{
  d->fieldList = s;
}

String TextIdentificationFrame::toString() const
{
  return d->fieldList.toString();
}

StringList TextIdentificationFrame::fieldList() const
{
  return d->fieldList;
}

String::Type TextIdentificationFrame::textEncoding() const
{
  return d->textEncoding;
}

void TextIdentificationFrame::setTextEncoding(String::Type encoding)
{
  d->textEncoding = encoding;
}

////////////////////////////////////////////////////////////////////////////////
// TextIdentificationFrame protected members
////////////////////////////////////////////////////////////////////////////////

void TextIdentificationFrame::parseFields(const ByteVector &data)
{
  // Don't try to parse invalid frames

  if(data.size() < 2)
    return;

  // read the string data type (the first byte of the field data)

  d->textEncoding = String::Type(data[0]);

  // split the byte array into chunks based on the string type (two byte delimiter
  // for unicode encodings)

  int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;

	// build a small counter to strip nulls off the end of the field

  int dataLength = data.size() - 1;

  while(dataLength > 0 && data[dataLength] == 0)
    dataLength--;

  while(dataLength % byteAlign != 0)
    dataLength++;

  ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign);

  d->fieldList.clear();

  // append those split values to the list and make sure that the new string's
  // type is the same specified for this frame

  for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) {
    String s(*it, d->textEncoding);
    d->fieldList.append(s);
  }
}

ByteVector TextIdentificationFrame::renderFields() const
{
  ByteVector v;

  v.append(char(d->textEncoding));

  for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) {

    // Since the field list is null delimited, if this is not the first
    // element in the list, append the appropriate delimiter for this
    // encoding.

    if(it != d->fieldList.begin())
      v.append(textDelimiter(d->textEncoding));

    v.append((*it).data(d->textEncoding));
  }

  return v;
}

////////////////////////////////////////////////////////////////////////////////
// TextIdentificationFrame private members
////////////////////////////////////////////////////////////////////////////////

TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h)
{
  d = new TextIdentificationFramePrivate;
  parseFields(fieldData(data));
}

////////////////////////////////////////////////////////////////////////////////
// UserTextIdentificationFrame public members
////////////////////////////////////////////////////////////////////////////////

UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) :
  TextIdentificationFrame("TXXX", encoding),
  d(0)
{
  StringList l;
  l.append(String::null);
  l.append(String::null);
  setText(l);
}

UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) :
  TextIdentificationFrame(data)
{
  checkFields();
}

String UserTextIdentificationFrame::toString() const
{
  return "[" + description() + "] " + fieldList().toString();
}

String UserTextIdentificationFrame::description() const
{
  return !TextIdentificationFrame::fieldList().isEmpty()
    ? TextIdentificationFrame::fieldList().front()
    : String::null;
}

StringList UserTextIdentificationFrame::fieldList() const
{
  // TODO: remove this function

  return TextIdentificationFrame::fieldList();
}

void UserTextIdentificationFrame::setText(const String &text)
{
  if(description().isEmpty())
    setDescription(String::null);

  TextIdentificationFrame::setText(StringList(description()).append(text));
}

void UserTextIdentificationFrame::setText(const StringList &fields)
{
  if(description().isEmpty())
    setDescription(String::null);

  TextIdentificationFrame::setText(StringList(description()).append(fields));
}

void UserTextIdentificationFrame::setDescription(const String &s)
{
  StringList l = fieldList();

  if(l.isEmpty())
    l.append(s);
  else
    l[0] = s;

  TextIdentificationFrame::setText(l);
}

UserTextIdentificationFrame *UserTextIdentificationFrame::find(
  ID3v2::Tag *tag, const String &description) // static
{
  FrameList l = tag->frameList("TXXX");
  for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) {
    UserTextIdentificationFrame *f = dynamic_cast<UserTextIdentificationFrame *>(*it);
    if(f && f->description() == description)
      return f;
  }
  return 0;
}

////////////////////////////////////////////////////////////////////////////////
// UserTextIdentificationFrame private members
////////////////////////////////////////////////////////////////////////////////

UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) :
  TextIdentificationFrame(data, h)
{
  checkFields();
}

void UserTextIdentificationFrame::checkFields()
{
  int fields = fieldList().size();

  if(fields == 0)
    setDescription(String::null);
  if(fields <= 1)
    setText(String::null);
}
<commit_msg>SVN_SILENT too many emacs modes...<commit_after>/***************************************************************************
    copyright            : (C) 2002, 2003 by Scott Wheeler
    email                : wheeler@kde.org
 ***************************************************************************/

/***************************************************************************
 *   This library is free software; you can redistribute it and/or modify  *
 *   it  under the terms of the GNU Lesser General Public License version  *
 *   2.1 as published by the Free Software Foundation.                     *
 *                                                                         *
 *   This library 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 this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
 *   USA                                                                   *
 ***************************************************************************/

#include <tbytevectorlist.h>
#include <id3v2tag.h>

#include "textidentificationframe.h"

using namespace TagLib;
using namespace ID3v2;

class TextIdentificationFrame::TextIdentificationFramePrivate
{
public:
  TextIdentificationFramePrivate() : textEncoding(String::Latin1) {}
  String::Type textEncoding;
  StringList fieldList;
};

////////////////////////////////////////////////////////////////////////////////
// TextIdentificationFrame public members
////////////////////////////////////////////////////////////////////////////////

TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) :
  Frame(type)
{
  d = new TextIdentificationFramePrivate;
  d->textEncoding = encoding;
}

TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) :
  Frame(data)
{
  d = new TextIdentificationFramePrivate;
  setData(data);
}

TextIdentificationFrame::~TextIdentificationFrame()
{
  delete d;
}

void TextIdentificationFrame::setText(const StringList &l)
{
  d->fieldList = l;
}

void TextIdentificationFrame::setText(const String &s)
{
  d->fieldList = s;
}

String TextIdentificationFrame::toString() const
{
  return d->fieldList.toString();
}

StringList TextIdentificationFrame::fieldList() const
{
  return d->fieldList;
}

String::Type TextIdentificationFrame::textEncoding() const
{
  return d->textEncoding;
}

void TextIdentificationFrame::setTextEncoding(String::Type encoding)
{
  d->textEncoding = encoding;
}

////////////////////////////////////////////////////////////////////////////////
// TextIdentificationFrame protected members
////////////////////////////////////////////////////////////////////////////////

void TextIdentificationFrame::parseFields(const ByteVector &data)
{
  // Don't try to parse invalid frames

  if(data.size() < 2)
    return;

  // read the string data type (the first byte of the field data)

  d->textEncoding = String::Type(data[0]);

  // split the byte array into chunks based on the string type (two byte delimiter
  // for unicode encodings)

  int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;

  // build a small counter to strip nulls off the end of the field

  int dataLength = data.size() - 1;

  while(dataLength > 0 && data[dataLength] == 0)
    dataLength--;

  while(dataLength % byteAlign != 0)
    dataLength++;

  ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign);

  d->fieldList.clear();

  // append those split values to the list and make sure that the new string's
  // type is the same specified for this frame

  for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) {
    String s(*it, d->textEncoding);
    d->fieldList.append(s);
  }
}

ByteVector TextIdentificationFrame::renderFields() const
{
  ByteVector v;

  v.append(char(d->textEncoding));

  for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) {

    // Since the field list is null delimited, if this is not the first
    // element in the list, append the appropriate delimiter for this
    // encoding.

    if(it != d->fieldList.begin())
      v.append(textDelimiter(d->textEncoding));

    v.append((*it).data(d->textEncoding));
  }

  return v;
}

////////////////////////////////////////////////////////////////////////////////
// TextIdentificationFrame private members
////////////////////////////////////////////////////////////////////////////////

TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h)
{
  d = new TextIdentificationFramePrivate;
  parseFields(fieldData(data));
}

////////////////////////////////////////////////////////////////////////////////
// UserTextIdentificationFrame public members
////////////////////////////////////////////////////////////////////////////////

UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) :
  TextIdentificationFrame("TXXX", encoding),
  d(0)
{
  StringList l;
  l.append(String::null);
  l.append(String::null);
  setText(l);
}

UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) :
  TextIdentificationFrame(data)
{
  checkFields();
}

String UserTextIdentificationFrame::toString() const
{
  return "[" + description() + "] " + fieldList().toString();
}

String UserTextIdentificationFrame::description() const
{
  return !TextIdentificationFrame::fieldList().isEmpty()
    ? TextIdentificationFrame::fieldList().front()
    : String::null;
}

StringList UserTextIdentificationFrame::fieldList() const
{
  // TODO: remove this function

  return TextIdentificationFrame::fieldList();
}

void UserTextIdentificationFrame::setText(const String &text)
{
  if(description().isEmpty())
    setDescription(String::null);

  TextIdentificationFrame::setText(StringList(description()).append(text));
}

void UserTextIdentificationFrame::setText(const StringList &fields)
{
  if(description().isEmpty())
    setDescription(String::null);

  TextIdentificationFrame::setText(StringList(description()).append(fields));
}

void UserTextIdentificationFrame::setDescription(const String &s)
{
  StringList l = fieldList();

  if(l.isEmpty())
    l.append(s);
  else
    l[0] = s;

  TextIdentificationFrame::setText(l);
}

UserTextIdentificationFrame *UserTextIdentificationFrame::find(
  ID3v2::Tag *tag, const String &description) // static
{
  FrameList l = tag->frameList("TXXX");
  for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) {
    UserTextIdentificationFrame *f = dynamic_cast<UserTextIdentificationFrame *>(*it);
    if(f && f->description() == description)
      return f;
  }
  return 0;
}

////////////////////////////////////////////////////////////////////////////////
// UserTextIdentificationFrame private members
////////////////////////////////////////////////////////////////////////////////

UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) :
  TextIdentificationFrame(data, h)
{
  checkFields();
}

void UserTextIdentificationFrame::checkFields()
{
  int fields = fieldList().size();

  if(fields == 0)
    setDescription(String::null);
  if(fields <= 1)
    setText(String::null);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qbs.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "buildgraphlocker.h"

#include "error.h"
#include "hostosinfo.h"
#include "processutils.h"
#include "version.h"

#include <logging/translator.h>

#include <QDir>
#include <QDirIterator>
#include <QFileInfo>
#include <QString>

namespace qbs {
namespace Internal {

static bool hasQtBug45497()
{
    return Version::fromString(QLatin1String(qVersion())) < Version(5, 5, 1);
}

static bool hasQtBug53392()
{
    return HostOsInfo::isWindowsHost()
            && Version::fromString(QLatin1String(qVersion())) < Version(5, 6, 2);
}

BuildGraphLocker::BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger)
    : m_lockFile(buildGraphFilePath + QLatin1String(".lock"))
    , m_logger(logger)
{
    const QString buildDir = QFileInfo(buildGraphFilePath).absolutePath();
    rememberCreatedDirectories(buildDir);
    if (!QDir::root().mkpath(buildDir)) {
        throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Failed to create directory.")
                        .arg(buildGraphFilePath));
    }
    m_lockFile.setStaleLockTime(0);
    int attemptsToGetInfo = 0;
    do {
        if (m_lockFile.tryLock(250))
            return;
        switch (m_lockFile.error()) {
        case QLockFile::LockFailedError: {
            qint64 pid;
            QString hostName;
            QString appName;
            if (m_lockFile.getLockInfo(&pid, &hostName, &appName)) {
                if ((!hasQtBug45497() && !hasQtBug53392()) || appName == processNameByPid(pid)) {
                    throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': "
                                           "Already locked by '%2' (PID %3).")
                                    .arg(buildGraphFilePath, appName).arg(pid));
                }

                // The process id was reused by some other process.
                m_logger.qbsInfo() << Tr::tr("Removing stale lock file.");
                m_lockFile.removeStaleLockFile();
            }
            break;
        }
        case QLockFile::PermissionError:
            throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Permission denied.")
                            .arg(buildGraphFilePath));
        case QLockFile::UnknownError:
        case QLockFile::NoError:
            throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).")
                            .arg(buildGraphFilePath));
        }
    } while (++attemptsToGetInfo < 10);

    // This very unlikely case arises if tryLock() repeatedly returns LockFailedError
    // with the subsequent getLockInfo() failing as well.
    throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).")
                    .arg(buildGraphFilePath));
}

BuildGraphLocker::~BuildGraphLocker()
{
    m_lockFile.unlock();
    removeEmptyCreatedDirectories();
}

void BuildGraphLocker::rememberCreatedDirectories(const QString &buildDir)
{
    QString parentDir = buildDir;
    while (!QFileInfo::exists(parentDir)) {
        m_createdParentDirs.enqueue(parentDir);
        parentDir = QDir::cleanPath(parentDir + QLatin1String("/.."));
    }
}

void BuildGraphLocker::removeEmptyCreatedDirectories()
{
    QDir root = QDir::root();
    while (!m_createdParentDirs.isEmpty()) {
        const QString parentDir = m_createdParentDirs.dequeue();
        QDirIterator it(parentDir, QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System,
                        QDirIterator::Subdirectories);
        if (it.hasNext())
            break;
        if (!root.rmdir(parentDir)) {
            m_logger.printWarning(ErrorInfo(Tr::tr("Failed to remove empty directory '%1'.")
                                            .arg(parentDir)));
        }
    }
}

} // namespace Internal
} // namespace qbs
<commit_msg>BuildGraphLocker: Include 5.7.0 in versions that have QTBUG-53392<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qbs.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "buildgraphlocker.h"

#include "error.h"
#include "hostosinfo.h"
#include "processutils.h"
#include "version.h"

#include <logging/translator.h>

#include <QDir>
#include <QDirIterator>
#include <QFileInfo>
#include <QString>

namespace qbs {
namespace Internal {

static bool hasQtBug45497()
{
    return Version::fromString(QLatin1String(qVersion())) < Version(5, 5, 1);
}

static bool hasQtBug53392()
{
    if (!HostOsInfo::isWindowsHost())
        return false;
    const Version qtVersion = Version::fromString(QLatin1String(qVersion()));
    // The fix is included in 5.6.2 and 5.7.1, but not in 5.7.0.
    return qtVersion == Version(5, 7, 0) || qtVersion < Version(5, 6, 2);
}

BuildGraphLocker::BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger)
    : m_lockFile(buildGraphFilePath + QLatin1String(".lock"))
    , m_logger(logger)
{
    const QString buildDir = QFileInfo(buildGraphFilePath).absolutePath();
    rememberCreatedDirectories(buildDir);
    if (!QDir::root().mkpath(buildDir)) {
        throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Failed to create directory.")
                        .arg(buildGraphFilePath));
    }
    m_lockFile.setStaleLockTime(0);
    int attemptsToGetInfo = 0;
    do {
        if (m_lockFile.tryLock(250))
            return;
        switch (m_lockFile.error()) {
        case QLockFile::LockFailedError: {
            qint64 pid;
            QString hostName;
            QString appName;
            if (m_lockFile.getLockInfo(&pid, &hostName, &appName)) {
                if ((!hasQtBug45497() && !hasQtBug53392()) || appName == processNameByPid(pid)) {
                    throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': "
                                           "Already locked by '%2' (PID %3).")
                                    .arg(buildGraphFilePath, appName).arg(pid));
                }

                // The process id was reused by some other process.
                m_logger.qbsInfo() << Tr::tr("Removing stale lock file.");
                m_lockFile.removeStaleLockFile();
            }
            break;
        }
        case QLockFile::PermissionError:
            throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Permission denied.")
                            .arg(buildGraphFilePath));
        case QLockFile::UnknownError:
        case QLockFile::NoError:
            throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).")
                            .arg(buildGraphFilePath));
        }
    } while (++attemptsToGetInfo < 10);

    // This very unlikely case arises if tryLock() repeatedly returns LockFailedError
    // with the subsequent getLockInfo() failing as well.
    throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).")
                    .arg(buildGraphFilePath));
}

BuildGraphLocker::~BuildGraphLocker()
{
    m_lockFile.unlock();
    removeEmptyCreatedDirectories();
}

void BuildGraphLocker::rememberCreatedDirectories(const QString &buildDir)
{
    QString parentDir = buildDir;
    while (!QFileInfo::exists(parentDir)) {
        m_createdParentDirs.enqueue(parentDir);
        parentDir = QDir::cleanPath(parentDir + QLatin1String("/.."));
    }
}

void BuildGraphLocker::removeEmptyCreatedDirectories()
{
    QDir root = QDir::root();
    while (!m_createdParentDirs.isEmpty()) {
        const QString parentDir = m_createdParentDirs.dequeue();
        QDirIterator it(parentDir, QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System,
                        QDirIterator::Subdirectories);
        if (it.hasNext())
            break;
        if (!root.rmdir(parentDir)) {
            m_logger.printWarning(ErrorInfo(Tr::tr("Failed to remove empty directory '%1'.")
                                            .arg(parentDir)));
        }
    }
}

} // namespace Internal
} // namespace qbs
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library 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 this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_MISC_READTOPOLOGY_INL
#define SOFA_COMPONENT_MISC_READTOPOLOGY_INL

#include <sofa/component/misc/ReadTopology.h>
#include <sofa/simulation/common/MechanicalVisitor.h>
#include <sofa/simulation/common/UpdateMappingVisitor.h>

#include <string.h>
#include <sstream>

namespace sofa
{

namespace component
{

namespace misc
{

ReadTopology::ReadTopology()
    : f_filename( initData(&f_filename, "filename", "input file name"))
    , f_interval( initData(&f_interval, 0.0, "interval", "time duration between inputs"))
    , f_shift( initData(&f_shift, 0.0, "shift", "shift between times in the file and times when they will be read"))
    , f_loop( initData(&f_loop, false, "loop", "set to 'true' to re-read the file when reaching the end"))
    , m_topology(NULL)
    , infile(NULL)
#ifdef SOFA_HAVE_ZLIB
    , gzfile(NULL)
#endif
    , nextTime(0.0)
    , lastTime(0.0)
    , loopTime(0.0)
{
    this->f_listening.setValue(true);
}

ReadTopology::~ReadTopology()
{
    if (infile)
        delete infile;
#ifdef SOFA_HAVE_ZLIB
    if (gzfile)
        gzclose(gzfile);
#endif
}

void ReadTopology::init()
{

    reset();
}

void ReadTopology::reset()
{
    m_topology = dynamic_cast<core::componentmodel::topology::BaseMeshTopology*>(this->getContext()->getMeshTopology());
    if (infile)
    {
        delete infile;
        infile = NULL;
    }
#ifdef SOFA_HAVE_ZLIB
    if (gzfile)
    {
        gzclose(gzfile);
        gzfile = NULL;
    }
#endif

    const std::string& filename = f_filename.getFullPath();
    if (filename.empty())
    {
        serr << "ERROR: empty filename"<<sendl;
    }
#ifdef SOFA_HAVE_ZLIB
    else if (filename.size() >= 3 && filename.substr(filename.size()-3)==".gz")
    {
        gzfile = gzopen(filename.c_str(),"rb");
        if( !gzfile )
        {
            serr << "Error opening compressed file "<<filename<<sendl;
        }
    }
#endif
    else
    {
        infile = new std::ifstream(filename.c_str());
        if( !infile->is_open() )
        {
            serr << "Error opening file "<<filename<<sendl;
            delete infile;
            infile = NULL;
        }
    }
    nextTime = 0;
}

void ReadTopology::handleEvent(sofa::core::objectmodel::Event* event)
{
    if (/* simulation::AnimateBeginEvent* ev = */ dynamic_cast<simulation::AnimateBeginEvent*>(event))
    {
        processReadTopology();
    }
    if (/* simulation::AnimateEndEvent* ev = */ dynamic_cast<simulation::AnimateEndEvent*>(event))
    {

    }
}

void ReadTopology::setTime(double time)
{
    if (time < nextTime) {reset(); nextTime=0.0; loopTime=0.0; }
}

void ReadTopology::processReadTopology(double time)
{
    if (time == lastTime) return;
    setTime(time);
    processReadTopology();
}

bool ReadTopology::readNext(double time, std::vector<std::string>& validLines)
{
    if (!m_topology) return false;
    if (!infile
#ifdef SOFA_HAVE_ZLIB
        && !gzfile
#endif
       )
        return false;
    lastTime = time;
    validLines.clear();
    std::string line, cmd;

    double epsilon = 0.00000001;

    while ((double)nextTime <= (time + epsilon))
    {

#ifdef SOFA_HAVE_ZLIB
        if (gzfile)
        {

            if (gzeof(gzfile))
            {
                if (!f_loop.getValue())
                    break;
                gzrewind(gzfile);
                loopTime = nextTime;
            }
            //getline(gzfile, line);
            line.clear();
            char buf[4097];
            buf[0] = '\0';
            while (gzgets(gzfile,buf,sizeof(buf))!=NULL && buf[0])
            {
                int l = strlen(buf);
                if (buf[l-1] == '\n')
                {
                    buf[l-1] = '\0';
                    line += buf;
                    break;
                }
                else
                {
                    line += buf;
                    buf[0] = '\0';
                }
            }
        }
        else
#endif
            if (infile)
            {
                if (infile->eof())
                {
                    if (!f_loop.getValue())
                        break;
                    infile->clear();
                    infile->seekg(0);
                    loopTime = nextTime;
                }
                getline(*infile, line);
            }
        //std::cout << "line= "<<line<<std::endl;
        std::istringstream str(line);
        str >> cmd;
        //std::cout << "cmd:: " << cmd << std::endl;
        if (cmd == "T=")
        {
            str >> nextTime;

            nextTime += loopTime;
            //sout << "next time: " << nextTime << sendl;
            if (nextTime <= time)
                validLines.clear();
        }

        if (nextTime <= time)
            validLines.push_back(line);
    }
    return true;
}

void ReadTopology::processReadTopology()
{
    double time = getContext()->getTime() + f_shift.getValue();
    std::cout <<std::setprecision (9)<<time << std::endl;

    std::vector<std::string> validLines;
    if (!readNext(time, validLines)) return;

    unsigned int nbr = 0;
    for (std::vector<std::string>::iterator it=validLines.begin(); it!=validLines.end();)
    {
        //For one Timestep store all topology data available.

        std::string buff;
        std::istringstream str(*it);

        str >> buff;

        if (buff == "T=")
        {
            //Nothing to do in this case.
            //std::cout << "cas T" << std::endl;
            ++it;
            continue;
        }
        else if ( buff == "Edges=")
        {
            //Looking fo the number of edges, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,2> >& my_edges = *(edges.beginEdit());
                std::istringstream Sedges(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,2> nodes;
                    Sedges >> nodes[0] >> nodes[1];

                    my_edges.push_back (nodes);
                }
                edges.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Triangles=")
        {
            //Looking fo the number of Triangles, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,3> >& my_triangles = *(triangles.beginEdit());
                std::istringstream Stri(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,3> nodes;
                    Stri >> nodes[0] >> nodes[1] >> nodes[2];

                    my_triangles.push_back (nodes);
                }
                triangles.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Quads=")
        {
            //Looking fo the number of Quads, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,4> >& my_quads = *(quads.beginEdit());
                std::istringstream Squads(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,4> nodes;
                    Squads >> nodes[0] >> nodes[1] >> nodes[2] >> nodes[3];

                    my_quads.push_back (nodes);
                }
                quads.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Tetrahedra=")
        {
            //Looking fo the number of Tetrahedra, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,4> >& my_tetrahedra = *(tetrahedra.beginEdit());
                std::istringstream Stetra(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,4> nodes;
                    Stetra >> nodes[0] >> nodes[1] >> nodes[2] >> nodes[3];

                    my_tetrahedra.push_back (nodes);
                }
                tetrahedra.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Hexahedra=")
        {
            //Looking fo the number of Hexahedra, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,8> >& my_hexahedra = *(hexahedra.beginEdit());
                std::istringstream Shexa(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,8> nodes;
                    Shexa >> nodes[0] >> nodes[1] >> nodes[2] >> nodes[3] >> nodes[4] >> nodes[5] >> nodes[6] >> nodes[7];

                    my_hexahedra.push_back (nodes);
                }
                hexahedra.endEdit();
            }

            ++it;
            continue;
        }
        else
        {
            ++it;
            continue;
        }

    }

}

} // namespace misc

} // namespace component

} // namespace sofa

#endif
<commit_msg>r5743/sofa-dev : FIX: compilation.<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library 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 this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_MISC_READTOPOLOGY_INL
#define SOFA_COMPONENT_MISC_READTOPOLOGY_INL

#include <sofa/component/misc/ReadTopology.h>
#include <sofa/simulation/common/MechanicalVisitor.h>
#include <sofa/simulation/common/UpdateMappingVisitor.h>

#include <string.h>
#include <sstream>

namespace sofa
{

namespace component
{

namespace misc
{

ReadTopology::ReadTopology()
    : f_filename( initData(&f_filename, "filename", "input file name"))
    , f_interval( initData(&f_interval, 0.0, "interval", "time duration between inputs"))
    , f_shift( initData(&f_shift, 0.0, "shift", "shift between times in the file and times when they will be read"))
    , f_loop( initData(&f_loop, false, "loop", "set to 'true' to re-read the file when reaching the end"))
    , m_topology(NULL)
    , infile(NULL)
#ifdef SOFA_HAVE_ZLIB
    , gzfile(NULL)
#endif
    , nextTime(0.0)
    , lastTime(0.0)
    , loopTime(0.0)
{
    this->f_listening.setValue(true);
}

ReadTopology::~ReadTopology()
{
    if (infile)
        delete infile;
#ifdef SOFA_HAVE_ZLIB
    if (gzfile)
        gzclose(gzfile);
#endif
}

void ReadTopology::init()
{

    reset();
}

void ReadTopology::reset()
{
    m_topology = dynamic_cast<core::componentmodel::topology::BaseMeshTopology*>(this->getContext()->getMeshTopology());
    if (infile)
    {
        delete infile;
        infile = NULL;
    }
#ifdef SOFA_HAVE_ZLIB
    if (gzfile)
    {
        gzclose(gzfile);
        gzfile = NULL;
    }
#endif

    const std::string& filename = f_filename.getFullPath();
    if (filename.empty())
    {
        serr << "ERROR: empty filename"<<sendl;
    }
#ifdef SOFA_HAVE_ZLIB
    else if (filename.size() >= 3 && filename.substr(filename.size()-3)==".gz")
    {
        gzfile = gzopen(filename.c_str(),"rb");
        if( !gzfile )
        {
            serr << "Error opening compressed file "<<filename<<sendl;
        }
    }
#endif
    else
    {
        infile = new std::ifstream(filename.c_str());
        if( !infile->is_open() )
        {
            serr << "Error opening file "<<filename<<sendl;
            delete infile;
            infile = NULL;
        }
    }
    nextTime = 0;
}

void ReadTopology::handleEvent(sofa::core::objectmodel::Event* event)
{
    if (/* simulation::AnimateBeginEvent* ev = */ dynamic_cast<simulation::AnimateBeginEvent*>(event))
    {
        processReadTopology();
    }
    if (/* simulation::AnimateEndEvent* ev = */ dynamic_cast<simulation::AnimateEndEvent*>(event))
    {

    }
}

void ReadTopology::setTime(double time)
{
    if (time < nextTime) {reset(); nextTime=0.0; loopTime=0.0; }
}

void ReadTopology::processReadTopology(double time)
{
    if (time == lastTime) return;
    setTime(time);
    processReadTopology();
}

bool ReadTopology::readNext(double time, std::vector<std::string>& validLines)
{
    if (!m_topology) return false;
    if (!infile
#ifdef SOFA_HAVE_ZLIB
        && !gzfile
#endif
       )
        return false;
    lastTime = time;
    validLines.clear();
    std::string line, cmd;

    double epsilon = 0.00000001;

    while ((double)nextTime <= (time + epsilon))
    {

#ifdef SOFA_HAVE_ZLIB
        if (gzfile)
        {

            if (gzeof(gzfile))
            {
                if (!f_loop.getValue())
                    break;
                gzrewind(gzfile);
                loopTime = nextTime;
            }
            //getline(gzfile, line);
            line.clear();
            char buf[4097];
            buf[0] = '\0';
            while (gzgets(gzfile,buf,sizeof(buf))!=NULL && buf[0])
            {
                int l = strlen(buf);
                if (buf[l-1] == '\n')
                {
                    buf[l-1] = '\0';
                    line += buf;
                    break;
                }
                else
                {
                    line += buf;
                    buf[0] = '\0';
                }
            }
        }
        else
#endif
            if (infile)
            {
                if (infile->eof())
                {
                    if (!f_loop.getValue())
                        break;
                    infile->clear();
                    infile->seekg(0);
                    loopTime = nextTime;
                }
                getline(*infile, line);
            }
        //std::cout << "line= "<<line<<std::endl;
        std::istringstream str(line);
        str >> cmd;
        //std::cout << "cmd:: " << cmd << std::endl;
        if (cmd == "T=")
        {
            str >> nextTime;

            nextTime += loopTime;
            //sout << "next time: " << nextTime << sendl;
            if (nextTime <= time)
                validLines.clear();
        }

        if (nextTime <= time)
            validLines.push_back(line);
    }
    return true;
}

void ReadTopology::processReadTopology()
{
    double time = getContext()->getTime() + f_shift.getValue();

    std::vector<std::string> validLines;
    if (!readNext(time, validLines)) return;

    unsigned int nbr = 0;
    for (std::vector<std::string>::iterator it=validLines.begin(); it!=validLines.end();)
    {
        //For one Timestep store all topology data available.

        std::string buff;
        std::istringstream str(*it);

        str >> buff;

        if (buff == "T=")
        {
            //Nothing to do in this case.
            //std::cout << "cas T" << std::endl;
            ++it;
            continue;
        }
        else if ( buff == "Edges=")
        {
            //Looking fo the number of edges, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,2> >& my_edges = *(edges.beginEdit());
                std::istringstream Sedges(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,2> nodes;
                    Sedges >> nodes[0] >> nodes[1];

                    my_edges.push_back (nodes);
                }
                edges.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Triangles=")
        {
            //Looking fo the number of Triangles, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,3> >& my_triangles = *(triangles.beginEdit());
                std::istringstream Stri(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,3> nodes;
                    Stri >> nodes[0] >> nodes[1] >> nodes[2];

                    my_triangles.push_back (nodes);
                }
                triangles.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Quads=")
        {
            //Looking fo the number of Quads, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,4> >& my_quads = *(quads.beginEdit());
                std::istringstream Squads(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,4> nodes;
                    Squads >> nodes[0] >> nodes[1] >> nodes[2] >> nodes[3];

                    my_quads.push_back (nodes);
                }
                quads.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Tetrahedra=")
        {
            //Looking fo the number of Tetrahedra, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,4> >& my_tetrahedra = *(tetrahedra.beginEdit());
                std::istringstream Stetra(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,4> nodes;
                    Stetra >> nodes[0] >> nodes[1] >> nodes[2] >> nodes[3];

                    my_tetrahedra.push_back (nodes);
                }
                tetrahedra.endEdit();
            }

            ++it;
            continue;
        }
        else if ( buff == "Hexahedra=")
        {
            //Looking fo the number of Hexahedra, if not null, then we store them..
            str >> nbr;
            ++it;

            if (nbr != 0)
            {
                helper::vector<helper::fixed_array <unsigned int,8> >& my_hexahedra = *(hexahedra.beginEdit());
                std::istringstream Shexa(*it);
                for (unsigned int i = 0; i<nbr; ++i)
                {
                    helper::fixed_array <unsigned int,8> nodes;
                    Shexa >> nodes[0] >> nodes[1] >> nodes[2] >> nodes[3] >> nodes[4] >> nodes[5] >> nodes[6] >> nodes[7];

                    my_hexahedra.push_back (nodes);
                }
                hexahedra.endEdit();
            }

            ++it;
            continue;
        }
        else
        {
            ++it;
            continue;
        }

    }

}

} // namespace misc

} // namespace component

} // namespace sofa

#endif
<|endoftext|>