diff --git a/core/src/partassembly.cpp b/core/src/partassembly.cpp index 32c87bb..7c3e2c8 100644 --- a/core/src/partassembly.cpp +++ b/core/src/partassembly.cpp @@ -36,15 +36,29 @@ PartAssembly::PartAssembly(std::vector> parts, bool worldM PartAssembly PartAssembly::FromSelection(std::vector> newSelection) { std::vector> selection; - for (std::weak_ptr obj : newSelection) { - if (obj.expired() || !obj.lock()->IsA()) continue; + for (std::shared_ptr obj : newSelection) { + if (!obj->IsA()) continue; - selection.push_back(obj.lock()->CastTo().expect()); + if (obj->IsA()) + selection.push_back(obj->CastTo().expect()); + + // Add object descendants + for (DescendantsIterator it = obj->GetDescendantsStart(); it != obj->GetDescendantsEnd(); it++) { + if (!(*it)->IsA()) continue; + + selection.push_back((*it)->CastTo().expect()); + } } return PartAssembly(selection, editorToolHandles.worldMode); } +void PartAssembly::SetCollisionsEnabled(bool enabled) { + for (auto part : parts) { + part->rigidBody->getCollider(0)->setIsWorldQueryCollider(enabled); + } +} + void PartAssembly::SetOrigin(CFrame newOrigin) { for (auto part : parts) { part->cframe = newOrigin * (_assemblyOrigin.Inverse() * part->cframe); diff --git a/core/src/partassembly.h b/core/src/partassembly.h index c37e80e..75be536 100644 --- a/core/src/partassembly.h +++ b/core/src/partassembly.h @@ -32,4 +32,8 @@ public: // If multiple parts are selected, finds the greatest scale factor of each component pair, and // scales it up by that amount void Scale(Vector3 newSize, bool scaleUp = true); + + // Update temporary collisions of rigidbodies. Useful for ignoring + // items for raycasts + void SetCollisionsEnabled(bool enabled); }; \ No newline at end of file diff --git a/editor/mainglwidget.cpp b/editor/mainglwidget.cpp index 95c9dc5..89d9564 100755 --- a/editor/mainglwidget.cpp +++ b/editor/mainglwidget.cpp @@ -132,10 +132,10 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { QPoint position = evt->pos(); + initialAssembly.SetCollisionsEnabled(false); glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height())); - std::optional rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000, [](std::shared_ptr part) { - return (part == draggingObject.lock()) ? FilterResult::PASS : FilterResult::TARGET; - }); + std::optional rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000); + initialAssembly.SetCollisionsEnabled(true); if (!rayHit) return; @@ -148,13 +148,13 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) { 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 - CFrame localFrame = (targetFrame.Inverse() * (draggingObject.lock()->cframe.Rotation() + vec)); + CFrame localFrame = (targetFrame.Inverse() * (initialAssembly.assemblyOrigin().Rotation() + vec)); // Snap axis localFrame = snapCFrame(localFrame); // Snap to studs - Vector3 draggingPartSize = draggingObject.lock()->size; + Vector3 draggingPartSize = initialAssembly.bounds(); glm::vec3 inverseNormalPartSize = (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 @@ -164,14 +164,9 @@ 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 - Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * draggingObject.lock()->size / 2); + Vector3 unsinkOffset = newFrame.Rotation() * ((newFrame.Rotation().Inverse() * rayHit->worldNormal) * initialAssembly.bounds() / 2); - draggingObject.lock()->cframe = newFrame + unsinkOffset; - - - gWorkspace()->SyncPartPhysics(draggingObject.lock()); - draggingObject.lock()->UpdateProperty("Position"); - sendPropertyUpdatedSignal(draggingObject.lock(), "Position", draggingObject.lock()->position()); + initialAssembly.SetOrigin(newFrame + unsinkOffset); } inline glm::vec3 vec3fy(glm::vec4 vec) { @@ -403,7 +398,8 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) { } } - initialFrame = part->cframe; + initialAssembly = PartAssembly::FromSelection({selObject}); + initialFrame = initialAssembly.assemblyOrigin(); initialHitPos = rayHit->worldPoint; initialHitNormal = rayHit->worldNormal;