feat: add click to select
This commit is contained in:
@@ -36,6 +36,8 @@ public:
|
||||
private:
|
||||
void setupSkybox();
|
||||
void updateViewMode();
|
||||
void focusSelection();
|
||||
void updateFocus(float dt);
|
||||
[[nodiscard]] CameraComponent* getSceneCamera() const;
|
||||
[[nodiscard]] Camera& getViewCamera();
|
||||
[[nodiscard]] bool isPlayerViewActive() const;
|
||||
@@ -57,6 +59,7 @@ private:
|
||||
|
||||
Camera camera{glm::vec3(0.f, 0.f, -5.f), glm::vec3(0, 1, 0)};
|
||||
std::optional<Camera> editorCamera;
|
||||
std::optional<glm::vec3> focusTarget;
|
||||
|
||||
std::unique_ptr<CubeMap> skyboxCubemap;
|
||||
MainSceneObjects mainScene{};
|
||||
|
||||
@@ -65,6 +65,11 @@ void LightKeeper::customUpdate(float dt)
|
||||
// after SDL events have been consumed.
|
||||
if (!isPlayerViewActive() && getSceneCamera() == nullptr)
|
||||
{
|
||||
if (InputManager::GetInstance().WasKeyPressed(SDL_SCANCODE_F))
|
||||
{
|
||||
focusSelection();
|
||||
}
|
||||
updateFocus(dt);
|
||||
camera.Update(dt);
|
||||
}
|
||||
if (InputManager::GetInstance().WasKeyPressed(SDL_SCANCODE_F11))
|
||||
|
||||
@@ -19,8 +19,12 @@
|
||||
|
||||
#include <components/FirstPersonController.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@@ -162,6 +166,11 @@ void LightKeeper::drawDebugMenuBar()
|
||||
if (ImGui::MenuItem("Forward+ Light Heatmap", nullptr, &lightHeatmap)) {
|
||||
renderer.setRenderLightHeatmap(lightHeatmap);
|
||||
}
|
||||
|
||||
bool selectionView = renderer.getRenderSelectionView();
|
||||
if (ImGui::MenuItem("Selection Buffer", nullptr, &selectionView)) {
|
||||
renderer.setRenderSelectionView(selectionView);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -217,6 +226,71 @@ void LightKeeper::onViewportAssetDropped(std::string_view path)
|
||||
}
|
||||
}
|
||||
|
||||
void LightKeeper::focusSelection()
|
||||
{
|
||||
GameObject* selected = SceneManager::GetInstance().GetCurrentScene().GetSelectedObject();
|
||||
if (selected == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec3 boundsMin{std::numeric_limits<float>::max()};
|
||||
glm::vec3 boundsMax{std::numeric_limits<float>::lowest()};
|
||||
std::vector<GameObject*> pending{selected};
|
||||
while (!pending.empty()) {
|
||||
GameObject* object = pending.back();
|
||||
pending.pop_back();
|
||||
for (const Transform* child : object->GetTransform().GetChildren()) {
|
||||
if (child != nullptr && child->GetOwner() != nullptr) {
|
||||
pending.push_back(child->GetOwner());
|
||||
}
|
||||
}
|
||||
|
||||
const auto* meshRenderer = object->GetComponent<MeshRendererComponent>();
|
||||
if (meshRenderer == nullptr || meshRenderer->GetMeshID() == NULL_MESH_ID) {
|
||||
continue;
|
||||
}
|
||||
const GPUMesh& mesh = resources.meshes().getMesh(meshRenderer->GetMeshID());
|
||||
const glm::mat4 world = object->GetTransform().GetWorldMatrix();
|
||||
for (int corner = 0; corner < 8; ++corner) {
|
||||
const glm::vec3 local{
|
||||
corner & 1 ? mesh.maxPos.x : mesh.minPos.x,
|
||||
corner & 2 ? mesh.maxPos.y : mesh.minPos.y,
|
||||
corner & 4 ? mesh.maxPos.z : mesh.minPos.z,
|
||||
};
|
||||
const glm::vec3 point{world * glm::vec4{local, 1.0f}};
|
||||
boundsMin = glm::min(boundsMin, point);
|
||||
boundsMax = glm::max(boundsMax, point);
|
||||
}
|
||||
}
|
||||
|
||||
const bool hasBounds = boundsMin.x <= boundsMax.x;
|
||||
const glm::vec3 center = hasBounds ? (boundsMin + boundsMax) * 0.5f : selected->GetTransform().GetWorldPosition();
|
||||
const float radius = hasBounds ? std::max(glm::length(boundsMax - boundsMin) * 0.5f, 0.1f) : 1.0f;
|
||||
|
||||
// Fit the bounding sphere in the narrower of the two field of view angles
|
||||
const float halfFovY = glm::radians(camera.GetFOVY()) * 0.5f;
|
||||
const float halfFovX = std::atan(std::tan(halfFovY) * camera.GetAspectRatio());
|
||||
const float distance = radius / std::sin(std::min(halfFovX, halfFovY)) * 1.1f;
|
||||
focusTarget = center - camera.GetForward() * distance;
|
||||
}
|
||||
|
||||
void LightKeeper::updateFocus(float dt)
|
||||
{
|
||||
if (!focusTarget) {
|
||||
return;
|
||||
}
|
||||
if (InputManager::GetInstance().IsMouseDown(SDL_BUTTON_RIGHT)) {
|
||||
focusTarget.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
camera.m_position = glm::mix(camera.m_position, *focusTarget, 1.0f - std::exp(-12.0f * dt));
|
||||
if (glm::distance(camera.m_position, *focusTarget) < 0.01f) {
|
||||
camera.m_position = *focusTarget;
|
||||
focusTarget.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void LightKeeper::drawViewportOverlay()
|
||||
{
|
||||
if (!showTransformGizmo || isPlayerViewActive()) {
|
||||
|
||||
Reference in New Issue
Block a user