<commit_before>/**
 * @file
 *  Zenderer/Objects/Entity.hpp - A generic entity class wrapping drawable
 *  primitives, materials, and easy sprite-like functionality together.
 *
 * @author      <NAME> (halcyon)
 * @version     2.0
 * @copyright   Apache License v2.0
 *  Licensed under the Apache License, Version 2.0 (the "License").         \n
 *  You may not use this file except in compliance with the License.        \n
 *  You may obtain a copy of the License at:
 *  http://www.apache.org/licenses/LICENSE-2.0                              \n
 *  Unless required by applicable law or agreed to in writing, software     \n
 *  distributed under the License is distributed on an "AS IS" BASIS,       \n
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n
 *  See the License for the specific language governing permissions and     \n
 *  limitations under the License.
 *
 * @addtogroup Objects
 *  A group containing renderable objects with a variety of controllable
 *  options and features like animation and collision detection.
 *  These classes are a step above the simple primitive rendering scheme
 *  set up by the architecture in zen::gfx::zPolygon, and are the most
 *  likely to face direct user interaction through the application.
 *
 * @{
 **/

#ifndef ZENDERER__OBJECTS__ENTITY_HPP
#define ZENDERER__OBJECTS__ENTITY_HPP

#include <regex>
#include <algorithm>

#include "Zenderer/Math/Math.hpp"
#include "Zenderer/CoreGraphics/Drawable.hpp"
#include "Zenderer/Graphics/Window.hpp"
#include "Zenderer/Graphics/Material.hpp"
#include "Zenderer/Graphics/Polygon.hpp"
#include "Zenderer/Graphics/Quad.hpp"
#include "Zenderer/Utilities/INIParser.hpp"

namespace zen
{
namespace gfx { class ZEN_API zScene; }
namespace gui { class ZEN_API zFont;  }

/// A group of sprite-like objects that operate at a high level of abstraction.
namespace obj
{
    /// A base class for all "in-game" objects.
    class ZEN_API zEntity
    {
    protected:
        // Internal error types.
        enum class ZEN_API ErrorType : uint16_t
        {
            BAD_PAIR,
            BAD_POSITION,
            BAD_MATERIAL,
            NO_TEXTURE
        };

    public:
        explicit zEntity(asset::zAssetManager& Assets);
        virtual ~zEntity();

        /**
         * Creates an entity mesh from a file.
         *  There is a detailed specification for well-formed loading of
         *  single and multi-primitive entity loading with unique material
         *  attachments for each. This will implicitly call Optimize()
         *  when loading is complete.
         *
         * @param   filename    The path to the entity file.
         *
         * @return  `true`  if loaded successfully, and
         *          `false` otherwise. There is no retrievable error, but
         *                  something appropriate will be logged.
         *
         * @see     The entity file specification page [here](index.html)
         **/
        bool LoadFromFile(const string_t& filename);

        /**
         * Creates an entity from a texture file.
         *  This will simply make a quad entity the exact width and height
         *  as the provided texture returns.
         *
         * @param   filename    Path to texture
         *
         * @return  `true`  if the image and entity loaded successfully,
         *          `false` otherwise. There is no retrievable error, but
         *                  something appropriate will be logged.
         **/
        bool LoadFromTexture(const string_t& filename);

        /**
         * Creates an entity from an existing primitive, or adds it.
         *  This will store a copy of the primitive locally, to prevent bad
         *  references occuring later. Thus it's advisable to `delete` heap
         *  memory when done here, or ensure that the given primitive will go
         *  off the stack soon, to prevent unnecessary memory duplication.
         *
         * @param   Prim    A primitive to make "high-level".
         *
         * @return  `true`  if the primitive loaded with a valid textre, and
         *          `false` otherwise.
         *
         * @note    Currently, multiple calls to this method will stack
         *          primitive on top of one another, since there is no position
         *          specification on them.
         **/
        bool AddPrimitive(const gfx::zPolygon& Prim);

        /**
         * Merges primitive data with shared materials.
         *  If multiple internal quads share the same material data, this will
         *  merge their vertex buffer data together in order to minimize draw
         *  calls and state changes later when rendering.
         *
         * @return  `true`  if any optimization was done, `false` otherwise.
         *
         * @warning Not implemented.
         **/
        bool Optimize();

        /**
         * Draws the entity on-screen.
         *  Since entities are just collections of one or more primitives, this
         *  will simply call gfx::zQuad::Draw on each individual internal
         *  primitive.
         *
         *  If `is_bound` is `true`, the draw call will only do drawing (go
         *  figure). Otherwise, it will create an internal vertex array (on
         *  first draw), bind its local material, set up the model-view matrix,
         *  etc, and then do drawing. This allows for various scenarios and
         *  prevents the user from having to set up this data on their own if
         *  they just want to get something on-screen.
         *
         * @param   is_bound    Is there already buffer / material data bound?
         *
         *
         **/
        bool Draw(bool is_bound = false);

        /**
         * Moves the entity to the specified position.
         *  In future revisions, this will adjust all internal primitives
         *  accordingly, once the default primitive stacking behavior is
         *  removed.
         *
         * @param   Pos     The coordinate to place the entity at
         *
         * @todo    Support a variety of primitive depths.
         **/
        void Move(const math::vector_t& Pos);

        /// @overload
        void Move(const real_t x, const real_t y, const real_t z = 1.0);

        /**
         * Places an object in the center of a window.
         *  This is a common operation, especially for placing labels
         *  and such on screens, so I've provided a simplistic wrapper for
         *  the task.<commit_msg>#16: Make base class inheritable.<commit_after>/**
 * @file
 *  Zenderer/Objects/Entity.hpp - A generic entity class wrapping drawable
 *  primitives, materials, and easy sprite-like functionality together.
 *
 * @author      <NAME> (halcyon)
 * @version     2.0
 * @copyright   Apache License v2.0
 *  Licensed under the Apache License, Version 2.0 (the "License").         \n
 *  You may not use this file except in compliance with the License.        \n
 *  You may obtain a copy of the License at:
 *  http://www.apache.org/licenses/LICENSE-2.0                              \n
 *  Unless required by applicable law or agreed to in writing, software     \n
 *  distributed under the License is distributed on an "AS IS" BASIS,       \n
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n
 *  See the License for the specific language governing permissions and     \n
 *  limitations under the License.
 *
 * @addtogroup Objects
 *  A group containing renderable objects with a variety of controllable
 *  options and features like animation and collision detection.
 *  These classes are a step above the simple primitive rendering scheme
 *  set up by the architecture in zen::gfx::zPolygon, and are the most
 *  likely to face direct user interaction through the application.
 *
 * @{
 **/

#ifndef ZENDERER__OBJECTS__ENTITY_HPP
#define ZENDERER__OBJECTS__ENTITY_HPP

#include <regex>
#include <algorithm>

#include "Zenderer/Math/Math.hpp"
#include "Zenderer/CoreGraphics/Drawable.hpp"
#include "Zenderer/Graphics/Window.hpp"
#include "Zenderer/Graphics/Material.hpp"
#include "Zenderer/Graphics/Polygon.hpp"
#include "Zenderer/Graphics/Quad.hpp"
#include "Zenderer/Utilities/INIParser.hpp"

namespace zen
{
namespace gfx { class ZEN_API zScene; }
namespace gui { class ZEN_API zFont;  }

/// A group of sprite-like objects that operate at a high level of abstraction.
namespace obj
{
    /// A base class for all "in-game" objects.
    class ZEN_API zEntity
    {
    protected:
        // Internal error types.
        enum class ZEN_API ErrorType : uint16_t
        {
            BAD_PAIR,
            BAD_POSITION,
            BAD_MATERIAL,
            NO_TEXTURE
        };

    public:
        explicit zEntity(asset::zAssetManager& Assets);
        virtual ~zEntity();

        /**
         * Creates an entity mesh from a file.
         *  There is a detailed specification for well-formed loading of
         *  single and multi-primitive entity loading with unique material
         *  attachments for each. This will implicitly call Optimize()
         *  when loading is complete.
         *
         * @param   filename    The path to the entity file.
         *
         * @return  `true`  if loaded successfully, and
         *          `false` otherwise. There is no retrievable error, but
         *                  something appropriate will be logged.
         *
         * @see     The entity file specification page [here](index.html)
         **/
        virtual bool LoadFromFile(const string_t& filename);

        /**
         * Creates an entity from a texture file.
         *  This will simply make a quad entity the exact width and height
         *  as the provided texture returns.
         *
         * @param   filename    Path to texture
         *
         * @return  `true`  if the image and entity loaded successfully,
         *          `false` otherwise. There is no retrievable error, but
         *                  something appropriate will be logged.
         **/
        virtual bool LoadFromTexture(const string_t& filename);

        /**
         * Creates an entity from an existing primitive, or adds it.
         *  This will store a copy of the primitive locally, to prevent bad
         *  references occuring later. Thus it's advisable to `delete` heap
         *  memory when done here, or ensure that the given primitive will go
         *  off the stack soon, to prevent unnecessary memory duplication.
         *
         * @param   Prim    A primitive to make "high-level".
         *
         * @return  `true`  if the primitive loaded with a valid textre, and
         *          `false` otherwise.
         *
         * @note    Currently, multiple calls to this method will stack
         *          primitive on top of one another, since there is no position
         *          specification on them.
         **/
        virtual bool AddPrimitive(const gfx::zPolygon& Prim);

        /**
         * Merges primitive data with shared materials.
         *  If multiple internal quads share the same material data, this will
         *  merge their vertex buffer data together in order to minimize draw
         *  calls and state changes later when rendering.
         *
         * @return  `true`  if any optimization was done, `false` otherwise.
         *
         * @warning Not implemented.
         **/
        bool Optimize();

        /**
         * Draws the entity on-screen.
         *  Since entities are just collections of one or more primitives, this
         *  will simply call gfx::zQuad::Draw on each individual internal
         *  primitive.
         *
         *  If `is_bound` is `true`, the draw call will only do drawing (go
         *  figure). Otherwise, it will create an internal vertex array (on
         *  first draw), bind its local material, set up the model-view matrix,
         *  etc, and then do drawing. This allows for various scenarios and
         *  prevents the user from having to set up this data on their own if
         *  they just want to get something on-screen.
         *
         * @param   is_bound    Is there already buffer / material data bound?
         *
         *
         **/
        virtual bool Draw(bool is_bound = false);

        /// Purely for inheritance compatibility.
        virtual bool Update() {}

        /**
         * Moves the entity to the specified position.
         *  In future revisions, this will adjust all internal primitives
         *  accordingly, once the default primitive stacking behavior is
         *  removed.
         *
         * @param   Pos     The coordinate to place the entity at
         *
         * @todo    Support a variety of primitive depths.
         **/
        void Move(const math::vector_t& Pos);

        /// @overload
        void Move(const real_t x, const real_t y, const real_t z = 1.0);

        /**
         * Places an object in the center of a window.
         *  This is a common operation, especially for placing labels
         *  and such on screens, so I've provided a simplistic wrapper for
         *  the task.
{'fraction_non_alphanumeric': 0.06940854492929907, 'fraction_numerical': 0.001976585069180477, 'mean_word_length': 2.0172018348623855, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6020268', 'n_tokens_mistral': 3415, 'n_tokens_neox': 3342, 'n_words': 1424}