openblocks/editor/mainglwidget.cpp

174 lines
5.7 KiB
C++
Raw Normal View History

2024-12-01 12:08:45 +00:00
#include <GL/glew.h>
#include <chrono>
#include <QMouseEvent>
2025-02-01 20:15:53 +00:00
#include <glm/ext/matrix_projection.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/geometric.hpp>
#include <glm/matrix.hpp>
2025-02-02 23:23:25 +00:00
#include <memory>
#include <optional>
2025-02-01 20:15:53 +00:00
#include <reactphysics3d/collision/RaycastInfo.h>
2025-02-01 21:55:07 +00:00
#include <vector>
2024-12-01 11:26:14 +00:00
2024-12-01 23:14:42 +00:00
#include "GLFW/glfw3.h"
2025-02-01 21:55:07 +00:00
#include "physics/util.h"
2024-12-01 23:14:42 +00:00
#include "qcursor.h"
2024-12-01 12:08:45 +00:00
#include "qevent.h"
#include "qnamespace.h"
2025-02-01 20:15:53 +00:00
#include "qwindowdefs.h"
2024-12-01 11:26:14 +00:00
#include "rendering/renderer.h"
#include "physics/simulation.h"
#include "camera.h"
#include "common.h"
#include "mainglwidget.h"
2024-12-02 10:01:51 +00:00
MainGLWidget::MainGLWidget(QWidget* parent): QOpenGLWidget(parent) {
setFocusPolicy(Qt::FocusPolicy::ClickFocus);
2025-02-02 23:23:25 +00:00
setMouseTracking(true);
2024-12-02 10:01:51 +00:00
}
2024-12-01 11:26:14 +00:00
void MainGLWidget::initializeGL() {
glewInit();
renderInit(NULL, width(), height());
2024-12-01 11:26:14 +00:00
}
extern int vpx, vpy;
2024-12-01 11:26:14 +00:00
void MainGLWidget::resizeGL(int w, int h) {
// Update projection matrix and other size related settings:
// m_projection.setToIdentity();
// m_projection.perspective(45.0f, w / float(h), 0.01f, 100.0f);
// ...
// glViewport(0, 0, w, h);
setViewport(w, h);
2024-12-01 11:26:14 +00:00
}
void MainGLWidget::paintGL() {
::render(NULL);
}
2024-12-01 12:08:45 +00:00
2025-02-02 23:23:25 +00:00
bool isMouseRightDragging = false;
2024-12-01 12:08:45 +00:00
QPoint lastMousePos;
2025-02-02 23:23:25 +00:00
void MainGLWidget::handleCameraRotate(QMouseEvent* evt) {
if (!isMouseRightDragging) return;
2024-12-01 12:08:45 +00:00
camera.processRotation(evt->pos().x() - lastMousePos.x(), evt->pos().y() - lastMousePos.y());
lastMousePos = evt->pos();
2025-02-02 23:23:25 +00:00
2024-12-01 23:14:42 +00:00
// QCursor::setPos(lastMousePos);
2024-12-01 12:08:45 +00:00
}
2025-02-02 23:23:25 +00:00
bool isMouseDragging = false;
std::optional<std::weak_ptr<Part>> draggingObject;
void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
if (!isMouseDragging) return;
2024-12-01 12:08:45 +00:00
2025-02-02 23:23:25 +00:00
QPoint position = evt->pos();
2025-02-01 20:15:53 +00:00
2025-02-02 23:23:25 +00:00
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
std::optional<const RaycastResult> rayHit = castRayNearest(camera.cameraPos, pointDir, 50000, [](std::shared_ptr<Part> part) {
return (part == draggingObject->lock()) ? FilterResult::PASS : FilterResult::TARGET;
});
if (!rayHit) return;
Data::Vector3 vec = rayHit->worldPoint;
vec = vec + Data::Vector3(rpToGlm(rayHit->worldNormal) * draggingObject->lock()->scale / 2.f);
draggingObject->lock()->cframe = draggingObject->lock()->cframe.Rotation() + vec;
2025-02-02 23:23:25 +00:00
syncPartPhysics(draggingObject->lock());
}
void MainGLWidget::handleCursorChange(QMouseEvent* evt) {
QPoint position = evt->pos();
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
std::optional<const RaycastResult> rayHit = castRayNearest(camera.cameraPos, pointDir, 50000);
setCursor((rayHit && partFromBody(rayHit->body)->name != "Baseplate") ? Qt::OpenHandCursor : Qt::ArrowCursor);
}
2025-02-01 20:15:53 +00:00
2025-02-02 23:23:25 +00:00
void MainGLWidget::mouseMoveEvent(QMouseEvent* evt) {
handleCameraRotate(evt);
handleObjectDrag(evt);
handleCursorChange(evt);
}
2025-02-01 20:15:53 +00:00
void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
switch(evt->button()) {
// Camera drag
case Qt::RightButton: {
lastMousePos = evt->pos();
2025-02-02 23:23:25 +00:00
isMouseRightDragging = true;
2025-02-01 20:15:53 +00:00
return;
// Clicking on objects
} case Qt::LeftButton: {
QPoint position = evt->pos();
2025-02-01 21:55:07 +00:00
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
2025-02-02 23:23:25 +00:00
std::optional<const RaycastResult> rayHit = castRayNearest(camera.cameraPos, pointDir, 50000);
if (!rayHit || !partFromBody(rayHit->body)) return;
std::shared_ptr<Part> part = partFromBody(rayHit->body);
if (part->name == "Baseplate") return;
2025-02-01 21:55:07 +00:00
//part.selected = true;
2025-02-02 23:23:25 +00:00
isMouseDragging = true;
draggingObject = part;
2025-02-01 21:55:07 +00:00
setSelection(std::vector<InstanceRefWeak> { part });
2025-02-02 23:23:25 +00:00
// Disable bit so that we can ignore the part while raycasting
// part->rigidBody->getCollider(0)->setCollisionCategoryBits(0b10);
2025-02-01 21:55:07 +00:00
2025-02-01 20:15:53 +00:00
return;
} default:
return;
}
2024-12-01 12:08:45 +00:00
}
void MainGLWidget::mouseReleaseEvent(QMouseEvent* evt) {
2025-02-02 23:23:25 +00:00
// if (isMouseDragging) draggingObject->lock()->rigidBody->getCollider(0)->setCollisionCategoryBits(0b11);
isMouseRightDragging = false;
2024-12-01 12:08:45 +00:00
isMouseDragging = false;
2025-02-02 23:23:25 +00:00
draggingObject = std::nullopt;
2024-12-02 10:01:51 +00:00
}
static int moveZ = 0;
static int moveX = 0;
static std::chrono::time_point lastTime = std::chrono::steady_clock::now();
void MainGLWidget::updateCycle() {
float deltaTime = std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - lastTime).count();
lastTime = std::chrono::steady_clock::now();
if (moveZ)
camera.processMovement(moveZ == 1 ? DIRECTION_FORWARD : DIRECTION_BACKWARDS, deltaTime);
if (moveX)
camera.processMovement(moveX == 1 ? DIRECTION_LEFT : DIRECTION_RIGHT, deltaTime);
}
void MainGLWidget::keyPressEvent(QKeyEvent* evt) {
if (evt->key() == Qt::Key_W) moveZ = 1;
else if (evt->key() == Qt::Key_S) moveZ = -1;
if (evt->key() == Qt::Key_A) moveX = 1;
else if (evt->key() == Qt::Key_D) moveX = -1;
if (evt->key() == Qt::Key_F) {
workspace()->AddChild(lastPart = Part::New({
2024-12-02 10:01:51 +00:00
.position = camera.cameraPos + camera.cameraFront * glm::vec3(3),
.rotation = glm::vec3(0),
.scale = glm::vec3(1, 1, 1),
.material = Material {
.diffuse = glm::vec3(1.0f, 0.5f, 0.31f),
.specular = glm::vec3(0.5f, 0.5f, 0.5f),
.shininess = 32.0f,
}
2025-01-17 08:24:18 +00:00
}));
syncPartPhysics(lastPart);
2024-12-02 10:01:51 +00:00
}
}
void MainGLWidget::keyReleaseEvent(QKeyEvent* evt) {
if (evt->key() == Qt::Key_W || evt->key() == Qt::Key_S) moveZ = 0;
else if (evt->key() == Qt::Key_A || evt->key() == Qt::Key_D) moveX = 0;
2024-12-01 12:08:45 +00:00
}