<reponame>LongerZrLong/TinyEngine<filename>TinyEngine/src/TinyEngine/Scene/Scene.cpp
#include "Scene.h"

#include "TinyEngine/Renderer/Renderer2D.h"
#include "Entity.h"
#include "Components.h"

namespace TNG {

    Entity Scene::CreateEntity(const std::string &name)
    {
        Entity entity(m_Registry.create(), this);

        // Every Entity will have Sprite Component and Transform Component
        std::string tag = (name.empty()? "Entity" : name);
        entity.AddComponent<TagComponent>(tag);
        entity.AddComponent<TransformComponent>();

        return entity;
    }

    void Scene::DestroyEntity(Entity entity)
    {
        m_Registry.destroy(entity);
    }

    Entity Scene::GetPrimaryCameraEntity()
    {
        auto view = m_Registry.view<CameraComponent>();
        for (auto entityID : view)
        {
            auto &cameraComponent = m_Registry.get<CameraComponent>(entityID);

            if (cameraComponent.Primary)
                return Entity(entityID, this);
        }

        return Entity();
    }

    void Scene::OnUpdateEditor(Timestep ts, EditorCamera &camera)
    {
        // Render from editor camera
        Renderer2D::BeginScene(camera);

        m_Registry.view<TransformComponent, SpriteRendererComponent>().each([](auto entityID, auto &trans, auto &sprite)
        {
            Renderer2D::DrawSprite(trans.GetTransform(), sprite, (int)entityID);
        });

        Renderer2D::EndScene();
    }

    void Scene::OnUpdateRuntime(Timestep ts)
    {
        // Update script component
        m_Registry.view<NativeScriptComponent>().each([=](auto entityID, auto &nsc)
        {
            if (!nsc.Instance)
            {
                nsc.Instance = nsc.InstantiateScript();
                nsc.Instance->m_Entity = Entity(entityID, this);
                nsc.Instance->OnCreate();
            }

            nsc.Instance->OnUpdate(ts);
        });

        // Get primary camera and its transform
        Camera *mainCameraPtr = nullptr;
        glm::mat4 mainCameraTransformPtr;
        {
            auto view = m_Registry.view<CameraComponent, TransformComponent>();
            for (auto entityID : view)
            {
                auto &cameraComponent = view.get<CameraComponent>(entityID);

                if (cameraComponent.Primary == true)
                {
                    mainCameraPtr = &cameraComponent.Camera;
                    mainCameraTransformPtr = view.get<TransformComponent>(entityID).GetTransform();
                    break;
                }
            }
        }

        // Render from main camera
        if (mainCameraPtr)
        {
            Renderer2D::BeginScene(*mainCameraPtr, mainCameraTransformPtr);

            m_Registry.view<TransformComponent, SpriteRendererComponent>().each([](auto entityID, auto &trans, auto &sprite)
            {
                Renderer2D::DrawSprite(trans.GetTransform(), sprite, (int)entityID);
            });

            Renderer2D::EndScene();
        }
    }

    void Scene::OnViewportResize(unsigned int width, unsigned int height)
    {
        m_ViewportWidth = width;
        m_ViewportHeight = height;

        m_Registry.view<CameraComponent, TransformComponent>().each([=](auto entityID, auto &cam, auto &trans)
        {
            if (!cam.FixedAspectRatio)
                cam.Camera.SetViewportSize(width, height);
        });
    }


}
