mirror of
https://github.com/Linloir/SceneEditor.git
synced 2025-12-17 07:28:12 +08:00
[CORE][ADD] Click selection test
- Hover detection - Click detection - Move / Scale / Rotate(have bug) - Bounding box display - Gesture done
This commit is contained in:
parent
5dd1200a6e
commit
64f65a2555
@ -38,6 +38,9 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
inline glm::vec3 front() const { return _front; }
|
inline glm::vec3 front() const { return _front; }
|
||||||
|
inline glm::vec3 right() const { return _right; }
|
||||||
|
inline glm::vec3 up() const { return _up; }
|
||||||
|
inline glm::vec3 position() const { return _position; }
|
||||||
|
|
||||||
inline float fovy() const { return _fovy; }
|
inline float fovy() const { return _fovy; }
|
||||||
inline float nearPlane() const { return _nearPlane; }
|
inline float nearPlane() const { return _nearPlane; }
|
||||||
@ -48,7 +51,6 @@ public:
|
|||||||
|
|
||||||
Ray generateRay(glm::vec2 mouseRelativePosition, float aspectRatio) const;
|
Ray generateRay(glm::vec2 mouseRelativePosition, float aspectRatio) const;
|
||||||
|
|
||||||
inline glm::vec3 position() const { return _position; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void move(glm::vec2 offset);
|
inline void move(glm::vec2 offset);
|
||||||
|
|||||||
@ -61,6 +61,8 @@ uniform DirLight dirlights[MAX_DIR_LIGHTS];
|
|||||||
uniform PointLight pointlights[MAX_POINT_LIGHTS];
|
uniform PointLight pointlights[MAX_POINT_LIGHTS];
|
||||||
uniform SpotLight spotlights[MAX_SPOT_LIGHTS];
|
uniform SpotLight spotlights[MAX_SPOT_LIGHTS];
|
||||||
|
|
||||||
|
uniform vec3 selColor;
|
||||||
|
|
||||||
// function prototypes
|
// function prototypes
|
||||||
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
|
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
|
||||||
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
|
||||||
@ -79,10 +81,13 @@ void main()
|
|||||||
// phase 2: point lights
|
// phase 2: point lights
|
||||||
for (int i = 0; i < pointlightnr; i++)
|
for (int i = 0; i < pointlightnr; i++)
|
||||||
result += CalcPointLight(pointlights[i], norm, FragPos, viewDir);
|
result += CalcPointLight(pointlights[i], norm, FragPos, viewDir);
|
||||||
// // phase 3: spot light
|
// phase 3: spot light
|
||||||
// for (int i = 0; i < spotlightnr; i++)
|
for (int i = 0; i < spotlightnr; i++)
|
||||||
// result += CalcSpotLight(spotlights[i], norm, FragPos, viewDir);
|
result += CalcSpotLight(spotlights[i], norm, FragPos, viewDir);
|
||||||
|
|
||||||
|
if (selColor != vec3(0.0))
|
||||||
|
result += selColor;
|
||||||
|
|
||||||
FragColor = vec4(result, 1.0);
|
FragColor = vec4(result, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
<file>skyboxfragmentshader.glsl</file>
|
<file>skyboxfragmentshader.glsl</file>
|
||||||
<file>boundfragmentshader.glsl</file>
|
<file>boundfragmentshader.glsl</file>
|
||||||
<file>boundvertexshader.glsl</file>
|
<file>boundvertexshader.glsl</file>
|
||||||
|
<file>thumbnailfragmentshader.glsl</file>
|
||||||
|
<file>thumbnailvertexshader.glsl</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/fonts">
|
<qresource prefix="/fonts">
|
||||||
<file>font_awesome_6_regular_free.otf</file>
|
<file>font_awesome_6_regular_free.otf</file>
|
||||||
|
|||||||
@ -13,6 +13,11 @@ SceneViewer::SceneViewer(QWidget* parent)
|
|||||||
{
|
{
|
||||||
// Set mouse tracking
|
// Set mouse tracking
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
// Set key tracking
|
||||||
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
// Set the focus
|
||||||
|
setFocus();
|
||||||
|
|
||||||
// OpenGL initialize
|
// OpenGL initialize
|
||||||
QSurfaceFormat format;
|
QSurfaceFormat format;
|
||||||
format.setProfile(QSurfaceFormat::CoreProfile);
|
format.setProfile(QSurfaceFormat::CoreProfile);
|
||||||
@ -61,13 +66,16 @@ void SceneViewer::extractShaderResource(const QString& shaderName) {
|
|||||||
QFile::setPermissions(shaderTempPath, QFile::ReadOwner | QFile::WriteOwner);
|
QFile::setPermissions(shaderTempPath, QFile::ReadOwner | QFile::WriteOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::hitTest(const Ray& ray) {
|
Renderable* SceneViewer::hitTest(const Ray& ray) {
|
||||||
HitRecord newRecord = HitRecord();
|
HitRecord newRecord = HitRecord();
|
||||||
Renderable* newObject = nullptr;
|
Renderable* newObject = nullptr;
|
||||||
int newObjectIndex = -1;
|
|
||||||
for (int i = 0; i < _objects.size(); i++) {
|
for (int i = 0; i < _objects.size(); i++) {
|
||||||
Logger::debug("Testing object " + std::to_string(i));
|
Logger::debug("Testing object " + std::to_string(i));
|
||||||
Renderable* obj = _objects[i];
|
Renderable* obj = _objects[i];
|
||||||
|
if (obj == _operatingObject) {
|
||||||
|
// Ignore current operating Object
|
||||||
|
continue;
|
||||||
|
}
|
||||||
HitRecord hitRecord = obj->hit(ray);
|
HitRecord hitRecord = obj->hit(ray);
|
||||||
if (hitRecord.hitted()) {
|
if (hitRecord.hitted()) {
|
||||||
Logger::debug("Hitted object " + std::to_string(i));
|
Logger::debug("Hitted object " + std::to_string(i));
|
||||||
@ -78,14 +86,10 @@ void SceneViewer::hitTest(const Ray& ray) {
|
|||||||
if (hitRecord.hitted() && hitRecord.t() < newRecord.t()) {
|
if (hitRecord.hitted() && hitRecord.t() < newRecord.t()) {
|
||||||
newRecord = hitRecord;
|
newRecord = hitRecord;
|
||||||
newObject = obj;
|
newObject = obj;
|
||||||
newObjectIndex = i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newRecord.hitted()) {
|
|
||||||
Logger::debug("Hit test hitted object with index " + std::to_string(newObjectIndex));
|
|
||||||
}
|
|
||||||
_hitRecord = newRecord;
|
_hitRecord = newRecord;
|
||||||
_hoveredObject = newObject;
|
return newObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::initializeGL() {
|
void SceneViewer::initializeGL() {
|
||||||
@ -191,12 +195,31 @@ void SceneViewer::paintGL() {
|
|||||||
_shaderProgram.setUniform("dirlightnr", _dirLight != nullptr ? 1 : 0);
|
_shaderProgram.setUniform("dirlightnr", _dirLight != nullptr ? 1 : 0);
|
||||||
|
|
||||||
for (auto object : _objects) {
|
for (auto object : _objects) {
|
||||||
|
if (object == _pressedObject) {
|
||||||
|
_shaderProgram.setUniform("selColor", glm::vec3(0.22f));
|
||||||
|
}
|
||||||
|
else if (object == _operatingObject) {
|
||||||
|
_shaderProgram.setUniform("selColor", glm::vec3(0.1f));
|
||||||
|
}
|
||||||
|
else if (object == _hoveredObject) {
|
||||||
|
_shaderProgram.setUniform("selColor", glm::vec3(0.2f));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_shaderProgram.setUniform("selColor", glm::vec3(0.0f));
|
||||||
|
}
|
||||||
object->render(_shaderProgram);
|
object->render(_shaderProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
_shaderProgram.unbind();
|
_shaderProgram.unbind();
|
||||||
|
|
||||||
if (_hoveredObject != nullptr) {
|
if (_selectedObject != nullptr && !_hideBound) {
|
||||||
|
_boundShader.bind();
|
||||||
|
_boundShader.setUniform("view", view);
|
||||||
|
_boundShader.setUniform("projection", projection);
|
||||||
|
_selectedObject->boundary().render();
|
||||||
|
_boundShader.unbind();
|
||||||
|
}
|
||||||
|
if (_hoveredObject != nullptr && _hoveredObject != _selectedObject) {
|
||||||
_boundShader.bind();
|
_boundShader.bind();
|
||||||
_boundShader.setUniform("view", view);
|
_boundShader.setUniform("view", view);
|
||||||
_boundShader.setUniform("projection", projection);
|
_boundShader.setUniform("projection", projection);
|
||||||
@ -212,58 +235,128 @@ void SceneViewer::paintGL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::mousePressEvent(QMouseEvent* event) {
|
void SceneViewer::mousePressEvent(QMouseEvent* event) {
|
||||||
Logger::debug("Mouse pressed at: " + std::to_string(event->x()) + ", " + std::to_string(event->y()));
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
// TODO: Hit test on objects
|
_pressedObject = _hoveredObject;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_lastMousePosition = event->pos();
|
_lastMousePosition = event->pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parentWidget()->update();
|
||||||
|
setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneViewer::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
|
// State transfer
|
||||||
|
bool startOperatingObject = false;
|
||||||
|
if (_operatingObject != nullptr) {
|
||||||
|
// Click when having an operating object
|
||||||
|
_operatingObject->updateBoundary();
|
||||||
|
if (!_dragged) {
|
||||||
|
// if haven't changed since last mouse press, it's a submission click
|
||||||
|
_operatingObject = nullptr;
|
||||||
|
_hideBound = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// dragged, keep it operational
|
||||||
|
_dragged = false;
|
||||||
|
_hideBound = true;
|
||||||
|
_operatingObject = _operatingObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_pressedObject != nullptr && _pressedObject == _selectedObject) {
|
||||||
|
// Double select on an object, set in operating mode
|
||||||
|
_operatingObject = _selectedObject;
|
||||||
|
_hideBound = true;
|
||||||
|
startOperatingObject = true;
|
||||||
|
}
|
||||||
|
else if (_dragged) {
|
||||||
|
_dragged = false;
|
||||||
|
_hideBound = false;
|
||||||
|
if (_selectedObject != nullptr) {
|
||||||
|
_selectedObject->updateBoundary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_selectedObject = _pressedObject;
|
||||||
|
_hideBound = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset pressed object
|
||||||
|
_pressedObject = nullptr;
|
||||||
|
|
||||||
|
// Update hover object
|
||||||
|
float relX = (float)event->x() / (float)width();
|
||||||
|
float relY = 1 - (float)event->y() / (float)height();
|
||||||
|
Ray ray = _camera.generateRay(glm::vec2(relX, relY), (float)width() / (float)height());
|
||||||
|
_hoveredObject = hitTest(ray);
|
||||||
|
|
||||||
|
if (startOperatingObject) {
|
||||||
|
// If just setted to operating mode, move the object
|
||||||
|
moveOperatingObject(ray);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the view
|
||||||
|
parentWidget()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneViewer::mouseMoveEvent(QMouseEvent* event) {
|
void SceneViewer::mouseMoveEvent(QMouseEvent* event) {
|
||||||
// Check the type of button pressed
|
// Check the type of button pressed
|
||||||
switch (event->buttons()) {
|
switch (event->buttons()) {
|
||||||
case Qt::LeftButton: {
|
case Qt::LeftButton: {
|
||||||
// Move the selected object
|
|
||||||
if (_selectedObject != nullptr) {
|
if (_selectedObject != nullptr) {
|
||||||
// TODO: move the selected object
|
// Set dragged
|
||||||
|
_dragged = true;
|
||||||
|
// Hide boundary
|
||||||
|
_hideBound = true;
|
||||||
|
// Rotate around camera up
|
||||||
|
glm::vec2 delta = glm::vec2(event->x() - _lastMousePosition.x(), event->y() - _lastMousePosition.y());
|
||||||
|
_selectedObject->rotate(_camera.up(), delta.x * 0.01f);
|
||||||
|
// Rotate around camera right
|
||||||
|
_selectedObject->rotate(_camera.right(), delta.y * 0.01f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Qt::RightButton: {
|
case Qt::RightButton: {
|
||||||
// Move the camera
|
// Set dragged
|
||||||
float xoffset = event->x() - _lastMousePosition.x();
|
_dragged = true;
|
||||||
float yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top
|
moveCamera(event);
|
||||||
float xmovement = xoffset * _cameraMovementSpeed;
|
|
||||||
float ymovement = yoffset * _cameraMovementSpeed;
|
|
||||||
glm::vec3 cameraPrevPos = _camera.position();
|
|
||||||
_camera.move({ -xmovement, -ymovement });
|
|
||||||
glm::vec3 cameraNewPos = _camera.position();
|
|
||||||
_rotateCenter += cameraNewPos - cameraPrevPos;
|
|
||||||
Logger::debug("Camera moved to: " + std::to_string(_camera.position().x) + ", " + std::to_string(_camera.position().y) + ", " + std::to_string(_camera.position().z));
|
|
||||||
Logger::debug("New center: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Qt::MiddleButton: {
|
case Qt::MiddleButton: {
|
||||||
// Rotate the camera
|
if (_controlPressed && _selectedObject != nullptr) {
|
||||||
float xoffset = event->x() - _lastMousePosition.x();
|
// Set dragged
|
||||||
float yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top
|
_dragged = true;
|
||||||
// Calculate pitch angle
|
// Hide boundary
|
||||||
float pitch = yoffset * _cameraRotationSpeed;
|
_hideBound = true;
|
||||||
// Calculate yaw angle
|
// Scale object
|
||||||
float yaw = xoffset * _cameraRotationSpeed;
|
glm::vec2 delta = glm::vec2(event->x() - _lastMousePosition.x(), event->y() - _lastMousePosition.y());
|
||||||
_camera.rotate(_rotateCenter, pitch, -yaw);
|
_selectedObject->scale(-delta.y * 0.01f);
|
||||||
Logger::debug("Camera rotated to: " + std::to_string(_camera.position().x) + ", " + std::to_string(_camera.position().y) + ", " + std::to_string(_camera.position().z));
|
}
|
||||||
Logger::debug("Center at: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z));
|
else {
|
||||||
|
// Set dragged
|
||||||
|
_dragged = true;
|
||||||
|
rotateCamera(event);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Qt::NoButton: {
|
case Qt::NoButton: {
|
||||||
// If no button pressed, do hit test and move the current object if selected
|
|
||||||
float relX = (float)event->x() / (float)width();
|
float relX = (float)event->x() / (float)width();
|
||||||
float relY = 1 - (float)event->y() / (float)height();
|
float relY = 1 - (float)event->y() / (float)height();
|
||||||
Ray ray = _camera.generateRay(glm::vec2(relX, relY), (float)width() / (float)height());
|
Ray ray = _camera.generateRay(glm::vec2(relX, relY), (float)width() / (float)height());
|
||||||
hitTest(ray);
|
if (_operatingObject == nullptr) {
|
||||||
|
// If no button pressed, do hit test and move the current object if selected
|
||||||
|
_hoveredObject = hitTest(ray);
|
||||||
|
if (_hoveredObject != nullptr) {
|
||||||
|
setCursor(Qt::PointingHandCursor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setCursor(Qt::ArrowCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
moveOperatingObject(ray);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -290,3 +383,101 @@ void SceneViewer::wheelEvent(QWheelEvent* event) {
|
|||||||
// Update the view
|
// Update the view
|
||||||
parentWidget()->update();
|
parentWidget()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneViewer::moveCamera(QMouseEvent* event) {
|
||||||
|
// Move the camera
|
||||||
|
float xoffset = event->x() - _lastMousePosition.x();
|
||||||
|
float yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top
|
||||||
|
float xmovement = xoffset * _cameraMovementSpeed;
|
||||||
|
float ymovement = yoffset * _cameraMovementSpeed;
|
||||||
|
glm::vec3 cameraPrevPos = _camera.position();
|
||||||
|
_camera.move({ -xmovement, -ymovement });
|
||||||
|
glm::vec3 cameraNewPos = _camera.position();
|
||||||
|
_rotateCenter += cameraNewPos - cameraPrevPos;
|
||||||
|
Logger::debug("Camera moved to: " + std::to_string(_camera.position().x) + ", " + std::to_string(_camera.position().y) + ", " + std::to_string(_camera.position().z));
|
||||||
|
Logger::debug("New center: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z));
|
||||||
|
if (_operatingObject != nullptr) {
|
||||||
|
float relX = (float)event->x() / (float)width();
|
||||||
|
float relY = 1 - (float)event->y() / (float)height();
|
||||||
|
Ray ray = _camera.generateRay(glm::vec2(relX, relY), (float)width() / (float)height());
|
||||||
|
moveOperatingObject(ray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneViewer::rotateCamera(QMouseEvent* event) {
|
||||||
|
// Rotate the camera
|
||||||
|
float xoffset = event->x() - _lastMousePosition.x();
|
||||||
|
float yoffset = _lastMousePosition.y() - event->y(); // reversed since y-coordinates go from bottom to top
|
||||||
|
// Calculate pitch angle
|
||||||
|
float pitch = yoffset * _cameraRotationSpeed;
|
||||||
|
// Calculate yaw angle
|
||||||
|
float yaw = xoffset * _cameraRotationSpeed;
|
||||||
|
_camera.rotate(_rotateCenter, pitch, -yaw);
|
||||||
|
Logger::debug("Camera rotated to: " + std::to_string(_camera.position().x) + ", " + std::to_string(_camera.position().y) + ", " + std::to_string(_camera.position().z));
|
||||||
|
Logger::debug("Center at: " + std::to_string(_rotateCenter.x) + ", " + std::to_string(_rotateCenter.y) + ", " + std::to_string(_rotateCenter.z));
|
||||||
|
if (_operatingObject != nullptr) {
|
||||||
|
float relX = (float)event->x() / (float)width();
|
||||||
|
float relY = 1 - (float)event->y() / (float)height();
|
||||||
|
Ray ray = _camera.generateRay(glm::vec2(relX, relY), (float)width() / (float)height());
|
||||||
|
moveOperatingObject(ray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneViewer::keyPressEvent(QKeyEvent* event) {
|
||||||
|
Logger::debug("Detect keypress " + std::to_string(event->key()));
|
||||||
|
// If ctrl pressed
|
||||||
|
if (event->modifiers().testFlag(Qt::ControlModifier)) {
|
||||||
|
Logger::debug("Control pressed");
|
||||||
|
_controlPressed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneViewer::keyReleaseEvent(QKeyEvent* event) {
|
||||||
|
// If no control pressed
|
||||||
|
if (!(event->modifiers().testFlag(Qt::ControlModifier))) {
|
||||||
|
Logger::debug("Control released");
|
||||||
|
_controlPressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneViewer::moveOperatingObject(const Ray& ray) {
|
||||||
|
// Current moving object
|
||||||
|
hitTest(ray);
|
||||||
|
if (!_hitRecord.hitted()) {
|
||||||
|
// Move to the direction of current ray
|
||||||
|
glm::vec3 target = _camera.position() + ray.direction() * 15.0f;
|
||||||
|
_operatingObject->setPosition(target);
|
||||||
|
_operatingObject->updateBoundary();
|
||||||
|
}
|
||||||
|
// Move the object so that the bottom center of the object is at the hit point
|
||||||
|
else if (_stickToSurface) {
|
||||||
|
// Stick the bottom center of the model to the surface
|
||||||
|
|
||||||
|
// Clear current translation and rotation while keeping scale
|
||||||
|
_operatingObject->setPosition(glm::vec3(0.0f));
|
||||||
|
_operatingObject->setRotation(glm::vec3(0.0f, 0.0f, 0.0f), 0.0f);
|
||||||
|
_operatingObject->updateBoundary();
|
||||||
|
|
||||||
|
// Set the bottom center of the model at local origin
|
||||||
|
glm::vec3 bottomCenter = _operatingObject->boundary().bottomCenterPoint();
|
||||||
|
_operatingObject->move(-bottomCenter);
|
||||||
|
|
||||||
|
// Rotate the model to align with the surface normal
|
||||||
|
glm::vec3 normal = _hitRecord.normal();
|
||||||
|
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
glm::vec3 axis = glm::cross(up, normal);
|
||||||
|
float angle = glm::acos(glm::dot(up, normal));
|
||||||
|
_operatingObject->rotate(axis, angle);
|
||||||
|
|
||||||
|
// Move the model to the hit point
|
||||||
|
glm::vec3 hitPoint = _hitRecord.position();
|
||||||
|
_operatingObject->move(hitPoint);
|
||||||
|
|
||||||
|
// Update boundary
|
||||||
|
_operatingObject->updateBoundary();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Move the object to the hit point
|
||||||
|
_operatingObject->setPosition(_hitRecord.position());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -43,8 +43,13 @@ private:
|
|||||||
|
|
||||||
// User Interaction flags section---------------------
|
// User Interaction flags section---------------------
|
||||||
QPoint _lastMousePosition;
|
QPoint _lastMousePosition;
|
||||||
|
bool _controlPressed = false;
|
||||||
|
bool _dragged = false;
|
||||||
|
bool _hideBound = false;
|
||||||
Renderable* _hoveredObject = nullptr;
|
Renderable* _hoveredObject = nullptr;
|
||||||
|
Renderable* _pressedObject = nullptr;
|
||||||
Renderable* _selectedObject = nullptr;
|
Renderable* _selectedObject = nullptr;
|
||||||
|
Renderable* _operatingObject = nullptr;
|
||||||
HitRecord _hitRecord;
|
HitRecord _hitRecord;
|
||||||
|
|
||||||
// UI interface control
|
// UI interface control
|
||||||
@ -57,7 +62,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void extractShaderResource(const QString& shaderName);
|
void extractShaderResource(const QString& shaderName);
|
||||||
void hitTest(const Ray& ray);
|
Renderable* hitTest(const Ray& ray);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void moveCamera(QMouseEvent* event);
|
||||||
|
void rotateCamera(QMouseEvent* event);
|
||||||
|
void moveOperatingObject(const Ray& ray);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// OpenGL functions
|
// OpenGL functions
|
||||||
@ -67,6 +77,14 @@ protected:
|
|||||||
|
|
||||||
// Mouse events
|
// Mouse events
|
||||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
virtual void mouseMoveEvent(QMouseEvent* event) override;
|
virtual void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
virtual void wheelEvent(QWheelEvent* event) override;
|
virtual void wheelEvent(QWheelEvent* event) override;
|
||||||
|
virtual void keyPressEvent(QKeyEvent* event) override;
|
||||||
|
virtual void keyReleaseEvent(QKeyEvent* event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void onHover(Renderable* object);
|
||||||
|
void onSelect(Renderable* object);
|
||||||
|
void onUpdate(Renderable* object);
|
||||||
};
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user