feat: basic moving and resizing support
This commit is contained in:
parent
81d172900b
commit
64fa46d496
109
assets/shaders/handle.fs
Normal file
109
assets/shaders/handle.fs
Normal file
|
@ -0,0 +1,109 @@
|
|||
#version 330 core
|
||||
|
||||
// Implements the Phong lighting model with respect to materials and lighting materials
|
||||
|
||||
// Structs
|
||||
|
||||
struct Material {
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct DirLight {
|
||||
vec3 direction;
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
vec3 position;
|
||||
// vec3 direction;
|
||||
vec3 ambient;
|
||||
vec3 diffuse;
|
||||
vec3 specular;
|
||||
|
||||
float constant;
|
||||
float linear;
|
||||
float quadratic;
|
||||
};
|
||||
|
||||
|
||||
// I/O
|
||||
|
||||
in vec3 vPos;
|
||||
in vec3 vNormal;
|
||||
in vec2 vTexCoords;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
#define NR_POINT_LIGHTS 4
|
||||
|
||||
uniform vec3 viewPos;
|
||||
uniform PointLight pointLights[NR_POINT_LIGHTS];
|
||||
uniform int numPointLights;
|
||||
uniform DirLight sunLight;
|
||||
uniform Material material;
|
||||
|
||||
// Functions
|
||||
|
||||
vec3 calculateDirectionalLight(DirLight light);
|
||||
vec3 calculatePointLight(PointLight light);
|
||||
|
||||
|
||||
// Main
|
||||
|
||||
void main() {
|
||||
vec3 result = vec3(0.0);
|
||||
|
||||
result += calculateDirectionalLight(sunLight);
|
||||
|
||||
for (int i = 0; i < numPointLights; i++) {
|
||||
result += calculatePointLight(pointLights[i]);
|
||||
}
|
||||
|
||||
FragColor = vec4(result, 1);
|
||||
}
|
||||
|
||||
vec3 calculateDirectionalLight(DirLight light) {
|
||||
// Calculate diffuse
|
||||
vec3 norm = normalize(vNormal);
|
||||
vec3 lightDir = normalize(-light.direction);
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
// Calculate specular
|
||||
vec3 viewDir = normalize(viewPos - vPos);
|
||||
vec3 reflectDir = reflect(-lightDir, norm);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
|
||||
vec3 ambient = light.ambient * material.diffuse;
|
||||
vec3 diffuse = light.diffuse * diff * material.diffuse;
|
||||
vec3 specular = light.specular * spec * material.specular;
|
||||
|
||||
return (ambient + diffuse + specular);
|
||||
}
|
||||
|
||||
vec3 calculatePointLight(PointLight light) {
|
||||
// Calculate ambient light
|
||||
|
||||
// Calculate diffuse light
|
||||
vec3 norm = normalize(vNormal);
|
||||
vec3 lightDir = normalize(light.position - vPos);
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
// Calculate specular
|
||||
vec3 viewDir = normalize(viewPos - vPos);
|
||||
vec3 reflectDir = reflect(-lightDir, norm);
|
||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
|
||||
|
||||
// Calculate attenuation
|
||||
float distance = length(light.position - vPos);
|
||||
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
|
||||
|
||||
vec3 ambient = light.ambient * material.diffuse;
|
||||
vec3 diffuse = light.diffuse * diff * material.diffuse;
|
||||
vec3 specular = light.specular * spec * material.specular;
|
||||
|
||||
return (ambient + diffuse + specular) * attenuation;
|
||||
}
|
20
assets/shaders/handle.vs
Normal file
20
assets/shaders/handle.vs
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNormal;
|
||||
layout (location = 2) in vec2 aTexCoords;
|
||||
|
||||
out vec3 vPos;
|
||||
out vec3 vNormal;
|
||||
out vec2 vTexCoords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat3 normalMatrix;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * view * model * vec4(aPos, 1.0);
|
||||
vPos = vec3(model * vec4(aPos, 1.0));
|
||||
vNormal = normalMatrix * aNormal;
|
||||
}
|
13
assets/shaders/identity.fs
Normal file
13
assets/shaders/identity.fs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 330 core
|
||||
|
||||
// I/O
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform vec3 aColor;
|
||||
|
||||
// Main
|
||||
|
||||
void main() {
|
||||
FragColor = vec4(aColor, 1);
|
||||
}
|
8
assets/shaders/identity.vs
Normal file
8
assets/shaders/identity.vs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
|
||||
out vec3 vPos;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPos, 1.0);
|
||||
}
|
|
@ -8,6 +8,7 @@ Camera camera(glm::vec3(0.0, 0.0, 3.0));
|
|||
std::shared_ptr<DataModel> dataModel = DataModel::New();
|
||||
std::optional<HierarchyPreUpdateHandler> hierarchyPreUpdateHandler;
|
||||
std::optional<HierarchyPostUpdateHandler> hierarchyPostUpdateHandler;
|
||||
std::shared_ptr<Handles> editorToolHandles = Handles::New();
|
||||
|
||||
|
||||
std::vector<InstanceRefWeak> currentSelection;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/handles.h"
|
||||
#include "objects/workspace.h"
|
||||
#include "camera.h"
|
||||
#include <functional>
|
||||
|
@ -18,6 +19,7 @@ extern std::shared_ptr<DataModel> dataModel;
|
|||
inline std::shared_ptr<Workspace> workspace() { return std::dynamic_pointer_cast<Workspace>(dataModel->services["Workspace"]); }
|
||||
extern std::optional<HierarchyPreUpdateHandler> hierarchyPreUpdateHandler;
|
||||
extern std::optional<HierarchyPostUpdateHandler> hierarchyPostUpdateHandler;
|
||||
extern std::shared_ptr<Handles> editorToolHandles;
|
||||
|
||||
void setSelection(std::vector<InstanceRefWeak> newSelection, bool fromExplorer = false);
|
||||
const std::vector<InstanceRefWeak> getSelection();
|
||||
|
|
62
core/src/objects/handles.cpp
Normal file
62
core/src/objects/handles.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "handles.h"
|
||||
#include "datatypes/cframe.h"
|
||||
#include "datatypes/vector.h"
|
||||
#include <optional>
|
||||
#include <reactphysics3d/collision/RaycastInfo.h>
|
||||
#include <reactphysics3d/engine/PhysicsCommon.h>
|
||||
#include <reactphysics3d/engine/PhysicsWorld.h>
|
||||
#include <reactphysics3d/mathematics/Transform.h>
|
||||
|
||||
HandleFace HandleFace::XPos(0, glm::vec3(1,0,0));
|
||||
HandleFace HandleFace::XNeg(1, glm::vec3(-1,0,0));
|
||||
HandleFace HandleFace::YPos(2, glm::vec3(0,1,0));
|
||||
HandleFace HandleFace::YNeg(3, glm::vec3(0,-1,0));
|
||||
HandleFace HandleFace::ZPos(4, glm::vec3(0,0,1));
|
||||
HandleFace HandleFace::ZNeg(5, glm::vec3(0,0,-1));
|
||||
std::array<HandleFace, 6> HandleFace::Faces { HandleFace::XPos, HandleFace::XNeg, HandleFace::YPos, HandleFace::YNeg, HandleFace::ZPos, HandleFace::ZNeg };
|
||||
|
||||
// Shitty solution
|
||||
static rp3d::PhysicsCommon common;
|
||||
static rp3d::PhysicsWorld* world = common.createPhysicsWorld();
|
||||
|
||||
const InstanceType Handles::TYPE = {
|
||||
.super = &Instance::TYPE,
|
||||
.className = "Handles",
|
||||
// .constructor = &Workspace::Create,
|
||||
// .explorerIcon = "",
|
||||
};
|
||||
|
||||
const InstanceType* Handles::GetClass() {
|
||||
return &TYPE;
|
||||
}
|
||||
|
||||
Handles::Handles(): Instance(&TYPE) {
|
||||
}
|
||||
|
||||
Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) {
|
||||
if (!adornee.has_value() || adornee->expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0));
|
||||
|
||||
// return adornee->lock()->cframe + face.normal * 5.f;
|
||||
if (worldMode)
|
||||
return adornee->lock()->cframe + (adornee->lock()->size * 0.5f * face.normal) + face.normal * 5.f;
|
||||
return adornee->lock()->cframe + glm::vec3(glm::mat4(adornee->lock()->cframe.Rotation()) * glm::vec4((adornee->lock()->size * 0.5f * face.normal) + face.normal * 5.f, 0));
|
||||
}
|
||||
|
||||
std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
|
||||
for (HandleFace face : HandleFace::Faces) {
|
||||
Data::CFrame cframe = GetCFrameOfHandle(face);
|
||||
// Implement manual detection via boxes instead of... this shit
|
||||
rp3d::RigidBody* body = world->createRigidBody(cframe);
|
||||
body->addCollider(common.createBoxShape(Data::Vector3(.5, .5, .5)), rp3d::Transform::identity());
|
||||
|
||||
rp3d::RaycastInfo info;
|
||||
if (body->raycast(ray, info)) {
|
||||
world->destroyRigidBody(body);
|
||||
return face;
|
||||
}
|
||||
|
||||
world->destroyRigidBody(body);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
44
core/src/objects/handles.h
Normal file
44
core/src/objects/handles.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
#include "datatypes/cframe.h"
|
||||
#include "objects/base/service.h"
|
||||
#include "objects/part.h"
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <reactphysics3d/body/RigidBody.h>
|
||||
|
||||
class HandleFace {
|
||||
HandleFace(int index, glm::vec3 normal) : index(index), normal(normal){}
|
||||
|
||||
public:
|
||||
int index;
|
||||
glm::vec3 normal;
|
||||
|
||||
static HandleFace XPos;
|
||||
static HandleFace XNeg;
|
||||
static HandleFace YPos;
|
||||
static HandleFace YNeg;
|
||||
static HandleFace ZPos;
|
||||
static HandleFace ZNeg;
|
||||
static std::array<HandleFace, 6> Faces;
|
||||
};
|
||||
|
||||
class Handles : public Instance {
|
||||
public:
|
||||
const static InstanceType TYPE;
|
||||
|
||||
std::optional<std::weak_ptr<Part>> adornee;
|
||||
// inline std::optional<std::weak_ptr<Part>> GetAdornee() { return adornee; }
|
||||
// inline void SetAdornee(std::optional<std::weak_ptr<Part>> newAdornee) { this->adornee = newAdornee; updateAdornee(); };
|
||||
|
||||
Handles();
|
||||
|
||||
// World-space handles vs local-space handles
|
||||
bool worldMode = false;
|
||||
Data::CFrame GetCFrameOfHandle(HandleFace face);
|
||||
std::optional<HandleFace> RaycastHandle(rp3d::Ray ray);
|
||||
|
||||
static inline std::shared_ptr<Handles> New() { return std::make_shared<Handles>(); };
|
||||
virtual const InstanceType* GetClass() override;
|
||||
};
|
|
@ -6,6 +6,7 @@
|
|||
#include <reactphysics3d/collision/shapes/BoxShape.h>
|
||||
#include <reactphysics3d/collision/shapes/CollisionShape.h>
|
||||
#include <reactphysics3d/components/RigidBodyComponents.h>
|
||||
#include <reactphysics3d/configuration.h>
|
||||
#include <reactphysics3d/engine/EventListener.h>
|
||||
#include <reactphysics3d/engine/PhysicsCommon.h>
|
||||
#include <reactphysics3d/mathematics/Quaternion.h>
|
||||
|
@ -39,6 +40,9 @@ void simulationInit() {
|
|||
world = physicsCommon->createPhysicsWorld();
|
||||
|
||||
world->setGravity(rp::Vector3(0, -196.2, 0));
|
||||
// world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::BAUMGARTE_CONTACTS);
|
||||
world->setNbIterationsPositionSolver(2000);
|
||||
world->setNbIterationsVelocitySolver(2000);
|
||||
|
||||
world->setEventListener(&eventListener);
|
||||
}
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
#include <glm/ext.hpp>
|
||||
#include <glm/ext/matrix_float4x4.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/trigonometric.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "datatypes/cframe.h"
|
||||
#include "physics/util.h"
|
||||
#include "shader.h"
|
||||
#include "mesh.h"
|
||||
|
@ -23,8 +25,9 @@
|
|||
|
||||
#include "renderer.h"
|
||||
|
||||
Shader *shader = NULL;
|
||||
Shader *skyboxShader = NULL;
|
||||
Shader* shader = NULL;
|
||||
Shader* skyboxShader = NULL;
|
||||
Shader* handleShader;
|
||||
extern Camera camera;
|
||||
Skybox* skyboxTexture = NULL;
|
||||
Texture3D* studsTexture = NULL;
|
||||
|
@ -54,9 +57,10 @@ void renderInit(GLFWwindow* window, int width, int height) {
|
|||
|
||||
studsTexture = new Texture3D("assets/textures/studs.png", 128, 128, 6, GL_RGBA);
|
||||
|
||||
// Compile shader
|
||||
// Compile shaders
|
||||
shader = new Shader("assets/shaders/phong.vs", "assets/shaders/phong.fs");
|
||||
skyboxShader = new Shader("assets/shaders/skybox.vs", "assets/shaders/skybox.fs");
|
||||
handleShader = new Shader("assets/shaders/handle.vs", "assets/shaders/handle.fs");
|
||||
}
|
||||
|
||||
void renderParts() {
|
||||
|
@ -109,22 +113,6 @@ void renderParts() {
|
|||
for (InstanceRef inst : workspace()->GetChildren()) {
|
||||
if (inst->GetClass()->className != "Part") continue;
|
||||
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(inst);
|
||||
|
||||
// if (inst->name == "Target") printf("(%f,%f,%f):(%f,%f,%f;%f,%f,%f;%f,%f,%f)\n",
|
||||
// part->cframe.X(),
|
||||
// part->cframe.Y(),
|
||||
// part->cframe.Z(),
|
||||
// part->cframe.RightVector().X(),
|
||||
// part->cframe.UpVector().X(),
|
||||
// part->cframe.LookVector().X(),
|
||||
// part->cframe.RightVector().Y(),
|
||||
// part->cframe.UpVector().Y(),
|
||||
// part->cframe.LookVector().Y(),
|
||||
// part->cframe.RightVector().Z(),
|
||||
// part->cframe.UpVector().Z(),
|
||||
// part->cframe.LookVector().Z()
|
||||
// );
|
||||
|
||||
glm::mat4 model = part->cframe;
|
||||
model = glm::scale(model, part->size);
|
||||
shader->set("model", model);
|
||||
|
@ -160,12 +148,56 @@ void renderSkyBox() {
|
|||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
}
|
||||
|
||||
void renderHandles() {
|
||||
// if (getSelection().size() == 0) return;
|
||||
// if (getSelection()[0].lock()->GetClass() != &Part::TYPE) return;
|
||||
if (!editorToolHandles->adornee.has_value()) return;
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
// Use shader
|
||||
handleShader->use();
|
||||
|
||||
// view/projection transformations
|
||||
glm::mat4 projection = glm::perspective(glm::radians(45.f), (float)viewportWidth / (float)viewportHeight, 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.getLookAt();
|
||||
handleShader->set("projection", projection);
|
||||
handleShader->set("view", view);
|
||||
handleShader->set("sunLight", DirLight {
|
||||
.direction = glm::vec3(-0.2f, -1.0f, -0.3f),
|
||||
.ambient = glm::vec3(0.2f, 0.2f, 0.2f),
|
||||
.diffuse = glm::vec3(0.5f, 0.5f, 0.5f),
|
||||
.specular = glm::vec3(1.0f, 1.0f, 1.0f),
|
||||
});
|
||||
handleShader->set("numPointLights", 0);
|
||||
|
||||
// Pass in the camera position
|
||||
handleShader->set("viewPos", camera.cameraPos);
|
||||
|
||||
for (auto face : HandleFace::Faces) {
|
||||
glm::mat4 model = editorToolHandles->GetCFrameOfHandle(face);
|
||||
model = glm::scale(model, glm::vec3(1,1,1));
|
||||
handleShader->set("model", model);
|
||||
handleShader->set("material", Material {
|
||||
.diffuse = glm::abs(face.normal),
|
||||
.specular = glm::vec3(0.5f, 0.5f, 0.5f),
|
||||
.shininess = 16.0f,
|
||||
});
|
||||
glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
|
||||
handleShader->set("normalMatrix", normalMatrix);
|
||||
|
||||
CUBE_MESH->bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
}
|
||||
}
|
||||
|
||||
void render(GLFWwindow* window) {
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
renderSkyBox();
|
||||
renderParts();
|
||||
renderHandles();
|
||||
}
|
||||
|
||||
void setViewport(int width, int height) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <reactphysics3d/collision/RaycastInfo.h>
|
||||
#include <vector>
|
||||
|
||||
#include "editorcommon.h"
|
||||
#include "physics/util.h"
|
||||
#include "qcursor.h"
|
||||
#include "qevent.h"
|
||||
|
@ -21,6 +22,7 @@
|
|||
#include "camera.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "rendering/shader.h"
|
||||
|
||||
#include "mainglwidget.h"
|
||||
|
||||
|
@ -29,9 +31,13 @@ MainGLWidget::MainGLWidget(QWidget* parent): QOpenGLWidget(parent) {
|
|||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
Shader* identityShader;
|
||||
|
||||
void MainGLWidget::initializeGL() {
|
||||
glewInit();
|
||||
renderInit(NULL, width(), height());
|
||||
|
||||
identityShader = new Shader("assets/shaders/identity.vs", "assets/shaders/identity.fs");
|
||||
}
|
||||
|
||||
extern int vpx, vpy;
|
||||
|
@ -45,6 +51,10 @@ void MainGLWidget::resizeGL(int w, int h) {
|
|||
setViewport(w, h);
|
||||
}
|
||||
|
||||
glm::vec2 firstPoint;
|
||||
glm::vec2 secondPoint;
|
||||
|
||||
extern std::optional<std::weak_ptr<Part>> draggingObject;
|
||||
void MainGLWidget::paintGL() {
|
||||
::render(NULL);
|
||||
}
|
||||
|
@ -62,8 +72,9 @@ void MainGLWidget::handleCameraRotate(QMouseEvent* evt) {
|
|||
|
||||
bool isMouseDragging = false;
|
||||
std::optional<std::weak_ptr<Part>> draggingObject;
|
||||
std::optional<HandleFace> draggingHandle;
|
||||
void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
||||
if (!isMouseDragging) return;
|
||||
if (!isMouseDragging || !draggingObject) return;
|
||||
|
||||
QPoint position = evt->pos();
|
||||
|
||||
|
@ -79,17 +90,62 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
|||
syncPartPhysics(draggingObject->lock());
|
||||
}
|
||||
|
||||
QPoint lastPoint;
|
||||
void MainGLWidget::handleHandleDrag(QMouseEvent* evt) {
|
||||
QPoint cLastPoint = lastPoint;
|
||||
lastPoint = evt->pos();
|
||||
|
||||
if (!isMouseDragging || !draggingHandle || !editorToolHandles->adornee) return;
|
||||
|
||||
// https://stackoverflow.com/a/57380616/16255372
|
||||
QPoint position = evt->pos();
|
||||
glm::mat4 projection = glm::perspective(glm::radians(45.f), (float)width() / (float)height(), 0.1f, 100.0f);
|
||||
glm::mat4 view = camera.getLookAt();
|
||||
glm::mat4 worldToScreen = projection * view;
|
||||
glm::vec4 a = worldToScreen * glm::vec4((glm::vec3)editorToolHandles->adornee->lock()->position(), 1);
|
||||
glm::vec4 b = worldToScreen * glm::vec4((glm::vec3)editorToolHandles->adornee->lock()->position() + draggingHandle->normal, 1);
|
||||
glm::vec2 screenDir = b / b.w - a / a.w;
|
||||
|
||||
QPoint mouseDelta_ = evt->pos() - cLastPoint;
|
||||
glm::vec2 mouseDelta(mouseDelta_.x(), mouseDelta_.y() * -1.f);
|
||||
float changeBy = glm::dot(mouseDelta, screenDir);
|
||||
|
||||
if (selectedTool == SelectedTool::MOVE)
|
||||
editorToolHandles->adornee->lock()->cframe = editorToolHandles->adornee->lock()->cframe + draggingHandle->normal * changeBy;
|
||||
else if (selectedTool == SelectedTool::SCALE)
|
||||
editorToolHandles->adornee->lock()->size += glm::abs(draggingHandle->normal) * changeBy;
|
||||
|
||||
syncPartPhysics(std::dynamic_pointer_cast<Part>(editorToolHandles->adornee->lock()));
|
||||
}
|
||||
|
||||
std::optional<HandleFace> MainGLWidget::raycastHandle(glm::vec3 pointDir) {
|
||||
if (!editorToolHandles->adornee.has_value()) return std::nullopt;
|
||||
return editorToolHandles->RaycastHandle(rp3d::Ray(glmToRp(camera.cameraPos), glmToRp(glm::normalize(pointDir)) * 50000));
|
||||
}
|
||||
|
||||
void MainGLWidget::handleCursorChange(QMouseEvent* evt) {
|
||||
QPoint position = evt->pos();
|
||||
|
||||
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
|
||||
|
||||
if (raycastHandle(pointDir)) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
return;
|
||||
};
|
||||
|
||||
std::optional<const RaycastResult> rayHit = castRayNearest(camera.cameraPos, pointDir, 50000);
|
||||
setCursor((rayHit && partFromBody(rayHit->body)->name != "Baseplate") ? Qt::OpenHandCursor : Qt::ArrowCursor);
|
||||
if (rayHit && partFromBody(rayHit->body)->name != "Baseplate") {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
return;
|
||||
}
|
||||
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
|
||||
void MainGLWidget::mouseMoveEvent(QMouseEvent* evt) {
|
||||
handleCameraRotate(evt);
|
||||
handleObjectDrag(evt);
|
||||
handleHandleDrag(evt);
|
||||
handleCursorChange(evt);
|
||||
}
|
||||
|
||||
|
@ -105,6 +161,15 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
|||
QPoint position = evt->pos();
|
||||
|
||||
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
|
||||
// raycast handles
|
||||
auto handle = raycastHandle(pointDir);
|
||||
if (handle.has_value()) {
|
||||
isMouseDragging = true;
|
||||
draggingHandle = handle;
|
||||
return;
|
||||
}
|
||||
|
||||
// raycast part
|
||||
std::optional<const RaycastResult> rayHit = castRayNearest(camera.cameraPos, pointDir, 50000);
|
||||
if (!rayHit || !partFromBody(rayHit->body)) return;
|
||||
std::shared_ptr<Part> part = partFromBody(rayHit->body);
|
||||
|
@ -128,6 +193,7 @@ void MainGLWidget::mouseReleaseEvent(QMouseEvent* evt) {
|
|||
isMouseRightDragging = false;
|
||||
isMouseDragging = false;
|
||||
draggingObject = std::nullopt;
|
||||
draggingHandle = std::nullopt;
|
||||
}
|
||||
|
||||
static int moveZ = 0;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <QWidget>
|
||||
#include <memory>
|
||||
|
||||
class HandleFace;
|
||||
|
||||
class MainGLWidget : public QOpenGLWidget {
|
||||
public:
|
||||
MainGLWidget(QWidget *parent = nullptr);
|
||||
|
@ -20,7 +22,9 @@ protected:
|
|||
|
||||
void handleCameraRotate(QMouseEvent* evt);
|
||||
void handleObjectDrag(QMouseEvent* evt);
|
||||
void handleHandleDrag(QMouseEvent* evt);
|
||||
void handleCursorChange(QMouseEvent* evt);
|
||||
std::optional<HandleFace> raycastHandle(glm::vec3 pointDir);
|
||||
|
||||
void mouseMoveEvent(QMouseEvent* evt) override;
|
||||
void mousePressEvent(QMouseEvent* evt) override;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <QWidget>
|
||||
#include <QTreeView>
|
||||
#include <QAbstractItemView>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "common.h"
|
||||
|
@ -78,6 +79,10 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
ConnectSelectionChangeHandler();
|
||||
});
|
||||
|
||||
addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) {
|
||||
updateSelectedTool();
|
||||
});
|
||||
|
||||
// ui->explorerView->Init(ui);
|
||||
|
||||
simulationInit();
|
||||
|
@ -134,6 +139,19 @@ void MainWindow::updateSelectedTool() {
|
|||
ui->actionToolMove->setChecked(selectedTool == SelectedTool::MOVE);
|
||||
ui->actionToolScale->setChecked(selectedTool == SelectedTool::SCALE);
|
||||
ui->actionToolRotate->setChecked(selectedTool == SelectedTool::ROTATE);
|
||||
|
||||
if (selectedTool == SelectedTool::MOVE) editorToolHandles->worldMode = true;
|
||||
if (selectedTool == SelectedTool::SCALE) editorToolHandles->worldMode = false;
|
||||
|
||||
// This code sucks. A lot
|
||||
if (selectedTool == SelectedTool::SELECT) return;
|
||||
if (getSelection().size() == 0) { editorToolHandles->adornee = std::nullopt; return; };
|
||||
InstanceRef inst = getSelection()[0].lock();
|
||||
if (inst->GetClass() != &Part::TYPE) { editorToolHandles->adornee = std::nullopt; return; };
|
||||
|
||||
editorToolHandles->adornee = std::dynamic_pointer_cast<Part>(inst);
|
||||
|
||||
// editorToolHandles->adornee = std::nullopt;
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
|
Loading…
Reference in a new issue