Program Listing for File engine.cpp¶
↰ Return to documentation for file (portal/engine/engine.cpp)
//
// Copyright © 2025 Jonatan Nevo.
// Distributed under the MIT license (see LICENSE file).
//
#include "engine.h"
#include "portal/application/settings.h"
#include "editor/editor_module.h"
#include "modules/resources_module.h"
#include "modules/system_orchestrator.h"
#include "portal/engine/modules/scheduler_module.h"
#include "portal/engine/resources/resources/composite.h"
#include "portal/engine/window/glfw_window.h"
#include "project/project.h"
#include "resources/database/resource_database_facade.h"
namespace portal
{
static auto logger = Log::get_logger("Engine");
Engine::Engine(const Reference<Project>& project, const ApplicationProperties& properties) : Application(properties),
project(project)
{
// Creating Input
auto& settings = project->get_settings();
auto& input = modules.add_module<InputManager>(
[this](auto& event)
{
on_event(event);
}
);
modules.add_module<SchedulerModule>(settings.get_setting<int32_t>("application.scheduler-threads", 0));
auto& registry = modules.add_module<ecs::Registry>();
auto& system_orchestrator = modules.add_module<SystemOrchestrator>();
// Creating vulkan context
const WindowProperties window_properties{
.title = properties.name,
.extent = {properties.width, properties.height},
.requested_frames_in_flight = settings.get_setting<size_t>("application.frames_in_flight", 3),
};
window = make_reference<GlfwWindow>(project->get_settings(), window_properties, CallbackConsumers{*this, input});
// TODO: find a better way of subscribing to this
event_handlers.emplace_back(*window);
vulkan_context = renderer::vulkan::VulkanContext::create();
auto& resources_module = modules.add_module<ResourcesModule>(*project, *vulkan_context);
auto surface = window->create_surface(*vulkan_context);
// TODO: find better surface control
vulkan_context->get_device().add_present_queue(*surface);
swapchain = make_reference<renderer::vulkan::VulkanSwapchain>(project->get_settings(), *vulkan_context, surface);
if (project->get_type() == ProjectType::Editor)
modules.add_module<EditorModule>(*project, *vulkan_context, *swapchain, *window);
else
modules.add_module<RuntimeModule>(*project, *vulkan_context, *swapchain);
// TODO: make a O(1) lookup inside the module stack, will make this class redundant
engine_context = std::make_unique<EngineContext>(
registry,
resources_module,
*window,
input,
system_orchestrator
);
}
Engine::~Engine()
{
LOGGER_INFO("Shutting down Engine");
vulkan_context->get_device().wait_idle();
// engine_context->get_renderer().cleanup();
engine_context->get_ecs_registry().clear();
modules.clean();
swapchain.reset();
vulkan_context.reset();
glfwTerminate();
}
void Engine::prepare()
{
const auto scene_id = project->get_starting_scene();
if (scene_id != INVALID_STRING_ID)
{
auto scene_reference = engine_context->get_resource_registry().immediate_load<Scene>(scene_id);
scene_reference->set_viewport_bounds({0, 0, swapchain->get_width(), swapchain->get_height()});
engine_context->get_system_orchestrator().set_active_scene(*scene_reference);
}
else
{
// TODO: This will not be ordered, maybe use some default empty scene here instead
// Take the first scene
auto scene = engine_context->get_resource_registry().list_all_resources_of_type<Scene>() | std::ranges::views::take(1);
scene.front()->set_viewport_bounds({0, 0, swapchain->get_width(), swapchain->get_height()});
engine_context->get_system_orchestrator().set_active_scene(*scene.front());
}
}
void Engine::process_events()
{
window->process_events();
}
void Engine::on_resize(const WindowExtent extent)
{
if (extent.width == 0 || extent.height == 0)
return;
const auto glfw_window = reference_cast<GlfwWindow>(window);
auto [width, height] = glfw_window->resize(extent);
swapchain->on_resize(width, height);
}
void Engine::on_close()
{
should_stop.test_and_set();
}
ProjectSettings& Engine::get_settings() const
{
return project->get_settings();
}
} // portal