You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.9 KiB
216 lines
5.9 KiB
/* |
|
* Copyright (C) 2022-2024 Riyyi |
|
* |
|
* SPDX-License-Identifier: MIT |
|
*/ |
|
|
|
#include <cstddef> // size_t |
|
#include <cstdint> // uint32_t |
|
#include <limits> // std::numeric_limits |
|
#include <utility> // std::pair |
|
|
|
#include "entt/entity/entity.hpp" // ent::entity |
|
#include "ruc/file.h" |
|
#include "ruc/format/log.h" |
|
#include "ruc/json/json.h" |
|
#include "ruc/meta/assert.h" |
|
|
|
#include "inferno/component/cameracomponent.h" |
|
#include "inferno/component/cubemap-component.h" |
|
#include "inferno/component/id-component.h" |
|
#include "inferno/component/luascriptcomponent.h" |
|
#include "inferno/component/nativescriptcomponent.h" |
|
#include "inferno/component/spritecomponent.h" |
|
#include "inferno/component/tagcomponent.h" |
|
#include "inferno/component/textareacomponent.h" |
|
#include "inferno/component/transformcomponent.h" |
|
#include "inferno/scene/scene.h" |
|
#include "inferno/script/nativescript.h" |
|
#include "inferno/system/camerasystem.h" |
|
#include "inferno/system/rendersystem.h" |
|
#include "inferno/system/scriptsystem.h" |
|
#include "inferno/system/textareasystem.h" |
|
#include "inferno/system/transformsystem.h" |
|
#include "inferno/uid.h" |
|
|
|
namespace Inferno { |
|
|
|
void Scene::initialize() |
|
{ |
|
// Initialize |
|
// --------------------------------- |
|
|
|
m_registry = std::make_shared<entt::registry>(); |
|
|
|
TransformSystem::the().setRegistry(m_registry); |
|
CameraSystem::the().setRegistry(m_registry); |
|
RenderSystem::the().setRegistry(m_registry); |
|
ScriptSystem::the().setScene(this); |
|
TextAreaSystem::the().setScene(this); |
|
|
|
// Load scene .json |
|
// ------------------------------------- |
|
|
|
auto sceneJson = ruc::Json::parse(ruc::File("assets/scene/scene1.json").data()); |
|
|
|
if (sceneJson.exists("init")) { |
|
// TODO: load either NativeScript or LuaScript? |
|
} |
|
|
|
// Entities |
|
// ------------------------------------- |
|
|
|
if (sceneJson.exists("entities")) { |
|
const auto& entityJson = sceneJson.at("entities"); |
|
VERIFY(entityJson.type() == ruc::Json::Type::Array); |
|
const auto& entities = entityJson.asArray(); |
|
for (size_t i = 0; i < entities.size(); ++i) { |
|
loadEntity(entities.at(i)); |
|
} |
|
} |
|
|
|
ruc::info("Scene initialized"); |
|
} |
|
|
|
void Scene::update(float deltaTime) |
|
{ |
|
ScriptSystem::the().update(deltaTime); |
|
|
|
TransformSystem::the().update(); |
|
CameraSystem::the().update(); |
|
} |
|
|
|
void Scene::render() |
|
{ |
|
RenderSystem::the().render(); |
|
TextAreaSystem::the().render(); |
|
} |
|
|
|
void Scene::destroy() |
|
{ |
|
ScriptSystem::destroy(); |
|
RenderSystem::destroy(); |
|
CameraSystem::destroy(); |
|
TransformSystem::destroy(); |
|
} |
|
|
|
// ----------------------------------------- |
|
|
|
uint32_t Scene::createEntity(const std::string& name) |
|
{ |
|
return createEntityWithUID(UID(), name); |
|
} |
|
|
|
uint32_t Scene::createEntityWithUID(UID id, const std::string& name) |
|
{ |
|
uint32_t entity = static_cast<uint32_t>(m_registry->create()); |
|
addComponent<IDComponent>(entity, id); |
|
addComponent<TagComponent>(entity, name.empty() ? "Unnamed Entity" : name); |
|
addComponent<TransformComponent>(entity); |
|
|
|
TransformSystem::the().add(entity); |
|
|
|
return entity; |
|
} |
|
|
|
uint32_t Scene::loadEntity(ruc::Json components, uint32_t parentEntity) |
|
{ |
|
VERIFY(components.type() == ruc::Json::Type::Object); |
|
|
|
uint32_t entity = createEntity(); |
|
|
|
// At minimum, ID is required |
|
VERIFY(components.exists("id"), "id not found"); |
|
auto& id = getComponent<IDComponent>(entity); |
|
components.at("id").getTo(id); |
|
|
|
if (components.exists("tag")) { |
|
auto& tag = getComponent<TagComponent>(entity); |
|
components.at("tag").getTo(tag); |
|
} |
|
if (components.exists("transform")) { |
|
auto& transform = getComponent<TransformComponent>(entity); |
|
components.at("transform").getTo(transform); |
|
transform.parent = static_cast<entt::entity>(parentEntity); |
|
} |
|
if (components.exists("camera")) { |
|
auto& camera = addComponent<CameraComponent>(entity); |
|
components.at("camera").getTo(camera); |
|
} |
|
if (components.exists("lua-scripts")) { |
|
VERIFY(components.at("lua-scripts").type() == ruc::Json::Type::Array); |
|
const auto& scripts = components.at("lua-scripts").asArray(); |
|
for (size_t i = 0; i < scripts.size(); ++i) { |
|
auto& script = addComponent<LuaScriptComponent>(entity); |
|
scripts.at(i).getTo(script); |
|
} |
|
} |
|
if (components.exists("native-scripts")) { |
|
VERIFY(components.at("native-scripts").type() == ruc::Json::Type::Array); |
|
const auto& scripts = components.at("native-scripts").asArray(); |
|
for (size_t i = 0; i < scripts.size(); ++i) { |
|
auto& script = addComponent<NativeScriptComponent>(entity); |
|
scripts.at(i).getTo(script); |
|
script.bind(); |
|
} |
|
} |
|
if (components.exists("sprite")) { |
|
auto& sprite = addComponent<SpriteComponent>(entity); |
|
components.at("sprite").getTo(sprite); |
|
} |
|
if (components.exists("cubemap")) { |
|
auto& cubemap = addComponent<CubemapComponent>(entity); |
|
components.at("cubemap").getTo(cubemap); |
|
} |
|
if (components.exists("text")) { |
|
auto& text = addComponent<TextAreaComponent>(entity); |
|
components.at("text").getTo(text); |
|
} |
|
if (components.exists("children")) { |
|
VERIFY(components.at("children").type() == ruc::Json::Type::Array); |
|
const auto& children = components.at("children").asArray(); |
|
for (size_t i = 0; i < children.size(); ++i) { |
|
loadEntity(components.at("children")[i], entity); |
|
} |
|
} |
|
|
|
return entity; |
|
} |
|
|
|
uint32_t Scene::findEntity(std::string_view name) |
|
{ |
|
auto view = m_registry->view<TagComponent>(); |
|
|
|
for (auto [entity, tag] : view.each()) { |
|
if (tag.tag == name) { |
|
return static_cast<uint32_t>(entity); |
|
} |
|
} |
|
|
|
return std::numeric_limits<uint32_t>::max(); |
|
} |
|
|
|
void Scene::destroyEntity(uint32_t entity) |
|
{ |
|
ScriptSystem::the().cleanup(entity); |
|
m_registry->destroy(entt::entity { entity }); |
|
} |
|
|
|
// ----------------------------------------- |
|
|
|
std::pair<glm::mat4, glm::mat4> Scene::cameraProjectionView() |
|
{ |
|
return CameraSystem::the().projectionView(); |
|
} |
|
|
|
void Scene::validEntity(uint32_t entity) const |
|
{ |
|
VERIFY(m_registry->valid(entt::entity { entity }), "invalid entity '{}'", entity); |
|
} |
|
|
|
} // namespace Inferno |
|
|
|
void ruc::format::Formatter<entt::entity>::format(Builder& builder, entt::entity value) const |
|
{ |
|
return Formatter<uint32_t>::format(builder, static_cast<uint32_t>(value)); |
|
}
|
|
|