diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index bb841934..c343aeba 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -3611,7 +3611,8 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) break; case LC_MODEL_PROPERTIES: - lcGetActiveModel()->ShowPropertiesDialog(); + if (ActiveModel) + ActiveModel->ShowPropertiesDialog(); break; case LC_MODEL_LIST: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 91a34e1a..70c9a42f 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1660,9 +1660,11 @@ void lcModel::GetScene(lcScene* Scene, const lcCamera* ViewCamera, bool AllowHig void lcModel::AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const { + const bool Editing = ParentActive || Scene->IsModelEditing(this); + for (const std::unique_ptr& Piece : mPieces) { - const bool Visible = ParentActive ? (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) : Piece->IsVisibleInSubModel(); + const bool Visible = Editing ? (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) : Piece->IsVisibleInSubModel(); if (Visible) { diff --git a/common/lc_scene.cpp b/common/lc_scene.cpp index 1f2ed7b3..8b551b8e 100644 --- a/common/lc_scene.cpp +++ b/common/lc_scene.cpp @@ -21,6 +21,7 @@ void lcScene::Begin(const lcMatrix44& ViewMatrix) mHighlightRenderMode = lcHighlightRenderMode::Tint; mViewMatrix = ViewMatrix; mActiveSubmodelInstance = nullptr; + mModelEditingPath.clear(); mRenderMeshes.clear(); mOpaqueMeshes.clear(); mTranslucentMeshes.clear(); diff --git a/common/lc_scene.h b/common/lc_scene.h index 6a757284..4fe13f73 100644 --- a/common/lc_scene.h +++ b/common/lc_scene.h @@ -35,10 +35,16 @@ class lcScene public: lcScene(); - void SetActiveSubmodelInstance(lcPiece* ActiveSubmodelInstance, const lcMatrix44& ActiveSubmodelTransform) + void SetActiveSubmodelInstance(lcPiece* ActiveSubmodelInstance, const lcMatrix44& ActiveSubmodelTransform, const std::vector& ModelEditingPath) { mActiveSubmodelInstance = ActiveSubmodelInstance; mActiveSubmodelTransform = ActiveSubmodelTransform; + mModelEditingPath = ModelEditingPath; + } + + bool IsModelEditing(const lcModel* Model) const + { + return mDrawInterface && mActiveSubmodelInstance && std::find(mModelEditingPath.begin(), mModelEditingPath.end(), Model) != mModelEditingPath.end(); } lcPiece* GetActiveSubmodelInstance() const @@ -165,6 +171,7 @@ protected: lcMatrix44 mViewMatrix; lcMatrix44 mActiveSubmodelTransform; lcPiece* mActiveSubmodelInstance = nullptr; + std::vector mModelEditingPath; lcShadingMode mShadingMode; bool mDrawInterface = false; lcHighlightRenderMode mHighlightRenderMode; diff --git a/common/lc_view.cpp b/common/lc_view.cpp index ecbe0037..3eea10b6 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -152,12 +152,24 @@ std::vector lcView::GetModelEditingPath() const { std::vector Models = { mModel }; - for (const std::pair& Entry : mSubmodelEditingPath) - Models.push_back(Entry.first->mPieceData->GetModel()); + for (const lcPiece* Piece : mSubmodelEditingPath) + Models.push_back(Piece->mPieceData->GetModel()); return Models; } +void lcView::RestoreModelEditingContext() +{ + mModel->SetActive(true); + mActiveSubmodelTransform = lcMatrix44Identity(); + + for (lcPiece* Piece : mSubmodelEditingPath) + { + mActiveSubmodelTransform = lcMul(Piece->mModelWorld, mActiveSubmodelTransform); + Piece->mPieceData->GetModel()->SetActive(true); + } +} + void lcView::SetSubmodelActive(size_t Depth) { if (Depth > mSubmodelEditingPath.size()) @@ -165,26 +177,22 @@ void lcView::SetSubmodelActive(size_t Depth) StopTracking(true); - lcModel* ActiveModel = GetActiveModel(); + const std::vector EditingModels = GetModelEditingPath(); - if (mActiveSubmodelInstance) - { - ActiveModel->SetActive(false); + for (size_t Index = EditingModels.size(); Index > Depth + 1; Index--) + EditingModels[Index - 1]->SetActive(false); - std::vector UpdatedModels; - ActiveModel->UpdatePieceData(UpdatedModels); - } + std::vector UpdatedModels; + for (size_t Index = EditingModels.size(); Index > Depth + 1; Index--) + EditingModels[Index - 1]->UpdatePieceData(UpdatedModels); mSubmodelEditingPath.resize(Depth); mActiveSubmodelInstance = nullptr; if (!mSubmodelEditingPath.empty()) - { - mActiveSubmodelInstance = mSubmodelEditingPath.back().first; - mActiveSubmodelTransform = mSubmodelEditingPath.back().second; - } + mActiveSubmodelInstance = mSubmodelEditingPath.back(); - GetActiveModel()->SetActive(true); + RestoreModelEditingContext(); GetActiveModel()->UpdateInterface(); } @@ -206,22 +214,13 @@ void lcView::SetSelectedSubmodelActive() if (!Piece->mPieceData->IsModel()) return; - // Preserve the selected instance path and capture its transform before SetActive(false) changes the step. - lcMatrix44 SubmodelTransform = Piece->mModelWorld; - - if (mActiveSubmodelInstance) - SubmodelTransform = lcMul(SubmodelTransform, mActiveSubmodelTransform); - - if (mActiveSubmodelInstance) - ActiveModel->SetActive(false); - - mSubmodelEditingPath.emplace_back(Piece, SubmodelTransform); - mActiveSubmodelTransform = SubmodelTransform; + // Keep ancestor models at their chosen steps so the selected instance stays in place. + mSubmodelEditingPath.push_back(Piece); mActiveSubmodelInstance = Piece; ActiveModel = mActiveSubmodelInstance->mPieceData->GetModel(); ActiveModel->SetTemporaryStep(ActiveModel->GetLastStep()); - ActiveModel->SetActive(true); + RestoreModelEditingContext(); RemoveCamera(); @@ -1048,7 +1047,7 @@ void lcView::OnDraw() mScene->Begin(mCamera->mWorldView); - mScene->SetActiveSubmodelInstance(mActiveSubmodelInstance, mActiveSubmodelTransform); + mScene->SetActiveSubmodelInstance(mActiveSubmodelInstance, mActiveSubmodelTransform, GetModelEditingPath()); mScene->SetDrawInterface(DrawInterface); bool DrawInsertPreview = DrawInterface && std::any_of(mViews.begin(), mViews.end(), [](lcView* View){ return View->mTrackTool == lcTrackTool::Insert; }); diff --git a/common/lc_view.h b/common/lc_view.h index 3f1e1ca4..69b17c57 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -236,6 +236,7 @@ public: lcModel* GetActiveModel() const; std::vector GetModelEditingPath() const; + void RestoreModelEditingContext(); void SetSubmodelActive(size_t Depth); void SetTopSubmodelActive(); void SetSelectedSubmodelActive(); @@ -395,7 +396,7 @@ protected: lcModel* mModel = nullptr; lcPiece* mActiveSubmodelInstance = nullptr; lcMatrix44 mActiveSubmodelTransform; - std::vector> mSubmodelEditingPath; + std::vector mSubmodelEditingPath; lcCamera* mCamera = nullptr; diff --git a/common/project.cpp b/common/project.cpp index 82cf5c75..1ac7e867 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -234,12 +234,13 @@ void Project::SetActiveModel(lcModel* ActiveModel, bool UpdateInterface) { gMainWindow->SetCurrentModelTab(mActiveModel, true); - // The tab may still be editing a nested submodel at its current step. - lcModel* EditingModel = gMainWindow->GetActiveModel(); - if (EditingModel) + // Restore the current steps of the editing target and its surrounding ancestors. + lcView* EditingView = gMainWindow->GetActiveView(); + + if (EditingView) { - EditingModel->SetActive(true); - EditingModel->UpdateInterface(); + EditingView->RestoreModelEditingContext(); + EditingView->GetActiveModel()->UpdateInterface(); } } }