feat: add basic canvas / improve inspector
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
#include <components/Checkpoint.h>
|
||||
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
|
||||
#include <components/PlayerRespawn.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
Checkpoint::Checkpoint(GameObject& parent)
|
||||
: Component(parent, "Checkpoint")
|
||||
{
|
||||
}
|
||||
|
||||
glm::vec3 Checkpoint::GetSpawnPoint() const
|
||||
{
|
||||
return GetTransform().GetWorldPosition() + m_SpawnOffset;
|
||||
}
|
||||
|
||||
void Checkpoint::OnTriggerEnter(GameObject* other)
|
||||
{
|
||||
if (other == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* respawn = other->GetComponent<PlayerRespawn>();
|
||||
const glm::vec3 spawnPoint = GetSpawnPoint();
|
||||
if (respawn == nullptr || respawn->GetRespawnPoint() == spawnPoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
respawn->SetRespawnPoint(spawnPoint);
|
||||
spdlog::info("{} reached checkpoint {}", other->GetName(), GetGameObject()->GetName());
|
||||
}
|
||||
|
||||
nlohmann::json Checkpoint::Serialize() const
|
||||
{
|
||||
return {{"spawnOffset", m_SpawnOffset}};
|
||||
}
|
||||
|
||||
void Checkpoint::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_SpawnOffset = data.value("spawnOffset", m_SpawnOffset);
|
||||
}
|
||||
|
||||
void Checkpoint::ImGuiInspector()
|
||||
{
|
||||
ImGui::DragFloat3("Spawn offset", glm::value_ptr(m_SpawnOffset), 0.05f);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#include <components/CrosshairUI.h>
|
||||
|
||||
#include <components/FirstPersonController.h>
|
||||
|
||||
#include <destrum/Components/UI/RectTransform.h>
|
||||
#include <destrum/Components/UI/UIGraphic.h>
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
#include <destrum/Scene/Scene.h>
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace {
|
||||
void TintHierarchy(GameObject& object, const glm::vec4& color)
|
||||
{
|
||||
for (const auto& component : object.GetComponents()) {
|
||||
if (auto* graphic = dynamic_cast<UIGraphic*>(component.get())) {
|
||||
graphic->SetColor(color);
|
||||
}
|
||||
}
|
||||
for (Transform* child : object.GetTransform().GetChildren()) {
|
||||
if (child != nullptr && child->GetOwner() != nullptr) {
|
||||
TintHierarchy(*child->GetOwner(), color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CrosshairUI::CrosshairUI(GameObject& parent)
|
||||
: Component(parent, "CrosshairUI")
|
||||
{
|
||||
}
|
||||
|
||||
void CrosshairUI::LateUpdate(float)
|
||||
{
|
||||
const Scene* scene = GetGameObject()->GetScene();
|
||||
if (scene == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject* player = m_Player.Get(*scene);
|
||||
const auto* controller = player != nullptr ? player->GetComponent<FirstPersonController>() : nullptr;
|
||||
const bool possessed = controller != nullptr && controller->IsPossessed();
|
||||
const bool focused = possessed && controller->GetFocusedInteractable() != nullptr;
|
||||
|
||||
if (GameObject* indicator = m_FocusIndicator.Get(*scene)) {
|
||||
indicator->SetActive(focused);
|
||||
}
|
||||
|
||||
GameObject* crosshair = m_Crosshair.Get(*scene);
|
||||
if (crosshair == nullptr) {
|
||||
return;
|
||||
}
|
||||
crosshair->SetActive(possessed);
|
||||
if (auto* rectTransform = crosshair->GetComponent<RectTransform>()) {
|
||||
rectTransform->SetSize(glm::vec2{focused ? m_FocusedSize : m_Size});
|
||||
}
|
||||
TintHierarchy(*crosshair, focused ? m_FocusedColor : m_Color);
|
||||
}
|
||||
|
||||
nlohmann::json CrosshairUI::Serialize() const
|
||||
{
|
||||
return {
|
||||
{"player", m_Player},
|
||||
{"crosshair", m_Crosshair},
|
||||
{"focusIndicator", m_FocusIndicator},
|
||||
{"color", m_Color},
|
||||
{"focusedColor", m_FocusedColor},
|
||||
{"size", m_Size},
|
||||
{"focusedSize", m_FocusedSize},
|
||||
};
|
||||
}
|
||||
|
||||
void CrosshairUI::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_Player = data.value("player", ObjectRef{});
|
||||
m_Crosshair = data.value("crosshair", ObjectRef{});
|
||||
m_FocusIndicator = data.value("focusIndicator", ObjectRef{});
|
||||
m_Color = data.value("color", m_Color);
|
||||
m_FocusedColor = data.value("focusedColor", m_FocusedColor);
|
||||
m_Size = data.value("size", m_Size);
|
||||
m_FocusedSize = data.value("focusedSize", m_FocusedSize);
|
||||
}
|
||||
|
||||
void CrosshairUI::ResolveReferences(const ObjectMap& objects)
|
||||
{
|
||||
m_Player.Resolve(objects);
|
||||
m_Crosshair.Resolve(objects);
|
||||
m_FocusIndicator.Resolve(objects);
|
||||
}
|
||||
|
||||
void CrosshairUI::ImGuiInspector()
|
||||
{
|
||||
if (const Scene* scene = GetGameObject()->GetScene()) {
|
||||
ImGuiUtils::DrawObjectRefPicker("Player", m_Player, *scene, [](const GameObject& object) {
|
||||
return object.GetComponent<FirstPersonController>() != nullptr;
|
||||
});
|
||||
ImGuiUtils::DrawObjectRefPicker("Crosshair", m_Crosshair, *scene);
|
||||
ImGuiUtils::DrawObjectRefPicker("Focus Indicator", m_FocusIndicator, *scene);
|
||||
}
|
||||
|
||||
ImGui::ColorEdit4("Color", &m_Color.x);
|
||||
ImGui::ColorEdit4("Focused Color", &m_FocusedColor.x);
|
||||
ImGui::DragFloat("Size", &m_Size, 0.5f, 0.0f, 500.0f);
|
||||
ImGui::DragFloat("Focused Size", &m_FocusedSize, 0.5f, 0.0f, 500.0f);
|
||||
}
|
||||
@@ -132,6 +132,17 @@ Interactable* FirstPersonController::FindFocusedInteractable() const
|
||||
return Interactable::FindOnObjectOrParents(hit.object);
|
||||
}
|
||||
|
||||
void FirstPersonController::Teleport(const glm::vec3& worldPosition)
|
||||
{
|
||||
if (m_Rigidbody != nullptr) {
|
||||
m_Rigidbody->Teleport(worldPosition);
|
||||
} else {
|
||||
GetTransform().SetWorldPosition(worldPosition);
|
||||
}
|
||||
m_PreviousPosition = worldPosition;
|
||||
m_HasPreviousPosition = true;
|
||||
}
|
||||
|
||||
void FirstPersonController::FixedUpdate(float fixedDt)
|
||||
{
|
||||
if (m_Rigidbody == nullptr || !m_Rigidbody->HasPhysicsBody())
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <components/PlayerRespawn.h>
|
||||
|
||||
#include <destrum/Components/Physics/Rigidbody.h>
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
#include <destrum/Serialization/GlmJson.h>
|
||||
|
||||
#include <components/FirstPersonController.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
PlayerRespawn::PlayerRespawn(GameObject& parent)
|
||||
: Component(parent, "PlayerRespawn")
|
||||
{
|
||||
}
|
||||
|
||||
void PlayerRespawn::Start()
|
||||
{
|
||||
if (!m_HasRespawnPoint) {
|
||||
SetRespawnPoint(GetTransform().GetWorldPosition());
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerRespawn::FixedUpdate(float)
|
||||
{
|
||||
if (GetTransform().GetWorldPosition().y < m_KillHeight) {
|
||||
Respawn();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerRespawn::SetRespawnPoint(const glm::vec3& worldPosition)
|
||||
{
|
||||
m_RespawnPoint = worldPosition;
|
||||
m_HasRespawnPoint = true;
|
||||
}
|
||||
|
||||
void PlayerRespawn::Respawn()
|
||||
{
|
||||
GameObject* object = GetGameObject();
|
||||
if (auto* controller = object->GetComponent<FirstPersonController>()) {
|
||||
controller->Teleport(m_RespawnPoint);
|
||||
} else if (auto* rigidbody = object->GetComponent<Rigidbody>()) {
|
||||
rigidbody->Teleport(m_RespawnPoint);
|
||||
} else {
|
||||
GetTransform().SetWorldPosition(m_RespawnPoint);
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json PlayerRespawn::Serialize() const
|
||||
{
|
||||
nlohmann::json data{{"killHeight", m_KillHeight}};
|
||||
if (m_HasRespawnPoint) {
|
||||
data["respawnPoint"] = m_RespawnPoint;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void PlayerRespawn::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_KillHeight = data.value("killHeight", m_KillHeight);
|
||||
if (data.contains("respawnPoint")) {
|
||||
SetRespawnPoint(data.at("respawnPoint").get<glm::vec3>());
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerRespawn::ImGuiInspector()
|
||||
{
|
||||
ImGui::DragFloat("Kill height", &m_KillHeight, 0.1f);
|
||||
ImGui::DragFloat3("Respawn point", glm::value_ptr(m_RespawnPoint), 0.1f);
|
||||
if (ImGui::Button("Respawn now")) {
|
||||
Respawn();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#include <components/WinGoal.h>
|
||||
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
WinGoal::WinGoal(GameObject& parent)
|
||||
: Activatable(parent, "WinGoal")
|
||||
{
|
||||
}
|
||||
|
||||
void WinGoal::OnActivate(GameObject& instigator)
|
||||
{
|
||||
if (!m_Reached) {
|
||||
spdlog::info("{} reached the goal", instigator.GetName());
|
||||
}
|
||||
m_Reached = true;
|
||||
}
|
||||
|
||||
nlohmann::json WinGoal::Serialize() const
|
||||
{
|
||||
return {{"reached", m_Reached}};
|
||||
}
|
||||
|
||||
void WinGoal::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_Reached = data.value("reached", m_Reached);
|
||||
}
|
||||
|
||||
void WinGoal::ImGuiInspector()
|
||||
{
|
||||
ImGui::Checkbox("Reached", &m_Reached);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <components/WinScreenUI.h>
|
||||
|
||||
#include <components/WinGoal.h>
|
||||
|
||||
#include <destrum/ObjectModel/GameObject.h>
|
||||
#include <destrum/Scene/Scene.h>
|
||||
#include <destrum/Util/ImGuiUtils.h>
|
||||
|
||||
WinScreenUI::WinScreenUI(GameObject& parent)
|
||||
: Component(parent, "WinScreenUI")
|
||||
{
|
||||
}
|
||||
|
||||
void WinScreenUI::LateUpdate(float)
|
||||
{
|
||||
const Scene* scene = GetGameObject()->GetScene();
|
||||
if (scene == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject* screen = m_Screen.Get(*scene);
|
||||
if (screen == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject* goal = m_Goal.Get(*scene);
|
||||
const auto* winGoal = goal != nullptr ? goal->GetComponent<WinGoal>() : nullptr;
|
||||
screen->SetActive(winGoal != nullptr && winGoal->IsReached());
|
||||
}
|
||||
|
||||
nlohmann::json WinScreenUI::Serialize() const
|
||||
{
|
||||
return {
|
||||
{"goal", m_Goal},
|
||||
{"screen", m_Screen},
|
||||
};
|
||||
}
|
||||
|
||||
void WinScreenUI::Deserialize(const nlohmann::json& data)
|
||||
{
|
||||
m_Goal = data.value("goal", ObjectRef{});
|
||||
m_Screen = data.value("screen", ObjectRef{});
|
||||
}
|
||||
|
||||
void WinScreenUI::ResolveReferences(const ObjectMap& objects)
|
||||
{
|
||||
m_Goal.Resolve(objects);
|
||||
m_Screen.Resolve(objects);
|
||||
}
|
||||
|
||||
void WinScreenUI::ImGuiInspector()
|
||||
{
|
||||
const Scene* scene = GetGameObject()->GetScene();
|
||||
if (scene == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiUtils::DrawObjectRefPicker("Goal", m_Goal, *scene, [](const GameObject& object) {
|
||||
return object.GetComponent<WinGoal>() != nullptr;
|
||||
});
|
||||
ImGuiUtils::DrawObjectRefPicker("Screen", m_Screen, *scene);
|
||||
}
|
||||
Reference in New Issue
Block a user