refactor: replaced optional<weak_ptr<T>> with weak_ptr<T> directly
This commit is contained in:
parent
8c2474abbf
commit
2569e3f56f
11 changed files with 84 additions and 74 deletions
|
@ -56,6 +56,16 @@ bool operator ==(std::optional<std::weak_ptr<T>> a, std::optional<std::weak_ptr<
|
|||
|| (a.has_value() && !a.value().expired()) && (b.has_value() && !b.value().expired()) && a.value().lock() == b.value().lock();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator ==(std::weak_ptr<T> a, std::weak_ptr<T> b) {
|
||||
return a.expired() && b.expired() || (!a.expired() && !b.expired() && a.lock() == b.lock());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::weak_ptr<T> optional_to_weak(std::optional<std::shared_ptr<T>> a) {
|
||||
return a ? a.value() : std::weak_ptr<T>();
|
||||
}
|
||||
|
||||
// TODO: Test this
|
||||
bool Instance::ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent) {
|
||||
for (std::optional<std::shared_ptr<Instance>> currentParent = newParent; currentParent.has_value(); currentParent = currentParent.value()->GetParent()) {
|
||||
|
@ -72,15 +82,15 @@ bool Instance::SetParent(std::optional<std::shared_ptr<Instance>> newParent) {
|
|||
auto lastParent = GetParent();
|
||||
if (hierarchyPreUpdateHandler.has_value()) hierarchyPreUpdateHandler.value()(this->shared_from_this(), lastParent, newParent);
|
||||
// If we currently have a parent, remove ourselves from it before adding ourselves to the new one
|
||||
if (this->parent.has_value() && !this->parent.value().expired()) {
|
||||
auto oldParent = this->parent.value().lock();
|
||||
if (!this->parent.expired()) {
|
||||
auto oldParent = this->parent.lock();
|
||||
oldParent->children.erase(std::find(oldParent->children.begin(), oldParent->children.end(), this->shared_from_this()));
|
||||
}
|
||||
// Add ourselves to the new parent
|
||||
if (newParent.has_value()) {
|
||||
newParent.value()->children.push_back(this->shared_from_this());
|
||||
}
|
||||
this->parent = newParent;
|
||||
this->parent = optional_to_weak(newParent);
|
||||
// TODO: Add code for sending signals for parent updates
|
||||
// TODO: Yeahhh maybe this isn't the best way of doing this?
|
||||
if (hierarchyPostUpdateHandler.has_value()) hierarchyPostUpdateHandler.value()(this->shared_from_this(), lastParent, newParent);
|
||||
|
@ -98,23 +108,23 @@ void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedCh
|
|||
|
||||
// Update parent data model and workspace, if applicable
|
||||
if (GetParent()) {
|
||||
this->_dataModel = GetParent().value()->GetClass() == &DataModel::TYPE ? std::make_optional(std::dynamic_pointer_cast<DataModel>(GetParent().value())) : GetParent().value()->dataModel();
|
||||
this->_workspace = GetParent().value()->GetClass() == &Workspace::TYPE ? std::make_optional(std::dynamic_pointer_cast<Workspace>(GetParent().value())) : GetParent().value()->workspace();
|
||||
this->_dataModel = GetParent().value()->GetClass() == &DataModel::TYPE ? std::dynamic_pointer_cast<DataModel>(GetParent().value()) : GetParent().value()->_dataModel;
|
||||
this->_workspace = GetParent().value()->GetClass() == &Workspace::TYPE ? std::dynamic_pointer_cast<Workspace>(GetParent().value()) : GetParent().value()->_workspace;
|
||||
} else {
|
||||
this->_dataModel = std::nullopt;
|
||||
this->_workspace = std::nullopt;
|
||||
this->_dataModel = {};
|
||||
this->_workspace = {};
|
||||
}
|
||||
|
||||
OnAncestryChanged(updatedChild, newParent);
|
||||
|
||||
// Old workspace used to exist, and workspaces differ
|
||||
if (oldWorkspace.has_value() && !oldWorkspace->expired() && (!_workspace || _workspace->expired() || oldWorkspace->lock() != _workspace->lock())) {
|
||||
OnWorkspaceRemoved((oldWorkspace.has_value() && !oldWorkspace->expired()) ? std::make_optional(oldWorkspace->lock()) : std::nullopt);
|
||||
if (!oldWorkspace.expired() && oldWorkspace != _workspace) {
|
||||
OnWorkspaceRemoved(!oldWorkspace.expired() ? std::make_optional(oldWorkspace.lock()) : std::nullopt);
|
||||
}
|
||||
|
||||
// New workspace exists, and workspaces differ
|
||||
if (_workspace.has_value() && !_workspace->expired() && (!oldWorkspace || oldWorkspace->expired() || _workspace->lock() != oldWorkspace->lock())) {
|
||||
OnWorkspaceAdded((oldWorkspace.has_value() && !oldWorkspace->expired()) ? std::make_optional(oldWorkspace->lock()) : std::nullopt, _workspace->lock());
|
||||
if (!_workspace.expired() && (_workspace != oldWorkspace)) {
|
||||
OnWorkspaceAdded(!oldWorkspace.expired() ? std::make_optional(oldWorkspace.lock()) : std::nullopt, _workspace.lock());
|
||||
}
|
||||
|
||||
// Update ancestry in descendants
|
||||
|
@ -124,17 +134,16 @@ void Instance::updateAncestry(std::optional<std::shared_ptr<Instance>> updatedCh
|
|||
}
|
||||
|
||||
std::optional<std::shared_ptr<DataModel>> Instance::dataModel() {
|
||||
return (!_dataModel || _dataModel->expired()) ? std::nullopt : std::make_optional(_dataModel.value().lock());
|
||||
return (_dataModel.expired()) ? std::nullopt : std::make_optional(_dataModel.lock());
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<Workspace>> Instance::workspace() {
|
||||
return (!_workspace || _workspace->expired()) ? std::nullopt : std::make_optional(_workspace.value().lock());
|
||||
return (_workspace.expired()) ? std::nullopt : std::make_optional(_workspace.lock());
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<Instance>> Instance::GetParent() {
|
||||
if (!parent.has_value()) return std::nullopt;
|
||||
if (parent.value().expired()) return std::nullopt;
|
||||
return parent.value().lock();
|
||||
if (parent.expired()) return std::nullopt;
|
||||
return parent.lock();
|
||||
}
|
||||
|
||||
static std::shared_ptr<Instance> DUMMY_INSTANCE;
|
||||
|
|
|
@ -45,13 +45,13 @@ class DescendantsIterator;
|
|||
// https://stackoverflow.com/q/56415222/16255372
|
||||
class Instance : public std::enable_shared_from_this<Instance> {
|
||||
private:
|
||||
std::optional<std::weak_ptr<Instance>> parent;
|
||||
std::weak_ptr<Instance> parent;
|
||||
std::vector<std::shared_ptr<Instance>> children;
|
||||
|
||||
std::optional<std::vector<std::string>> cachedMemberList;
|
||||
|
||||
std::optional<std::weak_ptr<DataModel>> _dataModel;
|
||||
std::optional<std::weak_ptr<Workspace>> _workspace;
|
||||
std::weak_ptr<DataModel> _dataModel;
|
||||
std::weak_ptr<Workspace> _workspace;
|
||||
|
||||
bool ancestryContinuityCheck(std::optional<std::shared_ptr<Instance>> newParent);
|
||||
void updateAncestry(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent);
|
||||
|
|
|
@ -37,9 +37,9 @@ 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));
|
||||
if (adornee.expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0));
|
||||
|
||||
Data::CFrame localFrame = worldMode ? Data::CFrame::IDENTITY + adornee->lock()->position() : adornee->lock()->cframe;
|
||||
Data::CFrame localFrame = worldMode ? Data::CFrame::IDENTITY + adornee.lock()->position() : adornee.lock()->cframe;
|
||||
|
||||
Data::Vector3 handleNormal = face.normal;
|
||||
if (nixAxes)
|
||||
|
@ -50,7 +50,7 @@ Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) {
|
|||
if (glm::abs(glm::dot(glm::vec3(localFrame.Rotation() * handleNormal), upAxis)) > 0.9999f)
|
||||
upAxis = glm::vec3(0, 1, 0);
|
||||
|
||||
Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee->lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + adornee->lock()->size * 0.5f);
|
||||
Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee.lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + adornee.lock()->size * 0.5f);
|
||||
Data::Vector3 handlePos = localFrame * (handleOffset * handleNormal);
|
||||
Data::CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -handleNormal, upAxis);
|
||||
|
||||
|
@ -58,17 +58,17 @@ Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) {
|
|||
}
|
||||
|
||||
Data::CFrame Handles::PartCFrameFromHandlePos(HandleFace face, Data::Vector3 newPos) {
|
||||
if (!adornee.has_value() || adornee->expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0));
|
||||
if (adornee.expired()) return Data::CFrame(glm::vec3(0,0,0), (Data::Vector3)glm::vec3(0,0,0));
|
||||
|
||||
Data::CFrame localFrame = worldMode ? Data::CFrame::IDENTITY + adornee->lock()->position() : adornee->lock()->cframe;
|
||||
Data::CFrame localFrame = worldMode ? Data::CFrame::IDENTITY + adornee.lock()->position() : adornee.lock()->cframe;
|
||||
Data::CFrame inverseFrame = localFrame.Inverse();
|
||||
Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee->lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + adornee->lock()->size * 0.5f);
|
||||
Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee.lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + adornee.lock()->size * 0.5f);
|
||||
|
||||
Data::Vector3 handlePos = localFrame * (handleOffset * face.normal);
|
||||
|
||||
// glm::vec3 localPos = inverseFrame * newPos;
|
||||
glm::vec3 newPartPos = newPos - localFrame.Rotation() * (handleOffset * face.normal);
|
||||
return adornee->lock()->cframe.Rotation() + newPartPos;
|
||||
return adornee.lock()->cframe.Rotation() + newPartPos;
|
||||
}
|
||||
|
||||
std::optional<HandleFace> Handles::RaycastHandle(rp3d::Ray ray) {
|
||||
|
|
|
@ -36,11 +36,11 @@ public:
|
|||
|
||||
bool nixAxes = false; // XYZ -> ZXY, used with rotation
|
||||
bool active;
|
||||
std::optional<std::weak_ptr<Part>> adornee;
|
||||
std::weak_ptr<Part> adornee;
|
||||
HandlesType handlesType;
|
||||
|
||||
// inline std::optional<std::weak_ptr<Part>> GetAdornee() { return adornee; }
|
||||
// inline void SetAdornee(std::optional<std::weak_ptr<Part>> newAdornee) { this->adornee = newAdornee; updateAdornee(); };
|
||||
// inline std::weak_ptr<Part> GetAdornee() { return adornee; }
|
||||
// inline void SetAdornee(std::weak_ptr<Part> newAdornee) { this->adornee = newAdornee; updateAdornee(); };
|
||||
|
||||
Handles();
|
||||
|
||||
|
|
|
@ -22,18 +22,18 @@ Snap::~Snap() {
|
|||
}
|
||||
|
||||
void Snap::OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) {
|
||||
if (!part0 || !part1 || part0->expired() || part1->expired()) return;
|
||||
if (part0.expired() || part1.expired()) return;
|
||||
|
||||
printVec((part0->lock()->cframe * (c1.Inverse() * c0)).Rotation().ToEulerAnglesXYZ());
|
||||
printVec(part1->lock()->cframe.Rotation().ToEulerAnglesXYZ());
|
||||
printVec((part0.lock()->cframe * (c1.Inverse() * c0)).Rotation().ToEulerAnglesXYZ());
|
||||
printVec(part1.lock()->cframe.Rotation().ToEulerAnglesXYZ());
|
||||
|
||||
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
||||
// used to be rather than specifying an anchor rotation, so whatever.
|
||||
Data::CFrame newFrame = part0->lock()->cframe * (c1.Inverse() * c0);
|
||||
part1->lock()->cframe = newFrame;
|
||||
newWorkspace->SyncPartPhysics(part1->lock());
|
||||
Data::CFrame newFrame = part0.lock()->cframe * (c1.Inverse() * c0);
|
||||
part1.lock()->cframe = newFrame;
|
||||
newWorkspace->SyncPartPhysics(part1.lock());
|
||||
|
||||
rp::FixedJointInfo jointInfo(part0->lock()->rigidBody, part1->lock()->rigidBody, (c0.Inverse() * c1).Position());
|
||||
rp::FixedJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (c0.Inverse() * c1).Position());
|
||||
this->joint = dynamic_cast<rp::FixedJoint*>(workspace().value()->physicsWorld->createJoint(jointInfo));
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ protected:
|
|||
public:
|
||||
const static InstanceType TYPE;
|
||||
|
||||
std::optional<std::weak_ptr<Part>> part0;
|
||||
std::optional<std::weak_ptr<Part>> part1;
|
||||
std::weak_ptr<Part> part0;
|
||||
std::weak_ptr<Part> part1;
|
||||
Data::CFrame c0;
|
||||
Data::CFrame c1;
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ void renderSkyBox() {
|
|||
}
|
||||
|
||||
void renderHandles() {
|
||||
if (!editorToolHandles->adornee.has_value() || !editorToolHandles->active) return;
|
||||
if (editorToolHandles->adornee.expired() || !editorToolHandles->active) return;
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glCullFace(GL_BACK);
|
||||
|
|
|
@ -44,7 +44,7 @@ void MainGLWidget::resizeGL(int w, int h) {
|
|||
glm::vec2 firstPoint;
|
||||
glm::vec2 secondPoint;
|
||||
|
||||
extern std::optional<std::weak_ptr<Part>> draggingObject;
|
||||
extern std::weak_ptr<Part> draggingObject;
|
||||
extern std::optional<HandleFace> draggingHandle;
|
||||
extern Shader* shader;
|
||||
void MainGLWidget::paintGL() {
|
||||
|
@ -107,19 +107,19 @@ Data::CFrame snapCFrame(Data::CFrame frame) {
|
|||
}
|
||||
|
||||
bool isMouseDragging = false;
|
||||
std::optional<std::weak_ptr<Part>> draggingObject;
|
||||
std::weak_ptr<Part> draggingObject;
|
||||
std::optional<HandleFace> draggingHandle;
|
||||
Data::Vector3 initialHitPos;
|
||||
Data::Vector3 initialHitNormal;
|
||||
Data::CFrame initialFrame;
|
||||
void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
||||
if (!isMouseDragging || !draggingObject || mainWindow()->selectedTool >= TOOL_SMOOTH) return;
|
||||
if (!isMouseDragging || draggingObject.expired() || mainWindow()->selectedTool >= TOOL_SMOOTH) return;
|
||||
|
||||
QPoint position = evt->pos();
|
||||
|
||||
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
|
||||
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000, [](std::shared_ptr<Part> part) {
|
||||
return (part == draggingObject->lock()) ? FilterResult::PASS : FilterResult::TARGET;
|
||||
return (part == draggingObject.lock()) ? FilterResult::PASS : FilterResult::TARGET;
|
||||
});
|
||||
|
||||
if (!rayHit) return;
|
||||
|
@ -133,13 +133,13 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
|||
Data::Vector3 vec = rayHit->worldPoint + (tFormedInitialPos - tFormedHitPos);
|
||||
// The part being dragged's frame local to the hit target's frame, but without its position component
|
||||
// To find a world vector local to the new frame, use newFrame, not localFrame, as localFrame is localFrame is local to targetFrame in itself
|
||||
Data::CFrame localFrame = (targetFrame.Inverse() * (draggingObject->lock()->cframe.Rotation() + vec));
|
||||
Data::CFrame localFrame = (targetFrame.Inverse() * (draggingObject.lock()->cframe.Rotation() + vec));
|
||||
|
||||
// Snap axis
|
||||
localFrame = snapCFrame(localFrame);
|
||||
|
||||
// Snap to studs
|
||||
Data::Vector3 draggingPartSize = draggingObject->lock()->size;
|
||||
Data::Vector3 draggingPartSize = draggingObject.lock()->size;
|
||||
glm::vec3 inverseNormalPartSize = (Data::Vector3)(partSize - glm::vec3(localFrame.Rotation() * draggingPartSize)) * inverseSurfaceNormal / 2.f;
|
||||
if (snappingFactor() > 0)
|
||||
localFrame = localFrame.Rotation() + glm::round(glm::vec3(localFrame.Position() * inverseSurfaceNormal - inverseNormalPartSize) / snappingFactor()) * snappingFactor() + inverseNormalPartSize
|
||||
|
@ -149,13 +149,13 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
|||
|
||||
// Unsink the object
|
||||
// Get the normal of the surface relative to the part's frame, and get the size along that vector
|
||||
Data::Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * draggingObject->lock()->size / 2);
|
||||
Data::Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * draggingObject.lock()->size / 2);
|
||||
|
||||
draggingObject->lock()->cframe = newFrame + unsinkOffset;
|
||||
draggingObject.lock()->cframe = newFrame + unsinkOffset;
|
||||
|
||||
|
||||
gWorkspace()->SyncPartPhysics(draggingObject->lock());
|
||||
sendPropertyUpdatedSignal(draggingObject->lock(), "Position", draggingObject->lock()->position());
|
||||
gWorkspace()->SyncPartPhysics(draggingObject.lock());
|
||||
sendPropertyUpdatedSignal(draggingObject.lock(), "Position", draggingObject.lock()->position());
|
||||
}
|
||||
|
||||
inline glm::vec3 vec3fy(glm::vec4 vec) {
|
||||
|
@ -164,11 +164,11 @@ inline glm::vec3 vec3fy(glm::vec4 vec) {
|
|||
|
||||
// Taken from Godot's implementation of moving handles (godot/editor/plugins/gizmos/gizmo_3d_helper.cpp)
|
||||
void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
||||
if (!isMouseDragging || !draggingHandle || !editorToolHandles->adornee || !editorToolHandles->active) return;
|
||||
if (!isMouseDragging || !draggingHandle|| editorToolHandles->adornee.expired() || !editorToolHandles->active) return;
|
||||
|
||||
QPoint position = evt->pos();
|
||||
|
||||
auto part = editorToolHandles->adornee->lock();
|
||||
auto part = editorToolHandles->adornee.lock();
|
||||
|
||||
// This was actually quite a difficult problem to solve, managing to get the handle to go underneath the cursor
|
||||
|
||||
|
@ -196,7 +196,7 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
|||
glm::vec3 centerPoint = editorToolHandles->PartCFrameFromHandlePos(draggingHandle.value(), handlePoint).Position();
|
||||
|
||||
// Apply snapping in the current frame
|
||||
glm::vec3 diff = centerPoint - (glm::vec3)editorToolHandles->adornee->lock()->position();
|
||||
glm::vec3 diff = centerPoint - (glm::vec3)part->position();
|
||||
if (snappingFactor()) diff = frame.Rotation() * (glm::round(glm::vec3(frame.Inverse().Rotation() * diff) / snappingFactor()) * snappingFactor());
|
||||
|
||||
Data::Vector3 oldSize = part->size;
|
||||
|
@ -204,7 +204,7 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
|||
switch (mainWindow()->selectedTool) {
|
||||
case TOOL_MOVE: {
|
||||
// Add difference
|
||||
editorToolHandles->adornee->lock()->cframe = editorToolHandles->adornee->lock()->cframe + diff;
|
||||
part->cframe = part->cframe + diff;
|
||||
} break;
|
||||
|
||||
case TOOL_SCALE: {
|
||||
|
@ -241,18 +241,18 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
|||
if (mainWindow()->editSoundEffects && (oldSize != part->size) && QFile::exists("./assets/excluded/switch.wav"))
|
||||
playSound("./assets/excluded/switch.wav");
|
||||
|
||||
gWorkspace()->SyncPartPhysics(std::dynamic_pointer_cast<Part>(editorToolHandles->adornee->lock()));
|
||||
sendPropertyUpdatedSignal(draggingObject->lock(), "Position", draggingObject->lock()->position());
|
||||
sendPropertyUpdatedSignal(draggingObject->lock(), "Size", Data::Vector3(draggingObject->lock()->size));
|
||||
gWorkspace()->SyncPartPhysics(part);
|
||||
sendPropertyUpdatedSignal(part, "Position", part->position());
|
||||
sendPropertyUpdatedSignal(part, "Size", Data::Vector3(part->size));
|
||||
}
|
||||
|
||||
// Also implemented based on Godot: [c7ea8614](godot/editor/plugins/canvas_item_editor_plugin.cpp#L1490)
|
||||
glm::vec2 startPoint;
|
||||
void MainGLWidget::handleRotationalTransform(QMouseEvent* evt) {
|
||||
if (!isMouseDragging || !draggingHandle || !editorToolHandles->adornee || !editorToolHandles->active) return;
|
||||
if (!isMouseDragging || !draggingHandle || editorToolHandles->adornee.expired() || !editorToolHandles->active) return;
|
||||
|
||||
glm::vec2 destPoint = glm::vec2(evt->pos().x(), evt->pos().y());
|
||||
auto part = editorToolHandles->adornee->lock();
|
||||
auto part = editorToolHandles->adornee.lock();
|
||||
|
||||
// Calculate part pos as screen point
|
||||
glm::mat4 projection = glm::perspective(glm::radians(45.f), (float)width() / (float)height(), 0.1f, 1000.0f);
|
||||
|
@ -284,12 +284,12 @@ void MainGLWidget::handleRotationalTransform(QMouseEvent* evt) {
|
|||
|
||||
part->cframe = initialFrame * Data::CFrame::FromEulerAnglesXYZ(-angles);
|
||||
|
||||
gWorkspace()->SyncPartPhysics(std::dynamic_pointer_cast<Part>(editorToolHandles->adornee->lock()));
|
||||
sendPropertyUpdatedSignal(draggingObject->lock(), "Rotation", draggingObject->lock()->cframe.ToEulerAnglesXYZ());
|
||||
gWorkspace()->SyncPartPhysics(part);
|
||||
sendPropertyUpdatedSignal(draggingObject.lock(), "Rotation", draggingObject.lock()->cframe.ToEulerAnglesXYZ());
|
||||
}
|
||||
|
||||
std::optional<HandleFace> MainGLWidget::raycastHandle(glm::vec3 pointDir) {
|
||||
if (!editorToolHandles->adornee.has_value() || !editorToolHandles->active) return std::nullopt;
|
||||
if (editorToolHandles->adornee.expired() || !editorToolHandles->active) return std::nullopt;
|
||||
return editorToolHandles->RaycastHandle(rp3d::Ray(glmToRp(camera.cameraPos), glmToRp(glm::normalize(pointDir)) * 50000));
|
||||
}
|
||||
|
||||
|
@ -353,7 +353,7 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
|||
auto handle = raycastHandle(pointDir);
|
||||
if (handle.has_value()) {
|
||||
startPoint = glm::vec2(evt->pos().x(), evt->pos().y());
|
||||
initialFrame = editorToolHandles->adornee->lock()->cframe;
|
||||
initialFrame = editorToolHandles->adornee.lock()->cframe;
|
||||
isMouseDragging = true;
|
||||
draggingHandle = handle;
|
||||
return;
|
||||
|
@ -417,10 +417,10 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
|||
}
|
||||
|
||||
void MainGLWidget::mouseReleaseEvent(QMouseEvent* evt) {
|
||||
// if (isMouseDragging) draggingObject->lock()->rigidBody->getCollider(0)->setCollisionCategoryBits(0b11);
|
||||
// if (isMouseDragging) draggingObject.lock()->rigidBody->getCollider(0)->setCollisionCategoryBits(0b11);
|
||||
isMouseRightDragging = false;
|
||||
isMouseDragging = false;
|
||||
draggingObject = std::nullopt;
|
||||
draggingObject = {};
|
||||
draggingHandle = std::nullopt;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
|
||||
// Update handles
|
||||
addSelectionListener([&](auto oldSelection, auto newSelection, bool fromExplorer) {
|
||||
editorToolHandles->adornee = std::nullopt;
|
||||
editorToolHandles->adornee = {};
|
||||
if (newSelection.size() == 0) return;
|
||||
InstanceRef inst = newSelection[0].lock();
|
||||
if (inst->GetClass() != &Part::TYPE) return;
|
||||
|
|
|
@ -36,8 +36,8 @@ public:
|
|||
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
|
||||
if (index.column() == 0) return nullptr;
|
||||
|
||||
if (!index.parent().isValid() || !view->currentInstance || view->currentInstance->expired()) return nullptr;
|
||||
InstanceRef inst = view->currentInstance->lock();
|
||||
if (!index.parent().isValid() || view->currentInstance.expired()) return nullptr;
|
||||
InstanceRef inst = view->currentInstance.lock();
|
||||
|
||||
// If the property is deeper than 1 layer, then it is considered composite
|
||||
// Handle specially
|
||||
|
@ -105,8 +105,8 @@ public:
|
|||
void setEditorData(QWidget *editor, const QModelIndex &index) const override {
|
||||
if (index.column() == 0) return;
|
||||
|
||||
if (!index.parent().isValid() || !view->currentInstance || view->currentInstance->expired()) return;
|
||||
InstanceRef inst = view->currentInstance->lock();
|
||||
if (!index.parent().isValid() || view->currentInstance.expired()) return;
|
||||
InstanceRef inst = view->currentInstance.lock();
|
||||
|
||||
bool isComposite = index.parent().parent().isValid();
|
||||
std::string componentName = isComposite ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString() : "";
|
||||
|
@ -157,8 +157,8 @@ public:
|
|||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override {
|
||||
if (index.column() == 0) return;
|
||||
|
||||
if (!index.parent().isValid() || !view->currentInstance || view->currentInstance->expired()) return;
|
||||
InstanceRef inst = view->currentInstance->lock();
|
||||
if (!index.parent().isValid() || view->currentInstance.expired()) return;
|
||||
InstanceRef inst = view->currentInstance.lock();
|
||||
|
||||
bool isComposite = index.parent().parent().isValid();
|
||||
std::string componentName = isComposite ? view->itemFromIndex(index)->data(0, Qt::DisplayRole).toString().toStdString() : "";
|
||||
|
@ -268,6 +268,7 @@ void PropertiesView::drawBranches(QPainter *painter, const QRect &rect, const QM
|
|||
|
||||
void PropertiesView::setSelected(std::optional<InstanceRef> instance) {
|
||||
clear();
|
||||
currentInstance = {};
|
||||
if (!instance) return;
|
||||
InstanceRef inst = instance.value();
|
||||
currentInstance = inst;
|
||||
|
@ -334,8 +335,8 @@ void PropertiesView::setSelected(std::optional<InstanceRef> instance) {
|
|||
}
|
||||
|
||||
void PropertiesView::propertyChanged(QTreeWidgetItem *item, int column) {
|
||||
if (!item->parent() || (item->parent() && item->parent()->parent()) || !currentInstance || currentInstance->expired()) return;
|
||||
InstanceRef inst = currentInstance->lock();
|
||||
if (!item->parent() || (item->parent() && item->parent()->parent()) || currentInstance.expired()) return;
|
||||
InstanceRef inst = currentInstance.lock();
|
||||
|
||||
std::string propertyName = item->data(0, Qt::DisplayRole).toString().toStdString();
|
||||
PropertyMeta meta = inst->GetPropertyMeta(propertyName).expect();
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Data { class Variant; };
|
|||
class PropertiesView : public QTreeWidget {
|
||||
Q_DECLARE_PRIVATE(QTreeView)
|
||||
|
||||
std::optional<InstanceRefWeak> currentInstance;
|
||||
InstanceRefWeak currentInstance;
|
||||
void propertyChanged(QTreeWidgetItem *item, int column);
|
||||
void activateProperty(QTreeWidgetItem *item, int column);
|
||||
void rebuildCompositeProperty(QTreeWidgetItem *item, const Data::TypeInfo*, Data::Variant);
|
||||
|
|
Loading…
Add table
Reference in a new issue