From d1064ad5c11a09b5de1e077b033d80e24c918d03 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 19 Oct 2025 10:57:50 -0700 Subject: [PATCH 01/93] New undo system. --- common/lc_global.h | 2 + common/lc_model.cpp | 346 +++++++++++++++++++++++++++++++------- common/lc_model.h | 39 +++-- common/lc_modelaction.cpp | 133 +++++++++++++++ common/lc_modelaction.h | 100 +++++++++++ leocad.pro | 2 + qt/lc_qutils.h | 2 + 7 files changed, 553 insertions(+), 71 deletions(-) create mode 100644 common/lc_modelaction.cpp create mode 100644 common/lc_modelaction.h diff --git a/common/lc_global.h b/common/lc_global.h index 2d1f72e5..9146f242 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -3,6 +3,7 @@ #ifdef __cplusplus +#define QT_NO_DEPRECATED_WARNINGS #include #include #include @@ -88,6 +89,7 @@ class lcLight; enum class lcLightType; enum class lcLightAreaShape; class lcGroup; +class lcModelAction; class PieceInfo; typedef std::map> lcPartsList; struct lcModelPartsEntry; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 8995966f..dd68c180 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1,6 +1,6 @@ #include "lc_global.h" #include "lc_model.h" -#include +#include "lc_modelaction.h" #include "piece.h" #include "camera.h" #include "light.h" @@ -26,6 +26,7 @@ #include "lc_lxf.h" #include "lc_previewwidget.h" #include "lc_findreplacewidget.h" +#include void lcModelProperties::LoadDefaults() { @@ -203,7 +204,6 @@ lcModel::~lcModel() } DeleteModel(); - DeleteHistory(); } bool lcModel::GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const @@ -245,16 +245,6 @@ bool lcModel::IncludesModel(const lcModel* Model) const return false; } -void lcModel::DeleteHistory() -{ - for (lcModelHistoryEntry* Entry : mUndoHistory) - delete Entry; - mUndoHistory.clear(); - for (lcModelHistoryEntry* Entry : mRedoHistory) - delete Entry; - mRedoHistory.clear(); -} - void lcModel::DeleteModel() { if (gMainWindow) @@ -1723,8 +1713,245 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v Piece->SubModelAddBoundingBoxPoints(WorldMatrix, Points); } -void lcModel::SaveCheckpoint(const QString& Description) +void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode) { + std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode); + + ModelActionSelection->SetSelection(mPieces, mCameras, mLights); + + RunSelectionAction(ModelActionSelection.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionSelection)); +} + +void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply) +{ + if (!ModelActionSelection) + return; + + switch (ModelActionSelection->GetMode()) + { + case lcModelActionSelectionMode::Clear: + if (Apply) + { + ClearSelection(true); + } + else + { + auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetSelection(mPieces, mCameras, mLights); + + SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); + } + break; + + case lcModelActionSelectionMode::Save: + if (Apply) + { + } + else + { + auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetSelection(mPieces, mCameras, mLights); + + SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); + } + break; + } +} + +void lcModel::RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode) +{ + std::unique_ptr ModelActionAddPieces = std::make_unique(mCurrentStep, SelectionMode); + + ModelActionAddPieces->SetPieceData(PieceInfoTransforms); + + RunAddPiecesAction(ModelActionAddPieces.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionAddPieces)); +} + +void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply) +{ + if (!ModelActionAddPieces) + return; + + if (Apply) + { + std::vector Pieces; + lcStep Step = ModelActionAddPieces->GetStep(); + + for (const lcModelActionAddPieces::PieceData& PieceData : ModelActionAddPieces->GetPieceData()) + { + PieceInfo* PieceInfo = lcGetPiecesLibrary()->FindPiece(PieceData.PieceId.c_str(), nullptr, true, false); + + if (!PieceInfo) + continue; + + lcPiece* Piece = new lcPiece(PieceInfo); + + Piece->Initialize(PieceData.Transform, Step); + Piece->SetColorIndex(lcGetColorIndex(PieceData.ColorCode)); + Piece->UpdatePosition(Step); + + AddPiece(Piece); + Pieces.push_back(Piece); + } + + if (Pieces.empty()) + return; + + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateInUseCategory(); + + switch (ModelActionAddPieces->GetSelectionMode()) + { + case lcModelActionAddPieceSelectionMode::FocusLast: + ClearSelectionAndSetFocus(Pieces.back(), LC_PIECE_SECTION_POSITION, false); + UpdateTrainTrackConnections(dynamic_cast(Pieces.back()), false); + break; + + case lcModelActionAddPieceSelectionMode::SelectAll: + SetSelectionAndFocus(Pieces, nullptr, 0, false); + break; + } + } + else + { + if (RemoveSelectedObjects()) + { + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateInUseCategory(); + } + } +} + +void lcModel::RecordGroupPiecesAction(const QString& GroupName) +{ + std::unique_ptr ModelActionGroupPieces = std::make_unique(GroupName); + + RunGroupPiecesAction(ModelActionGroupPieces.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionGroupPieces)); +} + +void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply) +{ + if (!ModelActionGroupPieces) + return; + + if (Apply) + { + lcGroup* NewGroup = AddGroup(ModelActionGroupPieces->GetGroupName(), nullptr); + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsSelected()) + { + lcGroup* TopGroup = Piece->GetTopGroup(); + + if (!TopGroup) + Piece->SetGroup(NewGroup); + else if (TopGroup != NewGroup) + TopGroup->mGroup = NewGroup; + } + } + } + else + { + std::set SelectedGroups; + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsSelected()) + { + lcGroup* Group = Piece->GetTopGroup(); + + if (SelectedGroups.insert(Group).second) + { + for (std::vector>::iterator GroupIt = mGroups.begin(); GroupIt != mGroups.end(); GroupIt++) + { + if (GroupIt->get() == Group) + { + GroupIt->release(); + mGroups.erase(GroupIt); + break; + } + } + } + } + } + + for (const std::unique_ptr& Piece : mPieces) + { + lcGroup* Group = Piece->GetGroup(); + + if (SelectedGroups.find(Group) != SelectedGroups.end()) + Piece->SetGroup(nullptr); + } + + for (const std::unique_ptr& Group : mGroups) + if (SelectedGroups.find(Group->mGroup) != SelectedGroups.end()) + Group->mGroup = nullptr; + + for (lcGroup* Group : SelectedGroups) + delete Group; + + RemoveEmptyGroups(); + } +} + +void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) +{ + auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) + { + if (const lcModelActionSelection* ModelActionSelection = dynamic_cast(ModelAction)) + RunSelectionAction(ModelActionSelection, Apply); + else if (const lcModelActionAddPieces* ModelActionAddPieces = dynamic_cast(ModelAction)) + RunAddPiecesAction(ModelActionAddPieces, Apply); + else if (const lcModelActionGroupPieces* ModelActionGroupPieces = dynamic_cast(ModelAction)) + RunGroupPiecesAction(ModelActionGroupPieces, Apply); + }; + + if (Apply) + { + for (auto ModelAction = ActionSequence.begin(); ModelAction != ActionSequence.end(); ++ModelAction) + PerformAction(ModelAction->get(), true); + } + else + { + for (auto ModelAction = ActionSequence.rbegin(); ModelAction != ActionSequence.rend(); ++ModelAction) + PerformAction(ModelAction->get(), false); + } + + UpdateAllViews(); +} + +void lcModel::BeginActionSequence() +{ + mActionSequence.clear(); +} + +void lcModel::EndActionSequence(const QString& Description) +{ + std::unique_ptr ModelHistoryEntry = std::make_unique(lcModelHistoryEntry()); + + ModelHistoryEntry->Description = Description; + ModelHistoryEntry->ModelActions = std::move(mActionSequence); + + mUndoHistory.insert(mUndoHistory.begin(), std::move(ModelHistoryEntry)); + mRedoHistory.clear(); + + gMainWindow->UpdateModified(IsModified()); + gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); +} + +void lcModel::CancelActionSequence() +{ +} + +void lcModel::SaveCheckpoint(const QString& ) +{ + /* lcModelHistoryEntry* ModelHistoryEntry = new lcModelHistoryEntry(); ModelHistoryEntry->Description = Description; @@ -1742,10 +1969,18 @@ void lcModel::SaveCheckpoint(const QString& Description) gMainWindow->UpdateModified(IsModified()); gMainWindow->UpdateUndoRedo(mUndoHistory.size() > 1 ? mUndoHistory[0]->Description : QString(), !mRedoHistory.empty() ? mRedoHistory[0]->Description : QString()); } + */ } -void lcModel::LoadCheckPoint(lcModelHistoryEntry* CheckPoint) +void lcModel::LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply) { + if (!CheckPoint->ModelActions.empty()) + { + PerformActionSequence(CheckPoint->ModelActions, Apply); + + return; + } + lcPiecesLibrary* Library = lcGetPiecesLibrary(); std::vector LoadedInfos; @@ -3457,8 +3692,7 @@ void lcModel::EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept) { if (!Accept) { - if (!mUndoHistory.empty()) - LoadCheckPoint(mUndoHistory.front()); + CancelActionSequence(); return; } @@ -4494,17 +4728,18 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) void lcModel::UndoAction() { - if (mUndoHistory.size() < 2) + if (mUndoHistory.empty()) return; - lcModelHistoryEntry* Undo = mUndoHistory.front(); - mUndoHistory.erase(mUndoHistory.begin()); - mRedoHistory.insert(mRedoHistory.begin(), Undo); + std::unique_ptr Undo = std::move(mUndoHistory.front()); - LoadCheckPoint(mUndoHistory[0]); + LoadCheckPoint(Undo.get(), false); + + mUndoHistory.erase(mUndoHistory.begin()); + mRedoHistory.insert(mRedoHistory.begin(), std::move(Undo)); gMainWindow->UpdateModified(IsModified()); - gMainWindow->UpdateUndoRedo(mUndoHistory.size() > 1 ? mUndoHistory[0]->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory[0]->Description : nullptr); + gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); } void lcModel::RedoAction() @@ -4512,14 +4747,15 @@ void lcModel::RedoAction() if (mRedoHistory.empty()) return; - lcModelHistoryEntry* Redo = mRedoHistory.front(); - mRedoHistory.erase(mRedoHistory.begin()); - mUndoHistory.insert(mUndoHistory.begin(), Redo); + std::unique_ptr Redo = std::move(mRedoHistory.front()); - LoadCheckPoint(Redo); + LoadCheckPoint(Redo.get(), true); + + mRedoHistory.erase(mRedoHistory.begin()); + mUndoHistory.insert(mUndoHistory.begin(), std::move(Redo)); gMainWindow->UpdateModified(IsModified()); - gMainWindow->UpdateUndoRedo(mUndoHistory.size() > 1 ? mUndoHistory[0]->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory[0]->Description : nullptr); + gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); } void lcModel::BeginMouseTool() @@ -4532,8 +4768,7 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) { if (!Accept) { - if (!mUndoHistory.empty()) - LoadCheckPoint(mUndoHistory.front()); + CancelActionSequence(); return; } @@ -4596,26 +4831,16 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) void lcModel::InsertPieceToolClicked(const std::vector& PieceInfoTransforms) { - lcPiece* Piece = nullptr; - - for (const lcInsertPieceInfo& PieceInfoTransform : PieceInfoTransforms) - { - Piece = new lcPiece(PieceInfoTransform.Info); - Piece->Initialize(PieceInfoTransform.Transform, mCurrentStep); - Piece->SetColorIndex(PieceInfoTransform.ColorIndex); - Piece->UpdatePosition(mCurrentStep); - AddPiece(Piece); - } - - if (!Piece) + if (PieceInfoTransforms.empty()) return; - gMainWindow->UpdateTimeline(false, false); - ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, false); + BeginActionSequence(); - UpdateTrainTrackConnections(Piece, false); + RecordSelectionAction(lcModelActionSelectionMode::Save); + RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::FocusLast); + RecordSelectionAction(lcModelActionSelectionMode::Save); - SaveCheckpoint(tr("Insert")); + EndActionSequence(tr("Add Piece")); } void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType) @@ -5109,30 +5334,29 @@ void lcModel::ShowMinifigDialog() gMainWindow->GetActiveView()->MakeCurrent(); - lcGroup* Group = AddGroup(tr("Minifig #"), nullptr); - std::vector Pieces; - Pieces.reserve(LC_MFW_NUMITEMS); + std::vector PieceInfoTransforms; lcMinifig& Minifig = Dialog.mMinifigWizard->mMinifig; - for (int PartIdx = 0; PartIdx < LC_MFW_NUMITEMS; PartIdx++) + for (int PartIndex = 0; PartIndex < LC_MFW_NUMITEMS; PartIndex++) { - if (Minifig.Parts[PartIdx] == nullptr) + if (!Minifig.Parts[PartIndex]) continue; - lcPiece* Piece = new lcPiece(Minifig.Parts[PartIdx]); + lcInsertPieceInfo& InsertPieceInfo = PieceInfoTransforms.emplace_back(); - Piece->Initialize(Minifig.Matrices[PartIdx], mCurrentStep); - Piece->SetColorIndex(Minifig.ColorIndices[PartIdx]); - Piece->SetGroup(Group); - AddPiece(Piece); - Piece->UpdatePosition(mCurrentStep); - - Pieces.emplace_back(Piece); + InsertPieceInfo.Info = Minifig.Parts[PartIndex]; + InsertPieceInfo.Transform = Minifig.Matrices[PartIndex]; + InsertPieceInfo.ColorIndex = Minifig.ColorIndices[PartIndex]; } - SetSelectionAndFocus(Pieces, nullptr, 0, false); - gMainWindow->UpdateTimeline(false, false); - SaveCheckpoint(tr("Minifig")); + BeginActionSequence(); + + RecordSelectionAction(lcModelActionSelectionMode::Save); + RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::SelectAll); + RecordGroupPiecesAction(tr("Minifig #")); + RecordSelectionAction(lcModelActionSelectionMode::Save); + + EndActionSequence(tr("Add Minifig")); } void lcModel::SetMinifig(const lcMinifig& Minifig) diff --git a/common/lc_model.h b/common/lc_model.h index a81ee024..6a33269d 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -4,6 +4,12 @@ #include "lc_commands.h" enum class lcObjectPropertyId; +class lcModelAction; +class lcModelActionSelection; +class lcModelActionAddPieces; +class lcModelActionGroupPieces; +enum class lcModelActionSelectionMode; +enum class lcModelActionAddPieceSelectionMode; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -99,6 +105,7 @@ public: struct lcModelHistoryEntry { + std::vector> ModelActions; QByteArray File; QString Description; }; @@ -121,7 +128,10 @@ public: bool IsModified() const { - return mSavedHistory != mUndoHistory[0]; + if (mUndoHistory.empty()) + return mSavedHistory != nullptr; + else + return mSavedHistory != mUndoHistory.front().get(); } bool IsActive() const @@ -253,11 +263,7 @@ public: void SetSaved() { - if (mUndoHistory.empty()) - SaveCheckpoint(QString()); - - if (!mIsPreview) - mSavedHistory = mUndoHistory[0]; + mSavedHistory = mUndoHistory.empty() ? nullptr : mUndoHistory.front().get(); } void SetMinifig(const lcMinifig& Minifig); @@ -392,9 +398,21 @@ public: protected: void DeleteModel(); - void DeleteHistory(); + + void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode); + void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); + void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); + void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); + void RecordGroupPiecesAction(const QString& GroupName); + void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); + + void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); + void BeginActionSequence(); + void EndActionSequence(const QString& Description); + void CancelActionSequence(); + void SaveCheckpoint(const QString& Description); - void LoadCheckPoint(lcModelHistoryEntry* CheckPoint); + void LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply); QString GetGroupName(const QString& Prefix); void RemoveEmptyGroups(); @@ -422,9 +440,10 @@ protected: std::vector> mGroups; QStringList mFileLines; + std::vector> mActionSequence; lcModelHistoryEntry* mSavedHistory; - std::vector mUndoHistory; - std::vector mRedoHistory; + std::vector> mUndoHistory; + std::vector> mRedoHistory; Q_DECLARE_TR_FUNCTIONS(lcModel); }; diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp new file mode 100644 index 00000000..e4da549b --- /dev/null +++ b/common/lc_modelaction.cpp @@ -0,0 +1,133 @@ +#include "lc_global.h" +#include "lc_modelaction.h" +#include "lc_model.h" +#include "piece.h" +#include "camera.h" +#include "light.h" +#include "pieceinf.h" +#include "lc_colors.h" + +lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode) + : mMode(Mode) +{ +} + +void lcModelActionSelection::SetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) +{ + mSelectedPieces.clear(); + mSelectedCameras.clear(); + mSelectedLights.clear(); + + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + { + lcPiece* Piece = Pieces[PieceIndex].get(); + + if (!Piece->IsSelected()) + continue; + + mSelectedPieces.push_back(PieceIndex); + + if (Piece->IsFocused()) + { + mFocusIndex = PieceIndex; + mFocusSection = Piece->GetFocusSection(); + mFocusType = lcObjectType::Piece; + } + } + + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + { + lcCamera* Camera = Cameras[CameraIndex].get(); + + if (!Camera->IsSelected()) + continue; + + mSelectedCameras.push_back(CameraIndex); + + if (Camera->IsFocused()) + { + mFocusIndex = CameraIndex; + mFocusSection = Camera->GetFocusSection(); + mFocusType = lcObjectType::Camera; + } + } + + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + { + lcLight* Light = Lights[LightIndex].get(); + + if (!Light->IsSelected()) + continue; + + if (Light->IsFocused()) + { + mFocusIndex = LightIndex; + mFocusSection = Light->GetFocusSection(); + mFocusType = lcObjectType::Light; + } + } +} + +std::tuple, lcObject*, uint32_t> lcModelActionSelection::GetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) const +{ + std::vector SelectedObjects; + lcObject* FocusObject = nullptr; + + for (size_t PieceIndex : mSelectedPieces) + if (PieceIndex < Pieces.size()) + SelectedObjects.push_back(Pieces[PieceIndex].get()); + + for (size_t CameraIndex : mSelectedCameras) + if (CameraIndex < Cameras.size()) + SelectedObjects.push_back(Cameras[CameraIndex].get()); + + for (size_t LightIndex : mSelectedLights) + if (LightIndex < Lights.size()) + SelectedObjects.push_back(Lights[LightIndex].get()); + + if (mFocusIndex != SIZE_MAX) + { + switch (mFocusType) + { + case lcObjectType::Piece: + if (mFocusIndex < Pieces.size()) + FocusObject = Pieces[mFocusIndex].get(); + break; + case lcObjectType::Camera: + if (mFocusIndex < Cameras.size()) + FocusObject = Cameras[mFocusIndex].get(); + break; + case lcObjectType::Light: + if (mFocusIndex < Lights.size()) + FocusObject = Lights[mFocusIndex].get(); + break; + } + } + + return { SelectedObjects, FocusObject, mFocusSection }; +} + +lcModelActionAddPieces::lcModelActionAddPieces(lcStep Step, lcModelActionAddPieceSelectionMode SelectionMode) + : mStep(Step), mSelectionMode(SelectionMode) +{ +} + +void lcModelActionAddPieces::SetPieceData(const std::vector& PieceInfoTransforms) +{ + mPieceData.clear(); + mPieceData.reserve(PieceInfoTransforms.size()); + + for (const lcInsertPieceInfo& PieceInfoTransform : PieceInfoTransforms) + { + lcModelActionAddPieces::PieceData& PieceData = mPieceData.emplace_back(); + + PieceData.PieceId = PieceInfoTransform.Info->mFileName; + PieceData.Transform = PieceInfoTransform.Transform; + PieceData.ColorCode = lcGetColorCode(PieceInfoTransform.ColorIndex); + } +} + +lcModelActionGroupPieces::lcModelActionGroupPieces(const QString& GroupName) + : mGroupName(GroupName) +{ +} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h new file mode 100644 index 00000000..8003d377 --- /dev/null +++ b/common/lc_modelaction.h @@ -0,0 +1,100 @@ +#pragma once + +#include "lc_math.h" + +struct lcInsertPieceInfo; +enum class lcObjectType; + +class lcModelAction +{ +public: + lcModelAction() = default; + virtual ~lcModelAction() = default; +}; + +enum class lcModelActionSelectionMode +{ + Clear, + Save +}; + +class lcModelActionSelection : public lcModelAction +{ +public: + lcModelActionSelection(lcModelActionSelectionMode Mode); + virtual ~lcModelActionSelection() = default; + + lcModelActionSelectionMode GetMode() const + { + return mMode; + } + + void SetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights); + std::tuple, lcObject*, uint32_t> GetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) const; + +protected: + std::vector mSelectedPieces; + std::vector mSelectedCameras; + std::vector mSelectedLights; + size_t mFocusIndex = SIZE_MAX; + uint32_t mFocusSection = 0; + lcObjectType mFocusType = (lcObjectType)0; + lcModelActionSelectionMode mMode = lcModelActionSelectionMode::Clear; +}; + +enum class lcModelActionAddPieceSelectionMode +{ + FocusLast, + SelectAll +}; + +class lcModelActionAddPieces : public lcModelAction +{ +public: + lcModelActionAddPieces(lcStep Step, lcModelActionAddPieceSelectionMode SelectionMode); + virtual ~lcModelActionAddPieces() = default; + + struct PieceData + { + std::string PieceId; + lcMatrix44 Transform; + quint32 ColorCode; + }; + + void SetPieceData(const std::vector& PieceInfoTransforms); + + const std::vector& GetPieceData() const + { + return mPieceData; + } + + lcStep GetStep() const + { + return mStep; + } + + lcModelActionAddPieceSelectionMode GetSelectionMode() const + { + return mSelectionMode; + } + +protected: + std::vector mPieceData; + lcStep mStep; + lcModelActionAddPieceSelectionMode mSelectionMode; +}; + +class lcModelActionGroupPieces : public lcModelAction +{ +public: + lcModelActionGroupPieces(const QString& GroupName); + virtual ~lcModelActionGroupPieces() = default; + + const QString& GetGroupName() const + { + return mGroupName; + } + +protected: + QString mGroupName; +}; diff --git a/leocad.pro b/leocad.pro index c23bb676..adabb7da 100644 --- a/leocad.pro +++ b/leocad.pro @@ -207,6 +207,7 @@ SOURCES += \ common/lc_meshloader.cpp \ common/lc_minifigdialog.cpp \ common/lc_model.cpp \ + common/lc_modelaction.cpp \ common/lc_modellistdialog.cpp \ common/lc_objectproperty.cpp \ common/lc_pagesetupdialog.cpp \ @@ -286,6 +287,7 @@ HEADERS += \ common/lc_meshloader.h \ common/lc_minifigdialog.h \ common/lc_model.h \ + common/lc_modelaction.h \ common/lc_modellistdialog.h \ common/lc_objectproperty.h \ common/lc_pagesetupdialog.h \ diff --git a/qt/lc_qutils.h b/qt/lc_qutils.h index 3383e1ee..5e7716a2 100644 --- a/qt/lc_qutils.h +++ b/qt/lc_qutils.h @@ -12,6 +12,8 @@ float lcParseValueLocalized(const QString& Value); #ifdef Q_OS_WIN +#include + int lcTerminateChildProcess(QWidget* Parent, const qint64 Pid, const qint64 Ppid); bool lcRunElevatedProcess(const LPCWSTR ExeName, const LPCWSTR Arguments, const LPCWSTR WorkingFolder); From ecc994d569ee349cce951af0b1e2e1e900ce2186 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 26 Oct 2025 10:56:55 -0700 Subject: [PATCH 02/93] Added group/ungroup actions. --- common/lc_model.cpp | 108 +++++++++++++------------------------- common/lc_model.h | 3 +- common/lc_modelaction.cpp | 4 +- common/lc_modelaction.h | 17 +++++- 4 files changed, 55 insertions(+), 77 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index dd68c180..2756d225 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1729,31 +1729,30 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect if (!ModelActionSelection) return; + auto LoadSelection = [this, ModelActionSelection]() + { + auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetSelection(mPieces, mCameras, mLights); + + SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); + }; + switch (ModelActionSelection->GetMode()) { case lcModelActionSelectionMode::Clear: if (Apply) - { ClearSelection(true); - } else - { - auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetSelection(mPieces, mCameras, mLights); - - SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); - } + LoadSelection(); break; case lcModelActionSelectionMode::Save: - if (Apply) - { - } - else - { - auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetSelection(mPieces, mCameras, mLights); + if (!Apply) + LoadSelection(); + break; - SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); - } + case lcModelActionSelectionMode::Restore: + if (Apply) + LoadSelection(); break; } } @@ -1825,9 +1824,9 @@ void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPie } } -void lcModel::RecordGroupPiecesAction(const QString& GroupName) +void lcModel::RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName) { - std::unique_ptr ModelActionGroupPieces = std::make_unique(GroupName); + std::unique_ptr ModelActionGroupPieces = std::make_unique(Mode, GroupName); RunGroupPiecesAction(ModelActionGroupPieces.get(), true); @@ -1839,9 +1838,13 @@ void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGr if (!ModelActionGroupPieces) return; - if (Apply) + if (Apply == (ModelActionGroupPieces->GetMode() == lcModelActionGroupPiecesMode::Group)) { - lcGroup* NewGroup = AddGroup(ModelActionGroupPieces->GetGroupName(), nullptr); + lcGroup* NewGroup = new lcGroup(); + mGroups.emplace_back(NewGroup); + + NewGroup->mName = ModelActionGroupPieces->GetGroupName(); + NewGroup->mGroup = nullptr; for (const std::unique_ptr& Piece : mPieces) { @@ -1898,6 +1901,8 @@ void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGr RemoveEmptyGroups(); } + + gMainWindow->UpdateSelectedObjects(true); } void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) @@ -2201,69 +2206,28 @@ void lcModel::GroupSelection() } lcGroupDialog Dialog(gMainWindow, GetGroupName(tr("Group #"))); + if (Dialog.exec() != QDialog::Accepted) return; - lcGroup* NewGroup = GetGroup(Dialog.mName, true); + BeginActionSequence(); - for (const std::unique_ptr& Piece : mPieces) - { - if (Piece->IsSelected()) - { - lcGroup* Group = Piece->GetTopGroup(); + RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, Dialog.mName); + RecordSelectionAction(lcModelActionSelectionMode::Save); - if (!Group) - Piece->SetGroup(NewGroup); - else if (Group != NewGroup) - Group->mGroup = NewGroup; - } - } - - SaveCheckpoint(tr("Grouping")); + EndActionSequence(tr("Group")); } void lcModel::UngroupSelection() { - std::set SelectedGroups; + BeginActionSequence(); - for (const std::unique_ptr& Piece : mPieces) - { - if (Piece->IsSelected()) - { - lcGroup* Group = Piece->GetTopGroup(); + RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Ungroup, QString()); + RecordSelectionAction(lcModelActionSelectionMode::Save); - if (SelectedGroups.insert(Group).second) - { - for (std::vector>::iterator GroupIt = mGroups.begin(); GroupIt != mGroups.end(); GroupIt++) - { - if (GroupIt->get() == Group) - { - GroupIt->release(); - mGroups.erase(GroupIt); - break; - } - } - } - } - } - - for (const std::unique_ptr& Piece : mPieces) - { - lcGroup* Group = Piece->GetGroup(); - - if (SelectedGroups.find(Group) != SelectedGroups.end()) - Piece->SetGroup(nullptr); - } - - for (const std::unique_ptr& Group : mGroups) - if (SelectedGroups.find(Group->mGroup) != SelectedGroups.end()) - Group->mGroup = nullptr; - - for (lcGroup* Group : SelectedGroups) - delete Group; - - RemoveEmptyGroups(); - SaveCheckpoint(tr("Ungrouping")); + EndActionSequence(tr("Ungroup")); } void lcModel::AddSelectedPiecesToGroup() @@ -5353,7 +5317,7 @@ void lcModel::ShowMinifigDialog() RecordSelectionAction(lcModelActionSelectionMode::Save); RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::SelectAll); - RecordGroupPiecesAction(tr("Minifig #")); + RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, GetGroupName(tr("Minifig #"))); RecordSelectionAction(lcModelActionSelectionMode::Save); EndActionSequence(tr("Add Minifig")); diff --git a/common/lc_model.h b/common/lc_model.h index 6a33269d..edbf6344 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -10,6 +10,7 @@ class lcModelActionAddPieces; class lcModelActionGroupPieces; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; +enum class lcModelActionGroupPiecesMode; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -403,7 +404,7 @@ protected: void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); - void RecordGroupPiecesAction(const QString& GroupName); + void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index e4da549b..33740a74 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -127,7 +127,7 @@ void lcModelActionAddPieces::SetPieceData(const std::vector& } } -lcModelActionGroupPieces::lcModelActionGroupPieces(const QString& GroupName) - : mGroupName(GroupName) +lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName) + : mMode(Mode), mGroupName(GroupName) { } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 8003d377..be718346 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -15,7 +15,8 @@ public: enum class lcModelActionSelectionMode { Clear, - Save + Save, + Restore }; class lcModelActionSelection : public lcModelAction @@ -84,17 +85,29 @@ protected: lcModelActionAddPieceSelectionMode mSelectionMode; }; +enum class lcModelActionGroupPiecesMode +{ + Group, + Ungroup +}; + class lcModelActionGroupPieces : public lcModelAction { public: - lcModelActionGroupPieces(const QString& GroupName); + lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName); virtual ~lcModelActionGroupPieces() = default; + lcModelActionGroupPiecesMode GetMode() const + { + return mMode; + } + const QString& GetGroupName() const { return mGroupName; } protected: + lcModelActionGroupPiecesMode mMode; QString mGroupName; }; From 5718cb7e7b11ca7fd738590e1f6349f360ba99de Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 30 Oct 2025 16:02:39 -0700 Subject: [PATCH 03/93] Added duplicate piece action. --- common/lc_model.cpp | 194 ++++++++++++++++++++++++++-------------- common/lc_model.h | 4 +- common/lc_modelaction.h | 5 ++ 3 files changed, 133 insertions(+), 70 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2756d225..a3a0b3b8 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1234,66 +1234,19 @@ void lcModel::Paste(bool PasteToCurrentStep) void lcModel::DuplicateSelectedPieces() { - std::vector NewPieces; - lcPiece* Focus = nullptr; - std::map GroupMap; - - std::function GetNewGroup = [this, &GroupMap, &GetNewGroup](lcGroup* Group) + if (!AnyPiecesSelected()) { - const auto GroupIt = GroupMap.find(Group); - if (GroupIt != GroupMap.end()) - return GroupIt->second; - else - { - lcGroup* Parent = Group->mGroup ? GetNewGroup(Group->mGroup) : nullptr; - QString GroupName = Group->mName; - - while (!GroupName.isEmpty()) - { - const QChar Last = GroupName[GroupName.size() - 1]; - if (Last.isDigit()) - GroupName.chop(1); - else - break; - } - - if (GroupName.isEmpty()) - GroupName = Group->mName; - - lcGroup* NewGroup = AddGroup(GroupName, Parent); - GroupMap[Group] = NewGroup; - return NewGroup; - } - }; - - for (size_t PieceIdx = 0; PieceIdx < mPieces.size(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx].get(); - - if (!Piece->IsSelected()) - continue; - - lcPiece* NewPiece = new lcPiece(*Piece); - NewPiece->UpdatePosition(mCurrentStep); - NewPieces.emplace_back(NewPiece); - - if (Piece->IsFocused()) - Focus = NewPiece; - - PieceIdx++; - InsertPiece(NewPiece, PieceIdx); - - lcGroup* Group = Piece->GetGroup(); - if (Group) - Piece->SetGroup(GetNewGroup(Group)); + QMessageBox::information(gMainWindow, tr("Duplicate Pieces"), tr("No pieces selected.")); + return; } - if (NewPieces.empty()) - return; + BeginActionSequence(); - gMainWindow->UpdateTimeline(false, false); - SetSelectionAndFocus(NewPieces, Focus, LC_PIECE_SECTION_POSITION, false); - SaveCheckpoint(tr("Duplicating Pieces")); + RecordSelectionAction(lcModelActionSelectionMode::Set); + RecordDuplicatePiecesAction(); + RecordSelectionAction(lcModelActionSelectionMode::Save); + + EndActionSequence(tr("Duplicate")); } void lcModel::PaintSelectedPieces() @@ -1745,6 +1698,10 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect LoadSelection(); break; + case lcModelActionSelectionMode::Set: + LoadSelection(); + break; + case lcModelActionSelectionMode::Save: if (!Apply) LoadSelection(); @@ -1905,6 +1862,90 @@ void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGr gMainWindow->UpdateSelectedObjects(true); } +void lcModel::RecordDuplicatePiecesAction() +{ + std::unique_ptr ModelActionDuplicatePieces = std::make_unique(); + + RunDuplicatePiecesAction(ModelActionDuplicatePieces.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionDuplicatePieces)); +} + +void lcModel::RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply) +{ + if (!ModelActionDuplicatePieces) + return; + + if (Apply) + { + std::vector NewPieces; + lcPiece* Focus = nullptr; + std::map GroupMap; + + std::function GetNewGroup = [this, &GroupMap, &GetNewGroup](lcGroup* Group) + { + const auto GroupIt = GroupMap.find(Group); + + if (GroupIt != GroupMap.end()) + return GroupIt->second; + else + { + lcGroup* Parent = Group->mGroup ? GetNewGroup(Group->mGroup) : nullptr; + QString GroupName = Group->mName; + + while (!GroupName.isEmpty()) + { + const QChar Last = GroupName[GroupName.size() - 1]; + if (Last.isDigit()) + GroupName.chop(1); + else + break; + } + + if (GroupName.isEmpty()) + GroupName = Group->mName; + + lcGroup* NewGroup = AddGroup(GroupName, Parent); + GroupMap[Group] = NewGroup; + return NewGroup; + } + }; + + for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) + { + lcPiece* Piece = mPieces[PieceIndex].get(); + + if (!Piece->IsSelected()) + continue; + + lcPiece* NewPiece = new lcPiece(*Piece); + NewPiece->UpdatePosition(mCurrentStep); + NewPieces.emplace_back(NewPiece); + + if (Piece->IsFocused()) + Focus = NewPiece; + + PieceIndex++; + InsertPiece(NewPiece, PieceIndex); + + lcGroup* Group = Piece->GetGroup(); + if (Group) + Piece->SetGroup(GetNewGroup(Group)); + } + + gMainWindow->UpdateTimeline(false, false); + SetSelectionAndFocus(NewPieces, Focus, LC_PIECE_SECTION_POSITION, false); + } + else + { + if (RemoveSelectedObjects()) + { + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateSelectedObjects(true); + } + } +} + void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) { auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) @@ -1915,6 +1956,8 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunGroupPiecesAction(ModelActionGroupPieces, Apply); + else if (const lcModelActionDuplicatePieces* ModelActionDuplicatePieces = dynamic_cast(ModelAction)) + RunDuplicatePiecesAction(ModelActionDuplicatePieces, Apply); }; if (Apply) @@ -2201,7 +2244,7 @@ void lcModel::GroupSelection() { if (!AnyPiecesSelected()) { - QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("No pieces selected.")); + QMessageBox::information(gMainWindow, tr("Group Selection"), tr("No pieces selected.")); return; } @@ -2221,6 +2264,29 @@ void lcModel::GroupSelection() void lcModel::UngroupSelection() { + if (!AnyPiecesSelected()) + { + QMessageBox::information(gMainWindow, tr("Ungroup Selection"), tr("No pieces selected.")); + return; + } + + bool FoundGroup = false; + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsSelected() && Piece->GetGroup()) + { + FoundGroup = true; + break; + } + } + + if (!FoundGroup) + { + QMessageBox::information(gMainWindow, tr("Ungroup Selection"), tr("No groups selected.")); + return; + } + BeginActionSequence(); RecordSelectionAction(lcModelActionSelectionMode::Restore); @@ -2758,18 +2824,6 @@ void lcModel::UpdateSelectedPiecesTrainTrackConnections() } } -void lcModel::DeleteAllCameras() -{ - if (mCameras.empty()) - return; - - mCameras.clear(); - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - SaveCheckpoint(tr("Resetting Cameras")); -} - void lcModel::DeleteSelectedObjects() { if (RemoveSelectedObjects()) @@ -2793,6 +2847,8 @@ void lcModel::ResetSelectedPiecesPivotPoint() Piece->ResetPivotPoint(); UpdateAllViews(); + + SaveCheckpoint(tr("Resetting Pivot Point")); } void lcModel::RemoveSelectedPiecesKeyFrames() diff --git a/common/lc_model.h b/common/lc_model.h index edbf6344..871da606 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -8,6 +8,7 @@ class lcModelAction; class lcModelActionSelection; class lcModelActionAddPieces; class lcModelActionGroupPieces; +class lcModelActionDuplicatePieces; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; enum class lcModelActionGroupPiecesMode; @@ -228,7 +229,6 @@ public: void RemoveStep(lcStep Step); lcPiece* AddPiece(PieceInfo* Info, quint32 Section); - void DeleteAllCameras(); void DeleteSelectedObjects(); void ResetSelectedPiecesPivotPoint(); void RemoveSelectedPiecesKeyFrames(); @@ -406,6 +406,8 @@ protected: void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); + void RecordDuplicatePiecesAction(); + void RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply); void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index be718346..774b05f7 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -15,6 +15,7 @@ public: enum class lcModelActionSelectionMode { Clear, + Set, Save, Restore }; @@ -111,3 +112,7 @@ protected: lcModelActionGroupPiecesMode mMode; QString mGroupName; }; + +class lcModelActionDuplicatePieces : public lcModelAction +{ +}; From 1469861e4532ae9edc660249d40be8d230466fff Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 30 Oct 2025 17:53:27 -0700 Subject: [PATCH 04/93] Added hide/unhide actions. --- common/lc_model.cpp | 156 +++++++++++++++++++++++++++----------- common/lc_model.h | 4 + common/lc_modelaction.cpp | 13 ++++ common/lc_modelaction.h | 31 ++++++++ 4 files changed, 158 insertions(+), 46 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index a3a0b3b8..f2fcbb46 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1946,6 +1946,71 @@ void lcModel::RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* Model } } +void lcModel::RecordHidePiecesAction(lcModelActionHidePiecesMode Mode) +{ + std::unique_ptr ModelActionHidePieces = std::make_unique(Mode); + + ModelActionHidePieces->SaveHiddenState(mPieces); + + RunHidePiecesAction(ModelActionHidePieces.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionHidePieces)); +} + +void lcModel::RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHidePieces, bool Apply) +{ + if (!ModelActionHidePieces) + return; + + if (Apply) + { + switch (ModelActionHidePieces->GetMode()) + { + case lcModelActionHidePiecesMode::HideSelected: + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsSelected()) + { + Piece->SetHidden(true); + Piece->SetSelected(false); + } + } + break; + + case lcModelActionHidePiecesMode::HideUnselected: + for (const std::unique_ptr& Piece : mPieces) + if (!Piece->IsSelected() && !Piece->IsHidden()) + Piece->SetHidden(true); + break; + + case lcModelActionHidePiecesMode::UnhideSelected: + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsSelected() && Piece->IsHidden()) + Piece->SetHidden(false); + break; + + case lcModelActionHidePiecesMode::UnhideAll: + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsHidden()) + Piece->SetHidden(false); + break; + } + + gMainWindow->UpdateTimeline(false, true); + gMainWindow->UpdateSelectedObjects(true); + } + else + { + const std::vector& HiddenState = ModelActionHidePieces->GetHiddenState(); + + if (mPieces.size() != HiddenState.size()) + return; + + for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) + mPieces[PieceIndex]->SetHidden(HiddenState[PieceIndex]); + } +} + void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) { auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) @@ -1958,6 +2023,8 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunDuplicatePiecesAction(ModelActionDuplicatePieces, Apply); + else if (const lcModelActionHidePieces* ModelActionHidePieces = dynamic_cast(ModelAction)) + RunHidePiecesAction(ModelActionHidePieces, Apply); }; if (Apply) @@ -4536,95 +4603,92 @@ void lcModel::InvertSelection() void lcModel::HideSelectedPieces() { - bool Modified = false; - - for (const std::unique_ptr& Piece : mPieces) + if (!AnyPiecesSelected()) { - if (Piece->IsSelected()) - { - Piece->SetHidden(true); - Piece->SetSelected(false); - Modified = true; - } + QMessageBox::information(gMainWindow, tr("Hide Pieces"), tr("No pieces selected.")); + return; } - if (!Modified) - return; + BeginActionSequence(); - gMainWindow->UpdateTimeline(false, true); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); + RecordSelectionAction(lcModelActionSelectionMode::Set); + RecordHidePiecesAction(lcModelActionHidePiecesMode::HideSelected); + RecordSelectionAction(lcModelActionSelectionMode::Save); - SaveCheckpoint(tr("Hide")); + EndActionSequence(tr("Hide Pieces")); } void lcModel::HideUnselectedPieces() { - bool Modified = false; + bool HasHidden = false; for (const std::unique_ptr& Piece : mPieces) { - if (!Piece->IsSelected()) + if (!Piece->IsSelected() && !Piece->IsHidden()) { - Piece->SetHidden(true); - Modified = true; + HasHidden = true; + break; } } - if (!Modified) + if (!HasHidden) + { + QMessageBox::information(gMainWindow, tr("Hide Unselected Pieces"), tr("No unselected pieces are hidden.")); return; + } - gMainWindow->UpdateTimeline(false, true); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); + BeginActionSequence(); - SaveCheckpoint(tr("Hide")); + RecordSelectionAction(lcModelActionSelectionMode::Set); + RecordHidePiecesAction(lcModelActionHidePiecesMode::HideUnselected); + RecordSelectionAction(lcModelActionSelectionMode::Save); + + EndActionSequence(tr("Hide Pieces")); } void lcModel::UnhideSelectedPieces() { - bool Modified = false; - - for (const std::unique_ptr& Piece : mPieces) + if (!AnyPiecesSelected()) { - if (Piece->IsSelected() && Piece->IsHidden()) - { - Piece->SetHidden(false); - Modified = true; - } + QMessageBox::information(gMainWindow, tr("Unhide Pieces"), tr("No pieces selected.")); + return; } - if (!Modified) - return; + BeginActionSequence(); - gMainWindow->UpdateTimeline(false, true); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); + RecordSelectionAction(lcModelActionSelectionMode::Set); + RecordHidePiecesAction(lcModelActionHidePiecesMode::UnhideSelected); + RecordSelectionAction(lcModelActionSelectionMode::Save); - SaveCheckpoint(tr("Unhide")); + EndActionSequence(tr("Unhide Pieces")); } void lcModel::UnhideAllPieces() { - bool Modified = false; + bool HasHidden = false; for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsHidden()) { - Piece->SetHidden(false); - Modified = true; + HasHidden = true; + break; } } - if (!Modified) + if (!HasHidden) + { + QMessageBox::information(gMainWindow, tr("Unhide All Pieces"), tr("No pieces are hidden.")); return; + } - gMainWindow->UpdateTimeline(false, true); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); + BeginActionSequence(); - SaveCheckpoint(tr("Unhide")); + RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordHidePiecesAction(lcModelActionHidePiecesMode::UnhideAll); + RecordSelectionAction(lcModelActionSelectionMode::Save); + + EndActionSequence(tr("Unhide All Pieces")); } void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) diff --git a/common/lc_model.h b/common/lc_model.h index 871da606..8a7e40f6 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -9,9 +9,11 @@ class lcModelActionSelection; class lcModelActionAddPieces; class lcModelActionGroupPieces; class lcModelActionDuplicatePieces; +class lcModelActionHidePieces; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; enum class lcModelActionGroupPiecesMode; +enum class lcModelActionHidePiecesMode; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -408,6 +410,8 @@ protected: void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); void RecordDuplicatePiecesAction(); void RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply); + void RecordHidePiecesAction(lcModelActionHidePiecesMode Mode); + void RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHidePieces, bool Apply); void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 33740a74..5baa2dc8 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -131,3 +131,16 @@ lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode : mMode(Mode), mGroupName(GroupName) { } + +lcModelActionHidePieces::lcModelActionHidePieces(lcModelActionHidePiecesMode Mode) + : mMode(Mode) +{ +} + +void lcModelActionHidePieces::SaveHiddenState(const std::vector>& Pieces) +{ + mHiddenState.resize(Pieces.size()); + + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + mHiddenState[PieceIndex] = Pieces[PieceIndex]->IsHidden(); +} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 774b05f7..2687ee15 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -116,3 +116,34 @@ protected: class lcModelActionDuplicatePieces : public lcModelAction { }; + +enum class lcModelActionHidePiecesMode +{ + HideSelected, + HideUnselected, + UnhideSelected, + UnhideAll +}; + +class lcModelActionHidePieces : public lcModelAction +{ +public: + lcModelActionHidePieces(lcModelActionHidePiecesMode Mode); + virtual ~lcModelActionHidePieces() = default; + + lcModelActionHidePiecesMode GetMode() const + { + return mMode; + } + + const std::vector& GetHiddenState() const + { + return mHiddenState; + } + + void SaveHiddenState(const std::vector>& Pieces); + +protected: + std::vector mHiddenState; + lcModelActionHidePiecesMode mMode; +}; From 051d375a4f48ef92fae063d2b4cd8f03ee5ec588 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 30 Oct 2025 17:58:13 -0700 Subject: [PATCH 05/93] Fixed duplicate action using the current step in redo. --- common/lc_model.cpp | 7 ++++--- common/lc_modelaction.cpp | 5 +++++ common/lc_modelaction.h | 11 +++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index f2fcbb46..429d3f34 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1733,7 +1733,7 @@ void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPie if (Apply) { std::vector Pieces; - lcStep Step = ModelActionAddPieces->GetStep(); + lcStep Step = ModelActionAddPieces->GetStep(); for (const lcModelActionAddPieces::PieceData& PieceData : ModelActionAddPieces->GetPieceData()) { @@ -1864,7 +1864,7 @@ void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGr void lcModel::RecordDuplicatePiecesAction() { - std::unique_ptr ModelActionDuplicatePieces = std::make_unique(); + std::unique_ptr ModelActionDuplicatePieces = std::make_unique(mCurrentStep); RunDuplicatePiecesAction(ModelActionDuplicatePieces.get(), true); @@ -1881,6 +1881,7 @@ void lcModel::RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* Model std::vector NewPieces; lcPiece* Focus = nullptr; std::map GroupMap; + lcStep Step = ModelActionDuplicatePieces->GetStep(); std::function GetNewGroup = [this, &GroupMap, &GetNewGroup](lcGroup* Group) { @@ -1919,7 +1920,7 @@ void lcModel::RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* Model continue; lcPiece* NewPiece = new lcPiece(*Piece); - NewPiece->UpdatePosition(mCurrentStep); + NewPiece->UpdatePosition(Step); NewPieces.emplace_back(NewPiece); if (Piece->IsFocused()) diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 5baa2dc8..b2920a67 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -132,6 +132,11 @@ lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode { } +lcModelActionDuplicatePieces::lcModelActionDuplicatePieces(lcStep Step) + : mStep(Step) +{ +} + lcModelActionHidePieces::lcModelActionHidePieces(lcModelActionHidePiecesMode Mode) : mMode(Mode) { diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 2687ee15..41bfadcd 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -115,6 +115,17 @@ protected: class lcModelActionDuplicatePieces : public lcModelAction { +public: + lcModelActionDuplicatePieces(lcStep Step); + virtual ~lcModelActionDuplicatePieces() = default; + + lcStep GetStep() const + { + return mStep; + } + +protected: + lcStep mStep; }; enum class lcModelActionHidePiecesMode From ec9ec5d328ed24341648d0d5e3b2f6cecf6ede93 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 1 Nov 2025 17:24:19 -0700 Subject: [PATCH 06/93] Added piece array action. --- common/lc_model.cpp | 50 ++++++++++++++++++++++------------------- common/lc_modelaction.h | 3 ++- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 429d3f34..0562c83c 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1768,16 +1768,27 @@ void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPie case lcModelActionAddPieceSelectionMode::SelectAll: SetSelectionAndFocus(Pieces, nullptr, 0, false); break; + + case lcModelActionAddPieceSelectionMode::AddToSelection: + AddToSelection(Pieces, false, true); + break; } } else { - if (RemoveSelectedObjects()) - { - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); - gMainWindow->UpdateInUseCategory(); - } + std::vector>::iterator PieceIt; + lcStep Step = ModelActionAddPieces->GetStep(); + + for (PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ++PieceIt) + if ((*PieceIt)->GetStepShow() > Step) + break; + + for (size_t PieceIndex = 0; PieceIndex < ModelActionAddPieces->GetPieceData().size(); PieceIndex++) + PieceIt = mPieces.erase(--PieceIt); + + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateInUseCategory(); } } @@ -4923,7 +4934,6 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece RecordSelectionAction(lcModelActionSelectionMode::Save); RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::FocusLast); - RecordSelectionAction(lcModelActionSelectionMode::Save); EndActionSequence(tr("Add Piece")); } @@ -5357,7 +5367,7 @@ void lcModel::ShowArrayDialog() return; } - std::vector NewPieces; + std::vector PieceInfoTransforms; for (int Step1 = 0; Step1 < Dialog.mCounts[0]; Step1++) { @@ -5387,27 +5397,22 @@ void lcModel::ShowArrayDialog() Position = lcVector3(ModelWorld.r[3].x, ModelWorld.r[3].y, ModelWorld.r[3].z); ModelWorld.SetTranslation(Position + Offset); - lcPiece* NewPiece = new lcPiece(nullptr); - NewPiece->SetPieceInfo(Piece->mPieceInfo, Piece->GetID(), true); - NewPiece->Initialize(ModelWorld, mCurrentStep); - NewPiece->SetColorIndex(Piece->GetColorIndex()); + lcInsertPieceInfo& InsertPieceInfo = PieceInfoTransforms.emplace_back(); - NewPieces.emplace_back(NewPiece); + InsertPieceInfo.Info = Piece->mPieceInfo; + InsertPieceInfo.Transform = ModelWorld; + InsertPieceInfo.ColorIndex = Piece->GetColorIndex(); } } } } - for (size_t PieceIdx = 0; PieceIdx < NewPieces.size(); PieceIdx++) - { - lcPiece* Piece = (lcPiece*)NewPieces[PieceIdx]; - Piece->UpdatePosition(mCurrentStep); - AddPiece(Piece); - } + BeginActionSequence(); - AddToSelection(NewPieces, false, true); - gMainWindow->UpdateTimeline(false, false); - SaveCheckpoint(tr("Array")); + RecordSelectionAction(lcModelActionSelectionMode::Save); + RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::AddToSelection); + + EndActionSequence(tr("Array")); } void lcModel::ShowMinifigDialog() @@ -5439,7 +5444,6 @@ void lcModel::ShowMinifigDialog() RecordSelectionAction(lcModelActionSelectionMode::Save); RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::SelectAll); RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, GetGroupName(tr("Minifig #"))); - RecordSelectionAction(lcModelActionSelectionMode::Save); EndActionSequence(tr("Add Minifig")); } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 41bfadcd..6efcb629 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -47,7 +47,8 @@ protected: enum class lcModelActionAddPieceSelectionMode { FocusLast, - SelectAll + SelectAll, + AddToSelection }; class lcModelActionAddPieces : public lcModelAction From 7fbd24ad8d6a4787f31698622ca9368baec1b0d1 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 1 Nov 2025 22:26:35 -0700 Subject: [PATCH 07/93] Static analysis fixes. --- common/lc_blenderpreferences.cpp | 96 +++++++++++++++---------------- common/lc_instructionsdialog.cpp | 2 +- common/lc_model.cpp | 4 +- common/lc_modellistdialog.cpp | 8 +-- common/lc_partpalettedialog.cpp | 2 +- common/lc_partselectionwidget.cpp | 4 +- common/lc_previewwidget.cpp | 2 +- common/lc_shortcuts.cpp | 2 +- common/lc_timelinewidget.cpp | 12 ++-- qt/lc_renderdialog.cpp | 32 +++++------ qt/lc_setsdatabasedialog.cpp | 4 +- 11 files changed, 82 insertions(+), 86 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 12511e96..d72310b4 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -549,7 +549,7 @@ lcBlenderPreferences::lcBlenderPreferences(int Width, int Height, double Scale, else mBlenderVersionEdit->setText(mBlenderVersion); - if (QFileInfo(QString("%1/Blender/%2").arg(mDataDir).arg(LC_BLENDER_ADDON_FILE)).isReadable()) + if (QFileInfo(QString("%1/Blender/%2").arg(mDataDir, LC_BLENDER_ADDON_FILE)).isReadable()) { mModulesBox->setEnabled(false); mImportActBox->setChecked(true); @@ -947,7 +947,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd const QString BlenderConfigDir = QString("%1/setup/addon_setup/config").arg(BlenderDir); const QString BlenderAddonDir = QDir::toNativeSeparators(QString("%1/addons").arg(BlenderDir)); const QString BlenderExeCompare = QDir::toNativeSeparators(lcGetProfileString(LC_PROFILE_BLENDER_PATH)).toLower(); - const QString BlenderInstallFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir).arg(LC_BLENDER_ADDON_INSTALL_FILE)); + const QString BlenderInstallFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir, LC_BLENDER_ADDON_INSTALL_FILE)); const QString BlenderTestString = QLatin1String("###TEST_BLENDER###"); QByteArray AddonPathsAndModuleNames; QString Message, ShellProgram; @@ -1018,7 +1018,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd if (!mProcess->waitForStarted()) { - Message = tr("Cannot start Blender %1 mProcess.\n%2").arg(ProcessAction).arg(QString(mProcess->readAllStandardError())); + Message = tr("Cannot start Blender %1 mProcess.\n%2").arg(ProcessAction, QString(mProcess->readAllStandardError())); delete mProcess; mProcess = nullptr; return PR_WAIT; @@ -1027,7 +1027,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd { if (mProcess->exitStatus() != QProcess::NormalExit || mProcess->exitCode() != 0) { - Message = tr("Failed to execute Blender %1.\n%2").arg(ProcessAction).arg(QString(mProcess->readAllStandardError())); + Message = tr("Failed to execute Blender %1.\n%2").arg(ProcessAction, QString(mProcess->readAllStandardError())); return PR_FAIL; } } @@ -1066,7 +1066,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd // set default LDraw import module if not configured if (!mImportActBox->isChecked() && !mImportMMActBox->isChecked()) mImportActBox->setChecked(true); - Message = tr("Blender %1 mProcess completed. Version: %2 validated.").arg(ProcessAction).arg(mBlenderVersion); + Message = tr("Blender %1 mProcess completed. Version: %2 validated.").arg(ProcessAction, mBlenderVersion); } } } @@ -1107,9 +1107,9 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd #else ScriptName = QLatin1String("blender_test.sh"); #endif - ScriptCommand = QString("\"%1\" %2").arg(BlenderExe).arg(Arguments.join(" ")); + ScriptCommand = QString("\"%1\" %2").arg(BlenderExe, Arguments.join(" ")); - ScriptFile.setFileName(QString("%1/%2").arg(QDir::tempPath()).arg(ScriptName)); + ScriptFile.setFileName(QString("%1/%2").arg(QDir::tempPath(), ScriptName)); if (ScriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream Stream(&ScriptFile); @@ -1213,7 +1213,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd return; } - if (!QFileInfo(BlenderInstallFile).exists()) + if (!QFileInfo::exists(BlenderInstallFile)) { ShowMessage(this, tr("Could not find addon install file: %1").arg(BlenderInstallFile)); StatusUpdate(true, true, tr("Not found.")); @@ -1242,7 +1242,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd Arguments << QString("--disable_ldraw_render"); Arguments << QString("--leocad"); - Message = tr("Blender Addon Install Arguments: %1 %2").arg(BlenderExe).arg(Arguments.join(" ")); + Message = tr("Blender Addon Install Arguments: %1 %2").arg(BlenderExe, Arguments.join(" ")); if (!TestBlender) mBlenderVersionFound = false; @@ -1250,10 +1250,10 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd if (QDir(BlenderAddonDir).entryInfoList(QDir::Dirs|QDir::NoSymLinks).count() > 0) { QJsonArray JsonArray; - QStringList AddonDirs = QDir(BlenderAddonDir).entryList(QDir::NoDotAndDotDot | QDir::Dirs, QDir::SortByMask); + const QStringList AddonDirs = QDir(BlenderAddonDir).entryList(QDir::NoDotAndDotDot | QDir::Dirs, QDir::SortByMask); for (const QString& Addon : AddonDirs) { - QDir Dir(QString("%1/%2").arg(BlenderAddonDir).arg(Addon)); + QDir Dir(QString("%1/%2").arg(BlenderAddonDir, Addon)); Dir.setFilter(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks); QFileInfoList List = Dir.entryInfoList(); for (int LblIdx = 0; LblIdx < List.size(); LblIdx++) @@ -1263,7 +1263,7 @@ void lcBlenderPreferences::ConfigureBlenderAddon(bool TestBlender, bool AddonUpd QFile File(QFileInfo(List.at(LblIdx)).absoluteFilePath()); if (!File.open(QFile::ReadOnly | QFile::Text)) { - ShowMessage(this, tr("Cannot read addon file %1
%2").arg(List.at(LblIdx).fileName()).arg(File.errorString())); + ShowMessage(this, tr("Cannot read addon file %1
%2").arg(List.at(LblIdx).fileName(), File.errorString())); break; } else @@ -1350,14 +1350,14 @@ bool lcBlenderPreferences::ExtractBlenderAddon(const QString& BlenderDir) if (AddonAction == ADDON_EXTRACT) { gAddonPreferences->StatusUpdate(true, false, tr("Extracting...")); - const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir).arg(LC_BLENDER_ADDON_FILE)); + const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir, LC_BLENDER_ADDON_FILE)); QString Result; Extracted = gAddonPreferences->ExtractAddon(BlenderAddonFile, Result); if (!Extracted) { - QString Message = tr("Failed to extract %1 to %2").arg(LC_BLENDER_ADDON_FILE).arg(BlenderDir); + QString Message = tr("Failed to extract %1 to %2").arg(LC_BLENDER_ADDON_FILE, BlenderDir); if (Result.size()) Message.append(" "+Result); @@ -1373,8 +1373,8 @@ bool lcBlenderPreferences::ExtractBlenderAddon(const QString& BlenderDir) int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) { const QString BlenderAddonDir = QDir::toNativeSeparators(QString("%1/addons").arg(BlenderDir)); - const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir).arg(LC_BLENDER_ADDON_FILE)); - const QString AddonVersionFile = QDir::toNativeSeparators(QString("%1/%2/__version__.py").arg(BlenderAddonDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER)); + const QString BlenderAddonFile = QDir::toNativeSeparators(QString("%1/%2").arg(BlenderDir, LC_BLENDER_ADDON_FILE)); + const QString AddonVersionFile = QDir::toNativeSeparators(QString("%1/%2/__version__.py").arg(BlenderAddonDir, LC_BLENDER_ADDON_RENDER_FOLDER)); bool ExtractedAddon = QFileInfo(AddonVersionFile).isReadable(); bool BlenderAddonValidated = ExtractedAddon || QFileInfo(BlenderAddonFile).isReadable(); AddonEnc AddonAction = ADDON_DOWNLOAD; @@ -1418,7 +1418,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) if (!gAddonPreferences->mData.isEmpty()) { QJsonDocument Json = QJsonDocument::fromJson(gAddonPreferences->mData); - OnlineVersion = Json.object()["tag_name"].toString(); + OnlineVersion = Json.object().value("tag_name").toString(); gAddonPreferences->mData.clear(); } else @@ -1460,7 +1460,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) QFile File(AddonVersionFile); if (!File.open(QIODevice::ReadOnly)) { - ShowMessage(this, tr("Cannot read addon version file: [%1]
%2.").arg(AddonVersionFile).arg(File.errorString())); + ShowMessage(this, tr("Cannot read addon version file: [%1]
%2.").arg(AddonVersionFile, File.errorString())); return false; // Download new archive } Ba = File.readAll(); @@ -1505,7 +1505,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) if (LocalVersion.isEmpty()) LocalVersion = gAddonPreferences->mAddonVersion; const QString& Title = tr ("%1 Blender LDraw Addon").arg(LC_PRODUCTNAME_STR); - const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR).arg(LocalVersion).arg(OnlineVersion); + const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR, LocalVersion, OnlineVersion); const QString& Body = tr ("Do you want to download version %1 ?").arg(OnlineVersion); int Exec = ShowMessage(this, Header, Title, Body, QString(), MBB_YES, QMessageBox::NoIcon); if (Exec == QMessageBox::Cancel) @@ -1526,7 +1526,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) auto RemoveOldBlenderAddon = [&] (const QString& OldBlenderAddonFile) { - if (QFileInfo(BlenderAddonDir).exists()) + if (QFileInfo::exists(BlenderAddonDir)) { bool Result = true; QDir Dir(BlenderAddonDir); @@ -1538,7 +1538,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) Result &= QFile::remove(FileInfo.absoluteFilePath()); } - if (QFileInfo(OldBlenderAddonFile).exists()) + if (QFileInfo::exists(OldBlenderAddonFile)) Result &= QFile::remove(OldBlenderAddonFile); Result &= Dir.rmdir(BlenderAddonDir); @@ -1556,7 +1556,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) if (!gAddonPreferences->mData.isEmpty()) { const QString OldBlenderAddonFile = QString("%1.hold").arg(BlenderAddonFile); - if (QFileInfo(BlenderAddonFile).exists()) + if (QFileInfo::exists(BlenderAddonFile)) { if (!QFile::rename(BlenderAddonFile, OldBlenderAddonFile)) ShowMessage(this, tr("Failed to rename existing Blender addon archive %1.").arg(BlenderAddonFile)); @@ -1615,17 +1615,17 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) ShowMessage(this, tr("Failed to receive SHA hash for Blender addon %1.sha256").arg(LC_BLENDER_ADDON_FILE)); } else - ShowMessage(this, tr("Failed to read Blender addon archive:
%1:
%2").arg(BlenderAddonFile).arg(File.errorString())); + ShowMessage(this, tr("Failed to read Blender addon archive:
%1:
%2").arg(BlenderAddonFile, File.errorString())); } else - ShowMessage(this, tr("Failed to write Blender addon archive:
%1:
%2").arg(BlenderAddonFile).arg(File.errorString())); + ShowMessage(this, tr("Failed to write Blender addon archive:
%1:
%2").arg(BlenderAddonFile, File.errorString())); if (!BlenderAddonValidated) { - if (QFileInfo(BlenderAddonFile).exists()) + if (QFileInfo::exists(BlenderAddonFile)) if (!QFile::remove(BlenderAddonFile)) ShowMessage(this, tr("Failed to remove invalid Blender addon archive:
%1").arg(BlenderAddonFile)); - if (QFileInfo(OldBlenderAddonFile).exists()) + if (QFileInfo::exists(OldBlenderAddonFile)) if (!QFile::rename(OldBlenderAddonFile, BlenderAddonFile)) ShowMessage(this, tr("Failed to restore Blender addon archive:
%1 from %2").arg(ArchiveFileName, OldArchiveFileName)); AddonAction = ADDON_FAIL; @@ -1640,7 +1640,7 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) if (!BlenderAddonValidated) gAddonPreferences->StatusUpdate(true, true, tr("Download failed.")); - if (!QDir(BlenderAddonDir).exists() && QFileInfo(BlenderAddonFile).exists()) + if (!QDir(BlenderAddonDir).exists() && QFileInfo::exists(BlenderAddonFile)) AddonAction = ADDON_EXTRACT; return AddonAction; @@ -1867,7 +1867,7 @@ void lcBlenderPreferences::ReadStdOut(const QString& StdOutput, QString& Errors) QRegularExpression RxError("^(?:\\w)*ERROR: ", QRegularExpression::CaseInsensitiveOption); QRegularExpression RxWarning("^(?:\\w)*WARNING: ", QRegularExpression::CaseInsensitiveOption); QRegularExpression RxAddonVersion("^ADDON VERSION: ", QRegularExpression::CaseInsensitiveOption); - QStringList StdOutLines = StdOutput.split(QRegularExpression("\n|\r\n|\r")); + const QStringList StdOutLines = StdOutput.split(QRegularExpression("\n|\r\n|\r")); #else QRegExp RxInfo("^INFO: "); QRegExp RxData("^DATA: "); @@ -2024,7 +2024,7 @@ QString lcBlenderPreferences::ReadStdErr(bool& Error) const QFile File(QString("%1/stderr-blender-addon-install").arg(BlenderDir)); if (!File.open(QFile::ReadOnly | QFile::Text)) { - const QString Message = tr("Failed to open log file: %1:\n%2").arg(File.fileName()).arg(File.errorString()); + const QString Message = tr("Failed to open log file: %1:\n%2").arg(File.fileName(), File.errorString()); return Message; } QTextStream In(&File); @@ -2045,13 +2045,13 @@ void lcBlenderPreferences::WriteStdOut() if (File.open(QFile::WriteOnly | QIODevice::Truncate | QFile::Text)) { QTextStream Out(&File); - for (const QString& Line : mStdOutList) + for (const QString& Line : std::as_const(mStdOutList)) Out << Line << LineEnding; File.close(); mAddonStdOutButton->setEnabled(true); } else - ShowMessage(this, tr("Error writing to %1 file '%2':\n%3").arg("stdout").arg(File.fileName(), File.errorString())); + ShowMessage(this, tr("Error writing to %1 file '%2':\n%3").arg("stdout", File.fileName(), File.errorString())); } bool lcBlenderPreferences::PromptCancel() @@ -2515,7 +2515,7 @@ void lcBlenderPreferences::LoadSettings() lcSetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE, QString()); } - if (!QDir(QString("%1/Blender/addons/%2").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable()) + if (!QDir(QString("%1/Blender/addons/%2").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable()) lcSetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE, QString()); bool UseArchiveLibrary = false; @@ -2538,11 +2538,11 @@ void lcBlenderPreferences::LoadSettings() if (!NumPaths()) { - const QString DefaultBlendFile = QString("%1/Blender/config/%2").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_BLEND_FILE); + const QString DefaultBlendFile = QString("%1/Blender/config/%2").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_BLEND_FILE); QStringList const AddonPaths = QStringList() /* 0 PATH_BLENDER */ << lcGetProfileString(LC_PROFILE_BLENDER_PATH) - /* 1 PATH_BLENDFILE */ << (QFileInfo(DefaultBlendFile).exists() ? DefaultBlendFile : QString()) + /* 1 PATH_BLENDFILE */ << (QFileInfo::exists(DefaultBlendFile) ? DefaultBlendFile : QString()) /* 2 PATH_ENVIRONMENT */ << QString() /* 3 PATH_LDCONFIG */ << lcGetProfileString(LC_PROFILE_COLOR_CONFIG) /* 4 PATH_LDRAW */ << LDrawPartsLibrary(lcGetProfileString(LC_PROFILE_PARTS_LIBRARY)) @@ -2607,7 +2607,7 @@ void lcBlenderPreferences::LoadSettings() continue; const QString& Key = QString("%1/%2").arg(LC_BLENDER_ADDON, mBlenderPaths[LblIdx].key); const QString& Value = Settings.value(Key, QString()).toString(); - if (QFileInfo(Value).exists()) + if (QFileInfo::exists(Value)) mBlenderPaths[LblIdx].value = QDir::toNativeSeparators(Value); } @@ -2617,7 +2617,7 @@ void lcBlenderPreferences::LoadSettings() continue; const QString& Key = QString("%1/%2").arg(LC_BLENDER_ADDON_MM, mBlenderPaths[LblIdx].key_mm); const QString& Value = Settings.value(Key, QString()).toString(); - if (QFileInfo(Value).exists()) + if (QFileInfo::exists(Value)) mBlenderPaths[LblIdx].value = QDir::toNativeSeparators(Value); } @@ -2635,7 +2635,7 @@ void lcBlenderPreferences::LoadSettings() if (LblIdx == LBL_IMAGE_WIDTH || LblIdx == LBL_IMAGE_HEIGHT || LblIdx == LBL_RENDER_PERCENTAGE) { const QString& Label = mDefaultSettings[LblIdx].label; - mBlenderSettings[LblIdx].label = QString("%1 - Setting (%2)").arg(Label).arg(Value); + mBlenderSettings[LblIdx].label = QString("%1 - Setting (%2)").arg(Label, Value); } } @@ -2653,7 +2653,7 @@ void lcBlenderPreferences::LoadSettings() if (LblIdx == LBL_RENDER_PERCENTAGE_MM || LblIdx == LBL_RESOLUTION_WIDTH || LblIdx == LBL_RESOLUTION_HEIGHT) { const QString& Label = mDefaultSettingsMM[LblIdx].label; - mBlenderSettingsMM[LblIdx].label = QString("%1 - Setting (%2)").arg(Label).arg(Value); + mBlenderSettingsMM[LblIdx].label = QString("%1 - Setting (%2)").arg(Label, Value); } } } @@ -2678,8 +2678,7 @@ void lcBlenderPreferences::LoadSettings() { ShowMessage(nullptr, tr("Blender config file was not found. " "Install log check failed:
%1:
%2") - .arg(File.fileName()) - .arg(File.errorString())); + .arg(File.fileName(), File.errorString())); } } } @@ -2720,24 +2719,24 @@ void lcBlenderPreferences::SaveSettings() lcSetProfileString(LC_PROFILE_BLENDER_VERSION, Value); - const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER); + const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_RENDER_FOLDER); Value = lcGetProfileString(LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH); if (!Value.contains(LC_BLENDER_ADDON_RENDER_FOLDER)) { - Value = QString("%1/%2").arg(BlenderConfigDir).arg(LC_BLENDER_ADDON_CONFIG_FILE); + Value = QString("%1/%2").arg(BlenderConfigDir, LC_BLENDER_ADDON_CONFIG_FILE); lcSetProfileString(LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH, QDir::toNativeSeparators(Value)); } QString searchDirectoriesKey = QLatin1String("additionalSearchPaths"); QString parameterFileKey = QLatin1String("ParameterFile"); - QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir).arg(LC_BLENDER_ADDON_PARAMS_FILE); + QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir, LC_BLENDER_ADDON_PARAMS_FILE); QSettings Settings(Value, QSettings::IniFormat); auto concludeSettingsGroup = [&]() { - if (!QFileInfo(ParameterFile).exists()) + if (!QFileInfo::exists(ParameterFile)) ExportParameterFile(); Value = QDir::toNativeSeparators(QFileInfo(lcGetProfileString(LC_PROFILE_PROJECTS_PATH)).absolutePath()); Settings.setValue(searchDirectoriesKey, QVariant(Value)); @@ -3127,7 +3126,7 @@ void lcBlenderPreferences::SetModelSize(bool Update) { const QString& Title = tr ("LDraw Render Settings Conflict"); const QString& Header = "" + tr ("Crop image configuration settings conflict were resolved.") + ""; - const QString& Body = QString("%1%2%3").arg(Conflict[0] ? tr("Keep aspect ratio set to false.
") : "").arg(Conflict[1] ? tr("Add environment (backdrop and base plane) set to false.
") : "").arg(Conflict[2] ? tr("Transparent background set to true.
") : ""); + const QString& Body = QString("%1%2%3").arg(Conflict[0] ? tr("Keep aspect ratio set to false.
") : "", Conflict[1] ? tr("Add environment (backdrop and base plane) set to false.
") : "", Conflict[2] ? tr("Transparent background set to true.
") : ""); ShowMessage(this, Header, Title, Body, QString(), MBB_OK, QMessageBox::Information); } } @@ -3457,8 +3456,8 @@ void lcBlenderPreferences::LoadDefaultParameters(QByteArray& Buffer, int Which) bool lcBlenderPreferences::ExportParameterFile() { - const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir).arg(LC_BLENDER_ADDON_RENDER_FOLDER); - const QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir).arg(LC_BLENDER_ADDON_PARAMS_FILE); + const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_RENDER_FOLDER); + const QString ParameterFile = QString("%1/%2").arg(BlenderConfigDir, LC_BLENDER_ADDON_PARAMS_FILE); QDir ConfigDir(BlenderConfigDir); if(!ConfigDir.exists()) ConfigDir.mkpath("."); @@ -3550,8 +3549,7 @@ bool lcBlenderPreferences::ExportParameterFile() else { Message = tr("Failed to open Blender parameter file: %1:
%2") - .arg(File.fileName()) - .arg(File.errorString()); + .arg(File.fileName(), File.errorString()); ShowMessage(nullptr, Message); return false; } diff --git a/common/lc_instructionsdialog.cpp b/common/lc_instructionsdialog.cpp index 265281f2..9fdb3b3b 100644 --- a/common/lc_instructionsdialog.cpp +++ b/common/lc_instructionsdialog.cpp @@ -81,7 +81,7 @@ void lcInstructionsPageWidget::StepSettingsChanged(lcModel* Model, lcStep Step) { QGraphicsScene* Scene = scene(); - QList Items = Scene->items(); + const QList Items = Scene->items(); for (QGraphicsItem* Item : Items) { diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 0562c83c..90021869 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -49,7 +49,7 @@ void lcModelProperties::SaveLDraw(QTextStream& Stream) const if (!mComments.isEmpty()) { - QStringList Comments = mComments.split('\n'); + const QStringList Comments = mComments.split('\n'); for (const QString& Comment : Comments) Stream << QLatin1String("0 !LEOCAD MODEL COMMENT ") << Comment << LineEnding; } @@ -1052,7 +1052,7 @@ bool lcModel::LoadInventory(const QByteArray& Inventory) { QJsonDocument Document = QJsonDocument::fromJson(Inventory); QJsonObject Root = Document.object(); - QJsonArray Parts = Root["results"].toArray(); + const QJsonArray Parts = Root["results"].toArray(); lcPiecesLibrary* Library = lcGetPiecesLibrary(); for (const QJsonValue& Part : Parts) diff --git a/common/lc_modellistdialog.cpp b/common/lc_modellistdialog.cpp index 8e4dac72..3ffc3baa 100644 --- a/common/lc_modellistdialog.cpp +++ b/common/lc_modellistdialog.cpp @@ -135,7 +135,7 @@ void lcModelListDialog::on_DeleteModel_clicked() return; } - QList SelectedItems = ui->ModelList->selectedItems(); + const QList SelectedItems = ui->ModelList->selectedItems(); if (SelectedItems.isEmpty()) { @@ -165,7 +165,7 @@ void lcModelListDialog::on_DeleteModel_clicked() void lcModelListDialog::on_RenameModel_clicked() { - QList SelectedItems = ui->ModelList->selectedItems(); + const QList SelectedItems = ui->ModelList->selectedItems(); if (SelectedItems.isEmpty()) { @@ -189,7 +189,7 @@ void lcModelListDialog::on_RenameModel_clicked() void lcModelListDialog::on_ExportModel_clicked() { - QList SelectedItems = ui->ModelList->selectedItems(); + const QList SelectedItems = ui->ModelList->selectedItems(); if (SelectedItems.isEmpty()) { @@ -248,7 +248,7 @@ void lcModelListDialog::on_ExportModel_clicked() void lcModelListDialog::on_DuplicateModel_clicked() { - QList SelectedItems = ui->ModelList->selectedItems(); + const QList SelectedItems = ui->ModelList->selectedItems(); if (SelectedItems.isEmpty()) { diff --git a/common/lc_partpalettedialog.cpp b/common/lc_partpalettedialog.cpp index 62d61fbc..20cdb5bf 100644 --- a/common/lc_partpalettedialog.cpp +++ b/common/lc_partpalettedialog.cpp @@ -127,7 +127,7 @@ void lcPartPaletteDialog::on_ImportButton_clicked() QByteArray Inventory = Dialog.GetSetInventory(); QJsonDocument Document = QJsonDocument::fromJson(Inventory); QJsonObject Root = Document.object(); - QJsonArray Parts = Root["results"].toArray(); + const QJsonArray Parts = Root["results"].toArray(); for (const QJsonValue& Part : Parts) { diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp index 7c645cf4..67a1227f 100644 --- a/common/lc_partselectionwidget.cpp +++ b/common/lc_partselectionwidget.cpp @@ -245,7 +245,7 @@ void lcPartSelectionListModel::SetCustomParts(const std::vectorLoad(ModelPath, false)) return false; diff --git a/common/lc_shortcuts.cpp b/common/lc_shortcuts.cpp index a4e0f813..f04bdd42 100644 --- a/common/lc_shortcuts.cpp +++ b/common/lc_shortcuts.cpp @@ -246,7 +246,7 @@ bool lcMouseShortcuts::Load(const QStringList& FullShortcuts) if (ToolIdx == static_cast(lcTool::Count)) continue; - QStringList Shortcuts = FullShortcut.mid(Equals + 1).split(','); + const QStringList Shortcuts = FullShortcut.mid(Equals + 1).split(','); bool AddedShortcut = false; for (const QString& Shortcut : Shortcuts) diff --git a/common/lc_timelinewidget.cpp b/common/lc_timelinewidget.cpp index 1b1cb09c..c01c46c8 100644 --- a/common/lc_timelinewidget.cpp +++ b/common/lc_timelinewidget.cpp @@ -4,8 +4,6 @@ #include "piece.h" #include "pieceinf.h" #include "lc_mainwindow.h" -#include "lc_viewwidget.h" -#include "lc_previewwidget.h" lcTimelineWidget::lcTimelineWidget(QWidget* Parent) : QTreeWidget(Parent) @@ -383,7 +381,7 @@ void lcTimelineWidget::MoveSelection() return; Step++; - QList SelectedItems = selectedItems(); + const QList SelectedItems = selectedItems(); for (QTreeWidgetItem* PieceItem : SelectedItems) { @@ -421,7 +419,7 @@ void lcTimelineWidget::MoveSelectionBefore() Step++; - QList SelectedItems = selectedItems(); + const QList SelectedItems = selectedItems(); gMainWindow->GetActiveModel()->InsertStep(Step); @@ -463,7 +461,7 @@ void lcTimelineWidget::MoveSelectionAfter() Step += 2; - QList SelectedItems = selectedItems(); + const QList SelectedItems = selectedItems(); gMainWindow->GetActiveModel()->InsertStep(Step); @@ -526,7 +524,7 @@ void lcTimelineWidget::ItemSelectionChanged() { std::vector Selection; lcStep LastStep = 1; - QList SelectedItems = selectedItems(); + const QList SelectedItems = selectedItems(); for (QTreeWidgetItem* PieceItem : SelectedItems) { @@ -589,7 +587,7 @@ void lcTimelineWidget::dropEvent(QDropEvent* Event) std::sort(SelectedItems.begin(), SelectedItems.end(), SortItems); - for (QTreeWidgetItem* SelectedItem : SelectedItems) + for (QTreeWidgetItem* SelectedItem : std::as_const(SelectedItems)) SelectedItem->setSelected(true); QTreeWidget::dropEvent(Event); diff --git a/qt/lc_renderdialog.cpp b/qt/lc_renderdialog.cpp index d0d85e4a..a32411a2 100644 --- a/qt/lc_renderdialog.cpp +++ b/qt/lc_renderdialog.cpp @@ -82,7 +82,7 @@ lcRenderDialog::lcRenderDialog(QWidget* Parent, lcRenderDialogMode RenderDialogM bool BlenderConfigured = !lcGetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE).isEmpty(); QStringList const& DataPathList = QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation); - if (!QDir(QString("%1/Blender/addons/%2").arg(DataPathList.first()).arg(LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable()) + if (!QDir(QString("%1/Blender/addons/%2").arg(DataPathList.first(), LC_BLENDER_ADDON_RENDER_FOLDER)).isReadable()) { BlenderConfigured = false; lcSetProfileString(LC_PROFILE_BLENDER_IMPORT_MODULE, QString()); @@ -305,28 +305,28 @@ void lcRenderDialog::RenderPOVRay() const QString POVRayDir = QFileInfo(POVRayPath).absolutePath(); const QString IncludePath = QDir::cleanPath(POVRayDir + "/include"); - if (QFileInfo(IncludePath).exists()) + if (QFileInfo::exists(IncludePath)) Arguments.append(QString("+L\"%1\"").arg(IncludePath)); const QString IniPath = QDir::cleanPath(POVRayDir + "/ini"); - if (QFileInfo(IniPath).exists()) + if (QFileInfo::exists(IniPath)) Arguments.append(QString("+L\"%1\"").arg(IniPath)); if (lcGetActiveProject()->GetModels()[0]->GetPOVRayOptions().UseLGEO) { const QString LGEOPath = lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH); - if (QFileInfo(LGEOPath).exists()) + if (QFileInfo::exists(LGEOPath)) { const QString LgPath = QDir::cleanPath(LGEOPath + "/lg"); - if (QFileInfo(LgPath).exists()) + if (QFileInfo::exists(LgPath)) Arguments.append(QString("+L\"%1\"").arg(LgPath)); const QString ArPath = QDir::cleanPath(LGEOPath + "/ar"); - if (QFileInfo(ArPath).exists()) + if (QFileInfo::exists(ArPath)) Arguments.append(QString("+L\"%1\"").arg(ArPath)); const QString StlPath = QDir::cleanPath(LGEOPath + "/stl"); - if (QFileInfo(StlPath).exists()) + if (QFileInfo::exists(StlPath)) Arguments.append(QString("+L\"%1\"").arg(StlPath)); } } @@ -376,7 +376,7 @@ void lcRenderDialog::RenderBlender() const QStringList DataPathList = QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation); mDataPath = DataPathList.first(); - const QString DefaultBlendFile = QString("%1/blender/config/%2").arg(mDataPath).arg(LC_BLENDER_ADDON_BLEND_FILE); + const QString DefaultBlendFile = QString("%1/blender/config/%2").arg(mDataPath, LC_BLENDER_ADDON_BLEND_FILE); lcModel* Model = lcGetActiveProject()->GetActiveModel(); const QString ModelFileName = QFileInfo(QDir(lcGetProfileString(LC_PROFILE_PROJECTS_PATH)), QString("%1_Step_%2.ldr").arg(QFileInfo(Model->GetProperties().mFileName).baseName()).arg(Model->GetCurrentStep())).absoluteFilePath(); @@ -400,8 +400,8 @@ void lcRenderDialog::RenderBlender() "image_file=r'%5'") .arg(mWidth).arg(mHeight) .arg(mScale * 100) - .arg(QDir::toNativeSeparators(ModelFileName).replace("\\","\\\\")) - .arg(QDir::toNativeSeparators(ui->OutputEdit->text()).replace("\\","\\\\")); + .arg(QDir::toNativeSeparators(ModelFileName).replace("\\","\\\\"), + QDir::toNativeSeparators(ui->OutputEdit->text()).replace("\\","\\\\")); if (BlenderImportModule == QLatin1String("MM")) PythonExpression.append(", use_ldraw_import_mm=True"); if (SearchCustomDir) @@ -421,7 +421,7 @@ void lcRenderDialog::RenderBlender() PythonExpression.append(", cli_render=True)\""); - if (QFileInfo(DefaultBlendFile).exists()) + if (QFileInfo::exists(DefaultBlendFile)) Arguments << QDir::toNativeSeparators(DefaultBlendFile); Arguments << QString("--python-expr"); Arguments << PythonExpression; @@ -433,14 +433,14 @@ void lcRenderDialog::RenderBlender() #else ScriptName = QLatin1String("render_ldraw_model.sh"); #endif - ScriptCommand = QString("\"%1\" %2").arg(lcGetProfileString(LC_PROFILE_BLENDER_PATH)).arg(Arguments.join(" ")); + ScriptCommand = QString("\"%1\" %2").arg(lcGetProfileString(LC_PROFILE_BLENDER_PATH), Arguments.join(" ")); if (mDialogMode == lcRenderDialogMode::OpenInBlender) ScriptCommand.append(QString(" > %1").arg(QDir::toNativeSeparators(GetStdOutFileName()))); const QLatin1String LineEnding("\r\n"); - QFile ScriptFile(QString("%1/%2").arg(QDir::tempPath()).arg(ScriptName)); + QFile ScriptFile(QString("%1/%2").arg(QDir::tempPath(), ScriptName)); if (ScriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream Stream(&ScriptFile); @@ -608,7 +608,7 @@ QString lcRenderDialog::ReadStdErr(bool& HasError) const if (!File.open(QFile::ReadOnly | QFile::Text)) { - const QString message = tr("Failed to open log file: %1:\n%2").arg(File.fileName()).arg(File.errorString()); + const QString message = tr("Failed to open log file: %1:\n%2").arg(File.fileName(), File.errorString()); return message; } @@ -646,7 +646,7 @@ void lcRenderDialog::WriteStdOut() { QTextStream Out(&File); - for (const QString& Line : mStdOutList) + for (const QString& Line : std::as_const(mStdOutList)) Out << Line; File.close(); @@ -774,7 +774,7 @@ void lcRenderDialog::ShowResult() } else if (mDialogMode == lcRenderDialogMode::RenderBlender) { - Success = QFileInfo(FileName).exists(); + Success = QFileInfo::exists(FileName); if (Success) { setMinimumSize(100, 100); diff --git a/qt/lc_setsdatabasedialog.cpp b/qt/lc_setsdatabasedialog.cpp index 196b7197..d377cf32 100644 --- a/qt/lc_setsdatabasedialog.cpp +++ b/qt/lc_setsdatabasedialog.cpp @@ -166,7 +166,7 @@ void lcSetsDatabaseDialog::DownloadFinished(lcHttpReply* Reply) if (Version == 1) { - QJsonArray Keys = Root["Keys"].toArray(); + const QJsonArray Keys = Root["Keys"].toArray(); for (const QJsonValue& Key : Keys) mKeys.append(Key.toString()); @@ -190,8 +190,8 @@ void lcSetsDatabaseDialog::DownloadFinished(lcHttpReply* Reply) { QJsonDocument Document = QJsonDocument::fromJson(Reply->readAll()); QJsonObject Root = Document.object(); + const QJsonArray Sets = Root["results"].toArray(); - QJsonArray Sets = Root["results"].toArray(); for (const QJsonValue& Set : Sets) { QJsonObject SetObject = Set.toObject(); From 684a361a2d4474e9cb96e703d6d38899251d8321 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 1 Nov 2025 22:34:56 -0700 Subject: [PATCH 08/93] Fixed uninitialized value. --- common/lc_lxf.cpp | 2 +- qt/lc_qselectdialog.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/common/lc_lxf.cpp b/common/lc_lxf.cpp index 98a49444..11038045 100644 --- a/common/lc_lxf.cpp +++ b/common/lc_lxf.cpp @@ -135,7 +135,7 @@ bool lcImportLXFMLFile(const QString& FileData, std::vector& Pieces, s WorldMatrix[2][0] = BoneElements[6].toFloat(); WorldMatrix[2][1] = BoneElements[7].toFloat(); WorldMatrix[2][2] = BoneElements[8].toFloat(); - WorldMatrix[3][3] = 0.0f; + WorldMatrix[2][3] = 0.0f; WorldMatrix[3][0] = BoneElements[9].toFloat(); WorldMatrix[3][1] = BoneElements[10].toFloat(); WorldMatrix[3][2] = BoneElements[11].toFloat(); diff --git a/qt/lc_qselectdialog.cpp b/qt/lc_qselectdialog.cpp index 63d9dd57..1096f8a3 100644 --- a/qt/lc_qselectdialog.cpp +++ b/qt/lc_qselectdialog.cpp @@ -1,7 +1,6 @@ #include "lc_global.h" #include "lc_qselectdialog.h" #include "ui_lc_qselectdialog.h" -#include "lc_application.h" #include "lc_model.h" #include "piece.h" #include "camera.h" From c0af32644af5b72f9569401beba7b4d1ffc1574b Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 2 Nov 2025 23:20:12 -0800 Subject: [PATCH 09/93] Added add light action. --- common/lc_model.cpp | 59 +++++++++++++++++++++++++++++++-------- common/lc_model.h | 3 ++ common/lc_modelaction.cpp | 5 ++++ common/lc_modelaction.h | 22 +++++++++++++++ 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 90021869..8316201d 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1792,6 +1792,38 @@ void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPie } } +void lcModel::RecordAddLightAction(const lcVector3& Position, lcLightType LightType) +{ + std::unique_ptr ModelActionAddLight = std::make_unique(Position, LightType); + + RunAddLightAction(ModelActionAddLight.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionAddLight)); +} + +void lcModel::RunAddLightAction(const lcModelActionAddLight* ModelActionAddLight, bool Apply) +{ + if (!ModelActionAddLight) + return; + + if (Apply) + { + lcLight* Light = new lcLight(ModelActionAddLight->GetPosition(), ModelActionAddLight->GetLightType()); + Light->CreateName(mLights); + mLights.emplace_back(Light); + + ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); + } + else + { + if (!mLights.empty()) + mLights.pop_back(); + + gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateInUseCategory(); + } +} + void lcModel::RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName) { std::unique_ptr ModelActionGroupPieces = std::make_unique(Mode, GroupName); @@ -2031,6 +2063,8 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunAddPiecesAction(ModelActionAddPieces, Apply); + else if (const lcModelActionAddLight* ModelActionAddLight = dynamic_cast(ModelAction)) + RunAddLightAction(ModelActionAddLight, Apply); else if (const lcModelActionGroupPieces* ModelActionGroupPieces = dynamic_cast(ModelAction)) RunGroupPiecesAction(ModelActionGroupPieces, Apply); else if (const lcModelActionDuplicatePieces* ModelActionDuplicatePieces = dynamic_cast(ModelAction)) @@ -4940,33 +4974,36 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType) { - lcLight* Light = new lcLight(Position, LightType); - Light->CreateName(mLights); - mLights.emplace_back(Light); - - ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); + QString ActionName; switch (LightType) { case lcLightType::Point: - SaveCheckpoint(tr("New Point Light")); + ActionName = tr("Add Point Light"); break; case lcLightType::Spot: - SaveCheckpoint(tr("New Spot Light")); + ActionName = tr("Add Spot Light"); break; case lcLightType::Directional: - SaveCheckpoint(tr("New Directional Light")); + ActionName = tr("Add Directional Light"); break; case lcLightType::Area: - SaveCheckpoint(tr("New Area Light")); + ActionName = tr("Add Area Light"); break; case lcLightType::Count: - break; + return; } + + BeginActionSequence(); + + RecordSelectionAction(lcModelActionSelectionMode::Save); + RecordAddLightAction(Position, LightType); + + EndActionSequence(ActionName); } void lcModel::BeginCameraTool(const lcVector3& Position, const lcVector3& Target) @@ -5412,7 +5449,7 @@ void lcModel::ShowArrayDialog() RecordSelectionAction(lcModelActionSelectionMode::Save); RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::AddToSelection); - EndActionSequence(tr("Array")); + EndActionSequence(tr("Piece Array")); } void lcModel::ShowMinifigDialog() diff --git a/common/lc_model.h b/common/lc_model.h index 8a7e40f6..a425bfb1 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -7,6 +7,7 @@ enum class lcObjectPropertyId; class lcModelAction; class lcModelActionSelection; class lcModelActionAddPieces; +class lcModelActionAddLight; class lcModelActionGroupPieces; class lcModelActionDuplicatePieces; class lcModelActionHidePieces; @@ -406,6 +407,8 @@ protected: void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); + void RecordAddLightAction(const lcVector3& Position, lcLightType LightType); + void RunAddLightAction(const lcModelActionAddLight* ModelActionAddLight, bool Apply); void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); void RecordDuplicatePiecesAction(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index b2920a67..786883b1 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -127,6 +127,11 @@ void lcModelActionAddPieces::SetPieceData(const std::vector& } } +lcModelActionAddLight::lcModelActionAddLight(const lcVector3& Position, lcLightType LightType) + : mPosition(Position), mLightType(LightType) +{ +} + lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName) : mMode(Mode), mGroupName(GroupName) { diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 6efcb629..7eacb02d 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -4,6 +4,7 @@ struct lcInsertPieceInfo; enum class lcObjectType; +enum class lcLightType; class lcModelAction { @@ -87,6 +88,27 @@ protected: lcModelActionAddPieceSelectionMode mSelectionMode; }; +class lcModelActionAddLight : public lcModelAction +{ +public: + lcModelActionAddLight(const lcVector3& Position, lcLightType LightType); + virtual ~lcModelActionAddLight() = default; + + const lcVector3& GetPosition() const + { + return mPosition; + } + + lcLightType GetLightType() const + { + return mLightType; + } + +protected: + lcVector3 mPosition; + lcLightType mLightType; +}; + enum class lcModelActionGroupPiecesMode { Group, From 6df16f574291fce001312ae514d5d7137dca861a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Wed, 19 Nov 2025 22:34:53 -0800 Subject: [PATCH 10/93] Added step insert and delete actions. --- common/camera.cpp | 12 ++++ common/camera.h | 2 + common/lc_model.cpp | 130 ++++++++++++++++++++++++++++++++++- common/lc_model.h | 4 ++ common/lc_modelaction.cpp | 47 +++++++++++++ common/lc_modelaction.h | 64 +++++++++++++++++ common/lc_objectproperty.cpp | 32 ++++++++- common/lc_objectproperty.h | 2 + common/light.cpp | 40 +++++++++++ common/light.h | 2 + common/object.h | 2 + common/piece.cpp | 11 +++ common/piece.h | 2 + 13 files changed, 347 insertions(+), 3 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 39910fb6..9c59bc46 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -896,6 +896,18 @@ void lcCamera::RemoveKeyFrames() mUpVector.RemoveAllKeys(); } +void lcCamera::SaveKeyFrames(QDataStream& Stream) const +{ + mPosition.SaveToDataStream(Stream); + mTargetPosition.SaveToDataStream(Stream); + mUpVector.SaveToDataStream(Stream); +} + +bool lcCamera::LoadKeyFrames(QDataStream& Stream) +{ + return mPosition.LoadFromDataStream(Stream) && mTargetPosition.LoadFromDataStream(Stream) && mUpVector.LoadFromDataStream(Stream); +} + void lcCamera::RayTest(lcObjectRayTest& ObjectRayTest) const { lcVector3 Min = lcVector3(-LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE); diff --git a/common/camera.h b/common/camera.h index 31cf0083..7c35778d 100644 --- a/common/camera.h +++ b/common/camera.h @@ -316,6 +316,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; + void SaveKeyFrames(QDataStream& Stream) const override; + bool LoadKeyFrames(QDataStream& Stream) override; void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 8316201d..f1fb4c9f 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2055,6 +2055,113 @@ void lcModel::RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHide } } +void lcModel::RecordStepAction(lcModelActionStepMode Mode, lcStep Step) +{ + std::unique_ptr ModelActionStep = std::make_unique(Mode, Step); + + ModelActionStep->SaveState(mPieces, mCameras, mLights); + + RunStepAction(ModelActionStep.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionStep)); +} + +void lcModel::RunStepAction(const lcModelActionStep* ModelActionStep, bool Apply) +{ + if (!ModelActionStep) + return; + + lcStep Step = ModelActionStep->GetStep(); + + if (Apply) + { + if (ModelActionStep->GetMode() == lcModelActionStepMode::Insert) + { + for (const std::unique_ptr& Piece : mPieces) + { + Piece->InsertTime(Step, 1); + + if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) + Piece->SetSelected(false); + } + + for (std::unique_ptr& Camera : mCameras) + Camera->InsertTime(Step, 1); + + for (const std::unique_ptr& Light : mLights) + Light->InsertTime(Step, 1); + } + else + { + for (const std::unique_ptr& Piece : mPieces) + { + Piece->RemoveTime(Step, 1); + + if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) + Piece->SetSelected(false); + } + + for (std::unique_ptr& Camera : mCameras) + Camera->RemoveTime(Step, 1); + + for (const std::unique_ptr& Light : mLights) + Light->RemoveTime(Step, 1); + } + } + else + { + const std::vector& PieceStates = ModelActionStep->GetPieceStates(); + + if (PieceStates.size() != mPieces.size()) + return; + + for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) + { + const lcModelActionStepPieceState& PieceState = PieceStates[PieceIndex]; + lcPiece* Piece = mPieces[PieceIndex].get(); + + Piece->SetStepShow(PieceState.StepShow); + Piece->SetStepHide(PieceState.StepHide); + + QDataStream Stream(const_cast(&PieceState.KeyFrames), QIODevice::ReadOnly); + + Piece->LoadKeyFrames(Stream); + } + + const std::vector& CameraStates = ModelActionStep->GetCameraStates(); + + if (CameraStates.size() != mCameras.size()) + return; + + for (size_t CameraIndex = 0; CameraIndex < mCameras.size(); CameraIndex++) + { + const lcModelActionStepCameraState& CameraState = CameraStates[CameraIndex]; + lcCamera* Camera = mCameras[CameraIndex].get(); + + QDataStream Stream(const_cast(&CameraState.KeyFrames), QIODevice::ReadOnly); + + Camera->LoadKeyFrames(Stream); + } + + const std::vector& LightStates = ModelActionStep->GetLightStates(); + + if (LightStates.size() != mLights.size()) + return; + + for (size_t LightIndex = 0; LightIndex < mLights.size(); LightIndex++) + { + const lcModelActionStepLightState& LightState = LightStates[LightIndex]; + lcLight* Light = mLights[LightIndex].get(); + + QDataStream Stream(const_cast(&LightState.KeyFrames), QIODevice::ReadOnly); + + Light->LoadKeyFrames(Stream); + } + } + + SetCurrentStep(mCurrentStep); +} + void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) { auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) @@ -2071,6 +2178,8 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunHidePiecesAction(ModelActionHidePieces, Apply); + else if (const lcModelActionStep* ModelActionStep = dynamic_cast(ModelAction)) + RunStepAction(ModelActionStep, Apply); }; if (Apply) @@ -2276,6 +2385,15 @@ lcStep lcModel::GetLastStep() const void lcModel::InsertStep(lcStep Step) { + BeginActionSequence(); + + RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordStepAction(lcModelActionStepMode::Insert, Step); +// RecordSelectionAction(lcModelActionSelectionMode::Save); + + EndActionSequence(tr("Insert Step")); + +/* for (const std::unique_ptr& Piece : mPieces) { Piece->InsertTime(Step, 1); @@ -2290,11 +2408,19 @@ void lcModel::InsertStep(lcStep Step) Light->InsertTime(Step, 1); SaveCheckpoint(tr("Inserting Step")); - SetCurrentStep(mCurrentStep); + SetCurrentStep(mCurrentStep);*/ } void lcModel::RemoveStep(lcStep Step) { + BeginActionSequence(); + + RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordStepAction(lcModelActionStepMode::Remove, Step); + // RecordSelectionAction(lcModelActionSelectionMode::Save); + + EndActionSequence(tr("Remove Step")); + /* for (const std::unique_ptr& Piece : mPieces) { Piece->RemoveTime(Step, 1); @@ -2309,7 +2435,7 @@ void lcModel::RemoveStep(lcStep Step) Light->RemoveTime(Step, 1); SaveCheckpoint(tr("Removing Step")); - SetCurrentStep(mCurrentStep); + SetCurrentStep(mCurrentStep);*/ } lcGroup* lcModel::AddGroup(const QString& Prefix, lcGroup* Parent) diff --git a/common/lc_model.h b/common/lc_model.h index a425bfb1..150f1940 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -11,10 +11,12 @@ class lcModelActionAddLight; class lcModelActionGroupPieces; class lcModelActionDuplicatePieces; class lcModelActionHidePieces; +class lcModelActionStep; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; enum class lcModelActionGroupPiecesMode; enum class lcModelActionHidePiecesMode; +enum class lcModelActionStepMode; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -415,6 +417,8 @@ protected: void RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply); void RecordHidePiecesAction(lcModelActionHidePiecesMode Mode); void RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHidePieces, bool Apply); + void RecordStepAction(lcModelActionStepMode Mode, lcStep Step); + void RunStepAction(const lcModelActionStep* ModelActionStep, bool Apply); void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 786883b1..91a317cd 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -154,3 +154,50 @@ void lcModelActionHidePieces::SaveHiddenState(const std::vectorIsHidden(); } + +lcModelActionStep::lcModelActionStep(lcModelActionStepMode Mode, lcStep Step) + : mMode(Mode), mStep(Step) +{ +} + +void lcModelActionStep::SaveState(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) +{ + mPieceStates.resize(Pieces.size()); + + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + { + lcModelActionStepPieceState& PieceState = mPieceStates[PieceIndex]; + const lcPiece* Piece = Pieces[PieceIndex].get(); + + PieceState.StepShow = Piece->GetStepShow(); + PieceState.StepHide = Piece->GetStepHide(); + + QDataStream Stream(&PieceState.KeyFrames, QIODevice::WriteOnly); + + Piece->SaveKeyFrames(Stream); + } + + mCameraStates.resize(Cameras.size()); + + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + { + lcModelActionStepCameraState& CameraState = mCameraStates[CameraIndex]; + const lcCamera* Camera = Cameras[CameraIndex].get(); + + QDataStream Stream(&CameraState.KeyFrames, QIODevice::WriteOnly); + + Camera->SaveKeyFrames(Stream); + } + + mLightStates.resize(Lights.size()); + + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + { + lcModelActionStepLightState& LightState = mLightStates[LightIndex]; + const lcLight* Light = Lights[LightIndex].get(); + + QDataStream Stream(&LightState.KeyFrames, QIODevice::WriteOnly); + + Light->SaveKeyFrames(Stream); + } +} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 7eacb02d..a0b46700 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -181,3 +181,67 @@ protected: std::vector mHiddenState; lcModelActionHidePiecesMode mMode; }; + +enum class lcModelActionStepMode +{ + Insert, + Remove +}; + +struct lcModelActionStepPieceState +{ + lcStep StepShow; + lcStep StepHide; + QByteArray KeyFrames; +}; + +struct lcModelActionStepCameraState +{ + QByteArray KeyFrames; +}; + +struct lcModelActionStepLightState +{ + QByteArray KeyFrames; +}; + +class lcModelActionStep : public lcModelAction +{ +public: + lcModelActionStep(lcModelActionStepMode Mode, lcStep Step); + virtual ~lcModelActionStep() = default; + + lcModelActionStepMode GetMode() const + { + return mMode; + } + + lcStep GetStep() const + { + return mStep; + } + + void SaveState(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights); + + const std::vector& GetPieceStates() const + { + return mPieceStates; + } + + const std::vector& GetCameraStates() const + { + return mCameraStates; + } + + const std::vector& GetLightStates() const + { + return mLightStates; + } + +protected: + std::vector mPieceStates; + std::vector mCameraStates; + std::vector mLightStates; + lcModelActionStepMode mMode; + lcStep mStep; +}; diff --git a/common/lc_objectproperty.cpp b/common/lc_objectproperty.cpp index 50958494..5dab936e 100644 --- a/common/lc_objectproperty.cpp +++ b/common/lc_objectproperty.cpp @@ -10,7 +10,9 @@ template bool lcObjectProperty::HasKeyFrame(lcStep Time) const; \ template bool lcObjectProperty::SetKeyFrame(lcStep Time, bool KeyFrame); \ template void lcObjectProperty::Save(QTextStream& Stream, const char* ObjectName, const char* VariableName, bool SaveEmpty) const; \ - template bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const char* VariableName); + template bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const char* VariableName); \ + template void lcObjectProperty::SaveToDataStream(QDataStream& Stream) const; \ + template bool lcObjectProperty::LoadFromDataStream(QDataStream& Stream); LC_OBJECT_PROPERTY(float) LC_OBJECT_PROPERTY(int) @@ -312,3 +314,31 @@ bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const return false; } + +template +void lcObjectProperty::SaveToDataStream(QDataStream& Stream) const +{ + size_t KeyCount = mKeys.size(); + size_t DataSize = KeyCount * sizeof(lcObjectPropertyKey); + + Stream.writeRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)); + Stream.writeRawData(reinterpret_cast(mKeys.data()), DataSize); +} + +template +bool lcObjectProperty::LoadFromDataStream(QDataStream& Stream) +{ + size_t KeyCount; + + if (Stream.readRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)) != sizeof(KeyCount)) + return false; + + mKeys.resize(KeyCount); + + int DataSize = KeyCount * sizeof(lcObjectPropertyKey); + + if (Stream.readRawData(reinterpret_cast(mKeys.data()), DataSize) != DataSize) + return false; + + return true; +} diff --git a/common/lc_objectproperty.h b/common/lc_objectproperty.h index 36c97394..6746d915 100644 --- a/common/lc_objectproperty.h +++ b/common/lc_objectproperty.h @@ -96,6 +96,8 @@ public: void Save(QTextStream& Stream, const char* ObjectName, const char* VariableName, bool SaveEmpty) const; bool Load(QTextStream& Stream, const QString& Token, const char* VariableName); + void SaveToDataStream(QDataStream& Stream) const; + bool LoadFromDataStream(QDataStream& Stream); protected: T mValue; diff --git a/common/light.cpp b/common/light.cpp index 4dc4399c..a8c6bcd0 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1506,3 +1506,43 @@ void lcLight::RemoveKeyFrames() mPOVRayFadeDistance.RemoveAllKeys(); mPOVRayFadePower.RemoveAllKeys(); } + +void lcLight::SaveKeyFrames(QDataStream& Stream) const +{ + mPosition.SaveToDataStream(Stream); + mRotation.SaveToDataStream(Stream); + mColor.SaveToDataStream(Stream); + mSpotConeAngle.SaveToDataStream(Stream); + mSpotPenumbraAngle.SaveToDataStream(Stream); + mPOVRaySpotTightness.SaveToDataStream(Stream); + mPOVRayAreaGridX.SaveToDataStream(Stream); + mPOVRayAreaGridY.SaveToDataStream(Stream); + mBlenderRadius.SaveToDataStream(Stream); + mBlenderAngle.SaveToDataStream(Stream); + mAreaSizeX.SaveToDataStream(Stream); + mAreaSizeY.SaveToDataStream(Stream); + mBlenderPower.SaveToDataStream(Stream); + mPOVRayPower.SaveToDataStream(Stream); + mPOVRayFadeDistance.SaveToDataStream(Stream); + mPOVRayFadePower.SaveToDataStream(Stream); +} + +bool lcLight::LoadKeyFrames(QDataStream& Stream) +{ + return mPosition.LoadFromDataStream(Stream) && + mRotation.LoadFromDataStream(Stream) && + mColor.LoadFromDataStream(Stream) && + mSpotConeAngle.LoadFromDataStream(Stream) && + mSpotPenumbraAngle.LoadFromDataStream(Stream) && + mPOVRaySpotTightness.LoadFromDataStream(Stream) && + mPOVRayAreaGridX.LoadFromDataStream(Stream) && + mPOVRayAreaGridY.LoadFromDataStream(Stream) && + mBlenderRadius.LoadFromDataStream(Stream) && + mBlenderAngle.LoadFromDataStream(Stream) && + mAreaSizeX.LoadFromDataStream(Stream) && + mAreaSizeY.LoadFromDataStream(Stream) && + mBlenderPower.LoadFromDataStream(Stream) && + mPOVRayPower.LoadFromDataStream(Stream) && + mPOVRayFadeDistance.LoadFromDataStream(Stream) && + mPOVRayFadePower.LoadFromDataStream(Stream); +} diff --git a/common/light.h b/common/light.h index 46aa1f12..fd1193a7 100644 --- a/common/light.h +++ b/common/light.h @@ -218,6 +218,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; + void SaveKeyFrames(QDataStream& Stream) const override; + bool LoadKeyFrames(QDataStream& Stream) override; void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/object.h b/common/object.h index e6e0ad77..323aea3f 100644 --- a/common/object.h +++ b/common/object.h @@ -107,6 +107,8 @@ public: virtual bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const = 0; virtual bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) = 0; virtual void RemoveKeyFrames() = 0; + virtual void SaveKeyFrames(QDataStream& Stream) const = 0; + virtual bool LoadKeyFrames(QDataStream& Stream) = 0; virtual QString GetName() const = 0; static QString GetCheckpointString(lcObjectPropertyId PropertyId); diff --git a/common/piece.cpp b/common/piece.cpp index d15650a8..e7e1b82e 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -907,6 +907,17 @@ void lcPiece::RemoveKeyFrames() mRotation.RemoveAllKeys(); } +void lcPiece::SaveKeyFrames(QDataStream& Stream) const +{ + mPosition.SaveToDataStream(Stream); + mRotation.SaveToDataStream(Stream); +} + +bool lcPiece::LoadKeyFrames(QDataStream& Stream) +{ + return mPosition.LoadFromDataStream(Stream) && mRotation.LoadFromDataStream(Stream); +} + void lcPiece::AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const { lcRenderMeshState RenderMeshState = lcRenderMeshState::Default; diff --git a/common/piece.h b/common/piece.h index 950479c0..b66c3851 100644 --- a/common/piece.h +++ b/common/piece.h @@ -114,6 +114,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; + void SaveKeyFrames(QDataStream& Stream) const override; + bool LoadKeyFrames(QDataStream& Stream) override; void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const; void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const; From 460bb0b8e247c943719a850f40d9b731d375f5bc Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Wed, 19 Nov 2025 23:10:18 -0800 Subject: [PATCH 11/93] Fixed warnings. --- common/camera.cpp | 6 ++---- common/lc_file.cpp | 2 +- common/lc_file.h | 6 +++--- common/lc_glextensions.cpp | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 9c59bc46..536d6838 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -1,8 +1,6 @@ #include "lc_global.h" #include "lc_math.h" -#include "lc_colors.h" #include -#include #include #include #include "lc_file.h" @@ -28,7 +26,7 @@ lcCamera::lcCamera(bool Simple) mTargetPosition.SetValue(lcVector3(0.0f, 0.0f, 0.0f)); mUpVector.SetValue(lcVector3(-0.2357f, -0.2357f, 0.94281f)); - UpdatePosition(1); + lcCamera::UpdatePosition(1); } } @@ -51,7 +49,7 @@ lcCamera::lcCamera(float ex, float ey, float ez, float tx, float ty, float tz) mTargetPosition.SetValue(lcVector3(tx, ty, tz)); mUpVector.SetValue(UpVector); - UpdatePosition(1); + lcCamera::UpdatePosition(1); } lcCamera::~lcCamera() diff --git a/common/lc_file.cpp b/common/lc_file.cpp index ac75d57b..60c756ea 100644 --- a/common/lc_file.cpp +++ b/common/lc_file.cpp @@ -16,7 +16,7 @@ lcMemFile::lcMemFile() lcMemFile::~lcMemFile() { - Close(); + lcMemFile::Close(); } void lcMemFile::Seek(qint64 Offset, int From) diff --git a/common/lc_file.h b/common/lc_file.h index 9d4e958d..adbf97e1 100644 --- a/common/lc_file.h +++ b/common/lc_file.h @@ -459,7 +459,7 @@ class lcMemFile : public lcFile { public: lcMemFile(); - ~lcMemFile(); + virtual ~lcMemFile(); lcMemFile(const lcMemFile&) = delete; lcMemFile(lcMemFile&&) = delete; @@ -498,9 +498,9 @@ public: { } - ~lcDiskFile() + virtual ~lcDiskFile() { - Close(); + lcDiskFile::Close(); } lcDiskFile(const lcDiskFile&) = delete; diff --git a/common/lc_glextensions.cpp b/common/lc_glextensions.cpp index 98cc0432..58efd2e2 100644 --- a/common/lc_glextensions.cpp +++ b/common/lc_glextensions.cpp @@ -31,7 +31,7 @@ static void APIENTRY lcGLDebugCallback(GLenum Source, GLenum Type, GLuint Id, GL void lcInitializeGLExtensions(const QOpenGLContext* Context) { - const QOpenGLFunctions* Functions = Context->functions(); + QOpenGLFunctions* Functions = Context->functions(); #if !defined(QT_NO_DEBUG) && defined(GL_ARB_debug_output) if (Context->hasExtension("GL_KHR_debug")) @@ -53,7 +53,7 @@ void lcInitializeGLExtensions(const QOpenGLContext* Context) if (Context->hasExtension("GL_EXT_texture_filter_anisotropic")) { - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gMaxAnisotropy); + Functions->glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gMaxAnisotropy); gSupportsAnisotropic = true; } From 3ff6f06f0421ddcab32507de5dd6d3986e7acc4f Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 20 Nov 2025 22:57:18 -0800 Subject: [PATCH 12/93] Fixed warnings. --- common/lc_bricklink.cpp | 6 +-- common/lc_colors.cpp | 8 ++-- common/lc_mesh.cpp | 24 +++++----- common/lc_model.cpp | 39 +-------------- common/lc_objectproperty.cpp | 2 +- common/lc_synth.cpp | 89 ++++++++++++++++------------------- common/lc_viewmanipulator.cpp | 2 +- 7 files changed, 65 insertions(+), 105 deletions(-) diff --git a/common/lc_bricklink.cpp b/common/lc_bricklink.cpp index af55fb09..98b09b2c 100644 --- a/common/lc_bricklink.cpp +++ b/common/lc_bricklink.cpp @@ -109,15 +109,15 @@ void lcExportBrickLink(const QString& SaveFileName, const lcPartsList& PartsList { BrickLinkFile.WriteLine(" \n"); BrickLinkFile.WriteLine(" P\n"); - sprintf(Line, " %s\n", Item.second.mId.c_str()); + snprintf(Line, sizeof(Line), " %s\n", Item.second.mId.c_str()); BrickLinkFile.WriteLine(Line); - sprintf(Line, " %d\n", Item.second.mCount); + snprintf(Line, sizeof(Line), " %d\n", Item.second.mCount); BrickLinkFile.WriteLine(Line); if (Item.second.mColor) { - sprintf(Line, " %d\n", Item.second.mColor); + snprintf(Line, sizeof(Line), " %d\n", Item.second.mColor); BrickLinkFile.WriteLine(Line); } diff --git a/common/lc_colors.cpp b/common/lc_colors.cpp index a1bfcc82..3b77be85 100644 --- a/common/lc_colors.cpp +++ b/common/lc_colors.cpp @@ -394,8 +394,8 @@ int lcGetColorIndex(quint32 ColorCode) Color.Value[1] = (float)((ColorCode & 0x00ff00) >> 8) / 255.0f; Color.Value[2] = (float)((ColorCode & 0x0000ff) >> 0) / 255.0f; Color.Value[3] = 1.0f; - sprintf(Color.Name, "Color %06X", ColorCode & 0xffffff); - sprintf(Color.SafeName, "Color_%06X", ColorCode & 0xffffff); + snprintf(Color.Name, sizeof(Color.Name), "Color %06X", ColorCode & 0xffffff); + snprintf(Color.SafeName, sizeof(Color.SafeName), "Color_%06X", ColorCode & 0xffffff); } else { @@ -403,8 +403,8 @@ int lcGetColorIndex(quint32 ColorCode) Color.Value[1] = 0.5f; Color.Value[2] = 0.5f; Color.Value[3] = 1.0f; - sprintf(Color.Name, "Color %03d", ColorCode); - sprintf(Color.SafeName, "Color_%03d", ColorCode); + snprintf(Color.Name, sizeof(Color.Name), "Color %03d", ColorCode); + snprintf(Color.SafeName, sizeof(Color.SafeName), "Color_%03d", ColorCode); } gColorList.push_back(Color); diff --git a/common/lc_mesh.cpp b/common/lc_mesh.cpp index bd9c0951..2222faa1 100644 --- a/common/lc_mesh.cpp +++ b/common/lc_mesh.cpp @@ -284,9 +284,9 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color } if (NumSections > 1) - sprintf(Line, "#declare lc_%s = union {\n", MeshName); + snprintf(Line, sizeof(Line), "#declare lc_%s = union {\n", MeshName); else - sprintf(Line, "#declare lc_%s = mesh {\n", MeshName); + snprintf(Line, sizeof(Line), "#declare lc_%s = mesh {\n", MeshName); File.WriteLine(Line); for (int SectionIdx = 0; SectionIdx < mLods[LC_MESH_LOD_HIGH].NumSections; SectionIdx++) @@ -310,8 +310,8 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal); const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal); - sprintf(Line, " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n", - -v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z); + snprintf(Line, sizeof(Line), " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n", + -v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z); File.WriteLine(Line); } } @@ -332,8 +332,8 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal); const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal); - sprintf(Line, " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n", - -v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z); + snprintf(Line, sizeof(Line), " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n", + -v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z); File.WriteLine(Line); } } @@ -342,7 +342,7 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color if (Section->ColorIndex != gDefaultColor) { - sprintf(Line, " material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]); + snprintf(Line, sizeof(Line), " material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]); File.WriteLine(Line); } @@ -376,9 +376,9 @@ void lcMesh::ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int Ver IndexType* Indices = (IndexType*)mIndexData + Section->IndexOffset / sizeof(IndexType); if (Section->ColorIndex == gDefaultColor) - sprintf(Line, "usemtl %s\n", gColorList[DefaultColorIndex].SafeName); + snprintf(Line, sizeof(Line), "usemtl %s\n", gColorList[DefaultColorIndex].SafeName); else - sprintf(Line, "usemtl %s\n", gColorList[Section->ColorIndex].SafeName); + snprintf(Line, sizeof(Line), "usemtl %s\n", gColorList[Section->ColorIndex].SafeName); File.WriteLine(Line); for (int Idx = 0; Idx < Section->NumIndices; Idx += 3) @@ -388,8 +388,10 @@ void lcMesh::ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int Ver const long int idx3 = Indices[Idx + 2] + VertexOffset; if (idx1 != idx2 && idx1 != idx3 && idx2 != idx3) - sprintf(Line, "f %ld//%ld %ld//%ld %ld//%ld\n", idx1, idx1, idx2, idx2, idx3, idx3); - File.WriteLine(Line); + { + snprintf(Line, sizeof(Line), "f %ld//%ld %ld//%ld %ld//%ld\n", idx1, idx1, idx2, idx2, idx3, idx3); + File.WriteLine(Line); + } } } diff --git a/common/lc_model.cpp b/common/lc_model.cpp index f1fb4c9f..d6663842 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2387,55 +2387,20 @@ void lcModel::InsertStep(lcStep Step) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordSelectionAction(lcModelActionSelectionMode::Set); RecordStepAction(lcModelActionStepMode::Insert, Step); -// RecordSelectionAction(lcModelActionSelectionMode::Save); EndActionSequence(tr("Insert Step")); - -/* - for (const std::unique_ptr& Piece : mPieces) - { - Piece->InsertTime(Step, 1); - if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - } - - for (std::unique_ptr& Camera : mCameras) - Camera->InsertTime(Step, 1); - - for (const std::unique_ptr& Light : mLights) - Light->InsertTime(Step, 1); - - SaveCheckpoint(tr("Inserting Step")); - SetCurrentStep(mCurrentStep);*/ } void lcModel::RemoveStep(lcStep Step) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordSelectionAction(lcModelActionSelectionMode::Set); RecordStepAction(lcModelActionStepMode::Remove, Step); - // RecordSelectionAction(lcModelActionSelectionMode::Save); EndActionSequence(tr("Remove Step")); - /* - for (const std::unique_ptr& Piece : mPieces) - { - Piece->RemoveTime(Step, 1); - if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - } - - for (std::unique_ptr& Camera : mCameras) - Camera->RemoveTime(Step, 1); - - for (const std::unique_ptr& Light : mLights) - Light->RemoveTime(Step, 1); - - SaveCheckpoint(tr("Removing Step")); - SetCurrentStep(mCurrentStep);*/ } lcGroup* lcModel::AddGroup(const QString& Prefix, lcGroup* Parent) diff --git a/common/lc_objectproperty.cpp b/common/lc_objectproperty.cpp index 5dab936e..1a2e7850 100644 --- a/common/lc_objectproperty.cpp +++ b/common/lc_objectproperty.cpp @@ -335,7 +335,7 @@ bool lcObjectProperty::LoadFromDataStream(QDataStream& Stream) mKeys.resize(KeyCount); - int DataSize = KeyCount * sizeof(lcObjectPropertyKey); + size_t DataSize = KeyCount * sizeof(lcObjectPropertyKey); if (Stream.readRawData(reinterpret_cast(mKeys.data()), DataSize) != DataSize) return false; diff --git a/common/lc_synth.cpp b/common/lc_synth.cpp index 5c8988b1..16835d9f 100644 --- a/common/lc_synth.cpp +++ b/common/lc_synth.cpp @@ -957,8 +957,8 @@ void lcSynthInfoFlexibleHose::AddParts(lcMemFile& File, lcLibraryMeshData&, cons lcMatrix33 Transform(lcMul(lcMul(EdgeTransforms[PartIdx], lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, -5.0f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); File.WriteBuffer(Line, strlen(Line)); } @@ -977,8 +977,8 @@ void lcSynthInfoFlexibleHose::AddParts(lcMemFile& File, lcLibraryMeshData&, cons const char* Part = SectionIndex != Sections.size() / 2 ? "754.dat" : "756.dat"; - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], Part); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], Part); File.WriteBuffer(Line, strlen(Line)); } @@ -989,8 +989,8 @@ void lcSynthInfoFlexibleHose::AddParts(lcMemFile& File, lcLibraryMeshData&, cons lcMatrix33 Transform(lcMul(EdgeTransforms[PartIdx], lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, 5.0f - 2.56f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); File.WriteBuffer(Line, strlen(Line)); } @@ -1082,8 +1082,8 @@ void lcSynthInfoFlexSystemHose::AddParts(lcMemFile& File, lcLibraryMeshData& Mes lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(-1.0f, 1.0f, 1.0f)), lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, -1.0f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); File.WriteBuffer(Line, strlen(Line)); } @@ -1093,8 +1093,8 @@ void lcSynthInfoFlexSystemHose::AddParts(lcMemFile& File, lcLibraryMeshData& Mes lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f)), lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, 1.0f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f u9053.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); File.WriteBuffer(Line, strlen(Line)); } @@ -1116,9 +1116,8 @@ void lcSynthInfoPneumaticTube::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh lcMatrix33 Transform(lcMul(lcMul(EdgeTransform, lcMatrix33Scale(lcVector3(1.0f, 1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, 0.0f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], - mEndPart); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart); File.WriteBuffer(Line, strlen(Line)); } @@ -1129,9 +1128,8 @@ void lcSynthInfoPneumaticTube::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh lcMatrix33 Transform(lcMul(lcMul(EdgeTransform, lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, 0.0f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], - mEndPart); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart); File.WriteBuffer(Line, strlen(Line)); } @@ -1152,8 +1150,8 @@ void lcSynthInfoRibbedHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const lcMatrix33 Transform(lcMul(lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f)), lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = Sections[SectionIndex].GetTranslation(); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); File.WriteBuffer(Line, strlen(Line)); } @@ -1162,8 +1160,8 @@ void lcSynthInfoRibbedHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const { const lcMatrix44& Transform = Sections[SectionIndex]; - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 80.dat\n", Transform[3][0], Transform[3][1], Transform[3][2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 80.dat\n", Transform[3][0], Transform[3][1], Transform[3][2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); File.WriteBuffer(Line, strlen(Line)); } @@ -1173,8 +1171,8 @@ void lcSynthInfoRibbedHose::AddParts(lcMemFile& File, lcLibraryMeshData&, const lcMatrix33 Transform(Sections[SectionIndex]); lcVector3 Offset = lcMul31(lcVector3(0.0f, -6.25f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 79.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); File.WriteBuffer(Line, strlen(Line)); } @@ -1209,8 +1207,8 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD lcMatrix33 Transform(lcMul(lcMul(EdgeTransforms[PartIdx], lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, -4.0f * (5 - PartIdx), 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); File.WriteBuffer(Line, strlen(Line)); } @@ -1221,8 +1219,8 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD lcMatrix33 Transform(lcMul(EdgeTransforms[PartIdx], lcMatrix33(Sections[SectionIndex]))); lcVector3 Offset = lcMul31(lcVector3(0.0f, 4.0f * (5 - PartIdx), 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], EdgeParts[PartIdx]); File.WriteBuffer(Line, strlen(Line)); } @@ -1332,8 +1330,8 @@ void lcSynthInfoBraidedString::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh lcMatrix33 Transform(Sections[SectionIndex]); lcVector3 Offset = lcMul31(lcVector3(-8.0f, 0.0f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); File.WriteBuffer(Line, strlen(Line)); } @@ -1439,8 +1437,8 @@ void lcSynthInfoBraidedString::AddParts(lcMemFile& File, lcLibraryMeshData& Mesh lcMatrix33 Transform(Sections[SectionIndex]); lcVector3 Offset = lcMul31(lcVector3(8.0f, 0.0f, 0.0f), Sections[SectionIndex]); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f 572A.dat\n", Offset[0], Offset[1], Offset[2], Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2]); File.WriteBuffer(Line, strlen(Line)); } @@ -1452,18 +1450,18 @@ void lcSynthInfoShockAbsorber::AddParts(lcMemFile& File, lcLibraryMeshData&, con lcVector3 Offset; Offset = Sections[0].GetTranslation(); - sprintf(Line, "1 0 %f %f %f 1 0 0 0 1 0 0 0 1 4254.dat\n", Offset[0], Offset[1], Offset[2]); + snprintf(Line, sizeof(Line), "1 0 %f %f %f 1 0 0 0 1 0 0 0 1 4254.dat\n", Offset[0], Offset[1], Offset[2]); File.WriteBuffer(Line, strlen(Line)); Offset = Sections[1].GetTranslation(); - sprintf(Line, "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 4255.dat\n", Offset[0], Offset[1], Offset[2]); + snprintf(Line, sizeof(Line), "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 4255.dat\n", Offset[0], Offset[1], Offset[2]); File.WriteBuffer(Line, strlen(Line)); float Distance = Sections[0].GetTranslation().y - Sections[1].GetTranslation().y; float Scale = (Distance - 66.0f) / 44.0f; Offset = Sections[0].GetTranslation(); - sprintf(Line, "1 494 %f %f %f 1 0 0 0 %f 0 0 0 1 %s\n", Offset[0], Offset[1] - 10 - 44.0f * Scale, Offset[2], Scale, mSpringPart); + snprintf(Line, sizeof(Line), "1 494 %f %f %f 1 0 0 0 %f 0 0 0 1 %s\n", Offset[0], Offset[1] - 10 - 44.0f * Scale, Offset[2], Scale, mSpringPart); File.WriteBuffer(Line, strlen(Line)); } @@ -1473,15 +1471,15 @@ void lcSynthInfoActuator::AddParts(lcMemFile& File, lcLibraryMeshData&, const st lcVector3 Offset; Offset = Sections[0].GetTranslation(); - sprintf(Line, "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mBodyPart); + snprintf(Line, sizeof(Line), "1 16 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mBodyPart); File.WriteBuffer(Line, strlen(Line)); Offset = lcMul(Sections[0], lcMatrix44Translation(lcVector3(0.0f, 0.0f, mAxleOffset))).GetTranslation(); - sprintf(Line, "1 25 %f %f %f 0 1 0 -1 0 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mAxlePart); + snprintf(Line, sizeof(Line), "1 25 %f %f %f 0 1 0 -1 0 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mAxlePart); File.WriteBuffer(Line, strlen(Line)); Offset = Sections[1].GetTranslation(); - sprintf(Line, "1 72 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mPistonPart); + snprintf(Line, sizeof(Line), "1 72 %f %f %f 1 0 0 0 1 0 0 0 1 %s\n", Offset[0], Offset[1], Offset[2], mPistonPart); File.WriteBuffer(Line, strlen(Line)); } @@ -1494,27 +1492,22 @@ void lcSynthInfoUniversalJoint::AddParts(lcMemFile& File, lcLibraryMeshData&, co lcMatrix44 Rotation = lcMatrix44RotationZ(Angle); lcMatrix44 Transform = lcMatrix44LeoCADToLDraw(Rotation); - sprintf(Line, "1 16 0 0 0 %f %f %f %f %f %f %f %f %f %s\n", Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mCenterPart); + snprintf(Line, sizeof(Line), "1 16 0 0 0 %f %f %f %f %f %f %f %f %f %s\n", Transform[0][0], Transform[1][0], Transform[2][0], + Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mCenterPart); File.WriteBuffer(Line, strlen(Line)); Angle = atan2f(Offset.y, hypotf(Offset.x, Offset.z)); Rotation = lcMul(Rotation, lcMatrix44RotationX(Angle)); - Transform = lcMul( - lcMatrix44Translation(lcVector3(0.0f, 0.0f, mEndOffset)), - lcMatrix44LeoCADToLDraw(Rotation) - ); + Transform = lcMul(lcMatrix44Translation(lcVector3(0.0f, 0.0f, mEndOffset)), lcMatrix44LeoCADToLDraw(Rotation)); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2], - Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2], + Transform[0][0], Transform[1][0], Transform[2][0], Transform[0][1], Transform[1][1], Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart); File.WriteBuffer(Line, strlen(Line)); Rotation = lcMatrix44FromEulerAngles(lcVector3(0.0f, LC_PI/2, LC_PI)); Transform = lcMatrix44LeoCADToLDraw(lcMul(lcMatrix44Translation(lcVector3(0.0f, mEndOffset, 0.0f)), Rotation)); - sprintf(Line, "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2], - Transform[0][0], Transform[1][0], Transform[2][0], - Transform[0][1], Transform[1][1], -Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart); + snprintf(Line, sizeof(Line), "1 16 %f %f %f %f %f %f %f %f %f %f %f %f %s\n", Transform[3][0], Transform[3][1], Transform[3][2], + Transform[0][0], Transform[1][0], Transform[2][0], Transform[0][1], Transform[1][1], -Transform[2][1], Transform[0][2], Transform[1][2], Transform[2][2], mEndPart); File.WriteBuffer(Line, strlen(Line)); } diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index 6d60216c..0af8ad8f 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -890,7 +890,7 @@ void lcViewManipulator::DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackT Context->EnableColorBlend(true); char buf[32]; - sprintf(buf, "[%.2f]", fabsf(Angle)); + snprintf(buf, sizeof(buf), "[%.2f]", fabsf(Angle)); int cx, cy; gTexFont.GetStringDimensions(&cx, &cy, buf); From 3bf01f2095afe87bcdabce362f261afb35835fc7 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 23 Nov 2025 20:33:59 -0800 Subject: [PATCH 13/93] Added actions for mouse drag changes. --- common/camera.cpp | 13 ++ common/camera.h | 4 +- common/lc_lxf.cpp | 2 +- common/lc_model.cpp | 270 ++++++++++++++++++++++++++++++++--- common/lc_model.h | 12 +- common/lc_modelaction.cpp | 99 +++++++++++++ common/lc_modelaction.h | 45 ++++++ common/lc_objectproperty.cpp | 6 +- common/lc_view.cpp | 16 +-- common/light.cpp | 23 +++ common/light.h | 2 + common/piece.cpp | 46 ++++-- common/piece.h | 6 +- 13 files changed, 496 insertions(+), 48 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 536d6838..f4da2ebc 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -56,6 +56,19 @@ lcCamera::~lcCamera() { } +void lcCamera::CopyProperties(const lcCamera& Other) +{ + m_fovy = Other.m_fovy; + m_zNear = Other.m_zNear; + m_zFar = Other.m_zFar; + + mPosition = Other.mPosition; + mTargetPosition = Other.mTargetPosition; + mUpVector = Other.mUpVector; + + SetOrtho(Other.IsOrtho()); +} + QString lcCamera::GetCameraTypeString(lcCameraType CameraType) { switch (CameraType) diff --git a/common/camera.h b/common/camera.h index 7c35778d..2b1802e6 100644 --- a/common/camera.h +++ b/common/camera.h @@ -48,7 +48,7 @@ class lcCamera : public lcObject public: lcCamera(bool Simple); lcCamera(float ex, float ey, float ez, float tx, float ty, float tz); - ~lcCamera(); + virtual ~lcCamera(); lcCamera(const lcCamera&) = delete; lcCamera(lcCamera&&) = delete; @@ -59,6 +59,8 @@ public: static QStringList GetCameraTypeStrings(); static lcViewpoint GetViewpoint(const QString& ViewpointName); + void CopyProperties(const lcCamera& Other); + QString GetName() const override { return mName; diff --git a/common/lc_lxf.cpp b/common/lc_lxf.cpp index 11038045..892e45eb 100644 --- a/common/lc_lxf.cpp +++ b/common/lc_lxf.cpp @@ -179,7 +179,7 @@ bool lcImportLXFMLFile(const QString& FileData, std::vector& Pieces, s lcVector4(-WorldMatrix[2][0], WorldMatrix[2][1], WorldMatrix[2][2], 0.0f), lcVector4(WorldMatrix[3][0] * 25.0f, -WorldMatrix[3][1] * 25.0f, -WorldMatrix[3][2] * 25.0f, 1.0f)); lcPiece* Piece = new lcPiece(nullptr); - Piece->SetPieceInfo(Info, QString(), false); + Piece->SetPieceInfo(Info, QString(), false, true); Piece->Initialize(lcMatrix44LDrawToLeoCAD(WorldMatrix), 1); Piece->SetColorCode(ColorCode); Pieces.push_back(Piece); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index d6663842..f8985962 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -331,6 +331,15 @@ void lcModel::UpdatePieceInfo(std::vector& UpdatedModels) mPieceInfo->SetBoundingBox(Min, Max); } +lcCamera* lcModel::GetCamera(const QString& Name) const +{ + for (const std::unique_ptr& Camera : mCameras) + if (Camera->GetName() == Name) + return Camera.get(); + + return nullptr; +} + void lcModel::SaveLDraw(QTextStream& Stream, bool SelectedOnly, lcStep LastStep) const { const QLatin1String LineEnding("\r\n"); @@ -737,7 +746,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) lcVector4(-Matrix[4], -Matrix[6], Matrix[5], 0.0f), lcVector4(Matrix[12], Matrix[14], -Matrix[13], 1.0f)); Piece->SetFileLine(mFileLines.size()); - Piece->SetPieceInfo(Info, PartId, false); + Piece->SetPieceInfo(Info, PartId, false, true); Piece->Initialize(Transform, CurrentStep); Piece->SetColorCode(ColorCode); Piece->VerifyControlPoints(ControlPoints); @@ -1073,7 +1082,7 @@ bool lcModel::LoadInventory(const QByteArray& Inventory) while (Quantity--) { lcPiece* Piece = new lcPiece(nullptr); - Piece->SetPieceInfo(Info, QString(), false); + Piece->SetPieceInfo(Info, QString(), false, true); Piece->Initialize(lcMatrix44Identity(), 1); Piece->SetColorCode(ColorCode); AddPiece(Piece); @@ -1714,6 +1723,167 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect } } +void lcModel::BeginMouseToolAction(lcTool Tool, lcView* View) +{ + std::unique_ptr ModelActionMouseTool = std::make_unique(Tool); + + switch (Tool) + { + case lcTool::Insert: + case lcTool::PointLight: + case lcTool::SpotLight: + case lcTool::DirectionalLight: + case lcTool::AreaLight: + break; + +// case lcTool::Camera: +// SaveCheckpoint(tr("New Camera")); +// break; + + case lcTool::Select: + break; + + case lcTool::Move: + case lcTool::Rotate: + ModelActionMouseTool->SaveSelectionStartState(this); + break; + + case lcTool::Eraser: + case lcTool::Paint: + case lcTool::ColorPicker: + break; + + case lcTool::Zoom: + case lcTool::Pan: + case lcTool::RotateView: + case lcTool::Roll: + ModelActionMouseTool->SetCameraStartState(View->GetCamera()); + break; + + case lcTool::ZoomRegion: + break; + + case lcTool::Count: + break; + } + + mActionSequence.emplace_back(std::move(ModelActionMouseTool)); +} + +void lcModel::EndMouseToolAction(lcTool Tool, lcView* View, const QString& Description) +{ + if (mActionSequence.empty()) + return; + + lcModelActionMouseTool* ModelActionMouseTool = dynamic_cast(mActionSequence.back().get()); + + if (!ModelActionMouseTool || Tool != ModelActionMouseTool->GetTool()) + return; + + switch (Tool) + { + case lcTool::Insert: + case lcTool::PointLight: + case lcTool::SpotLight: + case lcTool::DirectionalLight: + case lcTool::AreaLight: + break; + +// case lcTool::Camera: +// SaveCheckpoint(tr("New Camera")); +// break; + + case lcTool::Select: + break; + + case lcTool::Move: + case lcTool::Rotate: + ModelActionMouseTool->SaveSelectionEndState(this); + break; + + case lcTool::Eraser: + case lcTool::Paint: + case lcTool::ColorPicker: + break; + + case lcTool::Zoom: + case lcTool::Pan: + case lcTool::RotateView: + case lcTool::Roll: + ModelActionMouseTool->SetCameraEndState(View->GetCamera()); + break; + + case lcTool::ZoomRegion: + break; + + case lcTool::Count: + break; + } + + RecordSelectionAction(lcModelActionSelectionMode::Set); + EndActionSequence(Description); +} + +void lcModel::RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseTool, bool Apply) +{ + if (!ModelActionMouseTool) + return; + + lcTool Tool = ModelActionMouseTool->GetTool(); + + switch (Tool) + { + case lcTool::Insert: + case lcTool::PointLight: + case lcTool::SpotLight: + case lcTool::DirectionalLight: + case lcTool::AreaLight: + break; + +// case lcTool::Camera: +// SaveCheckpoint(tr("New Camera")); +// break; + + case lcTool::Select: + break; + + case lcTool::Move: + case lcTool::Rotate: + if (Apply) + ModelActionMouseTool->LoadSelectionEndState(this); + else + ModelActionMouseTool->LoadSelectionStartState(this); + SetCurrentStep(mCurrentStep); + break; + + case lcTool::Eraser: + case lcTool::Paint: + case lcTool::ColorPicker: + break; + + case lcTool::Zoom: + case lcTool::Pan: + case lcTool::RotateView: + case lcTool::Roll: + if (lcCamera* Camera = GetCamera(ModelActionMouseTool->GetCameraName())) + { + const QByteArray& State = Apply ? ModelActionMouseTool->GetEndState() : ModelActionMouseTool->GetStartState(); + QDataStream Stream(const_cast(&State), QIODevice::ReadOnly); + + Camera->LoadKeyFrames(Stream); + + SetCurrentStep(mCurrentStep); + } + break; + + case lcTool::ZoomRegion: + break; + + case lcTool::Count: + break; + } +} + void lcModel::RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode) { std::unique_ptr ModelActionAddPieces = std::make_unique(mCurrentStep, SelectionMode); @@ -2168,6 +2338,8 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunSelectionAction(ModelActionSelection, Apply); + else if (const lcModelActionMouseTool* ModelActionMouseTool = dynamic_cast(ModelAction)) + RunMouseToolAction(ModelActionMouseTool, Apply); else if (const lcModelActionAddPieces* ModelActionAddPieces = dynamic_cast(ModelAction)) RunAddPiecesAction(ModelActionAddPieces, Apply); else if (const lcModelActionAddLight* ModelActionAddLight = dynamic_cast(ModelAction)) @@ -2215,8 +2387,11 @@ void lcModel::EndActionSequence(const QString& Description) gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); } -void lcModel::CancelActionSequence() +void lcModel::RevertActionSequence() { + PerformActionSequence(mActionSequence, false); + + mActionSequence.clear(); } void lcModel::SaveCheckpoint(const QString& ) @@ -3328,7 +3503,7 @@ void lcModel::InlineSelectedModels() if (ColorIndex == gDefaultColor) ColorIndex = Piece->GetColorIndex(); - NewPiece->SetPieceInfo(ModelPiece->mPieceInfo, ModelPiece->GetID(), true); + NewPiece->SetPieceInfo(ModelPiece->mPieceInfo, ModelPiece->GetID(), true, true); NewPiece->Initialize(lcMul(ModelPiece->mModelWorld, Piece->mModelWorld), Piece->GetStepShow()); NewPiece->SetColorIndex(ColorIndex); NewPiece->UpdatePosition(mCurrentStep); @@ -3916,7 +4091,7 @@ void lcModel::EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept) { if (!Accept) { - CancelActionSequence(); + RevertActionSequence(); return; } @@ -4858,7 +5033,7 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) Piece->SetColorIndex(Params.ReplaceColorIndex); if (ReplacePieceInfo) - Piece->SetPieceInfo(Params.ReplacePieceInfo, QString(), true); + Piece->SetPieceInfo(Params.ReplacePieceInfo, QString(), true, true); }; size_t StartIndex = mPieces.size() - 1; @@ -4979,17 +5154,68 @@ void lcModel::RedoAction() gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); } -void lcModel::BeginMouseTool() +void lcModel::BeginMouseTool(lcTool Tool, lcView* View) { + switch (Tool) + { + case lcTool::Insert: + case lcTool::PointLight: + case lcTool::SpotLight: + case lcTool::DirectionalLight: + case lcTool::AreaLight: + break; + +// case lcTool::Camera: +// { +// lcVector3 Position = GetCameraLightInsertPosition(); +// lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); +// ActiveModel->BeginCameraTool(Position, Target); +// } +// break; + + case lcTool::Select: + break; + + case lcTool::Move: + case lcTool::Rotate: + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::Set); + BeginMouseToolAction(Tool, View); + break; + + case lcTool::Eraser: + case lcTool::Paint: + case lcTool::ColorPicker: + break; + + case lcTool::Pan: + case lcTool::Zoom: + case lcTool::RotateView: + case lcTool::Roll: + if (!View->GetCamera()->IsSimple()) + { + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::Set); + BeginMouseToolAction(Tool, View); + } + break; + + case lcTool::ZoomRegion: + break; + + case lcTool::Count: + break; + } + mMouseToolDistance = lcVector3(0.0f, 0.0f, 0.0f); mMouseToolFirstMove = true; } -void lcModel::EndMouseTool(lcTool Tool, bool Accept) +void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) { if (!Accept) { - CancelActionSequence(); + RevertActionSequence(); return; } @@ -5002,19 +5228,19 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) case lcTool::AreaLight: break; - case lcTool::Camera: - SaveCheckpoint(tr("New Camera")); - break; +// case lcTool::Camera: +// SaveCheckpoint(tr("New Camera")); +// break; case lcTool::Select: break; case lcTool::Move: - SaveCheckpoint(tr("Move")); + EndMouseToolAction(Tool, View, tr("Move")); break; case lcTool::Rotate: - SaveCheckpoint(tr("Rotate")); + EndMouseToolAction(Tool, View, tr("Rotate")); break; case lcTool::Eraser: @@ -5023,23 +5249,23 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) break; case lcTool::Zoom: - if (!gMainWindow->GetActiveView()->GetCamera()->IsSimple()) - SaveCheckpoint(tr("Zoom")); + if (!View->GetCamera()->IsSimple()) + EndMouseToolAction(Tool, View, tr("Zoom")); break; case lcTool::Pan: - if (!gMainWindow->GetActiveView()->GetCamera()->IsSimple()) - SaveCheckpoint(tr("Pan")); + if (!View->GetCamera()->IsSimple()) + EndMouseToolAction(Tool, View, tr("Pan")); break; case lcTool::RotateView: - if (!gMainWindow->GetActiveView()->GetCamera()->IsSimple()) - SaveCheckpoint(tr("Orbit")); + if (!View->GetCamera()->IsSimple()) + EndMouseToolAction(Tool, View, tr("Orbit")); break; case lcTool::Roll: - if (!gMainWindow->GetActiveView()->GetCamera()->IsSimple()) - SaveCheckpoint(tr("Roll")); + if (!View->GetCamera()->IsSimple()) + EndMouseToolAction(Tool, View, tr("Roll")); break; case lcTool::ZoomRegion: diff --git a/common/lc_model.h b/common/lc_model.h index 150f1940..b64c98e3 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -6,6 +6,7 @@ enum class lcObjectPropertyId; class lcModelAction; class lcModelActionSelection; +class lcModelActionMouseTool; class lcModelActionAddPieces; class lcModelActionAddLight; class lcModelActionGroupPieces; @@ -168,6 +169,8 @@ public: return mCameras; } + lcCamera* GetCamera(const QString& Name) const; + const std::vector>& GetLights() const { return mLights; @@ -351,8 +354,8 @@ public: return mMouseToolDistance; } - void BeginMouseTool(); - void EndMouseTool(lcTool Tool, bool Accept); + void BeginMouseTool(lcTool Tool, lcView* View); + void EndMouseTool(lcTool Tool, lcView* View, bool Accept); void InsertPieceToolClicked(const std::vector& PieceInfoTransforms); void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType); void BeginCameraTool(const lcVector3& Position, const lcVector3& Target); @@ -407,6 +410,9 @@ protected: void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); + void BeginMouseToolAction(lcTool Tool, lcView* View); + void EndMouseToolAction(lcTool Tool, lcView* View, const QString& Description); + void RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseTool, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); void RecordAddLightAction(const lcVector3& Position, lcLightType LightType); @@ -423,7 +429,7 @@ protected: void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); void EndActionSequence(const QString& Description); - void CancelActionSequence(); + void RevertActionSequence(); void SaveCheckpoint(const QString& Description); void LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 91a317cd..58319f62 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -107,6 +107,105 @@ std::tuple, lcObject*, uint32_t> lcModelActionSelection:: return { SelectedObjects, FocusObject, mFocusSection }; } +lcModelActionMouseTool::lcModelActionMouseTool(lcTool Tool) + : mTool( Tool ) +{ +} + +void lcModelActionMouseTool::SetCameraStartState(const lcCamera* Camera) +{ + QDataStream Stream(&mStartState, QIODevice::WriteOnly); + + Camera->SaveKeyFrames(Stream); + + mCameraName = Camera->GetName(); +} + +void lcModelActionMouseTool::SetCameraEndState(const lcCamera* Camera) +{ + QDataStream Stream(&mEndState, QIODevice::WriteOnly); + + Camera->SaveKeyFrames(Stream); +} + +void lcModelActionMouseTool::SaveSelectionStartState(const lcModel* Model) +{ + SaveSelectionState(Model, mStartState); +} + +void lcModelActionMouseTool::LoadSelectionStartState(lcModel* Model) const +{ + LoadSelectionState(Model, mStartState); +} + +void lcModelActionMouseTool::LoadSelectionEndState(lcModel* Model) const +{ + LoadSelectionState(Model, mEndState); +} + +void lcModelActionMouseTool::SaveSelectionEndState(const lcModel* Model) +{ + SaveSelectionState(Model, mEndState); +} + +void lcModelActionMouseTool::SaveSelectionState(const lcModel* Model, QByteArray& State) +{ + QTextStream Stream(&State, QIODevice::WriteOnly); + + Model->SaveLDraw(Stream, false, 0); +} + +void lcModelActionMouseTool::LoadSelectionState(lcModel* Model, const QByteArray& State) +{ + QBuffer Buffer(const_cast(&State)); + Buffer.open(QIODevice::ReadOnly); + + std::unique_ptr SavedModel = std::make_unique(QString(), Model->GetProject(), false); + SavedModel->LoadLDraw(Buffer, Model->GetProject()); + + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& SavedPieces = SavedModel->GetPieces(); + + if (Pieces.size() != SavedPieces.size()) + return; + + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + { + lcPiece* Piece = Pieces[PieceIndex].get(); + + if (Piece->IsSelected()) + Piece->CopyProperties(*SavedPieces[PieceIndex].get()); + } + + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& SavedCameras = SavedModel->GetCameras(); + + if (Cameras.size() != SavedCameras.size()) + return; + + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + { + lcCamera* Camera = Cameras[CameraIndex].get(); + + if (Camera->IsSelected()) + Camera->CopyProperties(*SavedCameras[CameraIndex].get()); + } + + const std::vector>& Lights = Model->GetLights(); + const std::vector>& SavedLights = SavedModel->GetLights(); + + if (Lights.size() != SavedLights.size()) + return; + + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + { + lcLight* Light = Lights[LightIndex].get(); + + if (Light->IsSelected()) + Light->CopyProperties(*SavedLights[LightIndex].get()); + } +} + lcModelActionAddPieces::lcModelActionAddPieces(lcStep Step, lcModelActionAddPieceSelectionMode SelectionMode) : mStep(Step), mSelectionMode(SelectionMode) { diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index a0b46700..8b800e70 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -5,6 +5,7 @@ struct lcInsertPieceInfo; enum class lcObjectType; enum class lcLightType; +enum class lcTool; class lcModelAction { @@ -45,6 +46,50 @@ protected: lcModelActionSelectionMode mMode = lcModelActionSelectionMode::Clear; }; +class lcModelActionMouseTool : public lcModelAction +{ +public: + lcModelActionMouseTool(lcTool Tool); + virtual ~lcModelActionMouseTool() = default; + + void SaveSelectionStartState(const lcModel* Model); + void LoadSelectionStartState(lcModel* Model) const; + void SaveSelectionEndState(const lcModel* Model); + void LoadSelectionEndState(lcModel* Model) const; + + void SetCameraStartState(const lcCamera* Camera); + void SetCameraEndState(const lcCamera* Camera); + + const QByteArray& GetStartState() const + { + return mStartState; + } + + const QByteArray& GetEndState() const + { + return mEndState; + } + + lcTool GetTool() const + { + return mTool; + } + + const QString& GetCameraName() const + { + return mCameraName; + } + +protected: + static void SaveSelectionState(const lcModel* Model, QByteArray& State); + static void LoadSelectionState(lcModel* Model, const QByteArray& State); + + lcTool mTool; + QString mCameraName; + QByteArray mStartState; + QByteArray mEndState; +}; + enum class lcModelActionAddPieceSelectionMode { FocusLast, diff --git a/common/lc_objectproperty.cpp b/common/lc_objectproperty.cpp index 1a2e7850..def6ac03 100644 --- a/common/lc_objectproperty.cpp +++ b/common/lc_objectproperty.cpp @@ -321,13 +321,17 @@ void lcObjectProperty::SaveToDataStream(QDataStream& Stream) const size_t KeyCount = mKeys.size(); size_t DataSize = KeyCount * sizeof(lcObjectPropertyKey); - Stream.writeRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)); + Stream.writeRawData(reinterpret_cast(&mValue), sizeof(mValue)); + Stream.writeRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)); Stream.writeRawData(reinterpret_cast(mKeys.data()), DataSize); } template bool lcObjectProperty::LoadFromDataStream(QDataStream& Stream) { + if (Stream.readRawData(reinterpret_cast(&mValue), sizeof(mValue)) != sizeof(mValue)) + return false; + size_t KeyCount; if (Stream.readRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)) != sizeof(KeyCount)) diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 842b7b2f..3f08632d 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2276,7 +2276,7 @@ void lcView::StartPanGesture() lcModel* ActiveModel = GetActiveModel(); StartPan(mWidth / 2, mHeight / 2); - ActiveModel->BeginMouseTool(); + ActiveModel->BeginMouseTool(lcTool::Pan, this); } void lcView::UpdatePanGesture(int dx, int dy) @@ -2336,7 +2336,7 @@ void lcView::EndPanGesture(bool Accept) { lcModel* ActiveModel = GetActiveModel(); - ActiveModel->EndMouseTool(lcTool::Pan, Accept); + ActiveModel->EndMouseTool(lcTool::Pan, this, Accept); } void lcView::StartTracking(lcTrackButton TrackButton) @@ -2370,7 +2370,7 @@ void lcView::StartTracking(lcTrackButton TrackButton) case lcTool::Move: case lcTool::Rotate: - ActiveModel->BeginMouseTool(); + ActiveModel->BeginMouseTool(Tool, this); break; case lcTool::Eraser: @@ -2380,13 +2380,13 @@ void lcView::StartTracking(lcTrackButton TrackButton) case lcTool::Pan: StartPan(mMouseX, mMouseY); - ActiveModel->BeginMouseTool(); + ActiveModel->BeginMouseTool(Tool, this); break; case lcTool::Zoom: case lcTool::RotateView: case lcTool::Roll: - ActiveModel->BeginMouseTool(); + ActiveModel->BeginMouseTool(Tool, this); break; case lcTool::ZoomRegion: @@ -2417,7 +2417,7 @@ void lcView::StopTracking(bool Accept) case lcTool::DirectionalLight: case lcTool::AreaLight: case lcTool::Camera: - ActiveModel->EndMouseTool(Tool, Accept); + ActiveModel->EndMouseTool(Tool, this, Accept); break; case lcTool::Select: @@ -2436,7 +2436,7 @@ void lcView::StopTracking(bool Accept) case lcTool::Move: case lcTool::Rotate: - ActiveModel->EndMouseTool(Tool, Accept); + ActiveModel->EndMouseTool(Tool, this, Accept); break; case lcTool::Eraser: @@ -2448,7 +2448,7 @@ void lcView::StopTracking(bool Accept) case lcTool::Pan: case lcTool::RotateView: case lcTool::Roll: - ActiveModel->EndMouseTool(Tool, Accept); + ActiveModel->EndMouseTool(Tool, this, Accept); break; case lcTool::ZoomRegion: diff --git a/common/light.cpp b/common/light.cpp index a8c6bcd0..0886b009 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -31,6 +31,29 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) UpdatePosition(1); } +void lcLight::CopyProperties(const lcLight& Other) +{ + mLightType = Other.mLightType; + mCastShadow = Other.mCastShadow; + mPosition = Other.mPosition; + mRotation = Other.mRotation; + mColor = Other.mColor; + mBlenderPower = Other.mBlenderPower; + mBlenderRadius = Other.mBlenderRadius; + mBlenderAngle = Other.mBlenderAngle; + mPOVRayPower = Other.mPOVRayPower; + mPOVRayFadeDistance = Other.mPOVRayFadeDistance; + mPOVRayFadePower = Other.mPOVRayFadePower; + mSpotConeAngle = Other.mSpotConeAngle; + mSpotPenumbraAngle = Other.mSpotPenumbraAngle; + mPOVRaySpotTightness = Other.mPOVRaySpotTightness; + mAreaShape = Other.mAreaShape; + mAreaSizeX = Other.mAreaSizeX; + mAreaSizeY = Other.mAreaSizeY; + mPOVRayAreaGridX = Other.mPOVRayAreaGridX; + mPOVRayAreaGridY = Other.mPOVRayAreaGridY; +} + QString lcLight::GetLightTypeString(lcLightType LightType) { switch (LightType) diff --git a/common/light.h b/common/light.h index fd1193a7..e0fdae29 100644 --- a/common/light.h +++ b/common/light.h @@ -47,6 +47,8 @@ public: static QString GetAreaShapeString(lcLightAreaShape LightAreaShape); static QStringList GetAreaShapeStrings(); + void CopyProperties(const lcLight& Other); + bool IsPointLight() const { return mLightType == lcLightType::Point; diff --git a/common/piece.cpp b/common/piece.cpp index e7e1b82e..ef6ef940 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -21,7 +21,7 @@ constexpr float LC_PIECE_CONTROL_POINT_SIZE = 10.0f; lcPiece::lcPiece(PieceInfo* Info) : lcObject(lcObjectType::Piece) { - SetPieceInfo(Info, QString(), true); + SetPieceInfo(Info, QString(), true, true); mColorIndex = gDefaultColor; mColorCode = 16; mStepShow = 1; @@ -33,7 +33,7 @@ lcPiece::lcPiece(PieceInfo* Info) lcPiece::lcPiece(const lcPiece& Other) : lcObject(lcObjectType::Piece) { - SetPieceInfo(Other.mPieceInfo, Other.mID, true); + SetPieceInfo(Other.mPieceInfo, Other.mID, true, true); mHidden = Other.mHidden; mSelected = Other.mSelected; mColorIndex = Other.mColorIndex; @@ -63,7 +63,29 @@ lcPiece::~lcPiece() delete mMesh; } -void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait) +void lcPiece::CopyProperties(const lcPiece& Other) +{ + SetPieceInfo(Other.mPieceInfo, Other.mID, true, false); + + mPosition = Other.mPosition; + mRotation = Other.mRotation; + + mColorIndex = Other.mColorIndex; + mColorCode = Other.mColorCode; + + mStepShow = Other.mStepShow; + mStepHide = Other.mStepHide; + + mPivotPointValid = Other.mPivotPointValid; + mPivotMatrix = Other.mPivotMatrix; + + mControlPoints = Other.mControlPoints; + mTrainTrackConnections = Other.mTrainTrackConnections; + + UpdateMesh(); +} + +void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait, bool UpdateSynthInfo) { lcPiecesLibrary* Library = lcGetPiecesLibrary(); @@ -79,15 +101,19 @@ void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait) mID.clear(); mControlPoints.clear(); + delete mMesh; mMesh = nullptr; - const lcSynthInfo* SynthInfo = mPieceInfo ? mPieceInfo->GetSynthInfo() : nullptr; - - if (SynthInfo) + if (UpdateSynthInfo) { - SynthInfo->GetDefaultControlPoints(mControlPoints); - UpdateMesh(); + const lcSynthInfo* SynthInfo = mPieceInfo ? mPieceInfo->GetSynthInfo() : nullptr; + + if (SynthInfo) + { + SynthInfo->GetDefaultControlPoints(mControlPoints); + UpdateMesh(); + } } } @@ -98,7 +124,7 @@ bool lcPiece::SetPieceId(PieceInfo* Info) lcPiecesLibrary* Library = lcGetPiecesLibrary(); Library->ReleasePieceInfo(mPieceInfo); - SetPieceInfo(Info, QString(), true); + SetPieceInfo(Info, QString(), true, true); return true; } @@ -313,7 +339,7 @@ bool lcPiece::FileLoad(lcFile& file) strcat(name, ".dat"); PieceInfo* pInfo = lcGetPiecesLibrary()->FindPiece(name, nullptr, true, false); - SetPieceInfo(pInfo, QString(), true); + SetPieceInfo(pInfo, QString(), true, true); // 11 (0.77) if (version < 11) diff --git a/common/piece.h b/common/piece.h index b66c3851..bc2d6b85 100644 --- a/common/piece.h +++ b/common/piece.h @@ -28,12 +28,14 @@ class lcPiece : public lcObject public: lcPiece(PieceInfo* Info); lcPiece(const lcPiece& Other); - ~lcPiece(); + virtual ~lcPiece(); lcPiece(lcPiece&&) = delete; lcPiece& operator=(const lcPiece&) = delete; lcPiece& operator=(lcPiece&&) = delete; + void CopyProperties(const lcPiece& Other); + bool IsSelected() const override { return mSelected; @@ -182,7 +184,7 @@ public: void Initialize(const lcMatrix44& WorldMatrix, lcStep Step); const lcBoundingBox& GetBoundingBox() const; void CompareBoundingBox(lcVector3& Min, lcVector3& Max) const; - void SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait); + void SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait, bool UpdateSynthInfo); bool SetPieceId(PieceInfo* Info); bool FileLoad(lcFile& file); From d70cd0fa94b0f015d25bb915425ec1fb21dd2e2b Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 23 Nov 2025 22:52:28 -0800 Subject: [PATCH 14/93] Fixed warnings. --- common/group.cpp | 2 +- common/lc_aboutdialog.cpp | 13 ++++++++++--- common/lc_blenderpreferences.cpp | 10 +++++----- common/lc_category.cpp | 2 +- common/lc_file.h | 2 +- common/lc_minifigdialog.cpp | 10 +++++++--- common/lc_model.cpp | 2 +- common/lc_objectproperty.cpp | 2 +- common/lc_shortcuts.cpp | 4 ++-- common/lc_stringcache.cpp | 2 +- qt/lc_qpreferencesdialog.cpp | 5 +++-- qt/lc_qutils.cpp | 2 +- 12 files changed, 34 insertions(+), 22 deletions(-) diff --git a/common/group.cpp b/common/group.cpp index 336d9582..d0ad896c 100644 --- a/common/group.cpp +++ b/common/group.cpp @@ -41,7 +41,7 @@ void lcGroup::CreateName(const std::vector>& Groups) int Max = 0; QString Prefix = QApplication::tr("Group #"); - const int Length = Prefix.length(); + const qsizetype Length = Prefix.length(); for (const std::unique_ptr& Group : Groups) { diff --git a/common/lc_aboutdialog.cpp b/common/lc_aboutdialog.cpp index 950e5385..bce828a2 100644 --- a/common/lc_aboutdialog.cpp +++ b/common/lc_aboutdialog.cpp @@ -18,14 +18,21 @@ lcAboutDialog::lcAboutDialog(QWidget* Parent) #endif lcViewWidget* Widget = gMainWindow->GetActiveView()->GetWidget(); - QSurfaceFormat Format = Widget->context()->format(); - + QOpenGLContext* Context = Widget->context(); + QOpenGLFunctions* Functions = Context->functions(); + QSurfaceFormat Format = Context->format(); + qDebug() << Format; int ColorDepth = Format.redBufferSize() + Format.greenBufferSize() + Format.blueBufferSize() + Format.alphaBufferSize(); const QString QtVersionFormat = tr("Qt Version %1 (compiled with %2)\n\n"); const QString QtVersion = QtVersionFormat.arg(qVersion(), QT_VERSION_STR); + const QString VersionFormat = tr("OpenGL Version %1 (GLSL %2)\n%3 - %4\n\n"); - const QString Version = VersionFormat.arg(QString((const char*)glGetString(GL_VERSION)), QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)), QString((const char*)glGetString(GL_RENDERER)), QString((const char*)glGetString(GL_VENDOR))); + const QString GLVersion(reinterpret_cast(Functions->glGetString(GL_VERSION))); + const QString ShaderVersion(reinterpret_cast(Functions->glGetString(GL_SHADING_LANGUAGE_VERSION))); + const QString Renderer(reinterpret_cast(Functions->glGetString(GL_RENDERER))); + const QString Vendor(reinterpret_cast(Functions->glGetString(GL_VENDOR))); + const QString Version = VersionFormat.arg(GLVersion, ShaderVersion, Renderer, Vendor); const QString BuffersFormat = tr("Color Buffer: %1 bits\nDepth Buffer: %2 bits\nStencil Buffer: %3 bits\n\n"); const QString Buffers = BuffersFormat.arg(QString::number(ColorDepth), QString::number(Format.depthBufferSize()), QString::number(Format.stencilBufferSize())); diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index d72310b4..380d0dfa 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -1578,8 +1578,8 @@ int lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir) qint64 DataSize = File.size(); const qint64 BufferSize = Q_INT64_C(1000); char Buf[BufferSize]; - int BytesRead; - int ReadSize = qMin(DataSize, BufferSize); + qint64 BytesRead; + qint64 ReadSize = qMin(DataSize, BufferSize); while (ReadSize > 0 && (BytesRead = File.read(Buf, ReadSize)) > 0) { DataSize -= BytesRead; @@ -1883,7 +1883,7 @@ void lcBlenderPreferences::ReadStdOut(const QString& StdOutput, QString& Errors) const QString SaveAddonVersion = mAddonVersion; const QString SaveVersion = mBlenderVersion; - int EditListItems = mPathLineEditList.size(); + qsizetype EditListItems = mPathLineEditList.size(); for (const QString& StdOutLine : StdOutLines) { if (StdOutLine.isEmpty()) @@ -3625,7 +3625,7 @@ int lcBlenderPreferences::ShowMessage(QWidget* Parent, const QString& Header, c QWidget* TextWidget = BoxLayoutItem->widget(); if (TextWidget) { - int FixedWidth = Body.length() * FontWidth; + qsizetype FixedWidth = Body.length() * FontWidth; if (FixedWidth == MinimumWidth) { int Index = (MinimumWidth / FontWidth) - 1; @@ -3634,7 +3634,7 @@ int lcBlenderPreferences::ShowMessage(QWidget* Parent, const QString& Header, c } else if (FixedWidth < MinimumWidth) FixedWidth = MinimumWidth; - TextWidget->setFixedWidth(FixedWidth); + TextWidget->setFixedWidth(static_cast(FixedWidth)); } } diff --git a/common/lc_category.cpp b/common/lc_category.cpp index 3899f423..d862c68a 100644 --- a/common/lc_category.cpp +++ b/common/lc_category.cpp @@ -106,7 +106,7 @@ bool lcLoadCategories(const QByteArray& Buffer, std::vector& for (QString Line = Stream.readLine(); !Line.isNull(); Line = Stream.readLine()) { - int Equals = Line.indexOf('='); + qsizetype Equals = Line.indexOf('='); if (Equals == -1) continue; diff --git a/common/lc_file.h b/common/lc_file.h index adbf97e1..7d33a54a 100644 --- a/common/lc_file.h +++ b/common/lc_file.h @@ -283,7 +283,7 @@ public: void WriteQString(const QString& String) { QByteArray Data = String.toUtf8(); - WriteU32(Data.size()); + WriteU32(static_cast(Data.size())); WriteBuffer(Data, Data.size()); } diff --git a/common/lc_minifigdialog.cpp b/common/lc_minifigdialog.cpp index d7b04d6f..ac672477 100644 --- a/common/lc_minifigdialog.cpp +++ b/common/lc_minifigdialog.cpp @@ -359,7 +359,7 @@ void lcMinifigDialog::PieceButtonClicked() if (Search == mPieceButtons.end()) return; - int ItemIndex = std::distance(mPieceButtons.begin(), Search); + int ItemIndex = static_cast(std::distance(mPieceButtons.begin(), Search)); PieceInfo* CurrentInfo = mMinifigWizard->mMinifig.Parts[ItemIndex]; QPoint Position = PieceButton->mapToGlobal(PieceButton->rect().bottomLeft()); @@ -411,7 +411,9 @@ void lcMinifigDialog::ColorChanged(int Index) SetCurrentTemplateModified(); UpdateTemplateCombo(); - mMinifigWizard->SetColorIndex(std::distance(mColorPickers.begin(), Search), Index); + int ItemIndex = static_cast(std::distance(mColorPickers.begin(), Search)); + + mMinifigWizard->SetColorIndex(ItemIndex, Index); mView->Redraw(); } @@ -425,6 +427,8 @@ void lcMinifigDialog::AngleChanged(double Value) SetCurrentTemplateModified(); UpdateTemplateCombo(); - mMinifigWizard->SetAngle(std::distance(mSpinBoxes.begin(), Search), Value); + int ItemIndex = static_cast(std::distance(mSpinBoxes.begin(), Search)); + + mMinifigWizard->SetAngle(ItemIndex, Value); mView->Redraw(); } diff --git a/common/lc_model.cpp b/common/lc_model.cpp index f8985962..9a1392bb 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2769,7 +2769,7 @@ void lcModel::ShowEditGroupsDialog() QString lcModel::GetGroupName(const QString& Prefix) { - const int Length = Prefix.length(); + const qsizetype Length = Prefix.length(); int Max = 0; for (const std::unique_ptr& Group : mGroups) diff --git a/common/lc_objectproperty.cpp b/common/lc_objectproperty.cpp index def6ac03..6648507a 100644 --- a/common/lc_objectproperty.cpp +++ b/common/lc_objectproperty.cpp @@ -339,7 +339,7 @@ bool lcObjectProperty::LoadFromDataStream(QDataStream& Stream) mKeys.resize(KeyCount); - size_t DataSize = KeyCount * sizeof(lcObjectPropertyKey); + qsizetype DataSize = KeyCount * sizeof(lcObjectPropertyKey); if (Stream.readRawData(reinterpret_cast(mKeys.data()), DataSize) != DataSize) return false; diff --git a/common/lc_shortcuts.cpp b/common/lc_shortcuts.cpp index f04bdd42..1e035b1a 100644 --- a/common/lc_shortcuts.cpp +++ b/common/lc_shortcuts.cpp @@ -107,7 +107,7 @@ bool lcKeyboardShortcuts::Load(QTextStream& Stream) for (QString Line = Stream.readLine(); !Line.isNull(); Line = Stream.readLine()) { - int Equals = Line.indexOf('='); + qsizetype Equals = Line.indexOf('='); if (Equals == -1) continue; @@ -231,7 +231,7 @@ bool lcMouseShortcuts::Load(const QStringList& FullShortcuts) for (const QString& FullShortcut : FullShortcuts) { - int Equals = FullShortcut.indexOf('='); + qsizetype Equals = FullShortcut.indexOf('='); if (Equals == -1) continue; diff --git a/common/lc_stringcache.cpp b/common/lc_stringcache.cpp index 618e1561..e05c1a70 100644 --- a/common/lc_stringcache.cpp +++ b/common/lc_stringcache.cpp @@ -195,6 +195,6 @@ void lcStringCache::DrawStrings(lcContext* Context, const lcMatrix44* Transforms Context->BindTexture2D(mTexture); Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f); - Context->DrawPrimitives(GL_TRIANGLES, 0, Strings.size() * 6); + Context->DrawPrimitives(GL_TRIANGLES, 0, static_cast(Strings.size()) * 6); } diff --git a/qt/lc_qpreferencesdialog.cpp b/qt/lc_qpreferencesdialog.cpp index 212f21b7..bc8e3eac 100644 --- a/qt/lc_qpreferencesdialog.cpp +++ b/qt/lc_qpreferencesdialog.cpp @@ -903,8 +903,9 @@ void lcQPreferencesDialog::updateCommandList() const QString identifier = tr(gCommands[actionIdx].ID); - int pos = identifier.indexOf(QLatin1Char('.')); - int subPos = identifier.indexOf(QLatin1Char('.'), pos + 1); + qsizetype pos = identifier.indexOf(QLatin1Char('.')); + qsizetype subPos = identifier.indexOf(QLatin1Char('.'), pos + 1); + if (subPos == -1) subPos = pos; diff --git a/qt/lc_qutils.cpp b/qt/lc_qutils.cpp index 3c7a6fbc..4130876b 100644 --- a/qt/lc_qutils.cpp +++ b/qt/lc_qutils.cpp @@ -15,7 +15,7 @@ QString lcFormatValue(float Value, int Precision) { QString String = QString::number(Value, 'f', Precision); - const int Dot = String.indexOf('.'); + const qsizetype Dot = String.indexOf('.'); if (Dot != -1) { From 3acb9bde3288e6ed16115585f8cffd9fc3a12684 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 28 Nov 2025 22:13:06 -0800 Subject: [PATCH 15/93] Fixed warnings. --- common/lc_aboutdialog.cpp | 2 +- common/lc_library.cpp | 20 +++---- common/lc_synth.cpp | 1 + common/project.cpp | 121 ++++++++++++++++++++------------------ 4 files changed, 75 insertions(+), 69 deletions(-) diff --git a/common/lc_aboutdialog.cpp b/common/lc_aboutdialog.cpp index bce828a2..d16729f2 100644 --- a/common/lc_aboutdialog.cpp +++ b/common/lc_aboutdialog.cpp @@ -21,7 +21,7 @@ lcAboutDialog::lcAboutDialog(QWidget* Parent) QOpenGLContext* Context = Widget->context(); QOpenGLFunctions* Functions = Context->functions(); QSurfaceFormat Format = Context->format(); - qDebug() << Format; + int ColorDepth = Format.redBufferSize() + Format.greenBufferSize() + Format.blueBufferSize() + Format.alphaBufferSize(); const QString QtVersionFormat = tr("Qt Version %1 (compiled with %2)\n\n"); diff --git a/common/lc_library.cpp b/common/lc_library.cpp index a0675812..8f1b161c 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -1282,15 +1282,15 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info) { char FileName[LC_MAXPATH]; lcDiskFile PieceFile; - - sprintf(FileName, "parts/%s", Info->mFileName); + + snprintf(FileName, sizeof(FileName), "parts/%s", Info->mFileName); PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); if (PieceFile.Open(QIODevice::ReadOnly)) Loaded = MeshLoader.LoadMesh(PieceFile, LC_MESHDATA_SHARED); if (mHasUnofficial && !Loaded) { - sprintf(FileName, "unofficial/parts/%s", Info->mFileName); + snprintf(FileName, sizeof(FileName), "unofficial/parts/%s", Info->mFileName); PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); if (PieceFile.Open(QIODevice::ReadOnly)) Loaded = MeshLoader.LoadMesh(PieceFile, LC_MESHDATA_SHARED); @@ -1356,14 +1356,14 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::functionmFileName); + + snprintf(FileName, sizeof(FileName), "parts/%s", Info->mFileName); IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); Found = IncludeFile.Open(QIODevice::ReadOnly); if (mHasUnofficial && !Found) { - sprintf(FileName, "unofficial/parts/%s", Info->mFileName); + snprintf(FileName, sizeof(FileName), "unofficial/parts/%s", Info->mFileName); IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); Found = IncludeFile.Open(QIODevice::ReadOnly); } @@ -1383,7 +1383,7 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::function(ZipFileType)]->ExtractFile(IncludeFileName, IncludeFile); }; @@ -1531,12 +1531,12 @@ bool lcPiecesLibrary::LoadTexture(lcTexture* Texture) if (mZipFiles[static_cast(lcZipFileType::Official)]) { lcMemFile TextureFile; - - sprintf(FileName, "ldraw/parts/textures/%s.png", Texture->mName); + + snprintf(FileName, sizeof(FileName), "ldraw/parts/textures/%s.png", Texture->mName); if (!mZipFiles[static_cast(lcZipFileType::Official)]->ExtractFile(FileName, TextureFile)) { - sprintf(FileName, "parts/textures/%s.png", Texture->mName); + snprintf(FileName, sizeof(FileName), "parts/textures/%s.png", Texture->mName); if (!mZipFiles[static_cast(lcZipFileType::Unofficial)] || !mZipFiles[static_cast(lcZipFileType::Unofficial)]->ExtractFile(FileName, TextureFile)) return false; diff --git a/common/lc_synth.cpp b/common/lc_synth.cpp index 16835d9f..a4429dd3 100644 --- a/common/lc_synth.cpp +++ b/common/lc_synth.cpp @@ -458,6 +458,7 @@ lcSynthInfoCurved::lcSynthInfoCurved(float Length, float DefaultScale, int NumSe mCurve = true; mStart.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f)); + mMiddle.Length = 0.0f; mEnd.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f)); } diff --git a/common/project.cpp b/common/project.cpp index d3488709..ac0770c9 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -267,10 +267,12 @@ lcModel* Project::CreateNewModel(bool ShowModel) SetActiveModel(mModels.back().get(), true); lcView* ActiveView = gMainWindow ? gMainWindow->GetActiveView() : nullptr; + if (ActiveView) ActiveView->GetCamera()->SetViewpoint(lcViewpoint::Home); - - gMainWindow->UpdateTitle(); + + if (gMainWindow) + gMainWindow->UpdateTitle(); } else SetActiveModel(mActiveModel, true); @@ -839,7 +841,7 @@ bool Project::Export3DStudio(const QString& FileName) { lcColor* Color = &gColorList[ColorIdx]; - sprintf(MaterialName, "Material%03d", (int)ColorIdx); + snprintf(MaterialName, sizeof(MaterialName), "Material%03d", (int)ColorIdx); long MaterialStart = File.GetPosition(); File.WriteU16(0xAFFF); // CHK_MAT_ENTRY @@ -1092,7 +1094,7 @@ bool Project::Export3DStudio(const QString& FileName) File.WriteU32(0); char Name[32]; - sprintf(Name, "Piece%.3d", NumPieces); + snprintf(Name, sizeof(Name), "Piece%.3d", NumPieces); NumPieces++; File.WriteBuffer(Name, strlen(Name) + 1); @@ -1179,8 +1181,8 @@ bool Project::Export3DStudio(const QString& FileName) File.WriteU16(0x4130); // CHK_MSH_MAT_GROUP File.WriteU32(6 + MaterialNameLength + 1 + 2 + 2 * Section->NumIndices / 3); - - sprintf(MaterialName, "Material%03d", MaterialIndex); + + snprintf(MaterialName, sizeof(MaterialName), "Material%03d", MaterialIndex); File.WriteBuffer(MaterialName, MaterialNameLength + 1); File.WriteU16(Section->NumIndices / 3); @@ -1565,7 +1567,7 @@ bool Project::ExportCSV(const QString& FileName) std::string Description = Info->m_strDescription; Description.erase(std::remove(Description.begin(), Description.end(), ','), Description.end()); - sprintf(Line, "\"%s\",\"%s\",%d,%s,%d\n", Description.c_str(), gColorList[ColorIt.first].Name, ColorIt.second, Info->mFileName, gColorList[ColorIt.first].Code); + snprintf(Line, sizeof(Line), "\"%s\",\"%s\",%d,%s,%d\n", Description.c_str(), gColorList[ColorIt.first].Name, ColorIt.second, Info->mFileName, gColorList[ColorIt.first].Code); CSVFile.WriteLine(Line); } } @@ -1840,7 +1842,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) char Line[2048]; - sprintf(Line, "// Generated By: LeoCAD %s\n// LDraw File: %s\n// Date: %s\n\n", + snprintf(Line, sizeof(Line), "// Generated By: LeoCAD %s\n// LDraw File: %s\n// Date: %s\n\n", LC_VERSION_TEXT, mModels[0]->GetProperties().mFileName.toLatin1().constData(), QDateTime::currentDateTime().toString(Qt::ISODate).toLatin1().constData()); @@ -1895,22 +1897,23 @@ std::pair Project::ExportPOVRay(const QString& FileName) lcVector3 FloorColor = POVRayOptions.FloorColor; float FloorAmbient = POVRayOptions.FloorAmbient; float FloorDiffuse = POVRayOptions.FloorDiffuse; - char FloorLocation[32]; - char FloorAxis[16]; + const char* FloorLocation; + const char* FloorAxis; + if (POVRayOptions.FloorAxis == 0) { - sprintf(FloorAxis, "x"); - sprintf(FloorLocation, "MaxX"); + FloorAxis = "x"; + FloorLocation = "MaxX"; } else if (POVRayOptions.FloorAxis == 1) { - sprintf(FloorAxis, "y"); - sprintf(FloorLocation, "MaxY"); + FloorAxis = "y"; + FloorLocation = "MaxY"; } else { - sprintf(FloorAxis, "z"); - sprintf(FloorLocation, "MaxZ"); + FloorAxis = "z"; + FloorLocation = "MaxZ"; } for (const std::unique_ptr& Light : Lights) @@ -1929,11 +1932,11 @@ std::pair Project::ExportPOVRay(const QString& FileName) if (!POVRayOptions.HeaderIncludeFile.isEmpty()) { - sprintf(Line, "#include \"%s\"\n\n", POVRayOptions.HeaderIncludeFile.toLatin1().constData()); + snprintf(Line, sizeof(Line), "#include \"%s\"\n\n", POVRayOptions.HeaderIncludeFile.toLatin1().constData()); POVFile.WriteLine(Line); } - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (MinX) #declare MinX = %g; #end\n" "#ifndef (MinY) #declare MinY = %g; #end\n" "#ifndef (MinZ) #declare MinZ = %g; #end\n" @@ -1947,19 +1950,19 @@ std::pair Project::ExportPOVRay(const QString& FileName) "#ifndef (Radius) #declare Radius = %g; #end\n", Min[0], Min[1], Min[2], Max[0], -Max[1], Max[2], Center[0], Center[1], Center[2], Radius); POVFile.WriteLine(Line); - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (CameraSky) #declare CameraSky = <%g,%g,%g>; #end\n" "#ifndef (CameraLocation) #declare CameraLocation = <%g, %g, %g>; #end\n" "#ifndef (CameraTarget) #declare CameraTarget = <%g, %g, %g>; #end\n" "#ifndef (CameraAngle) #declare CameraAngle = %g; #end\n", Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy); POVFile.WriteLine(Line); - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (BackgroundColor) #declare BackgroundColor = <%1g, %1g, %1g>; #end\n" "#ifndef (Background) #declare Background = %s; #end\n", BackgroundColor[0], BackgroundColor[1], BackgroundColor[2], (POVRayOptions.ExcludeBackground ? "false" : "true")); POVFile.WriteLine(Line); - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (FloorAxis) #declare FloorAxis = %s; #end\n" "#ifndef (FloorLocation) #declare FloorLocation = %s; #end\n" "#ifndef (FloorColor) #declare FloorColor = <%1g, %1g, %1g>; #end\n" @@ -1968,7 +1971,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) "#ifndef (Floor) #declare Floor = %s; #end\n", FloorAxis, FloorLocation, FloorColor[0], FloorColor[1], FloorColor[2], FloorAmbient, FloorDiffuse, (POVRayOptions.ExcludeFloor ? "false" : "true")); POVFile.WriteLine(Line); - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (Ambient) #declare Ambient = 0.4; #end\n" "#ifndef (Diffuse) #declare Diffuse = 0.4; #end\n" "#ifndef (Reflection) #declare Reflection = 0.08; #end\n" @@ -1987,7 +1990,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) "#ifndef (OpaqueNormal) #declare OpaqueNormal = normal { bumps 0.001 scale 0.5 }; #end\n" "#ifndef (TransNormal) #declare TransNormal = normal { bumps 0.001 scale 0.5 }; #end\n"); POVFile.WriteLine(Line); - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (Quality) #declare Quality = 3; #end\n" "#ifndef (Studs) #declare Studs = 1; #end\n" "#ifndef (LgeoLibrary) #declare LgeoLibrary = %s; #end\n" @@ -1996,7 +1999,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) (POVRayOptions.UseLGEO ? "true" : "false"), (POVRayOptions.NoReflection ? 0 : 1), (POVRayOptions.NoShadow ? 0 : 1)); POVFile.WriteLine(Line); - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (SkipWriteLightMacro)\n" "#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n" " #local PointLight = %i;\n" @@ -2048,7 +2051,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) { if (!ColorMacros.contains("TranslucentColor")) { - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (SkipTranslucentColorMacro)\n" "#macro TranslucentColor(r, g, b, f)\n" " material {\n" @@ -2070,7 +2073,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) { if (!ColorMacros.contains("ChromeColor")) { - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (SkipChromeColorMacro)\n" "#macro ChromeColor(r, g, b)\n" "#if (LgeoLibrary) material { #end\n" @@ -2090,7 +2093,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) { if (!ColorMacros.contains("RubberColor")) { - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (SkipRubberColorMacro)\n" "#macro RubberColor(r, g, b)\n" "#if (LgeoLibrary) material { #end\n" @@ -2110,7 +2113,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) { if (!ColorMacros.contains("OpaqueColor")) { - sprintf(Line, + snprintf(Line, sizeof(Line), "#ifndef (SkipOpaqueColorMacro)\n" "#macro OpaqueColor(r, g, b)\n" "#if (LgeoLibrary) material { #end\n" @@ -2129,10 +2132,10 @@ std::pair Project::ExportPOVRay(const QString& FileName) } } - sprintf(Line, "#if (Background)\n background {\n color rgb BackgroundColor\n }\n#end\n\n"); + snprintf(Line, sizeof(Line), "#if (Background)\n background {\n color rgb BackgroundColor\n }\n#end\n\n"); POVFile.WriteLine(Line); - sprintf(Line, "#ifndef (Skip%s)\n camera {\n perspective\n right x * image_width / image_height\n sky CameraSky\n location CameraLocation\n look_at CameraTarget\n angle CameraAngle * image_width / image_height\n }\n#end\n\n", + snprintf(Line, sizeof(Line), "#ifndef (Skip%s)\n camera {\n perspective\n right x * image_width / image_height\n sky CameraSky\n location CameraLocation\n look_at CameraTarget\n angle CameraAngle * image_width / image_height\n }\n#end\n\n", (CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData())); POVFile.WriteLine(Line); @@ -2155,7 +2158,8 @@ std::pair Project::ExportPOVRay(const QString& FileName) for (int Idx = 0; Idx < 4; Idx++) { Power = Idx < 2 ? 0.75f : 0.5f; - sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", + snprintf(Line, sizeof(Line), + "#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", Idx, static_cast(LightType), Shadowless, @@ -2190,7 +2194,8 @@ std::pair Project::ExportPOVRay(const QString& FileName) AreaY = lcVector3(Light->GetWorldMatrix()[1]) * Light->GetAreaSizeY(); AreaGrid = lcVector2i(Light->GetAreaPOVRayGridX(), Light->GetAreaPOVRayGridY()); - sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", + snprintf(Line, sizeof(Line), + "#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n", LightName.toLatin1().constData(), static_cast(LightType), Shadowless, @@ -2245,14 +2250,14 @@ std::pair Project::ExportPOVRay(const QString& FileName) { std::pair& Entry = PieceTable[Info]; Entry.second |= LGEO_PIECE_LGEO; - sprintf(Entry.first, "lg_%s", Dst); + snprintf(Entry.first, sizeof(Entry.first), "lg_%s", Dst); } if (strchr(Flags, 'A') && !LgeoPartFound) { std::pair& Entry = PieceTable[Info]; Entry.second |= LGEO_PIECE_AR; - sprintf(Entry.first, "ar_%s", Dst); + snprintf(Entry.first, sizeof(Entry.first), "ar_%s", Dst); } if (strchr(Flags, 'S')) @@ -2296,14 +2301,14 @@ std::pair Project::ExportPOVRay(const QString& FileName) if (LgeoColorTable[ColorIndex].empty()) { - sprintf(ColorTable[ColorIndex].data(), "lc_%s", Color->SafeName); + snprintf(ColorTable[ColorIndex].data(), ColorTable[ColorIndex].size(), "lc_%s", Color->SafeName); if (lcIsColorTranslucent(ColorIndex)) { if (!UseLGEO && !MaterialColors.contains(ColorTable[ColorIndex].data())) MaterialColors.append(ColorTable[ColorIndex].data()); - sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = TranslucentColor(%g, %g, %g, TransFilter)\n#end\n\n", + snprintf(Line, sizeof(Line), "#ifndef (lc_%s)\n#declare lc_%s = TranslucentColor(%g, %g, %g, TransFilter)\n#end\n\n", Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]); } else @@ -2317,14 +2322,14 @@ std::pair Project::ExportPOVRay(const QString& FileName) else MacroName = "Opaque"; - sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = %sColor(%g, %g, %g)\n#end\n\n", Color->SafeName, Color->SafeName, MacroName, Color->Value[0], Color->Value[1], Color->Value[2]); + snprintf(Line, sizeof(Line), "#ifndef (lc_%s)\n#declare lc_%s = %sColor(%g, %g, %g)\n#end\n\n", Color->SafeName, Color->SafeName, MacroName, Color->Value[0], Color->Value[1], Color->Value[2]); } } else { - sprintf(ColorTable[ColorIndex].data(), "LDXColor%i", Color->Code); + snprintf(ColorTable[ColorIndex].data(), ColorTable[ColorIndex].size(), "LDXColor%i", Color->Code); - sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n", + snprintf(Line, sizeof(Line), "#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n", Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIndex].c_str()); } @@ -2361,7 +2366,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) const std::pair& Entry = Search->second; if (Entry.first[0]) { - sprintf(Line, "#include \"%s.inc\" // %s\n", Entry.first, ModelPart.Info->m_strDescription); + snprintf(Line, sizeof(Line), "#include \"%s.inc\" // %s\n", Entry.first, ModelPart.Info->m_strDescription); POVFile.WriteLine(Line); } } @@ -2386,7 +2391,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) if (ModelPart.Mesh) { char Suffix[32]; - sprintf(Suffix, "_%p", ModelPart.Mesh); + snprintf(Suffix, sizeof(Suffix), "_%p", ModelPart.Mesh); strncat(Name, Suffix, sizeof(Name) - strlen(Name) - 1); Name[sizeof(Name) - 1] = 0; } @@ -2415,11 +2420,11 @@ std::pair Project::ExportPOVRay(const QString& FileName) Mesh->ExportPOVRay(POVFile, Name, &ColorTablePointer[0]); - sprintf(Line, "#declare lc_%s_clear = lc_%s\n\n", Name, Name); + snprintf(Line, sizeof(Line), "#declare lc_%s_clear = lc_%s\n\n", Name, Name); POVFile.WriteLine(Line); } - sprintf(Line, "#declare %s = union {\n", TopModelName.toLatin1().constData()); + snprintf(Line, sizeof(Line), "#declare %s = union {\n", TopModelName.toLatin1().constData()); POVFile.WriteLine(Line); for (const lcModelPartsEntry& ModelPart : ModelParts) @@ -2429,16 +2434,16 @@ std::pair Project::ExportPOVRay(const QString& FileName) const float* f = ModelPart.WorldMatrix.GetFloats(); char Modifier[32]; if (UseLGEO || MaterialColors.contains(ColorTable[ColorIdx].data())) - sprintf(Modifier, "material"); + snprintf(Modifier, sizeof(Modifier), "material"); else - sprintf(Modifier, "texture"); + snprintf(Modifier, sizeof(Modifier), "texture"); if (!ModelPart.Mesh) { std::pair& Entry = PieceTable[ModelPart.Info]; if (Entry.second & LGEO_PIECE_SLOPE) { - sprintf(Line, + snprintf(Line, sizeof(Line), " merge {\n object {\n %s%s\n %s { %s }\n }\n" " object {\n %s_slope\n texture {\n %s normal { bumps 0.3 scale 0.02 }\n }\n }\n" " matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", @@ -2450,7 +2455,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) if (!ModelPart.Info || !ModelPart.Info->GetMesh()) continue; - sprintf(Line, " object {\n %s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", + snprintf(Line, sizeof(Line), " object {\n %s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); } @@ -2460,26 +2465,26 @@ std::pair Project::ExportPOVRay(const QString& FileName) char Name[LC_PIECE_NAME_LEN]; GetMeshName(ModelPart, Name); - sprintf(Line, " object {\n lc_%s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", + snprintf(Line, sizeof(Line), " object {\n lc_%s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n", Name, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f); } POVFile.WriteLine(Line); } - sprintf(Line, "\n #if (ModelReflection = 0)\n no_reflection\n #end\n #if (ModelShadow = 0)\n no_shadow\n #end\n}\n\n"); + snprintf(Line, sizeof(Line), "\n #if (ModelReflection = 0)\n no_reflection\n #end\n #if (ModelShadow = 0)\n no_shadow\n #end\n}\n\n"); POVFile.WriteLine(Line); - sprintf(Line, "object {\n %s\n %s { %s }\n}\n\n", + snprintf(Line, sizeof(Line), "object {\n %s\n %s { %s }\n}\n\n", TopModelName.toLatin1().constData(), (UseLGEO ? "material" : "texture"), ColorTable[lcGetColorIndex(TopModelColorCode)].data()); POVFile.WriteLine(Line); - sprintf(Line, "#if (Floor)\n object {\n plane { FloorAxis, FloorLocation hollow }\n texture {\n pigment { color srgb FloorColor }\n finish { emission 0 ambient FloorAmbient diffuse FloorDiffuse }\n }\n }\n#end\n"); + snprintf(Line, sizeof(Line), "#if (Floor)\n object {\n plane { FloorAxis, FloorLocation hollow }\n texture {\n pigment { color srgb FloorColor }\n finish { emission 0 ambient FloorAmbient diffuse FloorDiffuse }\n }\n }\n#end\n"); POVFile.WriteLine(Line); if (!POVRayOptions.FooterIncludeFile.isEmpty()) { - sprintf(Line, "\n#include \"%s\"\n", POVRayOptions.FooterIncludeFile.toLatin1().constData()); + snprintf(Line, sizeof(Line), "\n#include \"%s\"\n", POVRayOptions.FooterIncludeFile.toLatin1().constData()); POVFile.WriteLine(Line); } @@ -2517,7 +2522,7 @@ bool Project::ExportWavefront(const QString& FileName) QFileInfo SaveInfo(SaveFileName); QString MaterialFileName = QDir(SaveInfo.absolutePath()).absoluteFilePath(SaveInfo.completeBaseName() + QLatin1String(".mtl")); - sprintf(Line, "#\n\nmtllib %s\n\n", QFileInfo(MaterialFileName).fileName().toLatin1().constData()); + snprintf(Line, sizeof(Line), "#\n\nmtllib %s\n\n", QFileInfo(MaterialFileName).fileName().toLatin1().constData()); OBJFile.WriteLine(Line); lcDiskFile MaterialFile(MaterialFileName); @@ -2531,9 +2536,9 @@ bool Project::ExportWavefront(const QString& FileName) for (const lcColor& Color : gColorList) { if (Color.Translucent) - sprintf(Line, "newmtl %s\nKd %.2f %.2f %.2f\nD %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2], Color.Value[3]); + snprintf(Line, sizeof(Line), "newmtl %s\nKd %.2f %.2f %.2f\nD %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2], Color.Value[3]); else - sprintf(Line, "newmtl %s\nKd %.2f %.2f %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2]); + snprintf(Line, sizeof(Line), "newmtl %s\nKd %.2f %.2f %.2f\n\n", Color.SafeName, Color.Value[0], Color.Value[1], Color.Value[2]); MaterialFile.WriteLine(Line); } @@ -2550,7 +2555,7 @@ bool Project::ExportWavefront(const QString& FileName) for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++) { lcVector3 Vertex = lcMul31(Verts[VertexIdx].Position, ModelWorld); - sprintf(Line, "v %.2f %.2f %.2f\n", Vertex[0], Vertex[1], Vertex[2]); + snprintf(Line, sizeof(Line), "v %.2f %.2f %.2f\n", Vertex[0], Vertex[1], Vertex[2]); OBJFile.WriteLine(Line); } @@ -2570,7 +2575,7 @@ bool Project::ExportWavefront(const QString& FileName) for (int VertexIdx = 0; VertexIdx < Mesh->mNumVertices; VertexIdx++) { lcVector3 Normal = lcMul30(lcUnpackNormal(Verts[VertexIdx].Normal), ModelWorld); - sprintf(Line, "vn %.2f %.2f %.2f\n", Normal[0], Normal[1], Normal[2]); + snprintf(Line, sizeof(Line), "vn %.2f %.2f %.2f\n", Normal[0], Normal[1], Normal[2]); OBJFile.WriteLine(Line); } @@ -2580,7 +2585,7 @@ bool Project::ExportWavefront(const QString& FileName) int NumPieces = 0; for (const lcModelPartsEntry& ModelPart : ModelParts) { - sprintf(Line, "g Piece%.3d\n", NumPieces++); + snprintf(Line, sizeof(Line), "g Piece%.3d\n", NumPieces++); OBJFile.WriteLine(Line); lcMesh* Mesh = !ModelPart.Mesh ? ModelPart.Info->GetMesh() : ModelPart.Mesh; From 4de6c095e4d7c1e36131a5604ac2ae0f88e495a9 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 4 Dec 2025 17:41:04 -0800 Subject: [PATCH 16/93] Save the entire object state to the undo buffer instead of only key frames. --- common/camera.cpp | 28 ++++++++++--- common/camera.h | 4 +- common/lc_math.h | 26 +++++++++++- common/lc_model.cpp | 29 ++++++------- common/lc_modelaction.cpp | 25 +++++------ common/lc_modelaction.h | 29 +++---------- common/lc_objectproperty.cpp | 23 +++++++---- common/lc_objectproperty.h | 4 +- common/light.cpp | 80 +++++++++++++++++++++--------------- common/light.h | 4 +- common/object.h | 4 +- common/piece.cpp | 54 +++++++++++++++++++++--- common/piece.h | 4 +- 13 files changed, 197 insertions(+), 117 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index f4da2ebc..1b40eeb1 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -907,16 +907,32 @@ void lcCamera::RemoveKeyFrames() mUpVector.RemoveAllKeys(); } -void lcCamera::SaveKeyFrames(QDataStream& Stream) const +void lcCamera::SaveUndoData(QDataStream& Stream) const { - mPosition.SaveToDataStream(Stream); - mTargetPosition.SaveToDataStream(Stream); - mUpVector.SaveToDataStream(Stream); + Stream << m_fovy; + Stream << m_zNear; + Stream << m_zFar; + Stream << mName; + Stream << (mState & (LC_CAMERA_HIDDEN | LC_CAMERA_ORTHO)); + + mPosition.SaveUndoData(Stream); + mTargetPosition.SaveUndoData(Stream); + mUpVector.SaveUndoData(Stream); } -bool lcCamera::LoadKeyFrames(QDataStream& Stream) +bool lcCamera::LoadUndoData(QDataStream& Stream) { - return mPosition.LoadFromDataStream(Stream) && mTargetPosition.LoadFromDataStream(Stream) && mUpVector.LoadFromDataStream(Stream); + Stream >> m_fovy; + Stream >> m_zNear; + Stream >> m_zFar; + Stream >> mName; + + quint32 State; + Stream >> State; + + mState = (mState & ~(LC_CAMERA_HIDDEN | LC_CAMERA_ORTHO)) | State; + + return mPosition.LoadUndoData(Stream) && mTargetPosition.LoadUndoData(Stream) && mUpVector.LoadUndoData(Stream); } void lcCamera::RayTest(lcObjectRayTest& ObjectRayTest) const diff --git a/common/camera.h b/common/camera.h index 2b1802e6..4d501513 100644 --- a/common/camera.h +++ b/common/camera.h @@ -318,8 +318,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - void SaveKeyFrames(QDataStream& Stream) const override; - bool LoadKeyFrames(QDataStream& Stream) override; + void SaveUndoData(QDataStream& Stream) const override; + bool LoadUndoData(QDataStream& Stream) override; void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/lc_math.h b/common/lc_math.h index f48efe73..c2ef475f 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -521,12 +521,36 @@ inline QDataStream& operator<<(QDataStream& Stream, const lcVector4& v) return Stream; } -inline QDataStream& operator >> (QDataStream& Stream, lcVector4& v) +inline QDataStream& operator>>(QDataStream& Stream, lcVector4& v) { Stream >> v.x >> v.y >> v.z >> v.w; return Stream; } +inline QDataStream& operator<<(QDataStream& Stream, const lcMatrix33& m) +{ + Stream << m[0] << m[1] << m[2]; + return Stream; +} + +inline QDataStream& operator>>(QDataStream& Stream, lcMatrix33& m) +{ + Stream >> m[0] >> m[1] >> m[2]; + return Stream; +} + +inline QDataStream& operator<<(QDataStream& Stream, const lcMatrix44& m) +{ + Stream << m[0] << m[1] << m[2] << m[3]; + return Stream; +} + +inline QDataStream& operator>>(QDataStream& Stream, lcMatrix44& m) +{ + Stream >> m[0] >> m[1] >> m[2] >> m[3]; + return Stream; +} + inline void lcVector3::Normalize() { const float InvLength = 1.0f / Length(); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 9a1392bb..67aa8614 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1870,7 +1870,7 @@ void lcModel::RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseT const QByteArray& State = Apply ? ModelActionMouseTool->GetEndState() : ModelActionMouseTool->GetStartState(); QDataStream Stream(const_cast(&State), QIODevice::ReadOnly); - Camera->LoadKeyFrames(Stream); + Camera->LoadUndoData(Stream); SetCurrentStep(mCurrentStep); } @@ -2280,52 +2280,49 @@ void lcModel::RunStepAction(const lcModelActionStep* ModelActionStep, bool Apply } else { - const std::vector& PieceStates = ModelActionStep->GetPieceStates(); + const std::vector& PieceStates = ModelActionStep->GetPieceStates(); if (PieceStates.size() != mPieces.size()) return; for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) { - const lcModelActionStepPieceState& PieceState = PieceStates[PieceIndex]; + const QByteArray& PieceState = PieceStates[PieceIndex]; lcPiece* Piece = mPieces[PieceIndex].get(); - Piece->SetStepShow(PieceState.StepShow); - Piece->SetStepHide(PieceState.StepHide); + QDataStream Stream(const_cast(&PieceState), QIODevice::ReadOnly); - QDataStream Stream(const_cast(&PieceState.KeyFrames), QIODevice::ReadOnly); - - Piece->LoadKeyFrames(Stream); + Piece->LoadUndoData(Stream); } - const std::vector& CameraStates = ModelActionStep->GetCameraStates(); + const std::vector& CameraStates = ModelActionStep->GetCameraStates(); if (CameraStates.size() != mCameras.size()) return; for (size_t CameraIndex = 0; CameraIndex < mCameras.size(); CameraIndex++) { - const lcModelActionStepCameraState& CameraState = CameraStates[CameraIndex]; + const QByteArray& CameraState = CameraStates[CameraIndex]; lcCamera* Camera = mCameras[CameraIndex].get(); - QDataStream Stream(const_cast(&CameraState.KeyFrames), QIODevice::ReadOnly); + QDataStream Stream(const_cast(&CameraState), QIODevice::ReadOnly); - Camera->LoadKeyFrames(Stream); + Camera->LoadUndoData(Stream); } - const std::vector& LightStates = ModelActionStep->GetLightStates(); + const std::vector& LightStates = ModelActionStep->GetLightStates(); if (LightStates.size() != mLights.size()) return; for (size_t LightIndex = 0; LightIndex < mLights.size(); LightIndex++) { - const lcModelActionStepLightState& LightState = LightStates[LightIndex]; + const QByteArray& LightState = LightStates[LightIndex]; lcLight* Light = mLights[LightIndex].get(); - QDataStream Stream(const_cast(&LightState.KeyFrames), QIODevice::ReadOnly); + QDataStream Stream(const_cast(&LightState), QIODevice::ReadOnly); - Light->LoadKeyFrames(Stream); + Light->LoadUndoData(Stream); } } diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 58319f62..1dbc6333 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -116,7 +116,7 @@ void lcModelActionMouseTool::SetCameraStartState(const lcCamera* Camera) { QDataStream Stream(&mStartState, QIODevice::WriteOnly); - Camera->SaveKeyFrames(Stream); + Camera->SaveUndoData(Stream); mCameraName = Camera->GetName(); } @@ -125,7 +125,7 @@ void lcModelActionMouseTool::SetCameraEndState(const lcCamera* Camera) { QDataStream Stream(&mEndState, QIODevice::WriteOnly); - Camera->SaveKeyFrames(Stream); + Camera->SaveUndoData(Stream); } void lcModelActionMouseTool::SaveSelectionStartState(const lcModel* Model) @@ -265,38 +265,35 @@ void lcModelActionStep::SaveState(const std::vector>& P for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) { - lcModelActionStepPieceState& PieceState = mPieceStates[PieceIndex]; + QByteArray& PieceState = mPieceStates[PieceIndex]; const lcPiece* Piece = Pieces[PieceIndex].get(); - PieceState.StepShow = Piece->GetStepShow(); - PieceState.StepHide = Piece->GetStepHide(); + QDataStream Stream(&PieceState, QIODevice::WriteOnly); - QDataStream Stream(&PieceState.KeyFrames, QIODevice::WriteOnly); - - Piece->SaveKeyFrames(Stream); + Piece->SaveUndoData(Stream); } mCameraStates.resize(Cameras.size()); for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) { - lcModelActionStepCameraState& CameraState = mCameraStates[CameraIndex]; + QByteArray& CameraState = mCameraStates[CameraIndex]; const lcCamera* Camera = Cameras[CameraIndex].get(); - QDataStream Stream(&CameraState.KeyFrames, QIODevice::WriteOnly); + QDataStream Stream(&CameraState, QIODevice::WriteOnly); - Camera->SaveKeyFrames(Stream); + Camera->SaveUndoData(Stream); } mLightStates.resize(Lights.size()); for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) { - lcModelActionStepLightState& LightState = mLightStates[LightIndex]; + QByteArray& LightState = mLightStates[LightIndex]; const lcLight* Light = Lights[LightIndex].get(); - QDataStream Stream(&LightState.KeyFrames, QIODevice::WriteOnly); + QDataStream Stream(&LightState, QIODevice::WriteOnly); - Light->SaveKeyFrames(Stream); + Light->SaveUndoData(Stream); } } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 8b800e70..995c8841 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -233,23 +233,6 @@ enum class lcModelActionStepMode Remove }; -struct lcModelActionStepPieceState -{ - lcStep StepShow; - lcStep StepHide; - QByteArray KeyFrames; -}; - -struct lcModelActionStepCameraState -{ - QByteArray KeyFrames; -}; - -struct lcModelActionStepLightState -{ - QByteArray KeyFrames; -}; - class lcModelActionStep : public lcModelAction { public: @@ -268,25 +251,25 @@ public: void SaveState(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights); - const std::vector& GetPieceStates() const + const std::vector& GetPieceStates() const { return mPieceStates; } - const std::vector& GetCameraStates() const + const std::vector& GetCameraStates() const { return mCameraStates; } - const std::vector& GetLightStates() const + const std::vector& GetLightStates() const { return mLightStates; } protected: - std::vector mPieceStates; - std::vector mCameraStates; - std::vector mLightStates; + std::vector mPieceStates; + std::vector mCameraStates; + std::vector mLightStates; lcModelActionStepMode mMode; lcStep mStep; }; diff --git a/common/lc_objectproperty.cpp b/common/lc_objectproperty.cpp index 6648507a..25ce5987 100644 --- a/common/lc_objectproperty.cpp +++ b/common/lc_objectproperty.cpp @@ -11,8 +11,8 @@ template bool lcObjectProperty::SetKeyFrame(lcStep Time, bool KeyFrame); \ template void lcObjectProperty::Save(QTextStream& Stream, const char* ObjectName, const char* VariableName, bool SaveEmpty) const; \ template bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const char* VariableName); \ - template void lcObjectProperty::SaveToDataStream(QDataStream& Stream) const; \ - template bool lcObjectProperty::LoadFromDataStream(QDataStream& Stream); + template bool lcObjectProperty::SaveUndoData(QDataStream& Stream) const; \ + template bool lcObjectProperty::LoadUndoData(QDataStream& Stream); LC_OBJECT_PROPERTY(float) LC_OBJECT_PROPERTY(int) @@ -316,18 +316,25 @@ bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const } template -void lcObjectProperty::SaveToDataStream(QDataStream& Stream) const +bool lcObjectProperty::SaveUndoData(QDataStream& Stream) const { size_t KeyCount = mKeys.size(); - size_t DataSize = KeyCount * sizeof(lcObjectPropertyKey); + qint64 DataSize = KeyCount * sizeof(lcObjectPropertyKey); - Stream.writeRawData(reinterpret_cast(&mValue), sizeof(mValue)); - Stream.writeRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)); - Stream.writeRawData(reinterpret_cast(mKeys.data()), DataSize); + if (Stream.writeRawData(reinterpret_cast(&mValue), sizeof(mValue)) != sizeof(mValue)) + return false; + + if (Stream.writeRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)) != sizeof(KeyCount)) + return false; + + if (Stream.writeRawData(reinterpret_cast(mKeys.data()), DataSize) != DataSize) + return false; + + return true; } template -bool lcObjectProperty::LoadFromDataStream(QDataStream& Stream) +bool lcObjectProperty::LoadUndoData(QDataStream& Stream) { if (Stream.readRawData(reinterpret_cast(&mValue), sizeof(mValue)) != sizeof(mValue)) return false; diff --git a/common/lc_objectproperty.h b/common/lc_objectproperty.h index 6746d915..8d572e6d 100644 --- a/common/lc_objectproperty.h +++ b/common/lc_objectproperty.h @@ -96,8 +96,8 @@ public: void Save(QTextStream& Stream, const char* ObjectName, const char* VariableName, bool SaveEmpty) const; bool Load(QTextStream& Stream, const QString& Token, const char* VariableName); - void SaveToDataStream(QDataStream& Stream) const; - bool LoadFromDataStream(QDataStream& Stream); + bool SaveUndoData(QDataStream& Stream) const; + bool LoadUndoData(QDataStream& Stream); protected: T mValue; diff --git a/common/light.cpp b/common/light.cpp index 0886b009..9b9238d8 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1530,42 +1530,54 @@ void lcLight::RemoveKeyFrames() mPOVRayFadePower.RemoveAllKeys(); } -void lcLight::SaveKeyFrames(QDataStream& Stream) const +void lcLight::SaveUndoData(QDataStream& Stream) const { - mPosition.SaveToDataStream(Stream); - mRotation.SaveToDataStream(Stream); - mColor.SaveToDataStream(Stream); - mSpotConeAngle.SaveToDataStream(Stream); - mSpotPenumbraAngle.SaveToDataStream(Stream); - mPOVRaySpotTightness.SaveToDataStream(Stream); - mPOVRayAreaGridX.SaveToDataStream(Stream); - mPOVRayAreaGridY.SaveToDataStream(Stream); - mBlenderRadius.SaveToDataStream(Stream); - mBlenderAngle.SaveToDataStream(Stream); - mAreaSizeX.SaveToDataStream(Stream); - mAreaSizeY.SaveToDataStream(Stream); - mBlenderPower.SaveToDataStream(Stream); - mPOVRayPower.SaveToDataStream(Stream); - mPOVRayFadeDistance.SaveToDataStream(Stream); - mPOVRayFadePower.SaveToDataStream(Stream); + Stream << mName; + Stream << mLightType; + Stream << mCastShadow; + Stream << mAreaShape; + Stream << mState; + + mPosition.SaveUndoData(Stream); + mRotation.SaveUndoData(Stream); + mColor.SaveUndoData(Stream); + mSpotConeAngle.SaveUndoData(Stream); + mSpotPenumbraAngle.SaveUndoData(Stream); + mPOVRaySpotTightness.SaveUndoData(Stream); + mPOVRayAreaGridX.SaveUndoData(Stream); + mPOVRayAreaGridY.SaveUndoData(Stream); + mBlenderRadius.SaveUndoData(Stream); + mBlenderAngle.SaveUndoData(Stream); + mAreaSizeX.SaveUndoData(Stream); + mAreaSizeY.SaveUndoData(Stream); + mBlenderPower.SaveUndoData(Stream); + mPOVRayPower.SaveUndoData(Stream); + mPOVRayFadeDistance.SaveUndoData(Stream); + mPOVRayFadePower.SaveUndoData(Stream); } -bool lcLight::LoadKeyFrames(QDataStream& Stream) +bool lcLight::LoadUndoData(QDataStream& Stream) { - return mPosition.LoadFromDataStream(Stream) && - mRotation.LoadFromDataStream(Stream) && - mColor.LoadFromDataStream(Stream) && - mSpotConeAngle.LoadFromDataStream(Stream) && - mSpotPenumbraAngle.LoadFromDataStream(Stream) && - mPOVRaySpotTightness.LoadFromDataStream(Stream) && - mPOVRayAreaGridX.LoadFromDataStream(Stream) && - mPOVRayAreaGridY.LoadFromDataStream(Stream) && - mBlenderRadius.LoadFromDataStream(Stream) && - mBlenderAngle.LoadFromDataStream(Stream) && - mAreaSizeX.LoadFromDataStream(Stream) && - mAreaSizeY.LoadFromDataStream(Stream) && - mBlenderPower.LoadFromDataStream(Stream) && - mPOVRayPower.LoadFromDataStream(Stream) && - mPOVRayFadeDistance.LoadFromDataStream(Stream) && - mPOVRayFadePower.LoadFromDataStream(Stream); + Stream >> mName; + Stream >> mLightType; + Stream >> mCastShadow; + Stream >> mAreaShape; + Stream >> mState; + + return mPosition.LoadUndoData(Stream) && + mRotation.LoadUndoData(Stream) && + mColor.LoadUndoData(Stream) && + mSpotConeAngle.LoadUndoData(Stream) && + mSpotPenumbraAngle.LoadUndoData(Stream) && + mPOVRaySpotTightness.LoadUndoData(Stream) && + mPOVRayAreaGridX.LoadUndoData(Stream) && + mPOVRayAreaGridY.LoadUndoData(Stream) && + mBlenderRadius.LoadUndoData(Stream) && + mBlenderAngle.LoadUndoData(Stream) && + mAreaSizeX.LoadUndoData(Stream) && + mAreaSizeY.LoadUndoData(Stream) && + mBlenderPower.LoadUndoData(Stream) && + mPOVRayPower.LoadUndoData(Stream) && + mPOVRayFadeDistance.LoadUndoData(Stream) && + mPOVRayFadePower.LoadUndoData(Stream); } diff --git a/common/light.h b/common/light.h index e0fdae29..0be2de5e 100644 --- a/common/light.h +++ b/common/light.h @@ -220,8 +220,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - void SaveKeyFrames(QDataStream& Stream) const override; - bool LoadKeyFrames(QDataStream& Stream) override; + void SaveUndoData(QDataStream& Stream) const override; + bool LoadUndoData(QDataStream& Stream) override; void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/object.h b/common/object.h index 323aea3f..cd2b8e2f 100644 --- a/common/object.h +++ b/common/object.h @@ -107,8 +107,8 @@ public: virtual bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const = 0; virtual bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) = 0; virtual void RemoveKeyFrames() = 0; - virtual void SaveKeyFrames(QDataStream& Stream) const = 0; - virtual bool LoadKeyFrames(QDataStream& Stream) = 0; + virtual void SaveUndoData(QDataStream& Stream) const = 0; + virtual bool LoadUndoData(QDataStream& Stream) = 0; virtual QString GetName() const = 0; static QString GetCheckpointString(lcObjectPropertyId PropertyId); diff --git a/common/piece.cpp b/common/piece.cpp index ef6ef940..5bc6848a 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -933,15 +933,59 @@ void lcPiece::RemoveKeyFrames() mRotation.RemoveAllKeys(); } -void lcPiece::SaveKeyFrames(QDataStream& Stream) const +void lcPiece::SaveUndoData(QDataStream& Stream) const { - mPosition.SaveToDataStream(Stream); - mRotation.SaveToDataStream(Stream); +// PieceInfo* mPieceInfo; + Stream << mFileLine; + Stream << mID; + +// lcGroup* mGroup; + + Stream << mColorIndex; + Stream << mColorCode; + + Stream << mStepShow; + Stream << mStepHide; + + Stream << mPivotMatrix; + Stream << mPivotPointValid; + + Stream << mHidden; + +// std::vector mControlPoints; +// std::vector mTrainTrackConnections; + + mPosition.SaveUndoData(Stream); + mRotation.SaveUndoData(Stream); } -bool lcPiece::LoadKeyFrames(QDataStream& Stream) +bool lcPiece::LoadUndoData(QDataStream& Stream) { - return mPosition.LoadFromDataStream(Stream) && mRotation.LoadFromDataStream(Stream); +// SetPieceInfo(Other.mPieceInfo, Other.mID, true, false); + +// PieceInfo* mPieceInfo; + Stream >> mFileLine; + Stream >> mID; + +// lcGroup* mGroup; + + Stream >> mColorIndex; + Stream >> mColorCode; + + Stream >> mStepShow; + Stream >> mStepHide; + + Stream >> mPivotMatrix; + Stream >> mPivotPointValid; + + Stream >> mHidden; + +// std::vector mControlPoints; +// std::vector mTrainTrackConnections; + +// UpdateMesh(); + + return mPosition.LoadUndoData(Stream) && mRotation.LoadUndoData(Stream); } void lcPiece::AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const diff --git a/common/piece.h b/common/piece.h index bc2d6b85..aa314c18 100644 --- a/common/piece.h +++ b/common/piece.h @@ -116,8 +116,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - void SaveKeyFrames(QDataStream& Stream) const override; - bool LoadKeyFrames(QDataStream& Stream) override; + void SaveUndoData(QDataStream& Stream) const override; + bool LoadUndoData(QDataStream& Stream) override; void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const; void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const; From 7febca85588ddd46f63ad2ee32285f0a39a88d7d Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 4 Dec 2025 18:50:10 -0800 Subject: [PATCH 17/93] Share code between step and mouse tool actions. --- common/lc_model.cpp | 66 +++---------- common/lc_modelaction.cpp | 190 +++++++++++++++++--------------------- common/lc_modelaction.h | 51 +++------- 3 files changed, 113 insertions(+), 194 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 67aa8614..c20532cc 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1757,7 +1757,7 @@ void lcModel::BeginMouseToolAction(lcTool Tool, lcView* View) case lcTool::Pan: case lcTool::RotateView: case lcTool::Roll: - ModelActionMouseTool->SetCameraStartState(View->GetCamera()); + ModelActionMouseTool->SaveCameraStartState(View->GetCamera()); break; case lcTool::ZoomRegion: @@ -1810,7 +1810,7 @@ void lcModel::EndMouseToolAction(lcTool Tool, lcView* View, const QString& Descr case lcTool::Pan: case lcTool::RotateView: case lcTool::Roll: - ModelActionMouseTool->SetCameraEndState(View->GetCamera()); + ModelActionMouseTool->SaveCameraEndState(View->GetCamera()); break; case lcTool::ZoomRegion: @@ -1853,6 +1853,7 @@ void lcModel::RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseT ModelActionMouseTool->LoadSelectionEndState(this); else ModelActionMouseTool->LoadSelectionStartState(this); + SetCurrentStep(mCurrentStep); break; @@ -1867,10 +1868,10 @@ void lcModel::RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseT case lcTool::Roll: if (lcCamera* Camera = GetCamera(ModelActionMouseTool->GetCameraName())) { - const QByteArray& State = Apply ? ModelActionMouseTool->GetEndState() : ModelActionMouseTool->GetStartState(); - QDataStream Stream(const_cast(&State), QIODevice::ReadOnly); - - Camera->LoadUndoData(Stream); + if (Apply) + ModelActionMouseTool->LoadCameraEndState(Camera); + else + ModelActionMouseTool->LoadCameraStartState(Camera); SetCurrentStep(mCurrentStep); } @@ -2229,11 +2230,11 @@ void lcModel::RecordStepAction(lcModelActionStepMode Mode, lcStep Step) { std::unique_ptr ModelActionStep = std::make_unique(Mode, Step); - ModelActionStep->SaveState(mPieces, mCameras, mLights); - + ModelActionStep->SaveModelState(this); + RunStepAction(ModelActionStep.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionStep)); + + mActionSequence.emplace_back(std::move(ModelActionStep)); } void lcModel::RunStepAction(const lcModelActionStep* ModelActionStep, bool Apply) @@ -2280,50 +2281,7 @@ void lcModel::RunStepAction(const lcModelActionStep* ModelActionStep, bool Apply } else { - const std::vector& PieceStates = ModelActionStep->GetPieceStates(); - - if (PieceStates.size() != mPieces.size()) - return; - - for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) - { - const QByteArray& PieceState = PieceStates[PieceIndex]; - lcPiece* Piece = mPieces[PieceIndex].get(); - - QDataStream Stream(const_cast(&PieceState), QIODevice::ReadOnly); - - Piece->LoadUndoData(Stream); - } - - const std::vector& CameraStates = ModelActionStep->GetCameraStates(); - - if (CameraStates.size() != mCameras.size()) - return; - - for (size_t CameraIndex = 0; CameraIndex < mCameras.size(); CameraIndex++) - { - const QByteArray& CameraState = CameraStates[CameraIndex]; - lcCamera* Camera = mCameras[CameraIndex].get(); - - QDataStream Stream(const_cast(&CameraState), QIODevice::ReadOnly); - - Camera->LoadUndoData(Stream); - } - - const std::vector& LightStates = ModelActionStep->GetLightStates(); - - if (LightStates.size() != mLights.size()) - return; - - for (size_t LightIndex = 0; LightIndex < mLights.size(); LightIndex++) - { - const QByteArray& LightState = LightStates[LightIndex]; - lcLight* Light = mLights[LightIndex].get(); - - QDataStream Stream(const_cast(&LightState), QIODevice::ReadOnly); - - Light->LoadUndoData(Stream); - } + ModelActionStep->LoadModelState(this); } SetCurrentStep(mCurrentStep); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 1dbc6333..2d94fbdd 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -7,6 +7,63 @@ #include "pieceinf.h" #include "lc_colors.h" +void lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly) +{ + QDataStream Stream(&Buffer, QIODevice::WriteOnly); + + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + + size_t PieceCount = Pieces.size(), CameraCount = Cameras.size(), LightCount = Lights.size(); + + Stream << PieceCount; + Stream << CameraCount; + Stream << LightCount; + + for (const std::unique_ptr& Piece : Pieces) + if (!SelectedOnly || Piece->IsSelected()) + Piece->SaveUndoData(Stream); + + for (const std::unique_ptr& Camera : Cameras) + if (!SelectedOnly || Camera->IsSelected()) + Camera->SaveUndoData(Stream); + + for (const std::unique_ptr& Light : Lights) + if (!SelectedOnly || Light->IsSelected()) + Light->SaveUndoData(Stream); +} + +void lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model, bool SelectedOnly) +{ + QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); + + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + + size_t PieceCount, CameraCount, LightCount; + + Stream >> PieceCount; + Stream >> CameraCount; + Stream >> LightCount; + + if (PieceCount != Pieces.size() || CameraCount != Cameras.size() || LightCount != Lights.size()) + return; + + for (const std::unique_ptr& Piece : Pieces) + if (!SelectedOnly || Piece->IsSelected()) + Piece->LoadUndoData(Stream); + + for (const std::unique_ptr& Camera : Cameras) + if (!SelectedOnly || Camera->IsSelected()) + Camera->LoadUndoData(Stream); + + for (const std::unique_ptr& Light : Lights) + if (!SelectedOnly || Light->IsSelected()) + Light->LoadUndoData(Stream); +} + lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode) : mMode(Mode) { @@ -112,98 +169,54 @@ lcModelActionMouseTool::lcModelActionMouseTool(lcTool Tool) { } -void lcModelActionMouseTool::SetCameraStartState(const lcCamera* Camera) +void lcModelActionMouseTool::SaveCameraStartState(const lcCamera* Camera) { - QDataStream Stream(&mStartState, QIODevice::WriteOnly); + QDataStream Stream(&mStartBuffer, QIODevice::WriteOnly); Camera->SaveUndoData(Stream); mCameraName = Camera->GetName(); } -void lcModelActionMouseTool::SetCameraEndState(const lcCamera* Camera) +void lcModelActionMouseTool::LoadCameraStartState(lcCamera* Camera) const { - QDataStream Stream(&mEndState, QIODevice::WriteOnly); + QDataStream Stream(const_cast(&mStartBuffer), QIODevice::ReadOnly); + + Camera->LoadUndoData(Stream); +} + +void lcModelActionMouseTool::SaveCameraEndState(const lcCamera* Camera) +{ + QDataStream Stream(&mEndBuffer, QIODevice::WriteOnly); Camera->SaveUndoData(Stream); } +void lcModelActionMouseTool::LoadCameraEndState(lcCamera* Camera) const +{ + QDataStream Stream(const_cast(&mEndBuffer), QIODevice::ReadOnly); + + Camera->LoadUndoData(Stream); +} + void lcModelActionMouseTool::SaveSelectionStartState(const lcModel* Model) { - SaveSelectionState(Model, mStartState); + SaveUndoBuffer(mStartBuffer, Model, true); } void lcModelActionMouseTool::LoadSelectionStartState(lcModel* Model) const { - LoadSelectionState(Model, mStartState); -} - -void lcModelActionMouseTool::LoadSelectionEndState(lcModel* Model) const -{ - LoadSelectionState(Model, mEndState); + LoadUndoBuffer(mStartBuffer, Model, true); } void lcModelActionMouseTool::SaveSelectionEndState(const lcModel* Model) { - SaveSelectionState(Model, mEndState); + SaveUndoBuffer(mEndBuffer, Model, true); } -void lcModelActionMouseTool::SaveSelectionState(const lcModel* Model, QByteArray& State) +void lcModelActionMouseTool::LoadSelectionEndState(lcModel* Model) const { - QTextStream Stream(&State, QIODevice::WriteOnly); - - Model->SaveLDraw(Stream, false, 0); -} - -void lcModelActionMouseTool::LoadSelectionState(lcModel* Model, const QByteArray& State) -{ - QBuffer Buffer(const_cast(&State)); - Buffer.open(QIODevice::ReadOnly); - - std::unique_ptr SavedModel = std::make_unique(QString(), Model->GetProject(), false); - SavedModel->LoadLDraw(Buffer, Model->GetProject()); - - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& SavedPieces = SavedModel->GetPieces(); - - if (Pieces.size() != SavedPieces.size()) - return; - - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - { - lcPiece* Piece = Pieces[PieceIndex].get(); - - if (Piece->IsSelected()) - Piece->CopyProperties(*SavedPieces[PieceIndex].get()); - } - - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& SavedCameras = SavedModel->GetCameras(); - - if (Cameras.size() != SavedCameras.size()) - return; - - for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) - { - lcCamera* Camera = Cameras[CameraIndex].get(); - - if (Camera->IsSelected()) - Camera->CopyProperties(*SavedCameras[CameraIndex].get()); - } - - const std::vector>& Lights = Model->GetLights(); - const std::vector>& SavedLights = SavedModel->GetLights(); - - if (Lights.size() != SavedLights.size()) - return; - - for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) - { - lcLight* Light = Lights[LightIndex].get(); - - if (Light->IsSelected()) - Light->CopyProperties(*SavedLights[LightIndex].get()); - } + LoadUndoBuffer(mEndBuffer, Model, true); } lcModelActionAddPieces::lcModelActionAddPieces(lcStep Step, lcModelActionAddPieceSelectionMode SelectionMode) @@ -259,41 +272,12 @@ lcModelActionStep::lcModelActionStep(lcModelActionStepMode Mode, lcStep Step) { } -void lcModelActionStep::SaveState(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) +void lcModelActionStep::SaveModelState(const lcModel* Model) { - mPieceStates.resize(Pieces.size()); - - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - { - QByteArray& PieceState = mPieceStates[PieceIndex]; - const lcPiece* Piece = Pieces[PieceIndex].get(); - - QDataStream Stream(&PieceState, QIODevice::WriteOnly); - - Piece->SaveUndoData(Stream); - } - - mCameraStates.resize(Cameras.size()); - - for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) - { - QByteArray& CameraState = mCameraStates[CameraIndex]; - const lcCamera* Camera = Cameras[CameraIndex].get(); - - QDataStream Stream(&CameraState, QIODevice::WriteOnly); - - Camera->SaveUndoData(Stream); - } - - mLightStates.resize(Lights.size()); - - for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) - { - QByteArray& LightState = mLightStates[LightIndex]; - const lcLight* Light = Lights[LightIndex].get(); - - QDataStream Stream(&LightState, QIODevice::WriteOnly); - - Light->SaveUndoData(Stream); - } + SaveUndoBuffer(mUndoBuffer, Model, false); +} + +void lcModelActionStep::LoadModelState(lcModel* Model) const +{ + LoadUndoBuffer(mUndoBuffer, Model, false); } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 995c8841..2c9dbdbf 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -12,6 +12,10 @@ class lcModelAction public: lcModelAction() = default; virtual ~lcModelAction() = default; + +protected: + static void SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly); + static void LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model, bool SelectedOnly); }; enum class lcModelActionSelectionMode @@ -52,24 +56,16 @@ public: lcModelActionMouseTool(lcTool Tool); virtual ~lcModelActionMouseTool() = default; + void SaveCameraStartState(const lcCamera* Camera); + void LoadCameraStartState(lcCamera* Camera) const; + void SaveCameraEndState(const lcCamera* Camera); + void LoadCameraEndState(lcCamera* Camera) const; + void SaveSelectionStartState(const lcModel* Model); void LoadSelectionStartState(lcModel* Model) const; void SaveSelectionEndState(const lcModel* Model); void LoadSelectionEndState(lcModel* Model) const; - void SetCameraStartState(const lcCamera* Camera); - void SetCameraEndState(const lcCamera* Camera); - - const QByteArray& GetStartState() const - { - return mStartState; - } - - const QByteArray& GetEndState() const - { - return mEndState; - } - lcTool GetTool() const { return mTool; @@ -81,13 +77,10 @@ public: } protected: - static void SaveSelectionState(const lcModel* Model, QByteArray& State); - static void LoadSelectionState(lcModel* Model, const QByteArray& State); - lcTool mTool; QString mCameraName; - QByteArray mStartState; - QByteArray mEndState; + QByteArray mStartBuffer; + QByteArray mEndBuffer; }; enum class lcModelActionAddPieceSelectionMode @@ -249,27 +242,11 @@ public: return mStep; } - void SaveState(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights); + void SaveModelState(const lcModel* Model); + void LoadModelState(lcModel* Model) const; - const std::vector& GetPieceStates() const - { - return mPieceStates; - } - - const std::vector& GetCameraStates() const - { - return mCameraStates; - } - - const std::vector& GetLightStates() const - { - return mLightStates; - } - protected: - std::vector mPieceStates; - std::vector mCameraStates; - std::vector mLightStates; + QByteArray mUndoBuffer; lcModelActionStepMode mMode; lcStep mStep; }; From 561cf9cf52a6f5d7d34ef8fcc4eec43192aede45 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 6 Dec 2025 16:21:33 -0800 Subject: [PATCH 18/93] Added camera action. --- common/camera.cpp | 8 +-- common/camera.h | 2 +- common/lc_model.cpp | 119 +++++++++++++++++--------------------- common/lc_model.h | 6 +- common/lc_modelaction.cpp | 9 ++- common/lc_modelaction.h | 21 +++++++ common/lc_view.cpp | 25 +++----- 7 files changed, 99 insertions(+), 91 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 1b40eeb1..4a4a3a3b 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -30,11 +30,11 @@ lcCamera::lcCamera(bool Simple) } } -lcCamera::lcCamera(float ex, float ey, float ez, float tx, float ty, float tz) +lcCamera::lcCamera(const lcVector3& Position, const lcVector3& TargetPosition) : lcObject(lcObjectType::Camera) { // Fix the up vector - lcVector3 UpVector(0, 0, 1), FrontVector(ex - tx, ey - ty, ez - tz), SideVector; + lcVector3 UpVector(0, 0, 1), FrontVector(Position - TargetPosition), SideVector; FrontVector.Normalize(); if (FrontVector == UpVector) SideVector = lcVector3(1, 0, 0); @@ -45,8 +45,8 @@ lcCamera::lcCamera(float ex, float ey, float ez, float tx, float ty, float tz) Initialize(); - mPosition.SetValue(lcVector3(ex, ey, ez)); - mTargetPosition.SetValue(lcVector3(tx, ty, tz)); + mPosition.SetValue(Position); + mTargetPosition.SetValue(TargetPosition); mUpVector.SetValue(UpVector); lcCamera::UpdatePosition(1); diff --git a/common/camera.h b/common/camera.h index 4d501513..6a97c392 100644 --- a/common/camera.h +++ b/common/camera.h @@ -47,7 +47,7 @@ class lcCamera : public lcObject { public: lcCamera(bool Simple); - lcCamera(float ex, float ey, float ez, float tx, float ty, float tz); + lcCamera(const lcVector3& Position, const lcVector3& TargetPosition); virtual ~lcCamera(); lcCamera(const lcCamera&) = delete; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index c20532cc..712ce667 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -9,8 +9,6 @@ #include "lc_profile.h" #include "lc_library.h" #include "lc_scene.h" -#include "lc_texture.h" -#include "lc_synth.h" #include "lc_traintrack.h" #include "lc_file.h" #include "pieceinf.h" @@ -25,7 +23,6 @@ #include "lc_qutils.h" #include "lc_lxf.h" #include "lc_previewwidget.h" -#include "lc_findreplacewidget.h" #include void lcModelProperties::LoadDefaults() @@ -1734,12 +1731,7 @@ void lcModel::BeginMouseToolAction(lcTool Tool, lcView* View) case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: - break; - -// case lcTool::Camera: -// SaveCheckpoint(tr("New Camera")); -// break; - + case lcTool::Camera: case lcTool::Select: break; @@ -1787,12 +1779,7 @@ void lcModel::EndMouseToolAction(lcTool Tool, lcView* View, const QString& Descr case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: - break; - -// case lcTool::Camera: -// SaveCheckpoint(tr("New Camera")); -// break; - + case lcTool::Camera: case lcTool::Select: break; @@ -1838,12 +1825,7 @@ void lcModel::RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseT case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: - break; - -// case lcTool::Camera: -// SaveCheckpoint(tr("New Camera")); -// break; - + case lcTool::Camera: case lcTool::Select: break; @@ -1963,6 +1945,38 @@ void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPie } } +void lcModel::RecordAddCameraAction(const lcVector3& Position, const lcVector3& TargetPosition) +{ + std::unique_ptr ModelActionAddCamera = std::make_unique(Position, TargetPosition); + + RunAddCameraAction(ModelActionAddCamera.get(), true); + + mActionSequence.emplace_back(std::move(ModelActionAddCamera)); +} + +void lcModel::RunAddCameraAction(const lcModelActionAddCamera* ModelActionAddCamera, bool Apply) +{ + if (!ModelActionAddCamera) + return; + + if (Apply) + { + lcCamera* Camera = new lcCamera(ModelActionAddCamera->GetPosition(), ModelActionAddCamera->GetTargetPosition()); + Camera->CreateName(mCameras); + mCameras.emplace_back(Camera); + + ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_POSITION, false); + } + else + { + if (!mCameras.empty()) + mCameras.pop_back(); + + gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateInUseCategory(); + } +} + void lcModel::RecordAddLightAction(const lcVector3& Position, lcLightType LightType) { std::unique_ptr ModelActionAddLight = std::make_unique(Position, LightType); @@ -2297,6 +2311,8 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunAddPiecesAction(ModelActionAddPieces, Apply); + else if (const lcModelActionAddCamera* ModelActionAddCamera = dynamic_cast(ModelAction)) + RunAddCameraAction(ModelActionAddCamera, Apply); else if (const lcModelActionAddLight* ModelActionAddLight = dynamic_cast(ModelAction)) RunAddLightAction(ModelActionAddLight, Apply); else if (const lcModelActionGroupPieces* ModelActionGroupPieces = dynamic_cast(ModelAction)) @@ -5118,16 +5134,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: - break; - -// case lcTool::Camera: -// { -// lcVector3 Position = GetCameraLightInsertPosition(); -// lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); -// ActiveModel->BeginCameraTool(Position, Target); -// } -// break; - + case lcTool::Camera: case lcTool::Select: break; @@ -5181,12 +5188,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: - break; - -// case lcTool::Camera: -// SaveCheckpoint(tr("New Camera")); -// break; - + case lcTool::Camera: case lcTool::Select: break; @@ -5244,6 +5246,20 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece EndActionSequence(tr("Add Piece")); } +void lcModel::InsertCameraToolClicked(const lcVector3& Position) +{ + lcVector3 TargetPosition; + + GetPieceFocusOrSelectionCenter(TargetPosition); + + BeginActionSequence(); + + RecordSelectionAction(lcModelActionSelectionMode::Save); + RecordAddCameraAction(Position, TargetPosition); + + EndActionSequence(tr("Add Camera")); +} + void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType) { QString ActionName; @@ -5278,35 +5294,6 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh EndActionSequence(ActionName); } -void lcModel::BeginCameraTool(const lcVector3& Position, const lcVector3& Target) -{ - lcCamera* Camera = new lcCamera(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2]); - Camera->CreateName(mCameras); - mCameras.emplace_back(Camera); - - mMouseToolDistance = Position; - mMouseToolFirstMove = false; - - ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_TARGET, false); -} - -void lcModel::UpdateCameraTool(const lcVector3& Position) -{ - if (mCameras.empty()) - return; - - std::unique_ptr& Camera = mCameras.back(); - - Camera->MoveSelected(1, false, Position - mMouseToolDistance); - Camera->UpdatePosition(1); - - mMouseToolDistance = Position; - mMouseToolFirstMove = false; - - gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); -} - void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag) { const lcVector3 PieceDistance = SnapPosition(Distance) - SnapPosition(mMouseToolDistance); diff --git a/common/lc_model.h b/common/lc_model.h index b64c98e3..01002932 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -8,6 +8,7 @@ class lcModelAction; class lcModelActionSelection; class lcModelActionMouseTool; class lcModelActionAddPieces; +class lcModelActionAddCamera; class lcModelActionAddLight; class lcModelActionGroupPieces; class lcModelActionDuplicatePieces; @@ -357,9 +358,8 @@ public: void BeginMouseTool(lcTool Tool, lcView* View); void EndMouseTool(lcTool Tool, lcView* View, bool Accept); void InsertPieceToolClicked(const std::vector& PieceInfoTransforms); + void InsertCameraToolClicked(const lcVector3& Position); void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType); - void BeginCameraTool(const lcVector3& Position, const lcVector3& Target); - void UpdateCameraTool(const lcVector3& Position); void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag); void UpdateFreeMoveTool(lcPiece* MousePiece, const lcMatrix44& StartTransform, const lcMatrix44& NewTransform, bool IsConnection, bool AlternateButtonDrag); void UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag); @@ -415,6 +415,8 @@ protected: void RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseTool, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); + void RecordAddCameraAction(const lcVector3& Position, const lcVector3& TargetPosition); + void RunAddCameraAction(const lcModelActionAddCamera* ModelActionAddCamera, bool Apply); void RecordAddLightAction(const lcVector3& Position, lcLightType LightType); void RunAddLightAction(const lcModelActionAddLight* ModelActionAddLight, bool Apply); void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 2d94fbdd..a46b7104 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -15,7 +15,7 @@ void lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, boo const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - size_t PieceCount = Pieces.size(), CameraCount = Cameras.size(), LightCount = Lights.size(); + uint64_t PieceCount = Pieces.size(), CameraCount = Cameras.size(), LightCount = Lights.size(); Stream << PieceCount; Stream << CameraCount; @@ -42,7 +42,7 @@ void lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model, boo const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - size_t PieceCount, CameraCount, LightCount; + uint64_t PieceCount, CameraCount, LightCount; Stream >> PieceCount; Stream >> CameraCount; @@ -239,6 +239,11 @@ void lcModelActionAddPieces::SetPieceData(const std::vector& } } +lcModelActionAddCamera::lcModelActionAddCamera(const lcVector3& Position, const lcVector3& TargetPosition) + : mPosition(Position), mTargetPosition(TargetPosition) +{ +} + lcModelActionAddLight::lcModelActionAddLight(const lcVector3& Position, lcLightType LightType) : mPosition(Position), mLightType(LightType) { diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 2c9dbdbf..aae64925 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -126,6 +126,27 @@ protected: lcModelActionAddPieceSelectionMode mSelectionMode; }; +class lcModelActionAddCamera : public lcModelAction +{ +public: + lcModelActionAddCamera(const lcVector3& Position, const lcVector3& TargetPosition); + virtual ~lcModelActionAddCamera() = default; + + const lcVector3& GetPosition() const + { + return mPosition; + } + + const lcVector3& GetTargetPosition() const + { + return mTargetPosition; + } + +protected: + lcVector3 mPosition; + lcVector3 mTargetPosition; +}; + class lcModelActionAddLight : public lcModelAction { public: diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 3f08632d..730e4c6a 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2355,16 +2355,7 @@ void lcView::StartTracking(lcTrackButton TrackButton) case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: - break; - case lcTool::Camera: - { - lcVector3 Position = GetCameraLightInsertPosition(); - lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); - ActiveModel->BeginCameraTool(Position, Target); - } - break; - case lcTool::Select: break; @@ -2411,13 +2402,10 @@ void lcView::StopTracking(bool Accept) { case lcTool::Insert: case lcTool::PointLight: - break; - case lcTool::SpotLight: case lcTool::DirectionalLight: case lcTool::AreaLight: case lcTool::Camera: - ActiveModel->EndMouseTool(Tool, this, Accept); break; case lcTool::Select: @@ -2562,7 +2550,15 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) break; case lcTrackTool::Camera: - StartTracking(TrackButton); + { + ActiveModel->InsertCameraToolClicked(GetCameraLightInsertPosition()); + + if ((mMouseModifiers & Qt::ControlModifier) == 0) + gMainWindow->SetTool(lcTool::Select); + + mToolClicked = true; + UpdateTrackTool(); + } break; case lcTrackTool::Select: @@ -2854,10 +2850,7 @@ void lcView::OnMouseMove() case lcTrackTool::SpotLight: case lcTrackTool::DirectionalLight: case lcTrackTool::AreaLight: - break; - case lcTrackTool::Camera: - ActiveModel->UpdateCameraTool(GetCameraLightInsertPosition()); break; case lcTrackTool::Select: From 6b7f9faad1817c7b926827a64d3bb022c585cd08 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 6 Dec 2025 17:30:34 -0800 Subject: [PATCH 19/93] Fixed minifig wizard combobox not working with Qt6. --- common/lc_minifigdialog.cpp | 17 +++++++++++------ common/lc_minifigdialog.h | 12 ++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/common/lc_minifigdialog.cpp b/common/lc_minifigdialog.cpp index ac672477..8b43931c 100644 --- a/common/lc_minifigdialog.cpp +++ b/common/lc_minifigdialog.cpp @@ -4,7 +4,6 @@ #include "lc_viewwidget.h" #include "lc_colorpicker.h" #include "minifig.h" -#include "lc_application.h" #include "pieceinf.h" #include "lc_library.h" #include "lc_view.h" @@ -135,6 +134,12 @@ lcMinifigDialog::lcMinifigDialog(QWidget* Parent) mMinifigWizard->Calculate(); mView->GetCamera()->SetViewpoint(lcVector3(0.0f, -270.0f, 90.0f)); mView->ZoomExtents(); + + connect(ui->TemplateComboBox, &QComboBox::currentTextChanged, this, &lcMinifigDialog::TemplateComboBoxCurrentTextChanged); + connect(ui->TemplateSaveButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateSaveButtonClicked); + connect(ui->TemplateDeleteButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateDeleteButtonClicked); + connect(ui->TemplateImportButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateImportButtonClicked); + connect(ui->TemplateExportButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateExportButtonClicked); } lcMinifigDialog::~lcMinifigDialog() @@ -175,7 +180,7 @@ void lcMinifigDialog::UpdateTemplateCombo() ui->TemplateComboBox->setCurrentText(CurrentName); } -void lcMinifigDialog::on_TemplateComboBox_currentIndexChanged(const QString& TemplateName) +void lcMinifigDialog::TemplateComboBoxCurrentTextChanged(const QString& TemplateName) { const auto& Templates = mMinifigWizard->GetTemplates(); const auto& Position = Templates.find(TemplateName); @@ -234,7 +239,7 @@ void lcMinifigDialog::on_TemplateComboBox_currentIndexChanged(const QString& Tem mView->Redraw(); } -void lcMinifigDialog::on_TemplateSaveButton_clicked() +void lcMinifigDialog::TemplateSaveButtonClicked() { QString CurrentName = mCurrentTemplateName; bool Ok; @@ -280,7 +285,7 @@ void lcMinifigDialog::on_TemplateSaveButton_clicked() UpdateTemplateCombo(); } -void lcMinifigDialog::on_TemplateDeleteButton_clicked() +void lcMinifigDialog::TemplateDeleteButtonClicked() { if (mCurrentTemplateName.isEmpty() || mCurrentTemplateName == MinifigWizard::GetDefaultTemplateName()) return; @@ -299,7 +304,7 @@ void lcMinifigDialog::on_TemplateDeleteButton_clicked() UpdateTemplateCombo(); } -void lcMinifigDialog::on_TemplateImportButton_clicked() +void lcMinifigDialog::TemplateImportButtonClicked() { QString FileName = QFileDialog::getOpenFileName(this, tr("Import Templates"), "", tr("Minifig Template Files (*.minifig);;All Files (*.*)")); @@ -320,7 +325,7 @@ void lcMinifigDialog::on_TemplateImportButton_clicked() UpdateTemplateCombo(); } -void lcMinifigDialog::on_TemplateExportButton_clicked() +void lcMinifigDialog::TemplateExportButtonClicked() { QString FileName = QFileDialog::getSaveFileName(this, tr("Export Templates"), "", tr("Minifig Template Files (*.minifig);;All Files (*.*)")); diff --git a/common/lc_minifigdialog.h b/common/lc_minifigdialog.h index 50d484a0..b83e0886 100644 --- a/common/lc_minifigdialog.h +++ b/common/lc_minifigdialog.h @@ -16,16 +16,16 @@ class lcMinifigDialog : public QDialog public: explicit lcMinifigDialog(QWidget* Parent); - ~lcMinifigDialog(); + virtual ~lcMinifigDialog(); MinifigWizard* mMinifigWizard; protected slots: - void on_TemplateComboBox_currentIndexChanged(const QString& TemplateName); - void on_TemplateSaveButton_clicked(); - void on_TemplateDeleteButton_clicked(); - void on_TemplateImportButton_clicked(); - void on_TemplateExportButton_clicked(); + void TemplateComboBoxCurrentTextChanged(const QString& TemplateName); + void TemplateSaveButtonClicked(); + void TemplateDeleteButtonClicked(); + void TemplateImportButtonClicked(); + void TemplateExportButtonClicked(); void PieceButtonClicked(); void ColorChanged(int Index); void AngleChanged(double Value); From 2da8a2709558d9e7be319b667d05af331d345003 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 7 Dec 2025 16:48:07 -0800 Subject: [PATCH 20/93] Replaced strcpy with a safe function. --- common/lc_bricklink.cpp | 3 ++- common/lc_category.cpp | 4 ++-- common/lc_colors.cpp | 21 +++++++++-------- common/lc_filter.cpp | 3 ++- common/lc_global.h | 6 ----- common/lc_library.cpp | 17 +++++++------- common/lc_meshloader.cpp | 7 +++--- common/lc_model.cpp | 3 ++- qt/system.cpp => common/lc_string.cpp | 33 +++++++++++++++++++-------- common/lc_string.h | 11 +++++++++ common/lc_texture.cpp | 3 ++- common/project.cpp | 4 ++-- leocad.pro | 3 ++- qt/lc_qutils.cpp | 5 ++-- 14 files changed, 74 insertions(+), 49 deletions(-) rename qt/system.cpp => common/lc_string.cpp (53%) create mode 100644 common/lc_string.h diff --git a/common/lc_bricklink.cpp b/common/lc_bricklink.cpp index 98b09b2c..059ec7bc 100644 --- a/common/lc_bricklink.cpp +++ b/common/lc_bricklink.cpp @@ -2,6 +2,7 @@ #include "lc_file.h" #include "lc_library.h" #include "lc_mainwindow.h" +#include "lc_string.h" #include "pieceinf.h" static QJsonDocument lcLoadBrickLinkMapping() @@ -84,7 +85,7 @@ void lcExportBrickLink(const QString& SaveFileName, const lcPartsList& PartsList for (const auto& ColorIt : PartIt.second) { char FileName[LC_PIECE_NAME_LEN]; - strcpy(FileName, Info->mFileName); + lcstrcpy(FileName, Info->mFileName); char* Ext = strchr(FileName, '.'); if (Ext) *Ext = 0; diff --git a/common/lc_category.cpp b/common/lc_category.cpp index d862c68a..192ecb3f 100644 --- a/common/lc_category.cpp +++ b/common/lc_category.cpp @@ -1,6 +1,6 @@ #include "lc_global.h" #include "lc_category.h" -#include "lc_file.h" +#include "lc_string.h" #include "lc_profile.h" std::vector gCategories; @@ -261,7 +261,7 @@ bool lcMatchCategory(const char* PieceName, const char* Expression) if (!Word[0]) return false; - const char* Result = strcasestr(PieceName, Word); + const char* Result = lcstrcasestr(PieceName, Word); if (!Result) return false; diff --git a/common/lc_colors.cpp b/common/lc_colors.cpp index 3b77be85..262c5d21 100644 --- a/common/lc_colors.cpp +++ b/common/lc_colors.cpp @@ -3,6 +3,7 @@ #include "lc_file.h" #include "lc_library.h" #include "lc_application.h" +#include "lc_string.h" #include std::vector gColorList; @@ -79,7 +80,7 @@ static std::vector lcParseColorFile(lcFile& File) continue; GetToken(Ptr, Token); - strupr(Token); + lcstrupr(Token); if (strcmp(Token, "!COLOUR")) continue; @@ -107,7 +108,7 @@ static std::vector lcParseColorFile(lcFile& File) for (GetToken(Ptr, Token); Token[0]; GetToken(Ptr, Token)) { - strupr(Token); + lcstrupr(Token); if (!strcmp(Token, "CODE")) { @@ -258,8 +259,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) MainColor.Edge[1] = 0.2f; MainColor.Edge[2] = 0.2f; MainColor.Edge[3] = 1.0f; - strcpy(MainColor.Name, "Main Color"); - strcpy(MainColor.SafeName, "Main_Color"); + lcstrcpy(MainColor.Name, "Main Color"); + lcstrcpy(MainColor.SafeName, "Main_Color"); Colors.push_back(MainColor); } @@ -281,8 +282,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) EdgeColor.Edge[1] = 0.2f; EdgeColor.Edge[2] = 0.2f; EdgeColor.Edge[3] = 1.0f; - strcpy(EdgeColor.Name, "Edge Color"); - strcpy(EdgeColor.SafeName, "Edge_Color"); + lcstrcpy(EdgeColor.Name, "Edge Color"); + lcstrcpy(EdgeColor.SafeName, "Edge_Color"); Colors.push_back(EdgeColor); } @@ -299,8 +300,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) StudCylinderColor.Group = LC_NUM_COLORGROUPS; StudCylinderColor.Value = lcVector4FromColor(Preferences.mStudCylinderColor); StudCylinderColor.Edge = lcVector4FromColor(Preferences.mPartEdgeColor); - strcpy(StudCylinderColor.Name, "Stud Cylinder Color"); - strcpy(StudCylinderColor.SafeName, "Stud_Cylinder_Color"); + lcstrcpy(StudCylinderColor.Name, "Stud Cylinder Color"); + lcstrcpy(StudCylinderColor.SafeName, "Stud_Cylinder_Color"); Colors.push_back(StudCylinderColor); } @@ -322,8 +323,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle) NoColor.Edge[1] = 0.2f; NoColor.Edge[2] = 0.2f; NoColor.Edge[3] = 1.0f; - strcpy(NoColor.Name, "No Color"); - strcpy(NoColor.SafeName, "No_Color"); + lcstrcpy(NoColor.Name, "No Color"); + lcstrcpy(NoColor.SafeName, "No_Color"); Colors.push_back(NoColor); } diff --git a/common/lc_filter.cpp b/common/lc_filter.cpp index e9656c1f..a008a820 100644 --- a/common/lc_filter.cpp +++ b/common/lc_filter.cpp @@ -1,5 +1,6 @@ #include "lc_global.h" #include "lc_filter.h" +#include "lc_string.h" lcFilter::lcFilter(const std::string_view FilterString) { @@ -80,7 +81,7 @@ bool lcFilter::Match(const char* String) const for (const FilterPart& FilterPart : mFilterParts) { - bool Match = FilterPart.Wildcard ? FastWildCompare(String, FilterPart.String.c_str()) : strcasestr(String, FilterPart.String.c_str()) != nullptr; + bool Match = FilterPart.Wildcard ? FastWildCompare(String, FilterPart.String.c_str()) : lcstrcasestr(String, FilterPart.String.c_str()) != nullptr; switch (FilterPart.Op) { diff --git a/common/lc_global.h b/common/lc_global.h index 9146f242..c9a7d227 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -67,12 +67,6 @@ class QPrinter; typedef quint32 lcStep; #define LC_STEP_MAX 0xffffffff -#ifdef Q_OS_WIN -char* strcasestr(const char *s, const char *find); -#else -char* strupr(char* string); -#endif - // Version number. #define LC_VERSION_MAJOR 25 #define LC_VERSION_MINOR 9 diff --git a/common/lc_library.cpp b/common/lc_library.cpp index 8f1b161c..fdf20d64 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -16,8 +16,7 @@ #include "project.h" #include "lc_profile.h" #include "lc_meshloader.h" -#include -#include +#include "lc_string.h" #include #include @@ -129,8 +128,8 @@ void lcPiecesLibrary::RenamePiece(PieceInfo* Info, const char* NewName) Info->m_strDescription[sizeof(Info->m_strDescription) - 1] = 0; char PieceName[LC_PIECE_NAME_LEN]; - strcpy(PieceName, Info->mFileName); - strupr(PieceName); + lcstrcpy(PieceName, Info->mFileName); + lcstrupr(PieceName); mPieces[PieceName] = Info; } @@ -761,7 +760,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists) if (FileTime == CachedFileTime) { - strcpy(Info->m_strDescription, Description); + lcstrcpy(Info->m_strDescription, Description); return; } } @@ -769,7 +768,7 @@ void lcPiecesLibrary::ReadDirectoryDescriptions(const QFileInfoList (&FileLists) if (!PieceFile.Open(QIODevice::ReadOnly) || !PieceFile.ReadLine(Line, sizeof(Line))) { - strcpy(Info->m_strDescription, "Unknown"); + lcstrcpy(Info->m_strDescription, "Unknown"); return; } @@ -1668,9 +1667,9 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive) if (strncmp(Primitive->mName, "8/", 2)) // todo: this is currently the only place that uses mName so use mFileName instead. this should also be done for the loose file libraries. { char Name[LC_PIECE_NAME_LEN]; - strcpy(Name, "8/"); + lcstrcpy(Name, "8/"); strcat(Name, Primitive->mName); - strupr(Name); + lcstrupr(Name); LowPrimitive = FindPrimitive(Name); // todo: low primitives don't work with studlogo, because the low stud gets added as shared } @@ -1769,7 +1768,7 @@ void lcPiecesLibrary::GetCategoryEntries(const char* CategoryKeywords, bool Grou // Find the parent of this patterned piece. char ParentName[LC_PIECE_NAME_LEN]; - strcpy(ParentName, Info->mFileName); + lcstrcpy(ParentName, Info->mFileName); *strchr(ParentName, 'P') = '\0'; strcat(ParentName, ".dat"); diff --git a/common/lc_meshloader.cpp b/common/lc_meshloader.cpp index 0b64d388..d4b53ca3 100644 --- a/common/lc_meshloader.cpp +++ b/common/lc_meshloader.cpp @@ -5,6 +5,7 @@ #include "lc_library.h" #include "lc_application.h" #include "lc_texture.h" +#include "lc_string.h" static void lcCheckTexCoordsWrap(const lcVector4& Plane2, const lcVector3 (&Positions)[3], lcVector2 (&TexCoords)[3]) { @@ -589,7 +590,7 @@ lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode, Material->Points[2] = TextureMap.Points[2]; Material->Angles[0] = TextureMap.Angles[0]; Material->Angles[1] = TextureMap.Angles[1]; - strcpy(Material->Name, TextureMap.Name); + lcstrcpy(Material->Name, TextureMap.Name); return Material; } @@ -831,7 +832,7 @@ lcMesh* lcLibraryMeshData::CreateMesh() FinalSection.PrimitiveType = Section->mPrimitiveType; FinalSection.Color = Section->mMaterial->Color; - strcpy(FinalSection.Name, Section->mMaterial->Name); + lcstrcpy(FinalSection.Name, Section->mMaterial->Name); }; for (const std::unique_ptr& Section : mData[LC_MESHDATA_SHARED].mSections) @@ -1370,7 +1371,7 @@ bool lcMeshLoader::ReadMeshData(lcFile& File, const lcMatrix44& CurrentTransform sscanf(Line, "%d %i %f %f %f %f %f %f %f %f %f %f %f %f %s", &LineType, &Dummy, &fm[0], &fm[1], &fm[2], &fm[3], &fm[4], &fm[5], &fm[6], &fm[7], &fm[8], &fm[9], &fm[10], &fm[11], OriginalFileName); char FileName[LC_MAXPATH]; - strcpy(FileName, OriginalFileName); + lcstrcpy(FileName, OriginalFileName); char* Ch; for (Ch = FileName; *Ch; Ch++) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 712ce667..a8180a24 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -23,6 +23,7 @@ #include "lc_qutils.h" #include "lc_lxf.h" #include "lc_previewwidget.h" +#include "lc_string.h" #include void lcModelProperties::LoadDefaults() @@ -4992,7 +4993,7 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) if (Params.FindInfo && Params.FindInfo != Piece->mPieceInfo) return false; - if (!Params.FindString.isEmpty() && !strcasestr(Piece->mPieceInfo->m_strDescription, Params.FindString.toLatin1())) + if (!Params.FindString.isEmpty() && !lcstrcasestr(Piece->mPieceInfo->m_strDescription, Params.FindString.toLatin1())) return false; return (lcGetColorCode(Params.FindColorIndex) == LC_COLOR_NOCOLOR) || (Piece->GetColorIndex() == Params.FindColorIndex); diff --git a/qt/system.cpp b/common/lc_string.cpp similarity index 53% rename from qt/system.cpp rename to common/lc_string.cpp index d201c97b..dcc8546e 100644 --- a/qt/system.cpp +++ b/common/lc_string.cpp @@ -1,11 +1,10 @@ #include "lc_global.h" +#include "lc_string.h" -#ifdef Q_OS_WIN - -char* strcasestr(const char* s, const char* find) +char* lcstrcasestr(const char* s, const char* find) { char c, sc; - + if ((c = *find++) != 0) { c = tolower((unsigned char)c); @@ -23,14 +22,30 @@ char* strcasestr(const char* s, const char* find) return ((char *)s); } -#else - -char* strupr(char* string) +char* lcstrupr(char* string) { for (char* c = string; *c; c++) *c = toupper(*c); - + return string; } -#endif +size_t lcstrcpy(char* dest, const char* source, size_t count) +{ + if (count == 0) + return 0; + + for (size_t i = 0; i < count; i++) + { + dest[i] = source[i]; + + if (source[i] == '\0') + { + return i; + } + } + + dest[--count] = '\0'; + + return count; +} diff --git a/common/lc_string.h b/common/lc_string.h new file mode 100644 index 00000000..3d4cdbdd --- /dev/null +++ b/common/lc_string.h @@ -0,0 +1,11 @@ +#pragma once + +char* lcstrcasestr(const char* s, const char* find); +char* lcstrupr(char* string); +size_t lcstrcpy(char* dest, const char* source, size_t count); + +template +size_t lcstrcpy(char (&dest)[size], const char* source) +{ + return lcstrcpy(dest, source, size); +} diff --git a/common/lc_texture.cpp b/common/lc_texture.cpp index 1f61a9c1..819e53e5 100644 --- a/common/lc_texture.cpp +++ b/common/lc_texture.cpp @@ -4,6 +4,7 @@ #include "lc_library.h" #include "image.h" #include "lc_glextensions.h" +#include "lc_string.h" lcTexture* gGridTexture; @@ -18,7 +19,7 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags) } else { - strcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1()); + lcstrcpy(Texture->mName, QFileInfo(FileName).baseName().toLatin1()); Texture->SetTemporary(true); } diff --git a/common/project.cpp b/common/project.cpp index ac0770c9..44545a42 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -1,7 +1,6 @@ #include "lc_global.h" #include "lc_math.h" #include "lc_mesh.h" -#include #include "pieceinf.h" #include "camera.h" #include "project.h" @@ -18,6 +17,7 @@ #include "lc_qimagedialog.h" #include "lc_modellistdialog.h" #include "lc_bricklink.h" +#include "lc_string.h" lcHTMLExportOptions::lcHTMLExportOptions(const Project* Project) { @@ -2413,7 +2413,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) if (!ModelPart.Mesh) { std::pair& Entry = PieceTable[ModelPart.Info]; - strcpy(Entry.first, "lc_"); + lcstrcpy(Entry.first, "lc_"); strncat(Entry.first, Name, sizeof(Entry.first) - 1); Entry.first[sizeof(Entry.first) - 1] = 0; } diff --git a/leocad.pro b/leocad.pro index adabb7da..15cf65d3 100644 --- a/leocad.pro +++ b/leocad.pro @@ -219,6 +219,7 @@ SOURCES += \ common/lc_propertieswidget.cpp \ common/lc_scene.cpp \ common/lc_shortcuts.cpp \ + common/lc_string.cpp \ common/lc_stringcache.cpp \ common/lc_synth.cpp \ common/lc_texture.cpp \ @@ -230,7 +231,6 @@ SOURCES += \ common/lc_viewsphere.cpp \ common/lc_viewwidget.cpp \ common/lc_zipfile.cpp \ - qt/system.cpp \ qt/qtmain.cpp \ qt/lc_qeditgroupsdialog.cpp \ qt/lc_qselectdialog.cpp \ @@ -298,6 +298,7 @@ HEADERS += \ common/lc_propertieswidget.h \ common/lc_scene.h \ common/lc_shortcuts.h \ + common/lc_string.h \ common/lc_stringcache.h \ common/lc_synth.h \ common/lc_texture.h \ diff --git a/qt/lc_qutils.cpp b/qt/lc_qutils.cpp index 4130876b..fe003e7d 100644 --- a/qt/lc_qutils.cpp +++ b/qt/lc_qutils.cpp @@ -4,8 +4,7 @@ #include "lc_library.h" #include "lc_model.h" #include "pieceinf.h" -#include "lc_partselectionwidget.h" -#include "lc_mainwindow.h" +#include "lc_string.h" #ifdef Q_OS_WIN #include @@ -238,7 +237,7 @@ std::vector lcPieceIdStringModel::GetFilteredRows(const QString& FilterTex { const PieceInfo* Info = mSortedPieces[PieceInfoIndex]; - FilteredRows[PieceInfoIndex] = (strcasestr(Info->m_strDescription, Text.c_str()) || strcasestr(Info->mFileName, Text.c_str())); + FilteredRows[PieceInfoIndex] = (lcstrcasestr(Info->m_strDescription, Text.c_str()) || lcstrcasestr(Info->mFileName, Text.c_str())); } return FilteredRows; From 7c196945f884c1bfa114cdfd55ded91c18a3fe79 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 7 Dec 2025 16:54:13 -0800 Subject: [PATCH 21/93] Removed LC_FIXED_FUNCTION. --- common/lc_context.cpp | 217 ------------------------------------------ common/lc_global.h | 9 +- 2 files changed, 1 insertion(+), 225 deletions(-) diff --git a/common/lc_context.cpp b/common/lc_context.cpp index 07cfb6fc..7e73f77a 100644 --- a/common/lc_context.cpp +++ b/common/lc_context.cpp @@ -52,10 +52,6 @@ lcContext::lcContext() mColorBlend = false; mCullFace = false; mLineWidth = 1.0f; -#if LC_FIXED_FUNCTION - mMatrixMode = GL_MODELVIEW; - mTextureEnabled = false; -#endif mColor = lcVector4(0.0f, 0.0f, 0.0f, 0.0f); mWorldMatrix = lcMatrix44Identity(); @@ -417,24 +413,6 @@ void lcContext::SetDefaultState() DisableVertexAttrib(lcProgramAttrib::Color); SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr); } - else - { -#if LC_FIXED_FUNCTION - glEnableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - glVertexPointer(3, GL_FLOAT, 0, nullptr); - glNormalPointer(GL_BYTE, 0, nullptr); - glTexCoordPointer(2, GL_FLOAT, 0, nullptr); - glColorPointer(4, GL_FLOAT, 0, nullptr); - - mNormalEnabled = false; - mTexCoordEnabled = false; - mColorEnabled = false; -#endif - } mVertexBufferObject = 0; mIndexBufferObject = 0; @@ -467,17 +445,6 @@ void lcContext::SetDefaultState() glUseProgram(0); mMaterialType = lcMaterialType::Count; } - else - { -#if LC_FIXED_FUNCTION - glMatrixMode(GL_MODELVIEW); - mMatrixMode = GL_MODELVIEW; - glShadeModel(GL_FLAT); - - glDisable(GL_TEXTURE_2D); - mTextureEnabled = false; -#endif - } } void lcContext::ClearColorAndDepth(const lcVector4& ClearColor) @@ -513,49 +480,6 @@ void lcContext::SetMaterial(lcMaterialType MaterialType) mViewMatrixDirty = true; mHighlightParamsDirty = true; } - else - { -#if LC_FIXED_FUNCTION - switch (MaterialType) - { - case lcMaterialType::UnlitTextureModulate: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (!mTextureEnabled) - { - glEnable(GL_TEXTURE_2D); - mTextureEnabled = true; - } - break; - - case lcMaterialType::FakeLitTextureDecal: - case lcMaterialType::UnlitTextureDecal: - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); - - if (!mTextureEnabled) - { - glEnable(GL_TEXTURE_2D); - mTextureEnabled = true; - } - break; - - case lcMaterialType::UnlitColor: - case lcMaterialType::UnlitColorConditional: - case lcMaterialType::UnlitVertexColor: - case lcMaterialType::FakeLitColor: - if (mTextureEnabled) - { - glDisable(GL_TEXTURE_2D); - mTextureEnabled = false; - } - break; - - case lcMaterialType::UnlitViewSphere: - case lcMaterialType::Count: - break; - } -#endif - } } void lcContext::SetViewport(int x, int y, int Width, int Height) @@ -981,24 +905,6 @@ void lcContext::ClearVertexBuffer() DisableVertexAttrib(lcProgramAttrib::Color); SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr); } - else - { -#if LC_FIXED_FUNCTION - if (mNormalEnabled) - glDisableClientState(GL_NORMAL_ARRAY); - - if (mTexCoordEnabled) - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - if (mColorEnabled) - glDisableClientState(GL_COLOR_ARRAY); - - glVertexPointer(3, GL_FLOAT, 0, nullptr); - glNormalPointer(GL_BYTE, 0, nullptr); - glTexCoordPointer(2, GL_FLOAT, 0, nullptr); - glColorPointer(4, GL_FLOAT, 0, nullptr); -#endif - } } void lcContext::SetVertexBuffer(lcVertexBuffer VertexBuffer) @@ -1088,34 +994,6 @@ void lcContext::SetVertexFormatPosition(int PositionSize) DisableVertexAttrib(lcProgramAttrib::TexCoord); DisableVertexAttrib(lcProgramAttrib::Color); } - else - { -#if LC_FIXED_FUNCTION - if (mVertexBufferOffset != mVertexBufferPointer) - { - glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer); - mVertexBufferOffset = VertexBufferPointer; - } - - if (mNormalEnabled) - { - glDisableClientState(GL_NORMAL_ARRAY); - mNormalEnabled = false; - } - - if (mTexCoordEnabled) - { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - mTexCoordEnabled = false; - } - - if (mColorEnabled) - { - glDisableClientState(GL_COLOR_ARRAY); - mColorEnabled = false; - } -#endif - } } void lcContext::SetVertexFormatConditional(int BufferOffset) @@ -1178,70 +1056,6 @@ void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSi else DisableVertexAttrib(lcProgramAttrib::Color); } - else - { -#if LC_FIXED_FUNCTION - if (mVertexBufferOffset != VertexBufferPointer) - { - glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer); - mVertexBufferOffset = VertexBufferPointer; - } - - int Offset = PositionSize * sizeof(float); - - if (NormalSize && EnableNormals) - { - glNormalPointer(GL_BYTE, VertexSize, VertexBufferPointer + Offset); - - if (!mNormalEnabled) - { - glEnableClientState(GL_NORMAL_ARRAY); - mNormalEnabled = true; - } - } - else if (mNormalEnabled) - { - glDisableClientState(GL_NORMAL_ARRAY); - mNormalEnabled = false; - } - - Offset += NormalSize * sizeof(quint32); - - if (TexCoordSize) - { - glTexCoordPointer(TexCoordSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset); - - if (!mTexCoordEnabled) - { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - mTexCoordEnabled = true; - } - - Offset += 2 * sizeof(float); - } - else if (mTexCoordEnabled) - { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - mTexCoordEnabled = false; - } - - if (ColorSize) - { - glColorPointer(ColorSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset); - - if (!mColorEnabled) - { - glEnableClientState(GL_COLOR_ARRAY); - mColorEnabled = true; - } - } - else if (mColorEnabled) - { - glDisableClientState(GL_COLOR_ARRAY); - mColorEnabled = false; - } -#endif - } } void lcContext::ClearIndexBuffer() @@ -1380,37 +1194,6 @@ void lcContext::FlushState() mHighlightParamsDirty = false; } } - else - { -#if LC_FIXED_FUNCTION - glColor4fv(mColor.GetFloats()); - - if (mWorldMatrixDirty || mViewMatrixDirty) - { - if (mMatrixMode != GL_MODELVIEW) - { - glMatrixMode(GL_MODELVIEW); - mMatrixMode = GL_MODELVIEW; - } - - glLoadMatrixf(lcMul(mWorldMatrix, mViewMatrix).GetFloats()); - mWorldMatrixDirty = false; - mViewMatrixDirty = false; - } - - if (mProjectionMatrixDirty) - { - if (mMatrixMode != GL_PROJECTION) - { - glMatrixMode(GL_PROJECTION); - mMatrixMode = GL_PROJECTION; - } - - glLoadMatrixf(mProjectionMatrix.GetFloats()); - mProjectionMatrixDirty = false; - } -#endif - } } void lcContext::DrawPrimitives(GLenum Mode, GLint First, GLsizei Count) diff --git a/common/lc_global.h b/common/lc_global.h index c9a7d227..2c5b428e 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -49,15 +49,8 @@ class QPrinter; #define LC_ARRAY_COUNT(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) #define LC_ARRAY_SIZE_CHECK(a,s) static_assert(LC_ARRAY_COUNT(a) == static_cast(s), QT_STRINGIFY(a) " size mismatch.") -#if !defined(EGL_VERSION_1_0) && !defined(GL_ES_VERSION_2_0) && !defined(GL_ES_VERSION_3_0) && !defined(QT_OPENGL_ES) -#ifdef Q_OS_MACOS -#define LC_FIXED_FUNCTION 0 -#else -#define LC_FIXED_FUNCTION 1 -#endif -#else +#if defined(EGL_VERSION_1_0) || defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0) || defined(QT_OPENGL_ES) #define LC_OPENGLES 1 -#define LC_FIXED_FUNCTION 0 #endif // Old defines and declarations. From 910c3de13ee5c017ecaa71d47d3821bac787a9f2 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 8 Dec 2025 21:08:48 -0800 Subject: [PATCH 22/93] Added zoom region action. --- common/lc_model.cpp | 197 ++++++++++++++------------------------ common/lc_model.h | 11 ++- common/lc_modelaction.cpp | 20 ++-- common/lc_modelaction.h | 19 ++-- common/lc_view.cpp | 3 +- common/lc_viewwidget.cpp | 2 +- 6 files changed, 104 insertions(+), 148 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index a8180a24..dff17fb8 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1721,149 +1721,76 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect } } -void lcModel::BeginMouseToolAction(lcTool Tool, lcView* View) +void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View) { - std::unique_ptr ModelActionMouseTool = std::make_unique(Tool); + std::unique_ptr ModelActionObjectEdit = std::make_unique(ModelActionObjectEditMode); - switch (Tool) + switch (ModelActionObjectEditMode) { - case lcTool::Insert: - case lcTool::PointLight: - case lcTool::SpotLight: - case lcTool::DirectionalLight: - case lcTool::AreaLight: - case lcTool::Camera: - case lcTool::Select: + case lcModelActionObjectEditMode::Camera: + ModelActionObjectEdit->SaveCameraStartState(View->GetCamera()); break; - - case lcTool::Move: - case lcTool::Rotate: - ModelActionMouseTool->SaveSelectionStartState(this); - break; - - case lcTool::Eraser: - case lcTool::Paint: - case lcTool::ColorPicker: - break; - - case lcTool::Zoom: - case lcTool::Pan: - case lcTool::RotateView: - case lcTool::Roll: - ModelActionMouseTool->SaveCameraStartState(View->GetCamera()); - break; - - case lcTool::ZoomRegion: - break; - - case lcTool::Count: + + case lcModelActionObjectEditMode::Selection: + ModelActionObjectEdit->SaveSelectionStartState(this); break; } - mActionSequence.emplace_back(std::move(ModelActionMouseTool)); + mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } -void lcModel::EndMouseToolAction(lcTool Tool, lcView* View, const QString& Description) +void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View) { if (mActionSequence.empty()) return; - lcModelActionMouseTool* ModelActionMouseTool = dynamic_cast(mActionSequence.back().get()); + lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(mActionSequence.back().get()); - if (!ModelActionMouseTool || Tool != ModelActionMouseTool->GetTool()) + if (!ModelActionObjectEdit || ModelActionObjectEditMode != ModelActionObjectEdit->GetMode()) return; - switch (Tool) + switch (ModelActionObjectEditMode) { - case lcTool::Insert: - case lcTool::PointLight: - case lcTool::SpotLight: - case lcTool::DirectionalLight: - case lcTool::AreaLight: - case lcTool::Camera: - case lcTool::Select: + case lcModelActionObjectEditMode::Camera: + ModelActionObjectEdit->SaveCameraEndState(View->GetCamera()); break; - - case lcTool::Move: - case lcTool::Rotate: - ModelActionMouseTool->SaveSelectionEndState(this); - break; - - case lcTool::Eraser: - case lcTool::Paint: - case lcTool::ColorPicker: - break; - - case lcTool::Zoom: - case lcTool::Pan: - case lcTool::RotateView: - case lcTool::Roll: - ModelActionMouseTool->SaveCameraEndState(View->GetCamera()); - break; - - case lcTool::ZoomRegion: - break; - - case lcTool::Count: + + case lcModelActionObjectEditMode::Selection: + ModelActionObjectEdit->SaveSelectionEndState(this); break; } RecordSelectionAction(lcModelActionSelectionMode::Set); - EndActionSequence(Description); } -void lcModel::RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseTool, bool Apply) +void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply) { - if (!ModelActionMouseTool) + if (!ModelActionObjectEdit) return; - lcTool Tool = ModelActionMouseTool->GetTool(); + lcModelActionObjectEditMode ModelActionObjectEditMode = ModelActionObjectEdit->GetMode(); - switch (Tool) + switch (ModelActionObjectEditMode) { - case lcTool::Insert: - case lcTool::PointLight: - case lcTool::SpotLight: - case lcTool::DirectionalLight: - case lcTool::AreaLight: - case lcTool::Camera: - case lcTool::Select: - break; - - case lcTool::Move: - case lcTool::Rotate: - if (Apply) - ModelActionMouseTool->LoadSelectionEndState(this); - else - ModelActionMouseTool->LoadSelectionStartState(this); - - SetCurrentStep(mCurrentStep); - break; - - case lcTool::Eraser: - case lcTool::Paint: - case lcTool::ColorPicker: - break; - - case lcTool::Zoom: - case lcTool::Pan: - case lcTool::RotateView: - case lcTool::Roll: - if (lcCamera* Camera = GetCamera(ModelActionMouseTool->GetCameraName())) + case lcModelActionObjectEditMode::Camera: + if (lcCamera* Camera = GetCamera(ModelActionObjectEdit->GetCameraName())) { if (Apply) - ModelActionMouseTool->LoadCameraEndState(Camera); + ModelActionObjectEdit->LoadCameraEndState(Camera); else - ModelActionMouseTool->LoadCameraStartState(Camera); - + ModelActionObjectEdit->LoadCameraStartState(Camera); + SetCurrentStep(mCurrentStep); } break; + + case lcModelActionObjectEditMode::Selection: + if (Apply) + ModelActionObjectEdit->LoadSelectionEndState(this); + else + ModelActionObjectEdit->LoadSelectionStartState(this); - case lcTool::ZoomRegion: - break; - - case lcTool::Count: + SetCurrentStep(mCurrentStep); break; } } @@ -2308,8 +2235,8 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunSelectionAction(ModelActionSelection, Apply); - else if (const lcModelActionMouseTool* ModelActionMouseTool = dynamic_cast(ModelAction)) - RunMouseToolAction(ModelActionMouseTool, Apply); + else if (const lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(ModelAction)) + RunObjectEditAction(ModelActionObjectEdit, Apply); else if (const lcModelActionAddPieces* ModelActionAddPieces = dynamic_cast(ModelAction)) RunAddPiecesAction(ModelActionAddPieces, Apply); else if (const lcModelActionAddCamera* ModelActionAddCamera = dynamic_cast(ModelAction)) @@ -5143,7 +5070,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::Rotate: BeginActionSequence(); RecordSelectionAction(lcModelActionSelectionMode::Set); - BeginMouseToolAction(Tool, View); + BeginObjectEditAction(lcModelActionObjectEditMode::Selection, View); break; case lcTool::Eraser: @@ -5158,8 +5085,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) if (!View->GetCamera()->IsSimple()) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Set); - BeginMouseToolAction(Tool, View); + BeginObjectEditAction(lcModelActionObjectEditMode::Camera, View); } break; @@ -5194,11 +5120,13 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) break; case lcTool::Move: - EndMouseToolAction(Tool, View, tr("Move")); + EndObjectEditAction(lcModelActionObjectEditMode::Selection, View); + EndActionSequence(tr("Move")); break; case lcTool::Rotate: - EndMouseToolAction(Tool, View, tr("Rotate")); + EndObjectEditAction(lcModelActionObjectEditMode::Selection, View); + EndActionSequence(tr("Rotate")); break; case lcTool::Eraser: @@ -5208,22 +5136,34 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Zoom: if (!View->GetCamera()->IsSimple()) - EndMouseToolAction(Tool, View, tr("Zoom")); + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndActionSequence(tr("Zoom")); + } break; case lcTool::Pan: if (!View->GetCamera()->IsSimple()) - EndMouseToolAction(Tool, View, tr("Pan")); + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndActionSequence(tr("Pan")); + } break; case lcTool::RotateView: if (!View->GetCamera()->IsSimple()) - EndMouseToolAction(Tool, View, tr("Orbit")); + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndActionSequence(tr("Orbit")); + } break; case lcTool::Roll: if (!View->GetCamera()->IsSimple()) - EndMouseToolAction(Tool, View, tr("Roll")); + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndActionSequence(tr("Roll")); + } break; case lcTool::ZoomRegion: @@ -5519,15 +5459,26 @@ void lcModel::UpdateRollTool(lcCamera* Camera, float Mouse) UpdateAllViews(); } -void lcModel::ZoomRegionToolClicked(lcCamera* Camera, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners) +void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners) { + lcCamera* Camera = View->GetCamera(); + + if (!Camera->IsSimple()) + { + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::Camera, View); + } + Camera->ZoomRegion(AspectRatio, Position, TargetPosition, Corners, mCurrentStep, gMainWindow->GetAddKeys()); - + + if (!Camera->IsSimple()) + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndActionSequence(tr("Zoom")); + } + gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); - - if (!Camera->IsSimple()) - SaveCheckpoint(tr("Zoom")); } void lcModel::LookAt(lcCamera* Camera) diff --git a/common/lc_model.h b/common/lc_model.h index 01002932..da5a4015 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -6,7 +6,7 @@ enum class lcObjectPropertyId; class lcModelAction; class lcModelActionSelection; -class lcModelActionMouseTool; +class lcModelActionObjectEdit; class lcModelActionAddPieces; class lcModelActionAddCamera; class lcModelActionAddLight; @@ -16,6 +16,7 @@ class lcModelActionHidePieces; class lcModelActionStep; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; +enum class lcModelActionObjectEditMode; enum class lcModelActionGroupPiecesMode; enum class lcModelActionHidePiecesMode; enum class lcModelActionStepMode; @@ -371,7 +372,7 @@ public: void UpdatePanTool(lcCamera* Camera, const lcVector3& Distance); void UpdateOrbitTool(lcCamera* Camera, float MouseX, float MouseY); void UpdateRollTool(lcCamera* Camera, float Mouse); - void ZoomRegionToolClicked(lcCamera* Camera, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners); + void ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners); void LookAt(lcCamera* Camera); void MoveCamera(lcCamera* Camera, const lcVector3& Direction); void ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& WorldMatrix); @@ -410,9 +411,9 @@ protected: void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); - void BeginMouseToolAction(lcTool Tool, lcView* View); - void EndMouseToolAction(lcTool Tool, lcView* View, const QString& Description); - void RunMouseToolAction(const lcModelActionMouseTool* ModelActionMouseTool, bool Apply); + void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View); + void EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View); + void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); void RecordAddCameraAction(const lcVector3& Position, const lcVector3& TargetPosition); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index a46b7104..d55dc20e 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -164,12 +164,12 @@ std::tuple, lcObject*, uint32_t> lcModelActionSelection:: return { SelectedObjects, FocusObject, mFocusSection }; } -lcModelActionMouseTool::lcModelActionMouseTool(lcTool Tool) - : mTool( Tool ) +lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mode) + : mMode(Mode) { } -void lcModelActionMouseTool::SaveCameraStartState(const lcCamera* Camera) +void lcModelActionObjectEdit::SaveCameraStartState(const lcCamera* Camera) { QDataStream Stream(&mStartBuffer, QIODevice::WriteOnly); @@ -178,43 +178,43 @@ void lcModelActionMouseTool::SaveCameraStartState(const lcCamera* Camera) mCameraName = Camera->GetName(); } -void lcModelActionMouseTool::LoadCameraStartState(lcCamera* Camera) const +void lcModelActionObjectEdit::LoadCameraStartState(lcCamera* Camera) const { QDataStream Stream(const_cast(&mStartBuffer), QIODevice::ReadOnly); Camera->LoadUndoData(Stream); } -void lcModelActionMouseTool::SaveCameraEndState(const lcCamera* Camera) +void lcModelActionObjectEdit::SaveCameraEndState(const lcCamera* Camera) { QDataStream Stream(&mEndBuffer, QIODevice::WriteOnly); Camera->SaveUndoData(Stream); } -void lcModelActionMouseTool::LoadCameraEndState(lcCamera* Camera) const +void lcModelActionObjectEdit::LoadCameraEndState(lcCamera* Camera) const { QDataStream Stream(const_cast(&mEndBuffer), QIODevice::ReadOnly); Camera->LoadUndoData(Stream); } -void lcModelActionMouseTool::SaveSelectionStartState(const lcModel* Model) +void lcModelActionObjectEdit::SaveSelectionStartState(const lcModel* Model) { SaveUndoBuffer(mStartBuffer, Model, true); } -void lcModelActionMouseTool::LoadSelectionStartState(lcModel* Model) const +void lcModelActionObjectEdit::LoadSelectionStartState(lcModel* Model) const { LoadUndoBuffer(mStartBuffer, Model, true); } -void lcModelActionMouseTool::SaveSelectionEndState(const lcModel* Model) +void lcModelActionObjectEdit::SaveSelectionEndState(const lcModel* Model) { SaveUndoBuffer(mEndBuffer, Model, true); } -void lcModelActionMouseTool::LoadSelectionEndState(lcModel* Model) const +void lcModelActionObjectEdit::LoadSelectionEndState(lcModel* Model) const { LoadUndoBuffer(mEndBuffer, Model, true); } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index aae64925..5b4d421f 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -5,7 +5,6 @@ struct lcInsertPieceInfo; enum class lcObjectType; enum class lcLightType; -enum class lcTool; class lcModelAction { @@ -50,11 +49,17 @@ protected: lcModelActionSelectionMode mMode = lcModelActionSelectionMode::Clear; }; -class lcModelActionMouseTool : public lcModelAction +enum class lcModelActionObjectEditMode +{ + Camera, + Selection +}; + +class lcModelActionObjectEdit: public lcModelAction { public: - lcModelActionMouseTool(lcTool Tool); - virtual ~lcModelActionMouseTool() = default; + lcModelActionObjectEdit(lcModelActionObjectEditMode Mode); + virtual ~lcModelActionObjectEdit() = default; void SaveCameraStartState(const lcCamera* Camera); void LoadCameraStartState(lcCamera* Camera) const; @@ -66,9 +71,9 @@ public: void SaveSelectionEndState(const lcModel* Model); void LoadSelectionEndState(lcModel* Model) const; - lcTool GetTool() const + lcModelActionObjectEditMode GetMode() const { - return mTool; + return mMode; } const QString& GetCameraName() const @@ -77,7 +82,7 @@ public: } protected: - lcTool mTool; + lcModelActionObjectEditMode mMode; QString mCameraName; QByteArray mStartBuffer; QByteArray mEndBuffer; diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 730e4c6a..3fd998e1 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -9,7 +9,6 @@ #include "lc_texture.h" #include "piece.h" #include "pieceinf.h" -#include "lc_synth.h" #include "lc_traintrack.h" #include "lc_scene.h" #include "lc_context.h" @@ -2465,7 +2464,7 @@ void lcView::StopTracking(bool Accept) if (lcLineSegmentPlaneIntersection(&Target, Points[0], Points[1], Plane) && lcLineSegmentPlaneIntersection(&Corners[0], Points[2], Points[3], Plane) && lcLineSegmentPlaneIntersection(&Corners[1], Points[3], Points[4], Plane)) { float AspectRatio = (float)mWidth / (float)mHeight; - ActiveModel->ZoomRegionToolClicked(mCamera, AspectRatio, Points[0], Target, Corners); + ActiveModel->ZoomRegionToolClicked(this, AspectRatio, Points[0], Target, Corners); } } break; diff --git a/common/lc_viewwidget.cpp b/common/lc_viewwidget.cpp index 9db02251..6f92a937 100644 --- a/common/lc_viewwidget.cpp +++ b/common/lc_viewwidget.cpp @@ -63,7 +63,7 @@ void lcViewWidget::SetView(lcView* View) void lcViewWidget::UpdateMousePosition() { - QPoint MousePosition = mapFromGlobal( QCursor::pos() ); + QPoint MousePosition = mapFromGlobal(QCursor::pos()); float DeviceScale = GetDeviceScale(); mView->SetMousePosition(MousePosition.x() * DeviceScale, mView->GetHeight() - MousePosition.y() * DeviceScale - 1); From a08dede88bbdf86901594d884d3de1cae148e1c7 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 15 Dec 2025 11:07:35 -0300 Subject: [PATCH 23/93] Fixed warnings. --- common/lc_application.cpp | 1 + common/lc_bricklink.cpp | 1 + common/lc_context.h | 3 +-- common/lc_partselectionwidget.cpp | 1 + common/lc_scene.cpp | 1 + common/lc_view.cpp | 5 +++-- common/project.cpp | 1 + qt/lc_qpreferencesdialog.cpp | 13 ++++++++++--- 8 files changed, 19 insertions(+), 7 deletions(-) diff --git a/common/lc_application.cpp b/common/lc_application.cpp index 4f6b790d..2a4f7a07 100644 --- a/common/lc_application.cpp +++ b/common/lc_application.cpp @@ -11,6 +11,7 @@ #include "lc_view.h" #include "camera.h" #include "lc_previewwidget.h" +#include "lc_colors.h" #ifdef Q_OS_WIN #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) diff --git a/common/lc_bricklink.cpp b/common/lc_bricklink.cpp index 059ec7bc..c85fbb21 100644 --- a/common/lc_bricklink.cpp +++ b/common/lc_bricklink.cpp @@ -4,6 +4,7 @@ #include "lc_mainwindow.h" #include "lc_string.h" #include "pieceinf.h" +#include "lc_colors.h" static QJsonDocument lcLoadBrickLinkMapping() { diff --git a/common/lc_context.h b/common/lc_context.h index 602a6f01..05ce730b 100644 --- a/common/lc_context.h +++ b/common/lc_context.h @@ -1,7 +1,6 @@ #pragma once #include "lc_math.h" -#include "lc_colors.h" #include "lc_mesh.h" class lcVertexBuffer @@ -105,7 +104,7 @@ struct lcVertexAttribState GLuint VertexBufferObject = 0; }; -class lcContext : protected QOpenGLFunctions +class lcContext : public QOpenGLFunctions { public: lcContext(); diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp index 67a1227f..125157ae 100644 --- a/common/lc_partselectionwidget.cpp +++ b/common/lc_partselectionwidget.cpp @@ -12,6 +12,7 @@ #include "lc_category.h" #include "lc_traintrack.h" #include "lc_filter.h" +#include "lc_colors.h" Q_DECLARE_METATYPE(QList) diff --git a/common/lc_scene.cpp b/common/lc_scene.cpp index d8c1129c..72dcb164 100644 --- a/common/lc_scene.cpp +++ b/common/lc_scene.cpp @@ -6,6 +6,7 @@ #include "lc_library.h" #include "lc_application.h" #include "object.h" +#include "lc_colors.h" lcScene::lcScene() { diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 3fd998e1..d649c1e2 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -806,9 +806,10 @@ void lcView::SaveStepImages(const QString& BaseName, bool AddStepSuffix, lcStep bool lcView::BeginRenderToImage(int Width, int Height) { + lcContext* Context = lcContext::GetGlobalOffscreenContext(); GLint MaxTexture; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture); - + + Context->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture); MaxTexture = qMin(MaxTexture, 2048); const int Samples = QSurfaceFormat::defaultFormat().samples(); diff --git a/common/project.cpp b/common/project.cpp index 44545a42..3d168caf 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -18,6 +18,7 @@ #include "lc_modellistdialog.h" #include "lc_bricklink.h" #include "lc_string.h" +#include "lc_colors.h" lcHTMLExportOptions::lcHTMLExportOptions(const Project* Project) { diff --git a/qt/lc_qpreferencesdialog.cpp b/qt/lc_qpreferencesdialog.cpp index bc8e3eac..0813b6ff 100644 --- a/qt/lc_qpreferencesdialog.cpp +++ b/qt/lc_qpreferencesdialog.cpp @@ -10,6 +10,9 @@ #include "pieceinf.h" #include "lc_edgecolordialog.h" #include "lc_blenderpreferences.h" +#include "lc_mainwindow.h" +#include "lc_viewwidget.h" +#include "lc_view.h" static const char* gLanguageLocales[] = { @@ -98,17 +101,21 @@ lcQPreferencesDialog::lcQPreferencesDialog(QWidget* Parent, lcPreferencesDialogO ui->ConditionalLinesCheckBox->setChecked(false); ui->ConditionalLinesCheckBox->setEnabled(false); } + + lcViewWidget* Widget = gMainWindow->GetActiveView()->GetWidget(); + QOpenGLContext* Context = Widget->context(); + QOpenGLFunctions* Functions = Context->functions(); #ifndef LC_OPENGLES if (QSurfaceFormat::defaultFormat().samples() > 1) { - glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, mLineWidthRange); - glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &mLineWidthGranularity); + Functions->glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, mLineWidthRange); + Functions->glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &mLineWidthGranularity); } else #endif { - glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, mLineWidthRange); + Functions->glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, mLineWidthRange); mLineWidthGranularity = 1.0f; } From c2db2d8d45d0802ed8807f4e33b6c2ec89ef7468 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 15 Dec 2025 11:19:23 -0300 Subject: [PATCH 24/93] Added bounds check to strcat. --- common/lc_library.cpp | 4 ++-- common/lc_model.cpp | 2 +- common/lc_string.cpp | 41 ++++++++++++++++++++++++++++++++++++----- common/lc_string.h | 9 ++++++++- common/piece.cpp | 3 ++- common/project.cpp | 2 +- 6 files changed, 50 insertions(+), 11 deletions(-) diff --git a/common/lc_library.cpp b/common/lc_library.cpp index fdf20d64..68775054 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -1668,7 +1668,7 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive) { char Name[LC_PIECE_NAME_LEN]; lcstrcpy(Name, "8/"); - strcat(Name, Primitive->mName); + lcstrcat(Name, Primitive->mName); lcstrupr(Name); LowPrimitive = FindPrimitive(Name); // todo: low primitives don't work with studlogo, because the low stud gets added as shared @@ -1770,7 +1770,7 @@ void lcPiecesLibrary::GetCategoryEntries(const char* CategoryKeywords, bool Grou char ParentName[LC_PIECE_NAME_LEN]; lcstrcpy(ParentName, Info->mFileName); *strchr(ParentName, 'P') = '\0'; - strcat(ParentName, ".dat"); + lcstrcat(ParentName, ".dat"); Parent = FindPiece(ParentName, nullptr, false, false); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index dff17fb8..47b9b8ea 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -850,7 +850,7 @@ bool lcModel::LoadBinary(lcFile* file) file->ReadFloats(rot.GetFloats(), 3); file->ReadU8(&color, 1); file->ReadBuffer(name, 9); - strcat(name, ".dat"); + lcstrcat(name, ".dat"); file->ReadU8(&step, 1); file->ReadU8(&group, 1); diff --git a/common/lc_string.cpp b/common/lc_string.cpp index dcc8546e..0e5cfa57 100644 --- a/common/lc_string.cpp +++ b/common/lc_string.cpp @@ -30,12 +30,12 @@ char* lcstrupr(char* string) return string; } -size_t lcstrcpy(char* dest, const char* source, size_t count) +size_t lcstrcpy(char* dest, const char* source, size_t size) { - if (count == 0) + if (size == 0) return 0; - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < size; i++) { dest[i] = source[i]; @@ -45,7 +45,38 @@ size_t lcstrcpy(char* dest, const char* source, size_t count) } } - dest[--count] = '\0'; + dest[--size] = '\0'; - return count; + return size; +} + +size_t lcstrcat(char* dest, const char* source, size_t size) +{ + char* d = dest; + const char* s = source; + size_t n = size; + size_t dlen; + + while (n-- != 0 && *d != '\0') + d++; + + dlen = d - dest; + n = size - dlen; + + if (n == 0) + return(dlen + strlen(s)); + + while (*s != '\0') + { + if (n != 1) + { + *d++ = *s; + n--; + } + s++; + } + + *d = '\0'; + + return (dlen + (s - source)); } diff --git a/common/lc_string.h b/common/lc_string.h index 3d4cdbdd..2117b8a7 100644 --- a/common/lc_string.h +++ b/common/lc_string.h @@ -2,10 +2,17 @@ char* lcstrcasestr(const char* s, const char* find); char* lcstrupr(char* string); -size_t lcstrcpy(char* dest, const char* source, size_t count); +size_t lcstrcpy(char* dest, const char* source, size_t size); +size_t lcstrcat(char* dest, const char* source, size_t size); template size_t lcstrcpy(char (&dest)[size], const char* source) { return lcstrcpy(dest, source, size); } + +template +size_t lcstrcat(char (&dest)[size], const char* source) +{ + return lcstrcat(dest, source, size); +} diff --git a/common/piece.cpp b/common/piece.cpp index 5bc6848a..842c29e6 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -15,6 +15,7 @@ #include "lc_qutils.h" #include "lc_synth.h" #include "lc_traintrack.h" +#include "lc_string.h" constexpr float LC_PIECE_CONTROL_POINT_SIZE = 10.0f; @@ -336,7 +337,7 @@ bool lcPiece::FileLoad(lcFile& file) } else file.ReadBuffer(name, LC_PIECE_NAME_LEN); - strcat(name, ".dat"); + lcstrcat(name, ".dat"); PieceInfo* pInfo = lcGetPiecesLibrary()->FindPiece(name, nullptr, true, false); SetPieceInfo(pInfo, QString(), true, true); diff --git a/common/project.cpp b/common/project.cpp index 3d168caf..0b2eecf8 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -2239,7 +2239,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) if (sscanf(Line,"%128s%128s%10s", Src, Dst, Flags) != 3) continue; - strcat(Src, ".dat"); + lcstrcat(Src, ".dat"); PieceInfo* Info = Library->FindPiece(Src, nullptr, false, false); if (!Info) From 6984b539908c531b20afb9eb6c89e7369debf8a0 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 15 Dec 2025 12:01:51 -0300 Subject: [PATCH 25/93] Fixed blurry thumbnails on retina displays. --- common/lc_partselectionwidget.cpp | 16 ++++++++++++---- common/lc_partselectionwidget.h | 3 ++- common/lc_thumbnailmanager.cpp | 17 +++++++++++------ common/lc_thumbnailmanager.h | 3 ++- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp index 125157ae..cecb3d09 100644 --- a/common/lc_partselectionwidget.cpp +++ b/common/lc_partselectionwidget.cpp @@ -399,7 +399,7 @@ void lcPartSelectionListModel::RequestThumbnail(int PartIndex) int ColorIndex = mParts[PartIndex].ColorIndex == -1 ? mColorIndex : mParts[PartIndex].ColorIndex; - auto [ThumbnailId, Thumbnail] = lcGetPiecesLibrary()->GetThumbnailManager()->RequestThumbnail(Info, ColorIndex, mIconSize); + auto [ThumbnailId, Thumbnail] = lcGetPiecesLibrary()->GetThumbnailManager()->RequestThumbnail(Info, ColorIndex, mIconSize, mDeviceScale); mParts[PartIndex].ThumbnailId = ThumbnailId; @@ -486,12 +486,13 @@ void lcPartSelectionListModel::SetPartDescriptionFilter(bool Option) SetFilter(mFilterString); } -void lcPartSelectionListModel::SetIconSize(int Size) +void lcPartSelectionListModel::SetIconSize(int Size, float DeviceScale) { - if (Size == mIconSize) + if (Size == mIconSize && DeviceScale == mDeviceScale) return; mIconSize = Size; + mDeviceScale = DeviceScale; beginResetModel(); @@ -770,7 +771,14 @@ void lcPartSelectionListView::SetIconSize(int Size) { setIconSize(QSize(Size, Size)); lcSetProfileInt(LC_PROFILE_PARTS_LIST_ICONS, Size); - mListModel->SetIconSize(Size); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) + float DeviceScale = devicePixelRatioF(); +#else + float DeviceScale = devicePixelRatio(); +#endif + + mListModel->SetIconSize(Size, DeviceScale); UpdateViewMode(); int Width = Size + 2 * frameWidth() + 6; diff --git a/common/lc_partselectionwidget.h b/common/lc_partselectionwidget.h index 10aa8f21..1d07a586 100644 --- a/common/lc_partselectionwidget.h +++ b/common/lc_partselectionwidget.h @@ -159,7 +159,7 @@ public: void SetCaseSensitiveFilter(bool Option); void SetFileNameFilter(bool Option); void SetPartDescriptionFilter(bool Option); - void SetIconSize(int Size); + void SetIconSize(int Size, float DeviceScale); void SetShowPartNames(bool Show); protected slots: @@ -172,6 +172,7 @@ protected: std::vector mParts; lcPartFilterType mPartFilterType; int mIconSize; + float mDeviceScale = 1.0f; bool mColorLocked; int mColorIndex; bool mShowPartNames; diff --git a/common/lc_thumbnailmanager.cpp b/common/lc_thumbnailmanager.cpp index b6188b0b..8d488dfb 100644 --- a/common/lc_thumbnailmanager.cpp +++ b/common/lc_thumbnailmanager.cpp @@ -19,10 +19,10 @@ lcThumbnailManager::~lcThumbnailManager() mLibrary->ReleasePieceInfo(Thumbnail.Info); } -std::pair lcThumbnailManager::RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size) +std::pair lcThumbnailManager::RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size, float DeviceScale) { for (auto &[ThumbnailId, Thumbnail] : mThumbnails) - if (Thumbnail.Info == Info && Thumbnail.ColorIndex == ColorIndex && Thumbnail.Size == Size) + if (Thumbnail.Info == Info && Thumbnail.ColorIndex == ColorIndex && Thumbnail.Size == Size && Thumbnail.DeviceScale == DeviceScale) return { ThumbnailId, Thumbnail.Pixmap }; lcPartThumbnailId ThumbnailId = static_cast(mNextThumbnailId++); @@ -31,6 +31,7 @@ std::pair lcThumbnailManager::RequestThumbnail(Piece Thumbnail.Info = Info; Thumbnail.ColorIndex = ColorIndex; Thumbnail.Size = Size; + Thumbnail.DeviceScale = DeviceScale; Thumbnail.ReferenceCount = 1; mLibrary->LoadPieceInfo(Info, false, false); @@ -70,8 +71,8 @@ void lcThumbnailManager::PartLoaded(PieceInfo* Info) void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThumbnail& Thumbnail) { - const int Width = Thumbnail.Size * 2; - const int Height = Thumbnail.Size * 2; + const int Width = Thumbnail.Size * 2 * Thumbnail.DeviceScale; + const int Height = Thumbnail.Size * 2 * Thumbnail.DeviceScale; if (mView && (mView->GetWidth() != Width || mView->GetHeight() != Height)) mView.reset(); @@ -145,8 +146,12 @@ void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThum Painter.drawImage(QPoint(0, 0), Icon); Painter.end(); } - - Thumbnail.Pixmap = QPixmap::fromImage(Image).scaled(Thumbnail.Size, Thumbnail.Size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + Image.setDevicePixelRatio(Thumbnail.DeviceScale); + + float ScaledSize = Thumbnail.Size * Thumbnail.DeviceScale; + + Thumbnail.Pixmap = QPixmap::fromImage(Image).scaled(ScaledSize, ScaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); mLibrary->ReleasePieceInfo(Info); diff --git a/common/lc_thumbnailmanager.h b/common/lc_thumbnailmanager.h index 03e98738..9b6c42eb 100644 --- a/common/lc_thumbnailmanager.h +++ b/common/lc_thumbnailmanager.h @@ -8,6 +8,7 @@ struct lcPartThumbnail PieceInfo* Info; int ColorIndex; int Size; + float DeviceScale; int ReferenceCount; }; @@ -24,7 +25,7 @@ public: lcThumbnailManager(lcPiecesLibrary* Library); ~lcThumbnailManager(); - std::pair RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size); + std::pair RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size, float DeviceScale); void ReleaseThumbnail(lcPartThumbnailId ThumbnailId); signals: From 4e49d4d0cc52d2f83c0daef83e77f4c4678b4f74 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 18 Dec 2025 16:18:45 -0300 Subject: [PATCH 26/93] Fixed warnings. --- common/camera.cpp | 4 +- common/lc_instructionsdialog.cpp | 4 + common/lc_propertieswidget.cpp | 6 +- common/lc_view.cpp | 133 ++++++++++++++++--------------- common/lc_viewmanipulator.cpp | 1 - common/light.cpp | 2 +- 6 files changed, 81 insertions(+), 69 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 89a54047..0e3f004f 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -363,11 +363,11 @@ bool lcCamera::FileLoad(lcFile& file) if (version < 5) { - n = file.ReadS32(); + file.ReadS32(); } else { - ch = file.ReadU8(); + file.ReadU8(); file.ReadU8(); } } diff --git a/common/lc_instructionsdialog.cpp b/common/lc_instructionsdialog.cpp index 9fdb3b3b..8301a381 100644 --- a/common/lc_instructionsdialog.cpp +++ b/common/lc_instructionsdialog.cpp @@ -649,7 +649,11 @@ void lcInstructionsDialog::Print(QPrinter* Printer) for (int PageCopy = 0; PageCopy < PageCopies; PageCopy++) { if (Printer->printerState() == QPrinter::Aborted || Printer->printerState() == QPrinter::Error) + { + delete Scene; + return; + } if (!FirstPage) Printer->newPage(); diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index 263fd4f0..d5b6f7f2 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -1324,8 +1324,10 @@ void lcPropertiesWidget::SetPiece(const std::vector& Selection, lcObj lcMatrix33 RelativeRotation; lcModel* Model = gMainWindow->GetActiveModel(); - if (Model) - Model->GetMoveRotateTransform(Position, RelativeRotation); + if (!Model) + return; + + Model->GetMoveRotateTransform(Position, RelativeRotation); UpdateFloat(lcObjectPropertyId::ObjectPositionX, Position[0]); UpdateFloat(lcObjectPropertyId::ObjectPositionY, Position[1]); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index d649c1e2..76702dd6 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -1518,70 +1518,77 @@ void lcView::DrawGrid() if (Preferences.mDrawGridLines) VertexBufferSize += 2 * (MaxX - MinX + MaxY - MinY + 2) * 3 * sizeof(float); - - float* Verts = (float*)malloc(VertexBufferSize); - if (!Verts) - return; - float* CurVert = Verts; - - if (Preferences.mDrawGridStuds) + + float* Verts = nullptr; + + if (VertexBufferSize) { - float Left = MinX * 20.0f * Spacing; - float Right = MaxX * 20.0f * Spacing; - float Top = MinY * 20.0f * Spacing; - float Bottom = MaxY * 20.0f * Spacing; - float Z = 0; - float U = (MaxX - MinX) * Spacing; - float V = (MaxY - MinY) * Spacing; - - *CurVert++ = Left; - *CurVert++ = Top; - *CurVert++ = Z; - *CurVert++ = 0.0f; - *CurVert++ = V; - - *CurVert++ = Right; - *CurVert++ = Top; - *CurVert++ = Z; - *CurVert++ = U; - *CurVert++ = V; - - *CurVert++ = Left; - *CurVert++ = Bottom; - *CurVert++ = Z; - *CurVert++ = 0.0f; - *CurVert++ = 0.0f; - - *CurVert++ = Right; - *CurVert++ = Bottom; - *CurVert++ = Z; - *CurVert++ = U; - *CurVert++ = 0.0f; - } - - if (Preferences.mDrawGridLines) - { - float LineSpacing = Spacing * 20.0f; - - for (int Step = MinX; Step < MaxX + 1; Step++) - { - *CurVert++ = Step * LineSpacing; - *CurVert++ = MinY * LineSpacing; - *CurVert++ = 0.0f; - *CurVert++ = Step * LineSpacing; - *CurVert++ = MaxY * LineSpacing; - *CurVert++ = 0.0f; - } - - for (int Step = MinY; Step < MaxY + 1; Step++) - { - *CurVert++ = MinX * LineSpacing; - *CurVert++ = Step * LineSpacing; - *CurVert++ = 0.0f; - *CurVert++ = MaxX * LineSpacing; - *CurVert++ = Step * LineSpacing; - *CurVert++ = 0.0f; - } + Verts = static_cast(malloc(VertexBufferSize)); + + if (!Verts) + return; + + float* CurVert = Verts; + + if (Preferences.mDrawGridStuds) + { + float Left = MinX * 20.0f * Spacing; + float Right = MaxX * 20.0f * Spacing; + float Top = MinY * 20.0f * Spacing; + float Bottom = MaxY * 20.0f * Spacing; + float Z = 0; + float U = (MaxX - MinX) * Spacing; + float V = (MaxY - MinY) * Spacing; + + *CurVert++ = Left; + *CurVert++ = Top; + *CurVert++ = Z; + *CurVert++ = 0.0f; + *CurVert++ = V; + + *CurVert++ = Right; + *CurVert++ = Top; + *CurVert++ = Z; + *CurVert++ = U; + *CurVert++ = V; + + *CurVert++ = Left; + *CurVert++ = Bottom; + *CurVert++ = Z; + *CurVert++ = 0.0f; + *CurVert++ = 0.0f; + + *CurVert++ = Right; + *CurVert++ = Bottom; + *CurVert++ = Z; + *CurVert++ = U; + *CurVert++ = 0.0f; + } + + if (Preferences.mDrawGridLines) + { + float LineSpacing = Spacing * 20.0f; + + for (int Step = MinX; Step < MaxX + 1; Step++) + { + *CurVert++ = Step * LineSpacing; + *CurVert++ = MinY * LineSpacing; + *CurVert++ = 0.0f; + *CurVert++ = Step * LineSpacing; + *CurVert++ = MaxY * LineSpacing; + *CurVert++ = 0.0f; + } + + for (int Step = MinY; Step < MaxY + 1; Step++) + { + *CurVert++ = MinX * LineSpacing; + *CurVert++ = Step * LineSpacing; + *CurVert++ = 0.0f; + *CurVert++ = MaxX * LineSpacing; + *CurVert++ = Step * LineSpacing; + *CurVert++ = 0.0f; + } + } } mGridSettings[0] = MinX; diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index 0af8ad8f..2a154162 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -1165,7 +1165,6 @@ std::pair lcViewManipulator::UpdateSelectMove(lcTrackButto { NewTrackTool = TrainTrackTool; NewTrackSection = TrainTrackSection; - ClosestIntersectionDistance = TrainDistance; } } diff --git a/common/light.cpp b/common/light.cpp index 9b9238d8..bcba6341 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -28,7 +28,7 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) mPosition.SetValue(Position); - UpdatePosition(1); + lcLight::UpdatePosition(1); } void lcLight::CopyProperties(const lcLight& Other) From b3be4125ebf67de83395f6ce9ccafe9c75cc3f2b Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 18 Dec 2025 16:59:47 -0300 Subject: [PATCH 27/93] Fixed warnings. --- common/lc_blenderpreferences.cpp | 15 +++++++-------- common/lc_shortcuts.cpp | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 380d0dfa..dd0f7be6 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -26,7 +26,6 @@ #include "lc_http.h" #include "lc_zipfile.h" #include "lc_file.h" -#include "lc_qutils.h" #include "project.h" #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) @@ -53,10 +52,10 @@ const QLatin1String LineEnding("\r\n"); #define LC_BLENDER_ADDON_URL LC_BLENDER_ADDON_STR "releases/latest/download/" LC_BLENDER_ADDON_FILE #define LC_BLENDER_ADDON_SHA_HASH_URL LC_BLENDER_ADDON_URL ".sha256" -#define LC_THEME_DARK_PALETTE_MIDLIGHT "#3E3E3E" // 62, 62, 62, 255 -#define LC_THEME_DEFAULT_PALETTE_LIGHT "#AEADAC" // 174, 173, 172, 255 +#define LC_THEME_DARK_PALETTE_MIDLIGHT QColor( 62, 62, 62, 255) +#define LC_THEME_DEFAULT_PALETTE_LIGHT QColor(174, 173, 172, 255) #define LC_THEME_DARK_DECORATE_QUOTED_TEXT "#81D4FA" // 129, 212, 250, 255 -#define LC_DISABLED_TEXT "#808080" // 128, 128, 128, 255 +#define LC_DISABLED_TEXT QColor(128, 128, 128, 255) #define LC_RENDER_IMAGE_MAX_SIZE 32768 // pixels @@ -415,10 +414,10 @@ lcBlenderPreferences::lcBlenderPreferences(int Width, int Height, double Scale, QPalette ReadOnlyPalette = QApplication::palette(); const lcPreferences& Preferences = lcGetPreferences(); if (Preferences.mColorTheme == lcColorTheme::Dark) - ReadOnlyPalette.setColor(QPalette::Base,QColor(LC_THEME_DARK_PALETTE_MIDLIGHT)); + ReadOnlyPalette.setColor(QPalette::Base, LC_THEME_DARK_PALETTE_MIDLIGHT); else - ReadOnlyPalette.setColor(QPalette::Base,QColor(LC_THEME_DEFAULT_PALETTE_LIGHT)); - ReadOnlyPalette.setColor(QPalette::Text,QColor(LC_DISABLED_TEXT)); + ReadOnlyPalette.setColor(QPalette::Base, LC_THEME_DEFAULT_PALETTE_LIGHT); + ReadOnlyPalette.setColor(QPalette::Text, LC_DISABLED_TEXT); QGroupBox* BlenderExeBox = new QGroupBox(tr("Blender Executable"),mContent); mForm->addRow(BlenderExeBox); @@ -3629,7 +3628,7 @@ int lcBlenderPreferences::ShowMessage(QWidget* Parent, const QString& Header, c if (FixedWidth == MinimumWidth) { int Index = (MinimumWidth / FontWidth) - 1; - if (!Body.mid(Index,1).isEmpty()) + if (!Body.mid(Index, 1).isEmpty()) FixedWidth = Body.indexOf(" ", Index); } else if (FixedWidth < MinimumWidth) diff --git a/common/lc_shortcuts.cpp b/common/lc_shortcuts.cpp index 1e035b1a..2cab2cdb 100644 --- a/common/lc_shortcuts.cpp +++ b/common/lc_shortcuts.cpp @@ -173,8 +173,8 @@ bool lcMouseShortcuts::Save(const QString& FileName) return false; QTextStream Stream(&File); - - for (const QString& Shortcut : Shortcuts) + + for (const QString& Shortcut : std::as_const(Shortcuts)) Stream << Shortcut << QLatin1String("\n"); Stream.flush(); From 3e43b37ed3215a9d7d0be5ed24c9e476586e6977 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 18 Dec 2025 17:16:48 -0300 Subject: [PATCH 28/93] Added actions for frame and look at. --- common/lc_model.cpp | 67 +++++++++++++++++++++++++++++---------------- common/lc_model.h | 4 +-- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 47b9b8ea..35920ea2 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1721,14 +1721,14 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect } } -void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View) +void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera) { std::unique_ptr ModelActionObjectEdit = std::make_unique(ModelActionObjectEditMode); switch (ModelActionObjectEditMode) { case lcModelActionObjectEditMode::Camera: - ModelActionObjectEdit->SaveCameraStartState(View->GetCamera()); + ModelActionObjectEdit->SaveCameraStartState(Camera); break; case lcModelActionObjectEditMode::Selection: @@ -1739,7 +1739,7 @@ void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjec mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } -void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View) +void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera) { if (mActionSequence.empty()) return; @@ -1752,7 +1752,7 @@ void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectE switch (ModelActionObjectEditMode) { case lcModelActionObjectEditMode::Camera: - ModelActionObjectEdit->SaveCameraEndState(View->GetCamera()); + ModelActionObjectEdit->SaveCameraEndState(Camera); break; case lcModelActionObjectEditMode::Selection: @@ -5070,7 +5070,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::Rotate: BeginActionSequence(); RecordSelectionAction(lcModelActionSelectionMode::Set); - BeginObjectEditAction(lcModelActionObjectEditMode::Selection, View); + BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); break; case lcTool::Eraser: @@ -5085,7 +5085,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) if (!View->GetCamera()->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Camera, View); + BeginObjectEditAction(lcModelActionObjectEditMode::Camera, View->GetCamera()); } break; @@ -5107,7 +5107,9 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) RevertActionSequence(); return; } - + + const lcCamera* Camera = View->GetCamera(); + switch (Tool) { case lcTool::Insert: @@ -5120,12 +5122,12 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) break; case lcTool::Move: - EndObjectEditAction(lcModelActionObjectEditMode::Selection, View); + EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); EndActionSequence(tr("Move")); break; case lcTool::Rotate: - EndObjectEditAction(lcModelActionObjectEditMode::Selection, View); + EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); EndActionSequence(tr("Rotate")); break; @@ -5135,33 +5137,33 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) break; case lcTool::Zoom: - if (!View->GetCamera()->IsSimple()) + if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); EndActionSequence(tr("Zoom")); } break; case lcTool::Pan: - if (!View->GetCamera()->IsSimple()) + if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); EndActionSequence(tr("Pan")); } break; case lcTool::RotateView: - if (!View->GetCamera()->IsSimple()) + if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); EndActionSequence(tr("Orbit")); } break; case lcTool::Roll: - if (!View->GetCamera()->IsSimple()) + if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); EndActionSequence(tr("Roll")); } break; @@ -5466,14 +5468,14 @@ void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVec if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Camera, View); + BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); } Camera->ZoomRegion(AspectRatio, Position, TargetPosition, Corners, mCurrentStep, gMainWindow->GetAddKeys()); if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, View); + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); EndActionSequence(tr("Zoom")); } @@ -5494,14 +5496,23 @@ void lcModel::LookAt(lcCamera* Camera) else Center = lcVector3(0.0f, 0.0f, 0.0f); } - + + if (!Camera->IsSimple()) + { + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + } + Camera->Center(Center, mCurrentStep, gMainWindow->GetAddKeys()); gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); if (!Camera->IsSimple()) - SaveCheckpoint(tr("Look At")); + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndActionSequence(tr("Look At")); + } } void lcModel::MoveCamera(lcCamera* Camera, const lcVector3& Direction) @@ -5532,15 +5543,25 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl } const lcVector3 Center = (Min + Max) / 2.0f; - + + if (!Camera->IsSimple()) + { + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + } + Camera->ZoomExtents(Aspect, Center, Points, mCurrentStep, gMainWindow ? gMainWindow->GetAddKeys() : false); if (!mIsPreview && gMainWindow) gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); if (!Camera->IsSimple()) - SaveCheckpoint(tr("Zoom")); + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndActionSequence(tr("Zoom Extents")); + } } void lcModel::Zoom(lcCamera* Camera, float Amount) diff --git a/common/lc_model.h b/common/lc_model.h index da5a4015..ca768013 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -411,8 +411,8 @@ protected: void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); - void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View); - void EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcView* View); + void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); + void EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); From 794ec0d2037e967673274d48fcf0031e20c62a4d Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 19 Dec 2025 18:11:13 -0300 Subject: [PATCH 29/93] Added reset pivot point action. --- common/lc_model.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 35920ea2..2eb65b62 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3120,17 +3120,26 @@ void lcModel::DeleteSelectedObjects() void lcModel::ResetSelectedPiecesPivotPoint() { + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::Set); + BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) Piece->ResetPivotPoint(); - + + EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndActionSequence(tr("Reset Pivot Point")); + UpdateAllViews(); - - SaveCheckpoint(tr("Resetting Pivot Point")); } void lcModel::RemoveSelectedPiecesKeyFrames() { + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::Set); + BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) Piece->RemoveKeyFrames(); @@ -3142,21 +3151,22 @@ void lcModel::RemoveSelectedPiecesKeyFrames() for (const std::unique_ptr& Light : mLights) if (Light->IsSelected()) Light->RemoveKeyFrames(); - + + EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndActionSequence(tr("Remove Key Frames")); + UpdateAllViews(); - SaveCheckpoint(tr("Removing Key Frames")); } void lcModel::InsertControlPoint() { - lcObject* Focus = GetFocusObject(); + lcPiece* Piece = dynamic_cast(GetFocusObject()); - if (!Focus || !Focus->IsPiece()) + if (!Piece) return; - lcPiece* Piece = (lcPiece*)Focus; - lcVector3 Start, End; + gMainWindow->GetActiveView()->GetRayUnderPointer(Start, End); if (Piece->InsertControlPoint(Start, End)) @@ -3169,13 +3179,11 @@ void lcModel::InsertControlPoint() void lcModel::RemoveFocusedControlPoint() { - lcObject* Focus = GetFocusObject(); - - if (!Focus || !Focus->IsPiece()) + lcPiece* Piece = dynamic_cast(GetFocusObject()); + + if (!Piece) return; - - lcPiece* Piece = (lcPiece*)Focus; - + if (Piece->RemoveFocusedControlPoint()) { SaveCheckpoint(tr("Modifying")); From 797325dc9405223a2770a8d42f2b234b3d8dc316 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 21 Dec 2025 00:22:21 -0300 Subject: [PATCH 30/93] Added actions for projection mode and paint. --- common/lc_model.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2eb65b62..0e99b96d 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3810,6 +3810,10 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) { + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::Set); + BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + bool Modified = false; for (const std::unique_ptr& Piece : mPieces) @@ -3823,11 +3827,17 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) if (Modified) { - SaveCheckpoint(tr("Painting")); + EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndActionSequence(tr("Paint")); + gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); gMainWindow->UpdateTimeline(false, true); } + else + { + RevertActionSequence(); + } } void lcModel::SetSelectedPiecesStepShow(lcStep Step) @@ -3906,11 +3916,22 @@ void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) { if (Camera->IsOrtho() == Ortho) return; - + + if (!Camera->IsSimple()) + { + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + } + Camera->SetOrtho(Ortho); Camera->UpdatePosition(mCurrentStep); - - SaveCheckpoint(tr("Editing Camera")); + + if (!Camera->IsSimple()) + { + EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndActionSequence(tr("Change Projection")); + } + UpdateAllViews(); gMainWindow->UpdateSelectedObjects(false); } From 2741b86e9c65734e3b44d0a19a35464970b96425 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 21 Dec 2025 13:39:34 -0300 Subject: [PATCH 31/93] Don't save selection in object edit actions. --- common/camera.cpp | 6 +- common/camera.h | 2 +- common/lc_model.cpp | 13 ++-- common/lc_model.h | 1 + common/lc_modelaction.cpp | 140 +++++++++++++++++++++++++++++++------- common/lc_modelaction.h | 6 +- common/light.cpp | 24 ++----- common/light.h | 2 +- common/object.h | 2 +- common/piece.cpp | 5 +- common/piece.h | 2 +- 11 files changed, 140 insertions(+), 63 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 0e3f004f..b910d4b9 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -907,7 +907,7 @@ void lcCamera::RemoveKeyFrames() mUpVector.RemoveAllKeys(); } -void lcCamera::SaveUndoData(QDataStream& Stream) const +bool lcCamera::SaveUndoData(QDataStream& Stream) const { Stream << m_fovy; Stream << m_zNear; @@ -915,9 +915,7 @@ void lcCamera::SaveUndoData(QDataStream& Stream) const Stream << mName; Stream << (mState & (LC_CAMERA_HIDDEN | LC_CAMERA_ORTHO)); - mPosition.SaveUndoData(Stream); - mTargetPosition.SaveUndoData(Stream); - mUpVector.SaveUndoData(Stream); + return mPosition.SaveUndoData(Stream) && mTargetPosition.SaveUndoData(Stream) && mUpVector.SaveUndoData(Stream); } bool lcCamera::LoadUndoData(QDataStream& Stream) diff --git a/common/camera.h b/common/camera.h index 6a97c392..4c44d6b8 100644 --- a/common/camera.h +++ b/common/camera.h @@ -318,7 +318,7 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - void SaveUndoData(QDataStream& Stream) const override; + bool SaveUndoData(QDataStream& Stream) const override; bool LoadUndoData(QDataStream& Stream) override; void InsertTime(lcStep Start, lcStep Time); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 0e99b96d..2035b5a0 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1759,8 +1759,6 @@ void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectE ModelActionObjectEdit->SaveSelectionEndState(this); break; } - - RecordSelectionAction(lcModelActionSelectionMode::Set); } void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply) @@ -2286,6 +2284,11 @@ void lcModel::EndActionSequence(const QString& Description) gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); } +void lcModel::DiscardActionSequence() +{ + mActionSequence.clear(); +} + void lcModel::RevertActionSequence() { PerformActionSequence(mActionSequence, false); @@ -3121,7 +3124,6 @@ void lcModel::DeleteSelectedObjects() void lcModel::ResetSelectedPiecesPivotPoint() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Set); BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); for (const std::unique_ptr& Piece : mPieces) @@ -3137,7 +3139,6 @@ void lcModel::ResetSelectedPiecesPivotPoint() void lcModel::RemoveSelectedPiecesKeyFrames() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Set); BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); for (const std::unique_ptr& Piece : mPieces) @@ -3811,7 +3812,6 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Set); BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); bool Modified = false; @@ -3836,7 +3836,7 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) } else { - RevertActionSequence(); + DiscardActionSequence(); } } @@ -5098,7 +5098,6 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::Move: case lcTool::Rotate: BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Set); BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); break; diff --git a/common/lc_model.h b/common/lc_model.h index ca768013..a7564752 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -432,6 +432,7 @@ protected: void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); void EndActionSequence(const QString& Description); + void DiscardActionSequence(); void RevertActionSequence(); void SaveCheckpoint(const QString& Description); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index d55dc20e..af40874f 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -7,7 +7,7 @@ #include "pieceinf.h" #include "lc_colors.h" -void lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly) +bool lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly) { QDataStream Stream(&Buffer, QIODevice::WriteOnly); @@ -21,20 +21,61 @@ void lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, boo Stream << CameraCount; Stream << LightCount; - for (const std::unique_ptr& Piece : Pieces) + for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + { + const std::unique_ptr& Piece = Pieces[PieceIndex]; + if (!SelectedOnly || Piece->IsSelected()) - Piece->SaveUndoData(Stream); - - for (const std::unique_ptr& Camera : Cameras) + { + if (Stream.writeRawData(reinterpret_cast(&PieceIndex), sizeof(PieceIndex)) != sizeof(PieceIndex)) + return false; + + if (!Piece->SaveUndoData(Stream)) + return false; + } + } + + if (Stream.writeRawData(reinterpret_cast(&mEndOfList), sizeof(mEndOfList)) != sizeof(mEndOfList)) + return false; + + for (uint64_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + { + const std::unique_ptr& Camera = Cameras[CameraIndex]; + if (!SelectedOnly || Camera->IsSelected()) - Camera->SaveUndoData(Stream); - - for (const std::unique_ptr& Light : Lights) + { + if (Stream.writeRawData(reinterpret_cast(&CameraIndex), sizeof(CameraIndex)) != sizeof(CameraIndex)) + return false; + + if (!Camera->SaveUndoData(Stream)) + return false; + } + } + + if (Stream.writeRawData(reinterpret_cast(&mEndOfList), sizeof(mEndOfList)) != sizeof(mEndOfList)) + return false; + + for (uint64_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + { + const std::unique_ptr& Light = Lights[LightIndex]; + if (!SelectedOnly || Light->IsSelected()) - Light->SaveUndoData(Stream); + { + if (Stream.writeRawData(reinterpret_cast(&LightIndex), sizeof(LightIndex)) != sizeof(LightIndex)) + return false; + + if (!Light->SaveUndoData(Stream)) + return false; + } + } + + if (Stream.writeRawData(reinterpret_cast(&mEndOfList), sizeof(mEndOfList)) != sizeof(mEndOfList)) + return false; + + return true; } -void lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model, bool SelectedOnly) +bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) { QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); @@ -49,19 +90,66 @@ void lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model, boo Stream >> LightCount; if (PieceCount != Pieces.size() || CameraCount != Cameras.size() || LightCount != Lights.size()) - return; - - for (const std::unique_ptr& Piece : Pieces) - if (!SelectedOnly || Piece->IsSelected()) - Piece->LoadUndoData(Stream); - - for (const std::unique_ptr& Camera : Cameras) - if (!SelectedOnly || Camera->IsSelected()) - Camera->LoadUndoData(Stream); - - for (const std::unique_ptr& Light : Lights) - if (!SelectedOnly || Light->IsSelected()) - Light->LoadUndoData(Stream); + return false; + + for (;;) + { + uint64_t PieceIndex; + + if (Stream.readRawData(reinterpret_cast(&PieceIndex), sizeof(PieceIndex)) != sizeof(PieceIndex)) + return false; + + if (PieceIndex == mEndOfList) + break; + + if (PieceIndex >= Pieces.size()) + return false; + + const std::unique_ptr& Piece = Pieces[PieceIndex]; + + if (!Piece->LoadUndoData(Stream)) + return false; + } + + for (;;) + { + uint64_t CameraIndex; + + if (Stream.readRawData(reinterpret_cast(&CameraIndex), sizeof(CameraIndex)) != sizeof(CameraIndex)) + return false; + + if (CameraIndex == mEndOfList) + break; + + if (CameraIndex >= Cameras.size()) + return false; + + const std::unique_ptr& Camera = Cameras[CameraIndex]; + + if (!Camera->LoadUndoData(Stream)) + return false; + } + + for (;;) + { + uint64_t LightIndex; + + if (Stream.readRawData(reinterpret_cast(&LightIndex), sizeof(LightIndex)) != sizeof(LightIndex)) + return false; + + if (LightIndex == mEndOfList) + break; + + if (LightIndex >= Lights.size()) + return false; + + const std::unique_ptr& Light = Lights[LightIndex]; + + if (!Light->LoadUndoData(Stream)) + return false; + } + + return true; } lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode) @@ -206,7 +294,7 @@ void lcModelActionObjectEdit::SaveSelectionStartState(const lcModel* Model) void lcModelActionObjectEdit::LoadSelectionStartState(lcModel* Model) const { - LoadUndoBuffer(mStartBuffer, Model, true); + LoadUndoBuffer(mStartBuffer, Model); } void lcModelActionObjectEdit::SaveSelectionEndState(const lcModel* Model) @@ -216,7 +304,7 @@ void lcModelActionObjectEdit::SaveSelectionEndState(const lcModel* Model) void lcModelActionObjectEdit::LoadSelectionEndState(lcModel* Model) const { - LoadUndoBuffer(mEndBuffer, Model, true); + LoadUndoBuffer(mEndBuffer, Model); } lcModelActionAddPieces::lcModelActionAddPieces(lcStep Step, lcModelActionAddPieceSelectionMode SelectionMode) @@ -284,5 +372,5 @@ void lcModelActionStep::SaveModelState(const lcModel* Model) void lcModelActionStep::LoadModelState(lcModel* Model) const { - LoadUndoBuffer(mUndoBuffer, Model, false); + LoadUndoBuffer(mUndoBuffer, Model); } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 5b4d421f..7faa3407 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -13,8 +13,10 @@ public: virtual ~lcModelAction() = default; protected: - static void SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly); - static void LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model, bool SelectedOnly); + static bool SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly); + static bool LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model); + + static constexpr uint64_t mEndOfList = UINT64_MAX; }; enum class lcModelActionSelectionMode diff --git a/common/light.cpp b/common/light.cpp index bcba6341..2420e9fb 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1530,7 +1530,7 @@ void lcLight::RemoveKeyFrames() mPOVRayFadePower.RemoveAllKeys(); } -void lcLight::SaveUndoData(QDataStream& Stream) const +bool lcLight::SaveUndoData(QDataStream& Stream) const { Stream << mName; Stream << mLightType; @@ -1538,22 +1538,12 @@ void lcLight::SaveUndoData(QDataStream& Stream) const Stream << mAreaShape; Stream << mState; - mPosition.SaveUndoData(Stream); - mRotation.SaveUndoData(Stream); - mColor.SaveUndoData(Stream); - mSpotConeAngle.SaveUndoData(Stream); - mSpotPenumbraAngle.SaveUndoData(Stream); - mPOVRaySpotTightness.SaveUndoData(Stream); - mPOVRayAreaGridX.SaveUndoData(Stream); - mPOVRayAreaGridY.SaveUndoData(Stream); - mBlenderRadius.SaveUndoData(Stream); - mBlenderAngle.SaveUndoData(Stream); - mAreaSizeX.SaveUndoData(Stream); - mAreaSizeY.SaveUndoData(Stream); - mBlenderPower.SaveUndoData(Stream); - mPOVRayPower.SaveUndoData(Stream); - mPOVRayFadeDistance.SaveUndoData(Stream); - mPOVRayFadePower.SaveUndoData(Stream); + return mPosition.SaveUndoData(Stream) && mRotation.SaveUndoData(Stream) && mColor.SaveUndoData(Stream) && + mSpotConeAngle.SaveUndoData(Stream) && mSpotPenumbraAngle.SaveUndoData(Stream) && mPOVRaySpotTightness.SaveUndoData(Stream) && + mPOVRayAreaGridX.SaveUndoData(Stream) && mPOVRayAreaGridY.SaveUndoData(Stream) && mBlenderRadius.SaveUndoData(Stream) && + mBlenderAngle.SaveUndoData(Stream) && mAreaSizeX.SaveUndoData(Stream) && mAreaSizeY.SaveUndoData(Stream) && + mBlenderPower.SaveUndoData(Stream) && mPOVRayPower.SaveUndoData(Stream) && mPOVRayFadeDistance.SaveUndoData(Stream) && + mPOVRayFadePower.SaveUndoData(Stream); } bool lcLight::LoadUndoData(QDataStream& Stream) diff --git a/common/light.h b/common/light.h index 0be2de5e..b1dd23e9 100644 --- a/common/light.h +++ b/common/light.h @@ -220,7 +220,7 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - void SaveUndoData(QDataStream& Stream) const override; + bool SaveUndoData(QDataStream& Stream) const override; bool LoadUndoData(QDataStream& Stream) override; void InsertTime(lcStep Start, lcStep Time); diff --git a/common/object.h b/common/object.h index cd2b8e2f..c71688f3 100644 --- a/common/object.h +++ b/common/object.h @@ -107,7 +107,7 @@ public: virtual bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const = 0; virtual bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) = 0; virtual void RemoveKeyFrames() = 0; - virtual void SaveUndoData(QDataStream& Stream) const = 0; + virtual bool SaveUndoData(QDataStream& Stream) const = 0; virtual bool LoadUndoData(QDataStream& Stream) = 0; virtual QString GetName() const = 0; static QString GetCheckpointString(lcObjectPropertyId PropertyId); diff --git a/common/piece.cpp b/common/piece.cpp index 842c29e6..78093af5 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -934,7 +934,7 @@ void lcPiece::RemoveKeyFrames() mRotation.RemoveAllKeys(); } -void lcPiece::SaveUndoData(QDataStream& Stream) const +bool lcPiece::SaveUndoData(QDataStream& Stream) const { // PieceInfo* mPieceInfo; Stream << mFileLine; @@ -956,8 +956,7 @@ void lcPiece::SaveUndoData(QDataStream& Stream) const // std::vector mControlPoints; // std::vector mTrainTrackConnections; - mPosition.SaveUndoData(Stream); - mRotation.SaveUndoData(Stream); + return mPosition.SaveUndoData(Stream) && mRotation.SaveUndoData(Stream); } bool lcPiece::LoadUndoData(QDataStream& Stream) diff --git a/common/piece.h b/common/piece.h index aa314c18..1410dcdb 100644 --- a/common/piece.h +++ b/common/piece.h @@ -116,7 +116,7 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - void SaveUndoData(QDataStream& Stream) const override; + bool SaveUndoData(QDataStream& Stream) const override; bool LoadUndoData(QDataStream& Stream) override; void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const; From 529ecff8dd25bf4bb78ae728edbed012a465a76c Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 21 Dec 2025 19:07:52 -0300 Subject: [PATCH 32/93] Merged step and object edit actions. --- common/lc_model.cpp | 143 +++++++++++++++----------------------- common/lc_model.h | 4 -- common/lc_modelaction.cpp | 27 ++----- common/lc_modelaction.h | 44 ++---------- 4 files changed, 70 insertions(+), 148 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2035b5a0..3e6ee615 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1727,13 +1727,14 @@ void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjec switch (ModelActionObjectEditMode) { + case lcModelActionObjectEditMode::All: + case lcModelActionObjectEditMode::Selection: + ModelActionObjectEdit->SaveModelStartState(this); + break; + case lcModelActionObjectEditMode::Camera: ModelActionObjectEdit->SaveCameraStartState(Camera); break; - - case lcModelActionObjectEditMode::Selection: - ModelActionObjectEdit->SaveSelectionStartState(this); - break; } mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); @@ -1751,12 +1752,13 @@ void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectE switch (ModelActionObjectEditMode) { - case lcModelActionObjectEditMode::Camera: - ModelActionObjectEdit->SaveCameraEndState(Camera); + case lcModelActionObjectEditMode::All: + case lcModelActionObjectEditMode::Selection: + ModelActionObjectEdit->SaveModelEndState(this); break; - case lcModelActionObjectEditMode::Selection: - ModelActionObjectEdit->SaveSelectionEndState(this); + case lcModelActionObjectEditMode::Camera: + ModelActionObjectEdit->SaveCameraEndState(Camera); break; } } @@ -1770,6 +1772,16 @@ void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObje switch (ModelActionObjectEditMode) { + case lcModelActionObjectEditMode::All: + case lcModelActionObjectEditMode::Selection: + if (Apply) + ModelActionObjectEdit->LoadModelEndState(this); + else + ModelActionObjectEdit->LoadModelStartState(this); + + SetCurrentStep(mCurrentStep); + break; + case lcModelActionObjectEditMode::Camera: if (lcCamera* Camera = GetCamera(ModelActionObjectEdit->GetCameraName())) { @@ -1781,15 +1793,6 @@ void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObje SetCurrentStep(mCurrentStep); } break; - - case lcModelActionObjectEditMode::Selection: - if (Apply) - ModelActionObjectEdit->LoadSelectionEndState(this); - else - ModelActionObjectEdit->LoadSelectionStartState(this); - - SetCurrentStep(mCurrentStep); - break; } } @@ -2166,67 +2169,6 @@ void lcModel::RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHide } } -void lcModel::RecordStepAction(lcModelActionStepMode Mode, lcStep Step) -{ - std::unique_ptr ModelActionStep = std::make_unique(Mode, Step); - - ModelActionStep->SaveModelState(this); - - RunStepAction(ModelActionStep.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionStep)); -} - -void lcModel::RunStepAction(const lcModelActionStep* ModelActionStep, bool Apply) -{ - if (!ModelActionStep) - return; - - lcStep Step = ModelActionStep->GetStep(); - - if (Apply) - { - if (ModelActionStep->GetMode() == lcModelActionStepMode::Insert) - { - for (const std::unique_ptr& Piece : mPieces) - { - Piece->InsertTime(Step, 1); - - if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - } - - for (std::unique_ptr& Camera : mCameras) - Camera->InsertTime(Step, 1); - - for (const std::unique_ptr& Light : mLights) - Light->InsertTime(Step, 1); - } - else - { - for (const std::unique_ptr& Piece : mPieces) - { - Piece->RemoveTime(Step, 1); - - if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - } - - for (std::unique_ptr& Camera : mCameras) - Camera->RemoveTime(Step, 1); - - for (const std::unique_ptr& Light : mLights) - Light->RemoveTime(Step, 1); - } - } - else - { - ModelActionStep->LoadModelState(this); - } - - SetCurrentStep(mCurrentStep); -} - void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) { auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) @@ -2247,8 +2189,6 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunHidePiecesAction(ModelActionHidePieces, Apply); - else if (const lcModelActionStep* ModelActionStep = dynamic_cast(ModelAction)) - RunStepAction(ModelActionStep, Apply); }; if (Apply) @@ -2463,21 +2403,52 @@ lcStep lcModel::GetLastStep() const void lcModel::InsertStep(lcStep Step) { BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Set); - RecordStepAction(lcModelActionStepMode::Insert, Step); - + BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + + for (const std::unique_ptr& Piece : mPieces) + { + Piece->InsertTime(Step, 1); + + if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) + Piece->SetSelected(false); + } + + for (std::unique_ptr& Camera : mCameras) + Camera->InsertTime(Step, 1); + + for (const std::unique_ptr& Light : mLights) + Light->InsertTime(Step, 1); + + + EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); EndActionSequence(tr("Insert Step")); + + SetCurrentStep(mCurrentStep); } void lcModel::RemoveStep(lcStep Step) { BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); - RecordSelectionAction(lcModelActionSelectionMode::Set); - RecordStepAction(lcModelActionStepMode::Remove, Step); + for (const std::unique_ptr& Piece : mPieces) + { + Piece->RemoveTime(Step, 1); + + if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) + Piece->SetSelected(false); + } + for (std::unique_ptr& Camera : mCameras) + Camera->RemoveTime(Step, 1); + + for (const std::unique_ptr& Light : mLights) + Light->RemoveTime(Step, 1); + + EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); EndActionSequence(tr("Remove Step")); + + SetCurrentStep(mCurrentStep); } lcGroup* lcModel::AddGroup(const QString& Prefix, lcGroup* Parent) diff --git a/common/lc_model.h b/common/lc_model.h index a7564752..c4d31426 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -13,13 +13,11 @@ class lcModelActionAddLight; class lcModelActionGroupPieces; class lcModelActionDuplicatePieces; class lcModelActionHidePieces; -class lcModelActionStep; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; enum class lcModelActionObjectEditMode; enum class lcModelActionGroupPiecesMode; enum class lcModelActionHidePiecesMode; -enum class lcModelActionStepMode; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -426,8 +424,6 @@ protected: void RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply); void RecordHidePiecesAction(lcModelActionHidePiecesMode Mode); void RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHidePieces, bool Apply); - void RecordStepAction(lcModelActionStepMode Mode, lcStep Step); - void RunStepAction(const lcModelActionStep* ModelActionStep, bool Apply); void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index af40874f..3a4604fa 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -287,22 +287,22 @@ void lcModelActionObjectEdit::LoadCameraEndState(lcCamera* Camera) const Camera->LoadUndoData(Stream); } -void lcModelActionObjectEdit::SaveSelectionStartState(const lcModel* Model) +void lcModelActionObjectEdit::SaveModelStartState(const lcModel* Model) { - SaveUndoBuffer(mStartBuffer, Model, true); + SaveUndoBuffer(mStartBuffer, Model, mMode == lcModelActionObjectEditMode::Selection); } -void lcModelActionObjectEdit::LoadSelectionStartState(lcModel* Model) const +void lcModelActionObjectEdit::LoadModelStartState(lcModel* Model) const { LoadUndoBuffer(mStartBuffer, Model); } -void lcModelActionObjectEdit::SaveSelectionEndState(const lcModel* Model) +void lcModelActionObjectEdit::SaveModelEndState(const lcModel* Model) { - SaveUndoBuffer(mEndBuffer, Model, true); + SaveUndoBuffer(mEndBuffer, Model, mMode == lcModelActionObjectEditMode::Selection); } -void lcModelActionObjectEdit::LoadSelectionEndState(lcModel* Model) const +void lcModelActionObjectEdit::LoadModelEndState(lcModel* Model) const { LoadUndoBuffer(mEndBuffer, Model); } @@ -359,18 +359,3 @@ void lcModelActionHidePieces::SaveHiddenState(const std::vectorIsHidden(); } - -lcModelActionStep::lcModelActionStep(lcModelActionStepMode Mode, lcStep Step) - : mMode(Mode), mStep(Step) -{ -} - -void lcModelActionStep::SaveModelState(const lcModel* Model) -{ - SaveUndoBuffer(mUndoBuffer, Model, false); -} - -void lcModelActionStep::LoadModelState(lcModel* Model) const -{ - LoadUndoBuffer(mUndoBuffer, Model); -} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 7faa3407..a8d25416 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -53,8 +53,9 @@ protected: enum class lcModelActionObjectEditMode { - Camera, - Selection + All, + Selection, + Camera }; class lcModelActionObjectEdit: public lcModelAction @@ -68,10 +69,10 @@ public: void SaveCameraEndState(const lcCamera* Camera); void LoadCameraEndState(lcCamera* Camera) const; - void SaveSelectionStartState(const lcModel* Model); - void LoadSelectionStartState(lcModel* Model) const; - void SaveSelectionEndState(const lcModel* Model); - void LoadSelectionEndState(lcModel* Model) const; + void SaveModelStartState(const lcModel* Model); + void LoadModelStartState(lcModel* Model) const; + void SaveModelEndState(const lcModel* Model); + void LoadModelEndState(lcModel* Model) const; lcModelActionObjectEditMode GetMode() const { @@ -247,34 +248,3 @@ protected: std::vector mHiddenState; lcModelActionHidePiecesMode mMode; }; - -enum class lcModelActionStepMode -{ - Insert, - Remove -}; - -class lcModelActionStep : public lcModelAction -{ -public: - lcModelActionStep(lcModelActionStepMode Mode, lcStep Step); - virtual ~lcModelActionStep() = default; - - lcModelActionStepMode GetMode() const - { - return mMode; - } - - lcStep GetStep() const - { - return mStep; - } - - void SaveModelState(const lcModel* Model); - void LoadModelState(lcModel* Model) const; - -protected: - QByteArray mUndoBuffer; - lcModelActionStepMode mMode; - lcStep mStep; -}; From e11a02eb34a845b6444397ae7b086c8d885190c1 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 21 Dec 2025 22:35:35 -0300 Subject: [PATCH 33/93] Replaced hide pieces with object edit action. --- common/lc_model.cpp | 212 +++++++++++++++++--------------------- common/lc_model.h | 4 - common/lc_modelaction.cpp | 13 --- common/lc_modelaction.h | 31 ------ 4 files changed, 92 insertions(+), 168 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 3e6ee615..771fecd1 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2104,71 +2104,6 @@ void lcModel::RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* Model } } -void lcModel::RecordHidePiecesAction(lcModelActionHidePiecesMode Mode) -{ - std::unique_ptr ModelActionHidePieces = std::make_unique(Mode); - - ModelActionHidePieces->SaveHiddenState(mPieces); - - RunHidePiecesAction(ModelActionHidePieces.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionHidePieces)); -} - -void lcModel::RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHidePieces, bool Apply) -{ - if (!ModelActionHidePieces) - return; - - if (Apply) - { - switch (ModelActionHidePieces->GetMode()) - { - case lcModelActionHidePiecesMode::HideSelected: - for (const std::unique_ptr& Piece : mPieces) - { - if (Piece->IsSelected()) - { - Piece->SetHidden(true); - Piece->SetSelected(false); - } - } - break; - - case lcModelActionHidePiecesMode::HideUnselected: - for (const std::unique_ptr& Piece : mPieces) - if (!Piece->IsSelected() && !Piece->IsHidden()) - Piece->SetHidden(true); - break; - - case lcModelActionHidePiecesMode::UnhideSelected: - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsSelected() && Piece->IsHidden()) - Piece->SetHidden(false); - break; - - case lcModelActionHidePiecesMode::UnhideAll: - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsHidden()) - Piece->SetHidden(false); - break; - } - - gMainWindow->UpdateTimeline(false, true); - gMainWindow->UpdateSelectedObjects(true); - } - else - { - const std::vector& HiddenState = ModelActionHidePieces->GetHiddenState(); - - if (mPieces.size() != HiddenState.size()) - return; - - for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) - mPieces[PieceIndex]->SetHidden(HiddenState[PieceIndex]); - } -} - void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) { auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) @@ -2187,8 +2122,6 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunDuplicatePiecesAction(ModelActionDuplicatePieces, Apply); - else if (const lcModelActionHidePieces* ModelActionHidePieces = dynamic_cast(ModelAction)) - RunHidePiecesAction(ModelActionHidePieces, Apply); }; if (Apply) @@ -4814,92 +4747,131 @@ void lcModel::InvertSelection() void lcModel::HideSelectedPieces() { - if (!AnyPiecesSelected()) - { - QMessageBox::information(gMainWindow, tr("Hide Pieces"), tr("No pieces selected.")); - return; - } - BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Set); - RecordHidePiecesAction(lcModelActionHidePiecesMode::HideSelected); - RecordSelectionAction(lcModelActionSelectionMode::Save); - + BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + + bool Modified = false; + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsSelected() && !Piece->IsHidden()) + { + Piece->SetHidden(true); + Piece->SetSelected(false); + + Modified = true; + } + } + + if (!Modified) + { + DiscardActionSequence(); + + return; + } + + EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); EndActionSequence(tr("Hide Pieces")); + + gMainWindow->UpdateTimeline(false, true); + gMainWindow->UpdateSelectedObjects(true); + UpdateAllViews(); } void lcModel::HideUnselectedPieces() { - bool HasHidden = false; - + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + + bool Modified = false; + for (const std::unique_ptr& Piece : mPieces) { if (!Piece->IsSelected() && !Piece->IsHidden()) { - HasHidden = true; - break; + Piece->SetHidden(true); + + Modified = true; } } - - if (!HasHidden) + + if (!Modified) { - QMessageBox::information(gMainWindow, tr("Hide Unselected Pieces"), tr("No unselected pieces are hidden.")); + DiscardActionSequence(); + return; - } - - BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Set); - RecordHidePiecesAction(lcModelActionHidePiecesMode::HideUnselected); - RecordSelectionAction(lcModelActionSelectionMode::Save); - + } + + EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); EndActionSequence(tr("Hide Pieces")); + + gMainWindow->UpdateTimeline(false, true); + gMainWindow->UpdateSelectedObjects(true); + UpdateAllViews(); } void lcModel::UnhideSelectedPieces() { - if (!AnyPiecesSelected()) - { - QMessageBox::information(gMainWindow, tr("Unhide Pieces"), tr("No pieces selected.")); - return; - } - BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Set); - RecordHidePiecesAction(lcModelActionHidePiecesMode::UnhideSelected); - RecordSelectionAction(lcModelActionSelectionMode::Save); - + BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + + bool Modified = false; + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsSelected() && Piece->IsHidden()) + { + Piece->SetHidden(false); + + Modified = true; + } + } + + if (!Modified) + { + DiscardActionSequence(); + + return; + } + + EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); EndActionSequence(tr("Unhide Pieces")); + + gMainWindow->UpdateTimeline(false, true); + gMainWindow->UpdateSelectedObjects(true); + UpdateAllViews(); } void lcModel::UnhideAllPieces() { - bool HasHidden = false; - + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + + bool Modified = false; + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsHidden()) { - HasHidden = true; - break; + Piece->SetHidden(false); + + Modified = true; } } - - if (!HasHidden) + + if (!Modified) { - QMessageBox::information(gMainWindow, tr("Unhide All Pieces"), tr("No pieces are hidden.")); + DiscardActionSequence(); + return; - } - - BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Restore); - RecordHidePiecesAction(lcModelActionHidePiecesMode::UnhideAll); - RecordSelectionAction(lcModelActionSelectionMode::Save); - - EndActionSequence(tr("Unhide All Pieces")); + } + + EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + EndActionSequence(tr("Unhide Pieces")); + + gMainWindow->UpdateTimeline(false, true); + gMainWindow->UpdateSelectedObjects(true); + UpdateAllViews(); } void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) diff --git a/common/lc_model.h b/common/lc_model.h index c4d31426..15e82cdc 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -12,12 +12,10 @@ class lcModelActionAddCamera; class lcModelActionAddLight; class lcModelActionGroupPieces; class lcModelActionDuplicatePieces; -class lcModelActionHidePieces; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; enum class lcModelActionObjectEditMode; enum class lcModelActionGroupPiecesMode; -enum class lcModelActionHidePiecesMode; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -422,8 +420,6 @@ protected: void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); void RecordDuplicatePiecesAction(); void RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply); - void RecordHidePiecesAction(lcModelActionHidePiecesMode Mode); - void RunHidePiecesAction(const lcModelActionHidePieces* ModelActionHidePieces, bool Apply); void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 3a4604fa..e14721d0 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -346,16 +346,3 @@ lcModelActionDuplicatePieces::lcModelActionDuplicatePieces(lcStep Step) : mStep(Step) { } - -lcModelActionHidePieces::lcModelActionHidePieces(lcModelActionHidePiecesMode Mode) - : mMode(Mode) -{ -} - -void lcModelActionHidePieces::SaveHiddenState(const std::vector>& Pieces) -{ - mHiddenState.resize(Pieces.size()); - - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - mHiddenState[PieceIndex] = Pieces[PieceIndex]->IsHidden(); -} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index a8d25416..ac445a97 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -217,34 +217,3 @@ public: protected: lcStep mStep; }; - -enum class lcModelActionHidePiecesMode -{ - HideSelected, - HideUnselected, - UnhideSelected, - UnhideAll -}; - -class lcModelActionHidePieces : public lcModelAction -{ -public: - lcModelActionHidePieces(lcModelActionHidePiecesMode Mode); - virtual ~lcModelActionHidePieces() = default; - - lcModelActionHidePiecesMode GetMode() const - { - return mMode; - } - - const std::vector& GetHiddenState() const - { - return mHiddenState; - } - - void SaveHiddenState(const std::vector>& Pieces); - -protected: - std::vector mHiddenState; - lcModelActionHidePiecesMode mMode; -}; From 859e45273fd88e014c057d1444c9583e23ea8088 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 25 Dec 2025 12:55:21 -0300 Subject: [PATCH 34/93] Made the edit action more generic. --- common/lc_mainwindow.cpp | 2 +- common/lc_model.cpp | 133 +++++++++--------------- common/lc_model.h | 2 +- common/lc_modelaction.cpp | 207 ++++++++++++++++---------------------- common/lc_modelaction.h | 40 ++++---- 5 files changed, 154 insertions(+), 230 deletions(-) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 131e80d6..63a83647 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2936,7 +2936,7 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_PIECE_REMOVE_KEY_FRAMES: if (ActiveModel) - ActiveModel->RemoveSelectedPiecesKeyFrames(); + ActiveModel->RemoveSelectedObjectsKeyFrames(); break; case LC_PIECE_CONTROL_POINT_INSERT: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 771fecd1..f5e6b159 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1724,18 +1724,11 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera) { std::unique_ptr ModelActionObjectEdit = std::make_unique(ModelActionObjectEditMode); - - switch (ModelActionObjectEditMode) - { - case lcModelActionObjectEditMode::All: - case lcModelActionObjectEditMode::Selection: - ModelActionObjectEdit->SaveModelStartState(this); - break; - - case lcModelActionObjectEditMode::Camera: - ModelActionObjectEdit->SaveCameraStartState(Camera); - break; - } + + if (!ModelActionObjectEdit) + return; + + ModelActionObjectEdit->SaveStartState(this, Camera); mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } @@ -1750,50 +1743,20 @@ void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectE if (!ModelActionObjectEdit || ModelActionObjectEditMode != ModelActionObjectEdit->GetMode()) return; - switch (ModelActionObjectEditMode) - { - case lcModelActionObjectEditMode::All: - case lcModelActionObjectEditMode::Selection: - ModelActionObjectEdit->SaveModelEndState(this); - break; - - case lcModelActionObjectEditMode::Camera: - ModelActionObjectEdit->SaveCameraEndState(Camera); - break; - } + ModelActionObjectEdit->SaveEndState(this, Camera); } void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply) { if (!ModelActionObjectEdit) return; - - lcModelActionObjectEditMode ModelActionObjectEditMode = ModelActionObjectEdit->GetMode(); - - switch (ModelActionObjectEditMode) - { - case lcModelActionObjectEditMode::All: - case lcModelActionObjectEditMode::Selection: - if (Apply) - ModelActionObjectEdit->LoadModelEndState(this); - else - ModelActionObjectEdit->LoadModelStartState(this); - - SetCurrentStep(mCurrentStep); - break; - - case lcModelActionObjectEditMode::Camera: - if (lcCamera* Camera = GetCamera(ModelActionObjectEdit->GetCameraName())) - { - if (Apply) - ModelActionObjectEdit->LoadCameraEndState(Camera); - else - ModelActionObjectEdit->LoadCameraStartState(Camera); - - SetCurrentStep(mCurrentStep); - } - break; - } + + if (Apply) + ModelActionObjectEdit->LoadEndState(this); + else + ModelActionObjectEdit->LoadStartState(this); + + SetCurrentStep(mCurrentStep); } void lcModel::RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode) @@ -2336,7 +2299,7 @@ lcStep lcModel::GetLastStep() const void lcModel::InsertStep(lcStep Step) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); for (const std::unique_ptr& Piece : mPieces) { @@ -2353,7 +2316,7 @@ void lcModel::InsertStep(lcStep Step) Light->InsertTime(Step, 1); - EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); EndActionSequence(tr("Insert Step")); SetCurrentStep(mCurrentStep); @@ -2362,7 +2325,7 @@ void lcModel::InsertStep(lcStep Step) void lcModel::RemoveStep(lcStep Step) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); for (const std::unique_ptr& Piece : mPieces) { @@ -2378,7 +2341,7 @@ void lcModel::RemoveStep(lcStep Step) for (const std::unique_ptr& Light : mLights) Light->RemoveTime(Step, 1); - EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); EndActionSequence(tr("Remove Step")); SetCurrentStep(mCurrentStep); @@ -3028,22 +2991,22 @@ void lcModel::DeleteSelectedObjects() void lcModel::ResetSelectedPiecesPivotPoint() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) Piece->ResetPivotPoint(); - EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); EndActionSequence(tr("Reset Pivot Point")); UpdateAllViews(); } -void lcModel::RemoveSelectedPiecesKeyFrames() +void lcModel::RemoveSelectedObjectsKeyFrames() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) @@ -3057,7 +3020,7 @@ void lcModel::RemoveSelectedPiecesKeyFrames() if (Light->IsSelected()) Light->RemoveKeyFrames(); - EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); EndActionSequence(tr("Remove Key Frames")); UpdateAllViews(); @@ -3716,7 +3679,7 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); bool Modified = false; @@ -3731,7 +3694,7 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) if (Modified) { - EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); EndActionSequence(tr("Paint")); gMainWindow->UpdateSelectedObjects(false); @@ -3824,7 +3787,7 @@ void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); } Camera->SetOrtho(Ortho); @@ -3832,7 +3795,7 @@ void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Change Projection")); } @@ -4748,7 +4711,7 @@ void lcModel::InvertSelection() void lcModel::HideSelectedPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); bool Modified = false; @@ -4770,7 +4733,7 @@ void lcModel::HideSelectedPieces() return; } - EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); EndActionSequence(tr("Hide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4781,7 +4744,7 @@ void lcModel::HideSelectedPieces() void lcModel::HideUnselectedPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditUnselectedPieces, nullptr); bool Modified = false; @@ -4802,7 +4765,7 @@ void lcModel::HideUnselectedPieces() return; } - EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditUnselectedPieces, nullptr); EndActionSequence(tr("Hide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4813,7 +4776,7 @@ void lcModel::HideUnselectedPieces() void lcModel::UnhideSelectedPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); bool Modified = false; @@ -4834,7 +4797,7 @@ void lcModel::UnhideSelectedPieces() return; } - EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); EndActionSequence(tr("Unhide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4845,7 +4808,7 @@ void lcModel::UnhideSelectedPieces() void lcModel::UnhideAllPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditAllPieces, nullptr); bool Modified = false; @@ -4866,7 +4829,7 @@ void lcModel::UnhideAllPieces() return; } - EndObjectEditAction(lcModelActionObjectEditMode::All, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditAllPieces, nullptr); EndActionSequence(tr("Unhide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -5041,7 +5004,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::Move: case lcTool::Rotate: BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); break; case lcTool::Eraser: @@ -5056,7 +5019,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) if (!View->GetCamera()->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Camera, View->GetCamera()); + BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, View->GetCamera()); } break; @@ -5093,12 +5056,12 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) break; case lcTool::Move: - EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); EndActionSequence(tr("Move")); break; case lcTool::Rotate: - EndObjectEditAction(lcModelActionObjectEditMode::Selection, nullptr); + EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); EndActionSequence(tr("Rotate")); break; @@ -5110,7 +5073,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Zoom: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Zoom")); } break; @@ -5118,7 +5081,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Pan: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Pan")); } break; @@ -5126,7 +5089,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::RotateView: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Orbit")); } break; @@ -5134,7 +5097,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Roll: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Roll")); } break; @@ -5439,14 +5402,14 @@ void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVec if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); } Camera->ZoomRegion(AspectRatio, Position, TargetPosition, Corners, mCurrentStep, gMainWindow->GetAddKeys()); if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Zoom")); } @@ -5471,7 +5434,7 @@ void lcModel::LookAt(lcCamera* Camera) if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); } Camera->Center(Center, mCurrentStep, gMainWindow->GetAddKeys()); @@ -5481,7 +5444,7 @@ void lcModel::LookAt(lcCamera* Camera) if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Look At")); } } @@ -5518,7 +5481,7 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); } Camera->ZoomExtents(Aspect, Center, Points, mCurrentStep, gMainWindow ? gMainWindow->GetAddKeys() : false); @@ -5530,7 +5493,7 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::Camera, Camera); + EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); EndActionSequence(tr("Zoom Extents")); } } diff --git a/common/lc_model.h b/common/lc_model.h index 15e82cdc..4a7b072e 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -237,7 +237,7 @@ public: lcPiece* AddPiece(PieceInfo* Info, quint32 Section); void DeleteSelectedObjects(); void ResetSelectedPiecesPivotPoint(); - void RemoveSelectedPiecesKeyFrames(); + void RemoveSelectedObjectsKeyFrames(); void InsertControlPoint(); void RemoveFocusedControlPoint(); void FocusNextTrainTrack(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index e14721d0..dc0aff12 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -7,7 +7,7 @@ #include "pieceinf.h" #include "lc_colors.h" -bool lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly) +bool lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model) { QDataStream Stream(&Buffer, QIODevice::WriteOnly); @@ -15,67 +15,27 @@ bool lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, boo const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - uint64_t PieceCount = Pieces.size(), CameraCount = Cameras.size(), LightCount = Lights.size(); - - Stream << PieceCount; - Stream << CameraCount; - Stream << LightCount; + uint64_t ObjectCount[3] = { Pieces.size(), Cameras.size(), Lights.size() }; - for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - { - const std::unique_ptr& Piece = Pieces[PieceIndex]; - - if (!SelectedOnly || Piece->IsSelected()) - { - if (Stream.writeRawData(reinterpret_cast(&PieceIndex), sizeof(PieceIndex)) != sizeof(PieceIndex)) - return false; - - if (!Piece->SaveUndoData(Stream)) - return false; - } - } - - if (Stream.writeRawData(reinterpret_cast(&mEndOfList), sizeof(mEndOfList)) != sizeof(mEndOfList)) + if (Stream.writeRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) return false; - for (uint64_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) - { - const std::unique_ptr& Camera = Cameras[CameraIndex]; - - if (!SelectedOnly || Camera->IsSelected()) - { - if (Stream.writeRawData(reinterpret_cast(&CameraIndex), sizeof(CameraIndex)) != sizeof(CameraIndex)) - return false; - - if (!Camera->SaveUndoData(Stream)) - return false; - } - } + for (size_t PieceIndex : mPieceIndices) + if (!Pieces[PieceIndex]->SaveUndoData(Stream)) + return false; - if (Stream.writeRawData(reinterpret_cast(&mEndOfList), sizeof(mEndOfList)) != sizeof(mEndOfList)) - return false; + for (size_t CameraIndex : mCameraIndices) + if (!Cameras[CameraIndex]->SaveUndoData(Stream)) + return false; - for (uint64_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) - { - const std::unique_ptr& Light = Lights[LightIndex]; - - if (!SelectedOnly || Light->IsSelected()) - { - if (Stream.writeRawData(reinterpret_cast(&LightIndex), sizeof(LightIndex)) != sizeof(LightIndex)) - return false; - - if (!Light->SaveUndoData(Stream)) - return false; - } - } - - if (Stream.writeRawData(reinterpret_cast(&mEndOfList), sizeof(mEndOfList)) != sizeof(mEndOfList)) - return false; + for (size_t LightIndex : mLightIndices) + if (!Lights[LightIndex]->SaveUndoData(Stream)) + return false; return true; } -bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) +bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) const { QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); @@ -83,25 +43,16 @@ bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - uint64_t PieceCount, CameraCount, LightCount; - - Stream >> PieceCount; - Stream >> CameraCount; - Stream >> LightCount; - - if (PieceCount != Pieces.size() || CameraCount != Cameras.size() || LightCount != Lights.size()) + uint64_t ObjectCount[3]; + + if (Stream.readRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) return false; - for (;;) + if (ObjectCount[0] != Pieces.size() || ObjectCount[1] != Cameras.size() || ObjectCount[2] != Lights.size()) + return false; + + for (size_t PieceIndex : mPieceIndices) { - uint64_t PieceIndex; - - if (Stream.readRawData(reinterpret_cast(&PieceIndex), sizeof(PieceIndex)) != sizeof(PieceIndex)) - return false; - - if (PieceIndex == mEndOfList) - break; - if (PieceIndex >= Pieces.size()) return false; @@ -111,16 +62,8 @@ bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) return false; } - for (;;) + for (size_t CameraIndex : mCameraIndices) { - uint64_t CameraIndex; - - if (Stream.readRawData(reinterpret_cast(&CameraIndex), sizeof(CameraIndex)) != sizeof(CameraIndex)) - return false; - - if (CameraIndex == mEndOfList) - break; - if (CameraIndex >= Cameras.size()) return false; @@ -130,16 +73,8 @@ bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) return false; } - for (;;) + for (size_t LightIndex : mLightIndices) { - uint64_t LightIndex; - - if (Stream.readRawData(reinterpret_cast(&LightIndex), sizeof(LightIndex)) != sizeof(LightIndex)) - return false; - - if (LightIndex == mEndOfList) - break; - if (LightIndex >= Lights.size()) return false; @@ -257,52 +192,82 @@ lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mod { } -void lcModelActionObjectEdit::SaveCameraStartState(const lcCamera* Camera) +void lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamera* Camera) { - QDataStream Stream(&mStartBuffer, QIODevice::WriteOnly); + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); - Camera->SaveUndoData(Stream); - - mCameraName = Camera->GetName(); -} - -void lcModelActionObjectEdit::LoadCameraStartState(lcCamera* Camera) const -{ - QDataStream Stream(const_cast(&mStartBuffer), QIODevice::ReadOnly); + switch (mMode) + { + case lcModelActionObjectEditMode::EditAllObjects: + mPieceIndices.resize(Pieces.size()); + std::iota(mPieceIndices.begin(), mPieceIndices.end(), 0); + + mCameraIndices.resize(Cameras.size()); + std::iota(mCameraIndices.begin(), mCameraIndices.end(), 0); + + mLightIndices.resize(Lights.size()); + std::iota(mLightIndices.begin(), mLightIndices.end(), 0); + break; + + case lcModelActionObjectEditMode::EditAllPieces: + mPieceIndices.resize(Pieces.size()); + std::iota(mPieceIndices.begin(), mPieceIndices.end(), 0); + break; + + case lcModelActionObjectEditMode::EditSelectedObjects: + for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + if (Pieces[PieceIndex]->IsSelected()) + mPieceIndices.push_back(PieceIndex); + + for (uint64_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + if (Cameras[CameraIndex]->IsSelected()) + mCameraIndices.push_back(CameraIndex); + + for (uint64_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + if (Lights[LightIndex]->IsSelected()) + mLightIndices.push_back(LightIndex); + break; + + case lcModelActionObjectEditMode::EditSelectedPieces: + for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + if (Pieces[PieceIndex]->IsSelected()) + mPieceIndices.push_back(PieceIndex); + break; + + case lcModelActionObjectEditMode::EditUnselectedPieces: + for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + if (!Pieces[PieceIndex]->IsSelected()) + mPieceIndices.push_back(PieceIndex); + break; + + case lcModelActionObjectEditMode::EditCamera: + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + { + if (Cameras[CameraIndex].get() == Camera) + { + mCameraIndices.push_back(CameraIndex); + break; + } + } + break; + }; - Camera->LoadUndoData(Stream); + SaveUndoBuffer(mStartBuffer, Model); } -void lcModelActionObjectEdit::SaveCameraEndState(const lcCamera* Camera) +void lcModelActionObjectEdit::SaveEndState(const lcModel* Model, const lcCamera* Camera) { - QDataStream Stream(&mEndBuffer, QIODevice::WriteOnly); - - Camera->SaveUndoData(Stream); + SaveUndoBuffer(mEndBuffer, Model); } -void lcModelActionObjectEdit::LoadCameraEndState(lcCamera* Camera) const -{ - QDataStream Stream(const_cast(&mEndBuffer), QIODevice::ReadOnly); - - Camera->LoadUndoData(Stream); -} - -void lcModelActionObjectEdit::SaveModelStartState(const lcModel* Model) -{ - SaveUndoBuffer(mStartBuffer, Model, mMode == lcModelActionObjectEditMode::Selection); -} - -void lcModelActionObjectEdit::LoadModelStartState(lcModel* Model) const +void lcModelActionObjectEdit::LoadStartState(lcModel* Model) const { LoadUndoBuffer(mStartBuffer, Model); } -void lcModelActionObjectEdit::SaveModelEndState(const lcModel* Model) -{ - SaveUndoBuffer(mEndBuffer, Model, mMode == lcModelActionObjectEditMode::Selection); -} - -void lcModelActionObjectEdit::LoadModelEndState(lcModel* Model) const +void lcModelActionObjectEdit::LoadEndState(lcModel* Model) const { LoadUndoBuffer(mEndBuffer, Model); } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index ac445a97..454c8236 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -13,10 +13,12 @@ public: virtual ~lcModelAction() = default; protected: - static bool SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model, bool SelectedOnly); - static bool LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model); + bool SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model); + bool LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) const; - static constexpr uint64_t mEndOfList = UINT64_MAX; + std::vector mPieceIndices; + std::vector mCameraIndices; + std::vector mLightIndices; }; enum class lcModelActionSelectionMode @@ -53,9 +55,12 @@ protected: enum class lcModelActionObjectEditMode { - All, - Selection, - Camera + EditAllObjects, + EditAllPieces, + EditSelectedObjects, + EditSelectedPieces, + EditUnselectedPieces, + EditCamera }; class lcModelActionObjectEdit: public lcModelAction @@ -63,30 +68,21 @@ class lcModelActionObjectEdit: public lcModelAction public: lcModelActionObjectEdit(lcModelActionObjectEditMode Mode); virtual ~lcModelActionObjectEdit() = default; - - void SaveCameraStartState(const lcCamera* Camera); - void LoadCameraStartState(lcCamera* Camera) const; - void SaveCameraEndState(const lcCamera* Camera); - void LoadCameraEndState(lcCamera* Camera) const; - - void SaveModelStartState(const lcModel* Model); - void LoadModelStartState(lcModel* Model) const; - void SaveModelEndState(const lcModel* Model); - void LoadModelEndState(lcModel* Model) const; + + void SaveStartState(const lcModel* Model, const lcCamera* Camera); + void SaveEndState(const lcModel* Model, const lcCamera* Camera); + void LoadStartState(lcModel* Model) const; + void LoadEndState(lcModel* Model) const; lcModelActionObjectEditMode GetMode() const { return mMode; } - const QString& GetCameraName() const - { - return mCameraName; - } - protected: + void SaveState(QByteArray& Buffer); + lcModelActionObjectEditMode mMode; - QString mCameraName; QByteArray mStartBuffer; QByteArray mEndBuffer; }; From e01d9581e5a78de6ac4502711798cdd14068fa59 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 25 Dec 2025 17:36:22 -0300 Subject: [PATCH 35/93] Moved add camera/light actions to object edit. --- common/lc_model.cpp | 165 ++++++++++++++++++-------------------- common/lc_model.h | 11 ++- common/lc_modelaction.cpp | 159 ++++++++++++++++++++++++++++-------- common/lc_modelaction.h | 54 ++----------- 4 files changed, 213 insertions(+), 176 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index f5e6b159..aba5cabe 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1728,7 +1728,8 @@ void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjec if (!ModelActionObjectEdit) return; - ModelActionObjectEdit->SaveStartState(this, Camera); + if (!ModelActionObjectEdit->SaveStartState(this, Camera)) + return; mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } @@ -1742,8 +1743,9 @@ void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectE if (!ModelActionObjectEdit || ModelActionObjectEditMode != ModelActionObjectEdit->GetMode()) return; - - ModelActionObjectEdit->SaveEndState(this, Camera); + + if (!ModelActionObjectEdit->SaveEndState(this, Camera)) + mActionSequence.pop_back(); } void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply) @@ -1837,70 +1839,6 @@ void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPie } } -void lcModel::RecordAddCameraAction(const lcVector3& Position, const lcVector3& TargetPosition) -{ - std::unique_ptr ModelActionAddCamera = std::make_unique(Position, TargetPosition); - - RunAddCameraAction(ModelActionAddCamera.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionAddCamera)); -} - -void lcModel::RunAddCameraAction(const lcModelActionAddCamera* ModelActionAddCamera, bool Apply) -{ - if (!ModelActionAddCamera) - return; - - if (Apply) - { - lcCamera* Camera = new lcCamera(ModelActionAddCamera->GetPosition(), ModelActionAddCamera->GetTargetPosition()); - Camera->CreateName(mCameras); - mCameras.emplace_back(Camera); - - ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_POSITION, false); - } - else - { - if (!mCameras.empty()) - mCameras.pop_back(); - - gMainWindow->UpdateSelectedObjects(true); - gMainWindow->UpdateInUseCategory(); - } -} - -void lcModel::RecordAddLightAction(const lcVector3& Position, lcLightType LightType) -{ - std::unique_ptr ModelActionAddLight = std::make_unique(Position, LightType); - - RunAddLightAction(ModelActionAddLight.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionAddLight)); -} - -void lcModel::RunAddLightAction(const lcModelActionAddLight* ModelActionAddLight, bool Apply) -{ - if (!ModelActionAddLight) - return; - - if (Apply) - { - lcLight* Light = new lcLight(ModelActionAddLight->GetPosition(), ModelActionAddLight->GetLightType()); - Light->CreateName(mLights); - mLights.emplace_back(Light); - - ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); - } - else - { - if (!mLights.empty()) - mLights.pop_back(); - - gMainWindow->UpdateSelectedObjects(true); - gMainWindow->UpdateInUseCategory(); - } -} - void lcModel::RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName) { std::unique_ptr ModelActionGroupPieces = std::make_unique(Mode, GroupName); @@ -2077,10 +2015,6 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunAddPiecesAction(ModelActionAddPieces, Apply); - else if (const lcModelActionAddCamera* ModelActionAddCamera = dynamic_cast(ModelAction)) - RunAddCameraAction(ModelActionAddCamera, Apply); - else if (const lcModelActionAddLight* ModelActionAddLight = dynamic_cast(ModelAction)) - RunAddLightAction(ModelActionAddLight, Apply); else if (const lcModelActionGroupPieces* ModelActionGroupPieces = dynamic_cast(ModelAction)) RunGroupPiecesAction(ModelActionGroupPieces, Apply); else if (const lcModelActionDuplicatePieces* ModelActionDuplicatePieces = dynamic_cast(ModelAction)) @@ -2800,6 +2734,48 @@ void lcModel::InsertPiece(lcPiece* Piece, size_t Index) mPieces.insert(mPieces.begin() + Index, std::unique_ptr(Piece)); } +void lcModel::AddCamera(std::unique_ptr Camera, size_t CameraIndex) +{ + if (CameraIndex > mCameras.size()) + return; + + mCameras.insert(mCameras.begin() + CameraIndex, std::move(Camera)); +} + +void lcModel::DeleteCamera(size_t CameraIndex) +{ + if (CameraIndex >= mCameras.size()) + return; + + std::vector>::iterator CameraIt = mCameras.begin() + CameraIndex; + + RemoveCameraFromViews(CameraIt->get()); + + mCameras.erase(CameraIt); + + gMainWindow->UpdateSelectedObjects(true); +} + +void lcModel::AddLight(std::unique_ptr Light, size_t LightIndex) +{ + if (LightIndex > mLights.size()) + return; + + mLights.insert(mLights.begin() + LightIndex, std::move(Light)); +} + +void lcModel::DeleteLight(size_t LightIndex) +{ + if (LightIndex >= mLights.size()) + return; + + std::vector>::iterator LightIt = mLights.begin() + LightIndex; + + mLights.erase(LightIt); + + gMainWindow->UpdateSelectedObjects(true); +} + void lcModel::FocusNextTrainTrack() { const lcObject* Focus = GetFocusObject(); @@ -3302,13 +3278,22 @@ void lcModel::InlineSelectedModels() SetSelectionAndFocus(NewPieces, nullptr, 0, false); } +void lcModel::RemoveCameraFromViews(lcCamera* Camera) +{ + std::vector Views = lcView::GetModelViews(this); + + for (lcView* View : Views) + if (Camera == View->GetCamera()) + View->SetCamera(Camera, true); +} + bool lcModel::RemoveSelectedObjects() { bool RemovedPiece = false; bool RemovedCamera = false; bool RemovedLight = false; - for (auto PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ) + for (std::vector>::iterator PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ) { lcPiece* Piece = PieceIt->get(); @@ -3327,12 +3312,8 @@ bool lcModel::RemoveSelectedObjects() if (Camera->IsSelected()) { - std::vector Views = lcView::GetModelViews(this); - - for (lcView* View : Views) - if (Camera == View->GetCamera()) - View->SetCamera(Camera, true); - + RemoveCameraFromViews(Camera); + RemovedCamera = true; CameraIt = mCameras.erase(CameraIt); } @@ -5125,16 +5106,18 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece void lcModel::InsertCameraToolClicked(const lcVector3& Position) { - lcVector3 TargetPosition; - - GetPieceFocusOrSelectionCenter(TargetPosition); - BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::CreateCamera, nullptr); - RecordSelectionAction(lcModelActionSelectionMode::Save); - RecordAddCameraAction(Position, TargetPosition); + lcCamera* Camera = new lcCamera(Position, GetSelectionOrModelCenter()); - EndActionSequence(tr("Add Camera")); + Camera->CreateName(mCameras); + mCameras.emplace_back(Camera); + + EndObjectEditAction(lcModelActionObjectEditMode::CreateCamera, nullptr); + EndActionSequence(tr("Add Camera")); + + ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_POSITION, false); } void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType) @@ -5164,11 +5147,17 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh } BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::CreateLight, nullptr); - RecordSelectionAction(lcModelActionSelectionMode::Save); - RecordAddLightAction(Position, LightType); - + lcLight* Light = new lcLight(Position, LightType); + + Light->CreateName(mLights); + mLights.emplace_back(Light); + + EndObjectEditAction(lcModelActionObjectEditMode::CreateLight, nullptr); EndActionSequence(ActionName); + + ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); } void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag) diff --git a/common/lc_model.h b/common/lc_model.h index 4a7b072e..fd645c4e 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -8,8 +8,6 @@ class lcModelAction; class lcModelActionSelection; class lcModelActionObjectEdit; class lcModelActionAddPieces; -class lcModelActionAddCamera; -class lcModelActionAddLight; class lcModelActionGroupPieces; class lcModelActionDuplicatePieces; enum class lcModelActionSelectionMode; @@ -235,6 +233,10 @@ public: void RemoveStep(lcStep Step); lcPiece* AddPiece(PieceInfo* Info, quint32 Section); + void AddCamera(std::unique_ptr Camera, size_t CameraIndex); + void DeleteCamera(size_t CameraIndex); + void AddLight(std::unique_ptr Light, size_t LightIndex); + void DeleteLight(size_t LightIndex); void DeleteSelectedObjects(); void ResetSelectedPiecesPivotPoint(); void RemoveSelectedObjectsKeyFrames(); @@ -412,10 +414,6 @@ protected: void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); - void RecordAddCameraAction(const lcVector3& Position, const lcVector3& TargetPosition); - void RunAddCameraAction(const lcModelActionAddCamera* ModelActionAddCamera, bool Apply); - void RecordAddLightAction(const lcVector3& Position, lcLightType LightType); - void RunAddLightAction(const lcModelActionAddLight* ModelActionAddLight, bool Apply); void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); void RecordDuplicatePiecesAction(); @@ -433,6 +431,7 @@ protected: QString GetGroupName(const QString& Prefix); void RemoveEmptyGroups(); bool RemoveSelectedObjects(); + void RemoveCameraFromViews(lcCamera* Camera); void SelectGroup(lcGroup* TopGroup, bool Select); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index dc0aff12..b7aa7c9d 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -7,7 +7,7 @@ #include "pieceinf.h" #include "lc_colors.h" -bool lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model) +bool lcModelAction::SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model) { QDataStream Stream(&Buffer, QIODevice::WriteOnly); @@ -35,7 +35,7 @@ bool lcModelAction::SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model) return true; } -bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) const +bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const { QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); @@ -48,6 +48,13 @@ bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) con if (Stream.readRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) return false; + if (CreateObjects) + { + ObjectCount[0] -= mPieceIndices.size(); + ObjectCount[1] -= mCameraIndices.size(); + ObjectCount[2] -= mLightIndices.size(); + } + if (ObjectCount[0] != Pieces.size() || ObjectCount[1] != Cameras.size() || ObjectCount[2] != Lights.size()) return false; @@ -62,28 +69,59 @@ bool lcModelAction::LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) con return false; } - for (size_t CameraIndex : mCameraIndices) + if (CreateObjects) { - if (CameraIndex >= Cameras.size()) - return false; + for (size_t CameraIndex : mCameraIndices) + { + if (CameraIndex > Cameras.size()) + return false; + + std::unique_ptr Camera(new lcCamera(false)); + + if (!Camera->LoadUndoData(Stream)) + return false; + + Model->AddCamera(std::move(Camera), CameraIndex); + } - const std::unique_ptr& Camera = Cameras[CameraIndex]; - - if (!Camera->LoadUndoData(Stream)) - return false; + for (size_t LightIndex : mLightIndices) + { + if (LightIndex > Lights.size()) + return false; + + std::unique_ptr Light(new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point)); + + if (!Light->LoadUndoData(Stream)) + return false; + + Model->AddLight(std::move(Light), LightIndex); + } } - - for (size_t LightIndex : mLightIndices) + else { - if (LightIndex >= Lights.size()) - return false; + for (size_t CameraIndex : mCameraIndices) + { + if (CameraIndex >= Cameras.size()) + return false; + + const std::unique_ptr& Camera = Cameras[CameraIndex]; + + if (!Camera->LoadUndoData(Stream)) + return false; + } - const std::unique_ptr& Light = Lights[LightIndex]; + for (size_t LightIndex : mLightIndices) + { + if (LightIndex >= Lights.size()) + return false; + + const std::unique_ptr& Light = Lights[LightIndex]; + + if (!Light->LoadUndoData(Stream)) + return false; + } + } - if (!Light->LoadUndoData(Stream)) - return false; - } - return true; } @@ -192,7 +230,7 @@ lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mod { } -void lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamera* Camera) +bool lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamera* Camera) { const std::vector>& Pieces = Model->GetPieces(); const std::vector>& Cameras = Model->GetCameras(); @@ -252,24 +290,85 @@ void lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamer } } break; - }; - SaveUndoBuffer(mStartBuffer, Model); + case lcModelActionObjectEditMode::CreateCamera: + case lcModelActionObjectEditMode::CreateLight: + break; + }; + + return SaveHistoryBuffer(mStartBuffer, Model); } -void lcModelActionObjectEdit::SaveEndState(const lcModel* Model, const lcCamera* Camera) +bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, const lcCamera* Camera) { - SaveUndoBuffer(mEndBuffer, Model); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + + switch (mMode) + { + case lcModelActionObjectEditMode::EditAllObjects: + case lcModelActionObjectEditMode::EditAllPieces: + case lcModelActionObjectEditMode::EditSelectedObjects: + case lcModelActionObjectEditMode::EditSelectedPieces: + case lcModelActionObjectEditMode::EditUnselectedPieces: + case lcModelActionObjectEditMode::EditCamera: + break; + + case lcModelActionObjectEditMode::CreateCamera: + mCameraIndices.push_back(Cameras.size() - 1); + break; + + case lcModelActionObjectEditMode::CreateLight: + mLightIndices.push_back(Lights.size() - 1); + break; + }; + + return SaveHistoryBuffer(mEndBuffer, Model); } void lcModelActionObjectEdit::LoadStartState(lcModel* Model) const { - LoadUndoBuffer(mStartBuffer, Model); + switch (mMode) + { + case lcModelActionObjectEditMode::EditAllObjects: + case lcModelActionObjectEditMode::EditAllPieces: + case lcModelActionObjectEditMode::EditSelectedObjects: + case lcModelActionObjectEditMode::EditSelectedPieces: + case lcModelActionObjectEditMode::EditUnselectedPieces: + case lcModelActionObjectEditMode::EditCamera: + LoadHistoryBuffer(mStartBuffer, Model, false); + break; + + case lcModelActionObjectEditMode::CreateCamera: + for (size_t CameraIndex : mCameraIndices) + Model->DeleteCamera(CameraIndex); + break; + + case lcModelActionObjectEditMode::CreateLight: + for (size_t LightIndex : mLightIndices) + Model->DeleteLight(LightIndex); + break; + }; } void lcModelActionObjectEdit::LoadEndState(lcModel* Model) const { - LoadUndoBuffer(mEndBuffer, Model); + switch (mMode) + { + case lcModelActionObjectEditMode::EditAllObjects: + case lcModelActionObjectEditMode::EditAllPieces: + case lcModelActionObjectEditMode::EditSelectedObjects: + case lcModelActionObjectEditMode::EditSelectedPieces: + case lcModelActionObjectEditMode::EditUnselectedPieces: + case lcModelActionObjectEditMode::EditCamera: + LoadHistoryBuffer(mEndBuffer, Model, false); + break; + + case lcModelActionObjectEditMode::CreateCamera: + case lcModelActionObjectEditMode::CreateLight: + LoadHistoryBuffer(mEndBuffer, Model, true); + break; + }; } lcModelActionAddPieces::lcModelActionAddPieces(lcStep Step, lcModelActionAddPieceSelectionMode SelectionMode) @@ -292,16 +391,6 @@ void lcModelActionAddPieces::SetPieceData(const std::vector& } } -lcModelActionAddCamera::lcModelActionAddCamera(const lcVector3& Position, const lcVector3& TargetPosition) - : mPosition(Position), mTargetPosition(TargetPosition) -{ -} - -lcModelActionAddLight::lcModelActionAddLight(const lcVector3& Position, lcLightType LightType) - : mPosition(Position), mLightType(LightType) -{ -} - lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName) : mMode(Mode), mGroupName(GroupName) { diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 454c8236..cf991a2a 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -13,8 +13,8 @@ public: virtual ~lcModelAction() = default; protected: - bool SaveUndoBuffer(QByteArray& Buffer, const lcModel* Model); - bool LoadUndoBuffer(const QByteArray& Buffer, lcModel* Model) const; + bool SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model); + bool LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const; std::vector mPieceIndices; std::vector mCameraIndices; @@ -60,7 +60,9 @@ enum class lcModelActionObjectEditMode EditSelectedObjects, EditSelectedPieces, EditUnselectedPieces, - EditCamera + EditCamera, + CreateCamera, + CreateLight }; class lcModelActionObjectEdit: public lcModelAction @@ -69,8 +71,8 @@ public: lcModelActionObjectEdit(lcModelActionObjectEditMode Mode); virtual ~lcModelActionObjectEdit() = default; - void SaveStartState(const lcModel* Model, const lcCamera* Camera); - void SaveEndState(const lcModel* Model, const lcCamera* Camera); + bool SaveStartState(const lcModel* Model, const lcCamera* Camera); + bool SaveEndState(const lcModel* Model, const lcCamera* Camera); void LoadStartState(lcModel* Model) const; void LoadEndState(lcModel* Model) const; @@ -130,48 +132,6 @@ protected: lcModelActionAddPieceSelectionMode mSelectionMode; }; -class lcModelActionAddCamera : public lcModelAction -{ -public: - lcModelActionAddCamera(const lcVector3& Position, const lcVector3& TargetPosition); - virtual ~lcModelActionAddCamera() = default; - - const lcVector3& GetPosition() const - { - return mPosition; - } - - const lcVector3& GetTargetPosition() const - { - return mTargetPosition; - } - -protected: - lcVector3 mPosition; - lcVector3 mTargetPosition; -}; - -class lcModelActionAddLight : public lcModelAction -{ -public: - lcModelActionAddLight(const lcVector3& Position, lcLightType LightType); - virtual ~lcModelActionAddLight() = default; - - const lcVector3& GetPosition() const - { - return mPosition; - } - - lcLightType GetLightType() const - { - return mLightType; - } - -protected: - lcVector3 mPosition; - lcLightType mLightType; -}; - enum class lcModelActionGroupPiecesMode { Group, From 8dfa1772b3585795962261f40db33cbae00dd7b0 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 26 Dec 2025 11:53:51 -0300 Subject: [PATCH 36/93] Fixed control point undo. --- common/camera.cpp | 2 ++ common/lc_modelaction.h | 1 - common/light.cpp | 2 ++ common/piece.cpp | 35 ++++++++++++++++++++++++++++------- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index b910d4b9..b7a56614 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -909,6 +909,8 @@ void lcCamera::RemoveKeyFrames() bool lcCamera::SaveUndoData(QDataStream& Stream) const { + static_assert(sizeof(lcCamera) == 240); + Stream << m_fovy; Stream << m_zNear; Stream << m_zFar; diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index cf991a2a..7e00bd9f 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -4,7 +4,6 @@ struct lcInsertPieceInfo; enum class lcObjectType; -enum class lcLightType; class lcModelAction { diff --git a/common/light.cpp b/common/light.cpp index 2420e9fb..aaf0317f 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1532,6 +1532,8 @@ void lcLight::RemoveKeyFrames() bool lcLight::SaveUndoData(QDataStream& Stream) const { + static_assert(sizeof(lcLight) == 704); + Stream << mName; Stream << mLightType; Stream << mCastShadow; diff --git a/common/piece.cpp b/common/piece.cpp index 78093af5..5ada0349 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -936,6 +936,8 @@ void lcPiece::RemoveKeyFrames() bool lcPiece::SaveUndoData(QDataStream& Stream) const { + static_assert(sizeof(lcPiece) == 376); + // PieceInfo* mPieceInfo; Stream << mFileLine; Stream << mID; @@ -952,15 +954,23 @@ bool lcPiece::SaveUndoData(QDataStream& Stream) const Stream << mPivotPointValid; Stream << mHidden; - -// std::vector mControlPoints; + + size_t ControlPointCount = mControlPoints.size(); + qint64 DataSize = ControlPointCount * sizeof(lcPieceControlPoint); + + if (Stream.writeRawData(reinterpret_cast(&ControlPointCount), sizeof(ControlPointCount)) != sizeof(ControlPointCount)) + return false; + + if (Stream.writeRawData(reinterpret_cast(mControlPoints.data()), DataSize) != DataSize) + return false; + // std::vector mTrainTrackConnections; return mPosition.SaveUndoData(Stream) && mRotation.SaveUndoData(Stream); } bool lcPiece::LoadUndoData(QDataStream& Stream) -{ +{ // SetPieceInfo(Other.mPieceInfo, Other.mID, true, false); // PieceInfo* mPieceInfo; @@ -979,12 +989,23 @@ bool lcPiece::LoadUndoData(QDataStream& Stream) Stream >> mPivotPointValid; Stream >> mHidden; - -// std::vector mControlPoints; + + size_t ControlPointCount; + + if (Stream.readRawData(reinterpret_cast(&ControlPointCount), sizeof(ControlPointCount)) != sizeof(ControlPointCount)) + return false; + + mControlPoints.resize(ControlPointCount); + + qsizetype DataSize = ControlPointCount * sizeof(lcPieceControlPoint); + + if (Stream.readRawData(reinterpret_cast(mControlPoints.data()), DataSize) != DataSize) + return false; + + UpdateMesh(); + // std::vector mTrainTrackConnections; -// UpdateMesh(); - return mPosition.LoadUndoData(Stream) && mRotation.LoadUndoData(Stream); } From 49308948d133d2740cdc710b7962e4fad4cc2951 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 26 Dec 2025 16:50:46 -0300 Subject: [PATCH 37/93] Removed duplicate piece action. --- common/lc_model.cpp | 300 +++++++++++++++++++------------------- common/lc_model.h | 12 +- common/lc_modelaction.cpp | 65 +++++---- common/lc_modelaction.h | 18 +-- common/piece.cpp | 12 +- 5 files changed, 203 insertions(+), 204 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index aba5cabe..3a61a7c4 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1248,12 +1248,71 @@ void lcModel::DuplicateSelectedPieces() } BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Set); - RecordDuplicatePiecesAction(); - RecordSelectionAction(lcModelActionSelectionMode::Save); - + BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); + + std::vector NewPieces; + lcPiece* Focus = nullptr; + std::map GroupMap; + + std::function GetNewGroup = [this, &GroupMap, &GetNewGroup](lcGroup* Group) + { + const auto GroupIt = GroupMap.find(Group); + + if (GroupIt != GroupMap.end()) + return GroupIt->second; + else + { + lcGroup* Parent = Group->mGroup ? GetNewGroup(Group->mGroup) : nullptr; + QString GroupName = Group->mName; + + while (!GroupName.isEmpty()) + { + const QChar Last = GroupName[GroupName.size() - 1]; + if (Last.isDigit()) + GroupName.chop(1); + else + break; + } + + if (GroupName.isEmpty()) + GroupName = Group->mName; + + lcGroup* NewGroup = AddGroup(GroupName, Parent); + GroupMap[Group] = NewGroup; + return NewGroup; + } + }; + + std::vector PieceIndices; + + for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) + { + lcPiece* Piece = mPieces[PieceIndex].get(); + + if (!Piece->IsSelected()) + continue; + + lcPiece* NewPiece = new lcPiece(*Piece); + NewPiece->UpdatePosition(mCurrentStep); + NewPieces.emplace_back(NewPiece); + + if (Piece->IsFocused()) + Focus = NewPiece; + + PieceIndex++; + PieceIndices.push_back(PieceIndex); + AddPiece(std::unique_ptr(NewPiece), PieceIndex); + + lcGroup* Group = Piece->GetGroup(); + if (Group) + Piece->SetGroup(GetNewGroup(Group)); + } + + EndObjectEditAction(std::move(PieceIndices)); EndActionSequence(tr("Duplicate")); + + gMainWindow->UpdateTimeline(false, false); + SetSelectionAndFocus(NewPieces, Focus, LC_PIECE_SECTION_POSITION, false); } void lcModel::PaintSelectedPieces() @@ -1734,17 +1793,17 @@ void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjec mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } -void lcModel::EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera) +void lcModel::EndObjectEditAction(std::vector&& ObjectIndices) { if (mActionSequence.empty()) return; lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(mActionSequence.back().get()); - if (!ModelActionObjectEdit || ModelActionObjectEditMode != ModelActionObjectEdit->GetMode()) + if (!ModelActionObjectEdit) return; - if (!ModelActionObjectEdit->SaveEndState(this, Camera)) + if (!ModelActionObjectEdit->SaveEndState(this, std::move(ObjectIndices))) mActionSequence.pop_back(); } @@ -1920,91 +1979,6 @@ void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGr gMainWindow->UpdateSelectedObjects(true); } -void lcModel::RecordDuplicatePiecesAction() -{ - std::unique_ptr ModelActionDuplicatePieces = std::make_unique(mCurrentStep); - - RunDuplicatePiecesAction(ModelActionDuplicatePieces.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionDuplicatePieces)); -} - -void lcModel::RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply) -{ - if (!ModelActionDuplicatePieces) - return; - - if (Apply) - { - std::vector NewPieces; - lcPiece* Focus = nullptr; - std::map GroupMap; - lcStep Step = ModelActionDuplicatePieces->GetStep(); - - std::function GetNewGroup = [this, &GroupMap, &GetNewGroup](lcGroup* Group) - { - const auto GroupIt = GroupMap.find(Group); - - if (GroupIt != GroupMap.end()) - return GroupIt->second; - else - { - lcGroup* Parent = Group->mGroup ? GetNewGroup(Group->mGroup) : nullptr; - QString GroupName = Group->mName; - - while (!GroupName.isEmpty()) - { - const QChar Last = GroupName[GroupName.size() - 1]; - if (Last.isDigit()) - GroupName.chop(1); - else - break; - } - - if (GroupName.isEmpty()) - GroupName = Group->mName; - - lcGroup* NewGroup = AddGroup(GroupName, Parent); - GroupMap[Group] = NewGroup; - return NewGroup; - } - }; - - for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) - { - lcPiece* Piece = mPieces[PieceIndex].get(); - - if (!Piece->IsSelected()) - continue; - - lcPiece* NewPiece = new lcPiece(*Piece); - NewPiece->UpdatePosition(Step); - NewPieces.emplace_back(NewPiece); - - if (Piece->IsFocused()) - Focus = NewPiece; - - PieceIndex++; - InsertPiece(NewPiece, PieceIndex); - - lcGroup* Group = Piece->GetGroup(); - if (Group) - Piece->SetGroup(GetNewGroup(Group)); - } - - gMainWindow->UpdateTimeline(false, false); - SetSelectionAndFocus(NewPieces, Focus, LC_PIECE_SECTION_POSITION, false); - } - else - { - if (RemoveSelectedObjects()) - { - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); - } - } -} - void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) { auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) @@ -2017,8 +1991,6 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunGroupPiecesAction(ModelActionGroupPieces, Apply); - else if (const lcModelActionDuplicatePieces* ModelActionDuplicatePieces = dynamic_cast(ModelAction)) - RunDuplicatePiecesAction(ModelActionDuplicatePieces, Apply); }; if (Apply) @@ -2250,7 +2222,7 @@ void lcModel::InsertStep(lcStep Step) Light->InsertTime(Step, 1); - EndObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Insert Step")); SetCurrentStep(mCurrentStep); @@ -2275,7 +2247,7 @@ void lcModel::RemoveStep(lcStep Step) for (const std::unique_ptr& Light : mLights) Light->RemoveTime(Step, 1); - EndObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Remove Step")); SetCurrentStep(mCurrentStep); @@ -2705,33 +2677,53 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) return Piece; } +void lcModel::AddPiece(std::unique_ptr Piece, size_t PieceIndex) +{ + const PieceInfo* Info = Piece->mPieceInfo; + + if (!Info->IsModel()) + { + const lcMesh* Mesh = Info->GetMesh(); + + if (Mesh && Mesh->mVertexCacheOffset == -1) + lcGetPiecesLibrary()->mBuffersDirty = true; + } + + mPieces.insert(mPieces.begin() + PieceIndex, std::move(Piece)); +} + +void lcModel::RemovePieces(const std::vector& PieceIndices) +{ + for (auto PieceIndicesIt = PieceIndices.crbegin(); PieceIndicesIt != PieceIndices.crend(); ++PieceIndicesIt) + { + size_t PieceIndex = *PieceIndicesIt; + + if (PieceIndex >= mPieces.size()) + continue; + + std::vector>::iterator PieceIt = mPieces.begin() + PieceIndex; + + mPieces.erase(PieceIt); + } + + RemoveEmptyGroups(); + + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateSelectedObjects(true); +} + void lcModel::AddPiece(lcPiece* Piece) { for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) { if (mPieces[PieceIndex]->GetStepShow() > Piece->GetStepShow()) { - InsertPiece(Piece, PieceIndex); + AddPiece(std::unique_ptr(Piece), PieceIndex); return; } } - InsertPiece(Piece, mPieces.size()); -} - -void lcModel::InsertPiece(lcPiece* Piece, size_t Index) -{ - const PieceInfo* Info = Piece->mPieceInfo; - - if (!Info->IsModel()) - { - const lcMesh* Mesh = Info->GetMesh(); - - if (Mesh && Mesh->mVertexCacheOffset == -1) - lcGetPiecesLibrary()->mBuffersDirty = true; - } - - mPieces.insert(mPieces.begin() + Index, std::unique_ptr(Piece)); + AddPiece(std::unique_ptr(Piece), mPieces.size()); } void lcModel::AddCamera(std::unique_ptr Camera, size_t CameraIndex) @@ -2742,16 +2734,21 @@ void lcModel::AddCamera(std::unique_ptr Camera, size_t CameraIndex) mCameras.insert(mCameras.begin() + CameraIndex, std::move(Camera)); } -void lcModel::DeleteCamera(size_t CameraIndex) +void lcModel::RemoveCameras(const std::vector& CameraIndices) { - if (CameraIndex >= mCameras.size()) - return; + for (auto CameraIndicesIt = CameraIndices.crbegin(); CameraIndicesIt != CameraIndices.crend(); ++CameraIndicesIt) + { + size_t CameraIndex = *CameraIndicesIt; + + if (CameraIndex >= mCameras.size()) + continue; - std::vector>::iterator CameraIt = mCameras.begin() + CameraIndex; - - RemoveCameraFromViews(CameraIt->get()); - - mCameras.erase(CameraIt); + std::vector>::iterator CameraIt = mCameras.begin() + CameraIndex; + + RemoveCameraFromViews(CameraIt->get()); + + mCameras.erase(CameraIt); + } gMainWindow->UpdateSelectedObjects(true); } @@ -2764,14 +2761,19 @@ void lcModel::AddLight(std::unique_ptr Light, size_t LightIndex) mLights.insert(mLights.begin() + LightIndex, std::move(Light)); } -void lcModel::DeleteLight(size_t LightIndex) +void lcModel::RemoveLights(const std::vector& LightIndices) { - if (LightIndex >= mLights.size()) - return; + for (auto LightIndicesIt = LightIndices.crbegin(); LightIndicesIt != LightIndices.crbegin(); ++LightIndicesIt) + { + size_t LightIndex = *LightIndicesIt; + + if (LightIndex >= mLights.size()) + return; - std::vector>::iterator LightIt = mLights.begin() + LightIndex; + std::vector>::iterator LightIt = mLights.begin() + LightIndex; - mLights.erase(LightIt); + mLights.erase(LightIt); + } gMainWindow->UpdateSelectedObjects(true); } @@ -2973,7 +2975,7 @@ void lcModel::ResetSelectedPiecesPivotPoint() if (Piece->IsSelected()) Piece->ResetPivotPoint(); - EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Reset Pivot Point")); UpdateAllViews(); @@ -2996,7 +2998,7 @@ void lcModel::RemoveSelectedObjectsKeyFrames() if (Light->IsSelected()) Light->RemoveKeyFrames(); - EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Remove Key Frames")); UpdateAllViews(); @@ -3192,7 +3194,7 @@ void lcModel::MoveSelectionToModel(lcModel* Model) { ModelPiece = new lcPiece(Model->mPieceInfo); ModelPiece->SetColorIndex(gDefaultColor); - InsertPiece(ModelPiece, PieceIndex); + AddPiece(std::unique_ptr(ModelPiece), PieceIndex); PieceIndex++; } } @@ -3260,7 +3262,7 @@ void lcModel::InlineSelectedModels() NewPiece->UpdatePosition(mCurrentStep); NewPieces.emplace_back(NewPiece); - InsertPiece(NewPiece, PieceIndex); + AddPiece(std::unique_ptr(NewPiece), PieceIndex); PieceIndex++; } @@ -3675,7 +3677,7 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) if (Modified) { - EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Paint")); gMainWindow->UpdateSelectedObjects(false); @@ -3776,7 +3778,7 @@ void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Change Projection")); } @@ -4714,7 +4716,7 @@ void lcModel::HideSelectedPieces() return; } - EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Hide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4746,7 +4748,7 @@ void lcModel::HideUnselectedPieces() return; } - EndObjectEditAction(lcModelActionObjectEditMode::EditUnselectedPieces, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Hide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4778,7 +4780,7 @@ void lcModel::UnhideSelectedPieces() return; } - EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Unhide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4808,9 +4810,9 @@ void lcModel::UnhideAllPieces() DiscardActionSequence(); return; - } + } - EndObjectEditAction(lcModelActionObjectEditMode::EditAllPieces, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Unhide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -5037,12 +5039,12 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) break; case lcTool::Move: - EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Move")); break; case lcTool::Rotate: - EndObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Rotate")); break; @@ -5054,7 +5056,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Zoom: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Zoom")); } break; @@ -5062,7 +5064,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Pan: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Pan")); } break; @@ -5070,7 +5072,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::RotateView: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Orbit")); } break; @@ -5078,7 +5080,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Roll: if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Roll")); } break; @@ -5114,7 +5116,7 @@ void lcModel::InsertCameraToolClicked(const lcVector3& Position) Camera->CreateName(mCameras); mCameras.emplace_back(Camera); - EndObjectEditAction(lcModelActionObjectEditMode::CreateCamera, nullptr); + EndObjectEditAction({ mCameras.size() - 1 }); EndActionSequence(tr("Add Camera")); ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_POSITION, false); @@ -5154,7 +5156,7 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh Light->CreateName(mLights); mLights.emplace_back(Light); - EndObjectEditAction(lcModelActionObjectEditMode::CreateLight, nullptr); + EndObjectEditAction({ mLights.size() - 1 }); EndActionSequence(ActionName); ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); @@ -5398,7 +5400,7 @@ void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVec if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Zoom")); } @@ -5433,7 +5435,7 @@ void lcModel::LookAt(lcCamera* Camera) if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Look At")); } } @@ -5482,7 +5484,7 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl if (!Camera->IsSimple()) { - EndObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + EndObjectEditAction(std::vector()); EndActionSequence(tr("Zoom Extents")); } } diff --git a/common/lc_model.h b/common/lc_model.h index fd645c4e..352c3133 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -9,7 +9,6 @@ class lcModelActionSelection; class lcModelActionObjectEdit; class lcModelActionAddPieces; class lcModelActionGroupPieces; -class lcModelActionDuplicatePieces; enum class lcModelActionSelectionMode; enum class lcModelActionAddPieceSelectionMode; enum class lcModelActionObjectEditMode; @@ -233,10 +232,12 @@ public: void RemoveStep(lcStep Step); lcPiece* AddPiece(PieceInfo* Info, quint32 Section); + void AddPiece(std::unique_ptr Piece, size_t PieceIndex); + void RemovePieces(const std::vector& PieceIndices); void AddCamera(std::unique_ptr Camera, size_t CameraIndex); - void DeleteCamera(size_t CameraIndex); + void RemoveCameras(const std::vector& CameraIndices); void AddLight(std::unique_ptr Light, size_t LightIndex); - void DeleteLight(size_t LightIndex); + void RemoveLights(const std::vector& LightIndices); void DeleteSelectedObjects(); void ResetSelectedPiecesPivotPoint(); void RemoveSelectedObjectsKeyFrames(); @@ -410,14 +411,12 @@ protected: void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); - void EndObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); + void EndObjectEditAction(std::vector&& ObjectIndices); void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); - void RecordDuplicatePiecesAction(); - void RunDuplicatePiecesAction(const lcModelActionDuplicatePieces* ModelActionDuplicatePieces, bool Apply); void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); @@ -436,7 +435,6 @@ protected: void SelectGroup(lcGroup* TopGroup, bool Select); void AddPiece(lcPiece* Piece); - void InsertPiece(lcPiece* Piece, size_t Index); lcPOVRayOptions mPOVRayOptions; lcModelProperties mProperties; diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index b7aa7c9d..83001319 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -58,19 +58,21 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, if (ObjectCount[0] != Pieces.size() || ObjectCount[1] != Cameras.size() || ObjectCount[2] != Lights.size()) return false; - for (size_t PieceIndex : mPieceIndices) - { - if (PieceIndex >= Pieces.size()) - return false; - - const std::unique_ptr& Piece = Pieces[PieceIndex]; - - if (!Piece->LoadUndoData(Stream)) - return false; - } - if (CreateObjects) { + for (size_t PieceIndex : mPieceIndices) + { + if (PieceIndex > Pieces.size()) + return false; + + std::unique_ptr Piece(new lcPiece(nullptr)); + + if (!Piece->LoadUndoData(Stream)) + return false; + + Model->AddPiece(std::move(Piece), PieceIndex); + } + for (size_t CameraIndex : mCameraIndices) { if (CameraIndex > Cameras.size()) @@ -99,6 +101,17 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, } else { + for (size_t PieceIndex : mPieceIndices) + { + if (PieceIndex >= Pieces.size()) + return false; + + const std::unique_ptr& Piece = Pieces[PieceIndex]; + + if (!Piece->LoadUndoData(Stream)) + return false; + } + for (size_t CameraIndex : mCameraIndices) { if (CameraIndex >= Cameras.size()) @@ -291,6 +304,7 @@ bool lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamer } break; + case lcModelActionObjectEditMode::CreatePieces: case lcModelActionObjectEditMode::CreateCamera: case lcModelActionObjectEditMode::CreateLight: break; @@ -299,11 +313,8 @@ bool lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamer return SaveHistoryBuffer(mStartBuffer, Model); } -bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, const lcCamera* Camera) +bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector&& ObjectIndices) { - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - switch (mMode) { case lcModelActionObjectEditMode::EditAllObjects: @@ -314,12 +325,16 @@ bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, const lcCamera* case lcModelActionObjectEditMode::EditCamera: break; + case lcModelActionObjectEditMode::CreatePieces: + mPieceIndices = std::move(ObjectIndices); + break; + case lcModelActionObjectEditMode::CreateCamera: - mCameraIndices.push_back(Cameras.size() - 1); + mCameraIndices = std::move(ObjectIndices); break; case lcModelActionObjectEditMode::CreateLight: - mLightIndices.push_back(Lights.size() - 1); + mLightIndices = std::move(ObjectIndices); break; }; @@ -339,14 +354,16 @@ void lcModelActionObjectEdit::LoadStartState(lcModel* Model) const LoadHistoryBuffer(mStartBuffer, Model, false); break; + case lcModelActionObjectEditMode::CreatePieces: + Model->RemovePieces(mPieceIndices); + break; + case lcModelActionObjectEditMode::CreateCamera: - for (size_t CameraIndex : mCameraIndices) - Model->DeleteCamera(CameraIndex); + Model->RemoveCameras(mCameraIndices); break; case lcModelActionObjectEditMode::CreateLight: - for (size_t LightIndex : mLightIndices) - Model->DeleteLight(LightIndex); + Model->RemoveLights(mLightIndices); break; }; } @@ -364,6 +381,7 @@ void lcModelActionObjectEdit::LoadEndState(lcModel* Model) const LoadHistoryBuffer(mEndBuffer, Model, false); break; + case lcModelActionObjectEditMode::CreatePieces: case lcModelActionObjectEditMode::CreateCamera: case lcModelActionObjectEditMode::CreateLight: LoadHistoryBuffer(mEndBuffer, Model, true); @@ -395,8 +413,3 @@ lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode : mMode(Mode), mGroupName(GroupName) { } - -lcModelActionDuplicatePieces::lcModelActionDuplicatePieces(lcStep Step) - : mStep(Step) -{ -} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 7e00bd9f..f9a8b371 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -60,6 +60,7 @@ enum class lcModelActionObjectEditMode EditSelectedPieces, EditUnselectedPieces, EditCamera, + CreatePieces, CreateCamera, CreateLight }; @@ -71,7 +72,7 @@ public: virtual ~lcModelActionObjectEdit() = default; bool SaveStartState(const lcModel* Model, const lcCamera* Camera); - bool SaveEndState(const lcModel* Model, const lcCamera* Camera); + bool SaveEndState(const lcModel* Model, std::vector&& ObjectIndices); void LoadStartState(lcModel* Model) const; void LoadEndState(lcModel* Model) const; @@ -157,18 +158,3 @@ protected: lcModelActionGroupPiecesMode mMode; QString mGroupName; }; - -class lcModelActionDuplicatePieces : public lcModelAction -{ -public: - lcModelActionDuplicatePieces(lcStep Step); - virtual ~lcModelActionDuplicatePieces() = default; - - lcStep GetStep() const - { - return mStep; - } - -protected: - lcStep mStep; -}; diff --git a/common/piece.cpp b/common/piece.cpp index 5ada0349..0ce52a9e 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -938,7 +938,6 @@ bool lcPiece::SaveUndoData(QDataStream& Stream) const { static_assert(sizeof(lcPiece) == 376); -// PieceInfo* mPieceInfo; Stream << mFileLine; Stream << mID; @@ -970,13 +969,14 @@ bool lcPiece::SaveUndoData(QDataStream& Stream) const } bool lcPiece::LoadUndoData(QDataStream& Stream) -{ -// SetPieceInfo(Other.mPieceInfo, Other.mID, true, false); - -// PieceInfo* mPieceInfo; +{ Stream >> mFileLine; Stream >> mID; - + + PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(mID.toLatin1(), nullptr, true, false); + + SetPieceInfo(Info, mID, true, false); + // lcGroup* mGroup; Stream >> mColorIndex; From 6334c159a9eb8f79982a9ef5f6952c1b0099d609 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 28 Dec 2025 15:21:09 -0300 Subject: [PATCH 38/93] Removed add piece action. --- common/camera.cpp | 7 +- common/camera.h | 4 +- common/lc_minifigdialog.cpp | 2 + common/lc_model.cpp | 254 ++++++++++++++++-------------------- common/lc_model.h | 9 +- common/lc_modelaction.cpp | 105 +++++++++------ common/lc_modelaction.h | 49 +------ common/light.cpp | 8 +- common/light.h | 4 +- common/object.h | 4 +- common/piece.cpp | 29 ++-- common/piece.h | 4 +- 12 files changed, 223 insertions(+), 256 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index b7a56614..97dbcb69 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -907,9 +907,10 @@ void lcCamera::RemoveKeyFrames() mUpVector.RemoveAllKeys(); } -bool lcCamera::SaveUndoData(QDataStream& Stream) const +bool lcCamera::SaveUndoData(QDataStream& Stream, const lcModel* Model) const { static_assert(sizeof(lcCamera) == 240); + Q_UNUSED(Model); Stream << m_fovy; Stream << m_zNear; @@ -920,8 +921,10 @@ bool lcCamera::SaveUndoData(QDataStream& Stream) const return mPosition.SaveUndoData(Stream) && mTargetPosition.SaveUndoData(Stream) && mUpVector.SaveUndoData(Stream); } -bool lcCamera::LoadUndoData(QDataStream& Stream) +bool lcCamera::LoadUndoData(QDataStream& Stream, const lcModel* Model) { + Q_UNUSED(Model); + Stream >> m_fovy; Stream >> m_zNear; Stream >> m_zFar; diff --git a/common/camera.h b/common/camera.h index 4c44d6b8..faada241 100644 --- a/common/camera.h +++ b/common/camera.h @@ -318,8 +318,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - bool SaveUndoData(QDataStream& Stream) const override; - bool LoadUndoData(QDataStream& Stream) override; + bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const override; + bool LoadUndoData(QDataStream& Stream, const lcModel* Model) override; void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/lc_minifigdialog.cpp b/common/lc_minifigdialog.cpp index 8b43931c..13079adb 100644 --- a/common/lc_minifigdialog.cpp +++ b/common/lc_minifigdialog.cpp @@ -135,6 +135,8 @@ lcMinifigDialog::lcMinifigDialog(QWidget* Parent) mView->GetCamera()->SetViewpoint(lcVector3(0.0f, -270.0f, 90.0f)); mView->ZoomExtents(); + ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setFocus(); + connect(ui->TemplateComboBox, &QComboBox::currentTextChanged, this, &lcMinifigDialog::TemplateComboBoxCurrentTextChanged); connect(ui->TemplateSaveButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateSaveButtonClicked); connect(ui->TemplateDeleteButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateDeleteButtonClicked); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 3a61a7c4..d3460f24 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1793,17 +1793,17 @@ void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjec mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } -void lcModel::EndObjectEditAction(std::vector&& ObjectIndices) +void lcModel::EndObjectEditAction(std::vector&& ObjectIndices, std::vector&& GroupIndices) { if (mActionSequence.empty()) return; - + lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(mActionSequence.back().get()); - + if (!ModelActionObjectEdit) return; - if (!ModelActionObjectEdit->SaveEndState(this, std::move(ObjectIndices))) + if (!ModelActionObjectEdit->SaveEndState(this, std::move(ObjectIndices), std::move(GroupIndices))) mActionSequence.pop_back(); } @@ -1820,84 +1820,6 @@ void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObje SetCurrentStep(mCurrentStep); } -void lcModel::RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode) -{ - std::unique_ptr ModelActionAddPieces = std::make_unique(mCurrentStep, SelectionMode); - - ModelActionAddPieces->SetPieceData(PieceInfoTransforms); - - RunAddPiecesAction(ModelActionAddPieces.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionAddPieces)); -} - -void lcModel::RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply) -{ - if (!ModelActionAddPieces) - return; - - if (Apply) - { - std::vector Pieces; - lcStep Step = ModelActionAddPieces->GetStep(); - - for (const lcModelActionAddPieces::PieceData& PieceData : ModelActionAddPieces->GetPieceData()) - { - PieceInfo* PieceInfo = lcGetPiecesLibrary()->FindPiece(PieceData.PieceId.c_str(), nullptr, true, false); - - if (!PieceInfo) - continue; - - lcPiece* Piece = new lcPiece(PieceInfo); - - Piece->Initialize(PieceData.Transform, Step); - Piece->SetColorIndex(lcGetColorIndex(PieceData.ColorCode)); - Piece->UpdatePosition(Step); - - AddPiece(Piece); - Pieces.push_back(Piece); - } - - if (Pieces.empty()) - return; - - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateInUseCategory(); - - switch (ModelActionAddPieces->GetSelectionMode()) - { - case lcModelActionAddPieceSelectionMode::FocusLast: - ClearSelectionAndSetFocus(Pieces.back(), LC_PIECE_SECTION_POSITION, false); - UpdateTrainTrackConnections(dynamic_cast(Pieces.back()), false); - break; - - case lcModelActionAddPieceSelectionMode::SelectAll: - SetSelectionAndFocus(Pieces, nullptr, 0, false); - break; - - case lcModelActionAddPieceSelectionMode::AddToSelection: - AddToSelection(Pieces, false, true); - break; - } - } - else - { - std::vector>::iterator PieceIt; - lcStep Step = ModelActionAddPieces->GetStep(); - - for (PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ++PieceIt) - if ((*PieceIt)->GetStepShow() > Step) - break; - - for (size_t PieceIndex = 0; PieceIndex < ModelActionAddPieces->GetPieceData().size(); PieceIndex++) - PieceIt = mPieces.erase(--PieceIt); - - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); - gMainWindow->UpdateInUseCategory(); - } -} - void lcModel::RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName) { std::unique_ptr ModelActionGroupPieces = std::make_unique(Mode, GroupName); @@ -1987,8 +1909,6 @@ void lcModel::PerformActionSequence(const std::vector(ModelAction)) RunObjectEditAction(ModelActionObjectEdit, Apply); - else if (const lcModelActionAddPieces* ModelActionAddPieces = dynamic_cast(ModelAction)) - RunAddPiecesAction(ModelActionAddPieces, Apply); else if (const lcModelActionGroupPieces* ModelActionGroupPieces = dynamic_cast(ModelAction)) RunGroupPiecesAction(ModelActionGroupPieces, Apply); }; @@ -2222,7 +2142,7 @@ void lcModel::InsertStep(lcStep Step) Light->InsertTime(Step, 1); - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Insert Step")); SetCurrentStep(mCurrentStep); @@ -2247,7 +2167,7 @@ void lcModel::RemoveStep(lcStep Step) for (const std::unique_ptr& Light : mLights) Light->RemoveTime(Step, 1); - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Remove Step")); SetCurrentStep(mCurrentStep); @@ -2264,6 +2184,11 @@ lcGroup* lcModel::AddGroup(const QString& Prefix, lcGroup* Parent) return Group; } +void lcModel::AddGroup(std::unique_ptr Group, size_t GroupIndex) +{ + mGroups.insert(mGroups.begin() + GroupIndex, std::move(Group)); +} + lcGroup* lcModel::GetGroup(const QString& Name, bool CreateIfMissing) { for (const std::unique_ptr& Group : mGroups) @@ -2712,18 +2637,23 @@ void lcModel::RemovePieces(const std::vector& PieceIndices) gMainWindow->UpdateSelectedObjects(true); } -void lcModel::AddPiece(lcPiece* Piece) +size_t lcModel::AddPiece(lcPiece* Piece) { - for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) + size_t PieceIndex; + + for (PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) { if (mPieces[PieceIndex]->GetStepShow() > Piece->GetStepShow()) { AddPiece(std::unique_ptr(Piece), PieceIndex); - return; + + return PieceIndex; } } - AddPiece(std::unique_ptr(Piece), mPieces.size()); + AddPiece(std::unique_ptr(Piece), PieceIndex); + + return PieceIndex; } void lcModel::AddCamera(std::unique_ptr Camera, size_t CameraIndex) @@ -2975,7 +2905,7 @@ void lcModel::ResetSelectedPiecesPivotPoint() if (Piece->IsSelected()) Piece->ResetPivotPoint(); - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Reset Pivot Point")); UpdateAllViews(); @@ -2998,7 +2928,7 @@ void lcModel::RemoveSelectedObjectsKeyFrames() if (Light->IsSelected()) Light->RemoveKeyFrames(); - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Remove Key Frames")); UpdateAllViews(); @@ -3677,7 +3607,7 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) if (Modified) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Paint")); gMainWindow->UpdateSelectedObjects(false); @@ -3778,7 +3708,7 @@ void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Change Projection")); } @@ -4716,7 +4646,7 @@ void lcModel::HideSelectedPieces() return; } - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Hide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4748,7 +4678,7 @@ void lcModel::HideUnselectedPieces() return; } - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Hide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4780,7 +4710,7 @@ void lcModel::UnhideSelectedPieces() return; } - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Unhide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -4812,7 +4742,7 @@ void lcModel::UnhideAllPieces() return; } - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Unhide Pieces")); gMainWindow->UpdateTimeline(false, true); @@ -5039,12 +4969,12 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) break; case lcTool::Move: - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Move")); break; case lcTool::Rotate: - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Rotate")); break; @@ -5056,7 +4986,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Zoom: if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Zoom")); } break; @@ -5064,7 +4994,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Pan: if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Pan")); } break; @@ -5072,7 +5002,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::RotateView: if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Orbit")); } break; @@ -5080,7 +5010,7 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) case lcTool::Roll: if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Roll")); } break; @@ -5099,11 +5029,31 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece return; BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); - RecordSelectionAction(lcModelActionSelectionMode::Save); - RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::FocusLast); - + lcPiece* Piece = nullptr; + std::vector PieceIndices; + + for (const lcInsertPieceInfo& PieceInfoTransform : PieceInfoTransforms) + { + Piece = new lcPiece(PieceInfoTransform.Info); + + Piece->Initialize(PieceInfoTransform.Transform, mCurrentStep); + Piece->SetColorIndex(PieceInfoTransform.ColorIndex); + Piece->UpdatePosition(mCurrentStep); + + PieceIndices.push_back(AddPiece(Piece)); + } + + EndObjectEditAction(std::move(PieceIndices)); EndActionSequence(tr("Add Piece")); + + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateInUseCategory(); + + ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, false); + + UpdateTrainTrackConnections(Piece, false); } void lcModel::InsertCameraToolClicked(const lcVector3& Position) @@ -5400,7 +5350,7 @@ void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVec if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Zoom")); } @@ -5435,7 +5385,7 @@ void lcModel::LookAt(lcCamera* Camera) if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Look At")); } } @@ -5484,7 +5434,7 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl if (!Camera->IsSimple()) { - EndObjectEditAction(std::vector()); + EndObjectEditAction(); EndActionSequence(tr("Zoom Extents")); } } @@ -5560,9 +5510,12 @@ void lcModel::ShowArrayDialog() QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Array only has 1 element or less, no pieces added.")); return; } - - std::vector PieceInfoTransforms; - + + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); + + std::vector NewPieces; + for (int Step1 = 0; Step1 < Dialog.mCounts[0]; Step1++) { for (int Step2 = 0; Step2 < Dialog.mCounts[1]; Step2++) @@ -5590,23 +5543,32 @@ void lcModel::ShowArrayDialog() Position = lcVector3(ModelWorld.r[3].x, ModelWorld.r[3].y, ModelWorld.r[3].z); ModelWorld.SetTranslation(Position + Offset); - - lcInsertPieceInfo& InsertPieceInfo = PieceInfoTransforms.emplace_back(); - - InsertPieceInfo.Info = Piece->mPieceInfo; - InsertPieceInfo.Transform = ModelWorld; - InsertPieceInfo.ColorIndex = Piece->GetColorIndex(); + + lcPiece* NewPiece = new lcPiece(nullptr); + NewPiece->SetPieceInfo(Piece->mPieceInfo, Piece->GetID(), true, true); + NewPiece->Initialize(ModelWorld, mCurrentStep); + NewPiece->SetColorIndex(Piece->GetColorIndex()); + + NewPieces.emplace_back(NewPiece); } } } } - - BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Save); - RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::AddToSelection); - + + std::vector PieceIndices; + + for (size_t PieceIdx = 0; PieceIdx < NewPieces.size(); PieceIdx++) + { + lcPiece* Piece = (lcPiece*)NewPieces[PieceIdx]; + Piece->UpdatePosition(mCurrentStep); + PieceIndices.push_back(AddPiece(Piece)); + } + + EndObjectEditAction(std::move(PieceIndices)); EndActionSequence(tr("Piece Array")); + + AddToSelection(NewPieces, false, true); + gMainWindow->UpdateTimeline(false, false); } void lcModel::ShowMinifigDialog() @@ -5617,29 +5579,39 @@ void lcModel::ShowMinifigDialog() return; gMainWindow->GetActiveView()->MakeCurrent(); - - std::vector PieceInfoTransforms; + + BeginActionSequence(); + BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); + + lcGroup* Group = AddGroup(tr("Minifig #"), nullptr); + std::vector Pieces; + std::vector PieceIndices; lcMinifig& Minifig = Dialog.mMinifigWizard->mMinifig; - + + Pieces.reserve(LC_MFW_NUMITEMS); + PieceIndices.reserve(LC_MFW_NUMITEMS); + for (int PartIndex = 0; PartIndex < LC_MFW_NUMITEMS; PartIndex++) { if (!Minifig.Parts[PartIndex]) continue; - - lcInsertPieceInfo& InsertPieceInfo = PieceInfoTransforms.emplace_back(); - - InsertPieceInfo.Info = Minifig.Parts[PartIndex]; - InsertPieceInfo.Transform = Minifig.Matrices[PartIndex]; - InsertPieceInfo.ColorIndex = Minifig.ColorIndices[PartIndex]; + + lcPiece* Piece = new lcPiece(Minifig.Parts[PartIndex]); + + Piece->Initialize(Minifig.Matrices[PartIndex], mCurrentStep); + Piece->SetColorIndex(Minifig.ColorIndices[PartIndex]); + Piece->SetGroup(Group); + PieceIndices.push_back(AddPiece(Piece)); + Piece->UpdatePosition(mCurrentStep); + + Pieces.emplace_back(Piece); } - - BeginActionSequence(); - - RecordSelectionAction(lcModelActionSelectionMode::Save); - RecordAddPiecesAction(PieceInfoTransforms, lcModelActionAddPieceSelectionMode::SelectAll); - RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, GetGroupName(tr("Minifig #"))); - + + EndObjectEditAction(std::move(PieceIndices), { mGroups.size() - 1}); EndActionSequence(tr("Add Minifig")); + + SetSelectionAndFocus(Pieces, nullptr, 0, false); + gMainWindow->UpdateTimeline(false, false); } void lcModel::SetMinifig(const lcMinifig& Minifig) diff --git a/common/lc_model.h b/common/lc_model.h index 352c3133..cf699d3d 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -7,10 +7,8 @@ enum class lcObjectPropertyId; class lcModelAction; class lcModelActionSelection; class lcModelActionObjectEdit; -class lcModelActionAddPieces; class lcModelActionGroupPieces; enum class lcModelActionSelectionMode; -enum class lcModelActionAddPieceSelectionMode; enum class lcModelActionObjectEditMode; enum class lcModelActionGroupPiecesMode; @@ -255,6 +253,7 @@ public: void InlineSelectedModels(); lcGroup* AddGroup(const QString& Prefix, lcGroup* Parent); + void AddGroup(std::unique_ptr Group, size_t GroupIndex); lcGroup* GetGroup(const QString& Name, bool CreateIfMissing); void RemoveGroup(lcGroup* Group); void GroupSelection(); @@ -411,10 +410,8 @@ protected: void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); - void EndObjectEditAction(std::vector&& ObjectIndices); + void EndObjectEditAction(std::vector&& ObjectIndices = std::vector(), std::vector&& GroupIndices = std::vector()); void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); - void RecordAddPiecesAction(const std::vector& PieceInfoTransforms, lcModelActionAddPieceSelectionMode SelectionMode); - void RunAddPiecesAction(const lcModelActionAddPieces* ModelActionAddPieces, bool Apply); void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); @@ -434,7 +431,7 @@ protected: void SelectGroup(lcGroup* TopGroup, bool Select); - void AddPiece(lcPiece* Piece); + size_t AddPiece(lcPiece* Piece); lcPOVRayOptions mPOVRayOptions; lcModelProperties mProperties; diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 83001319..f85660ef 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -4,32 +4,46 @@ #include "piece.h" #include "camera.h" #include "light.h" -#include "pieceinf.h" -#include "lc_colors.h" +#include "group.h" bool lcModelAction::SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model) { QDataStream Stream(&Buffer, QIODevice::WriteOnly); - + + const std::vector>& Groups = Model->GetGroups(); const std::vector>& Pieces = Model->GetPieces(); const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - uint64_t ObjectCount[3] = { Pieces.size(), Cameras.size(), Lights.size() }; + uint64_t ObjectCount[4] = { Groups.size(), Pieces.size(), Cameras.size(), Lights.size() }; if (Stream.writeRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) return false; + for (size_t GroupIndex : mGroupIndices) + { + const lcGroup* Group = Groups[GroupIndex].get(); + uint64_t ParentIndex = UINT64_MAX; + + if (Group->mGroup) + for (ParentIndex = 0; ParentIndex < Groups.size(); ParentIndex++) + if (Group->mGroup == Groups[ParentIndex].get()) + break; + + Stream << Group->mName; + Stream << ParentIndex; + } + for (size_t PieceIndex : mPieceIndices) - if (!Pieces[PieceIndex]->SaveUndoData(Stream)) + if (!Pieces[PieceIndex]->SaveUndoData(Stream, Model)) return false; for (size_t CameraIndex : mCameraIndices) - if (!Cameras[CameraIndex]->SaveUndoData(Stream)) + if (!Cameras[CameraIndex]->SaveUndoData(Stream, Model)) return false; for (size_t LightIndex : mLightIndices) - if (!Lights[LightIndex]->SaveUndoData(Stream)) + if (!Lights[LightIndex]->SaveUndoData(Stream, Model)) return false; return true; @@ -38,28 +52,45 @@ bool lcModelAction::SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model) bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const { QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); - + + const std::vector>& Groups = Model->GetGroups(); const std::vector>& Pieces = Model->GetPieces(); const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - uint64_t ObjectCount[3]; + uint64_t ObjectCount[4]; if (Stream.readRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) return false; if (CreateObjects) { - ObjectCount[0] -= mPieceIndices.size(); - ObjectCount[1] -= mCameraIndices.size(); - ObjectCount[2] -= mLightIndices.size(); + ObjectCount[0] -= mGroupIndices.size(); + ObjectCount[1] -= mPieceIndices.size(); + ObjectCount[2] -= mCameraIndices.size(); + ObjectCount[3] -= mLightIndices.size(); } - if (ObjectCount[0] != Pieces.size() || ObjectCount[1] != Cameras.size() || ObjectCount[2] != Lights.size()) + if (ObjectCount[0] != Groups.size() || ObjectCount[1] != Pieces.size() || ObjectCount[2] != Cameras.size() || ObjectCount[3] != Lights.size()) return false; if (CreateObjects) { + for (size_t GroupIndex : mGroupIndices) + { + std::unique_ptr Group(new lcGroup()); + QString Name; + uint64_t ParentIndex; + + Stream >> Name; + Stream >> ParentIndex; + + Group->mName = Name; + Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; + + Model->AddGroup(std::move(Group), GroupIndex); + } + for (size_t PieceIndex : mPieceIndices) { if (PieceIndex > Pieces.size()) @@ -67,7 +98,7 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, std::unique_ptr Piece(new lcPiece(nullptr)); - if (!Piece->LoadUndoData(Stream)) + if (!Piece->LoadUndoData(Stream, Model)) return false; Model->AddPiece(std::move(Piece), PieceIndex); @@ -80,7 +111,7 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, std::unique_ptr Camera(new lcCamera(false)); - if (!Camera->LoadUndoData(Stream)) + if (!Camera->LoadUndoData(Stream, Model)) return false; Model->AddCamera(std::move(Camera), CameraIndex); @@ -93,7 +124,7 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, std::unique_ptr Light(new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point)); - if (!Light->LoadUndoData(Stream)) + if (!Light->LoadUndoData(Stream, Model)) return false; Model->AddLight(std::move(Light), LightIndex); @@ -101,6 +132,19 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, } else { + for (size_t GroupIndex : mGroupIndices) + { + lcGroup* Group = Groups[GroupIndex].get(); + QString Name; + uint64_t ParentIndex; + + Stream >> Name; + Stream >> ParentIndex; + + Group->mName = Name; + Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; + } + for (size_t PieceIndex : mPieceIndices) { if (PieceIndex >= Pieces.size()) @@ -108,7 +152,7 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, const std::unique_ptr& Piece = Pieces[PieceIndex]; - if (!Piece->LoadUndoData(Stream)) + if (!Piece->LoadUndoData(Stream, Model)) return false; } @@ -119,7 +163,7 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, const std::unique_ptr& Camera = Cameras[CameraIndex]; - if (!Camera->LoadUndoData(Stream)) + if (!Camera->LoadUndoData(Stream, Model)) return false; } @@ -130,7 +174,7 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, const std::unique_ptr& Light = Lights[LightIndex]; - if (!Light->LoadUndoData(Stream)) + if (!Light->LoadUndoData(Stream, Model)) return false; } } @@ -313,7 +357,7 @@ bool lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamer return SaveHistoryBuffer(mStartBuffer, Model); } -bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector&& ObjectIndices) +bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices) { switch (mMode) { @@ -327,6 +371,7 @@ bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector& PieceInfoTransforms) -{ - mPieceData.clear(); - mPieceData.reserve(PieceInfoTransforms.size()); - - for (const lcInsertPieceInfo& PieceInfoTransform : PieceInfoTransforms) - { - lcModelActionAddPieces::PieceData& PieceData = mPieceData.emplace_back(); - - PieceData.PieceId = PieceInfoTransform.Info->mFileName; - PieceData.Transform = PieceInfoTransform.Transform; - PieceData.ColorCode = lcGetColorCode(PieceInfoTransform.ColorIndex); - } -} - lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName) : mMode(Mode), mGroupName(GroupName) { diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index f9a8b371..96d17c04 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -1,8 +1,5 @@ #pragma once -#include "lc_math.h" - -struct lcInsertPieceInfo; enum class lcObjectType; class lcModelAction @@ -15,6 +12,7 @@ protected: bool SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model); bool LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const; + std::vector mGroupIndices; std::vector mPieceIndices; std::vector mCameraIndices; std::vector mLightIndices; @@ -72,7 +70,7 @@ public: virtual ~lcModelActionObjectEdit() = default; bool SaveStartState(const lcModel* Model, const lcCamera* Camera); - bool SaveEndState(const lcModel* Model, std::vector&& ObjectIndices); + bool SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices); void LoadStartState(lcModel* Model) const; void LoadEndState(lcModel* Model) const; @@ -89,49 +87,6 @@ protected: QByteArray mEndBuffer; }; -enum class lcModelActionAddPieceSelectionMode -{ - FocusLast, - SelectAll, - AddToSelection -}; - -class lcModelActionAddPieces : public lcModelAction -{ -public: - lcModelActionAddPieces(lcStep Step, lcModelActionAddPieceSelectionMode SelectionMode); - virtual ~lcModelActionAddPieces() = default; - - struct PieceData - { - std::string PieceId; - lcMatrix44 Transform; - quint32 ColorCode; - }; - - void SetPieceData(const std::vector& PieceInfoTransforms); - - const std::vector& GetPieceData() const - { - return mPieceData; - } - - lcStep GetStep() const - { - return mStep; - } - - lcModelActionAddPieceSelectionMode GetSelectionMode() const - { - return mSelectionMode; - } - -protected: - std::vector mPieceData; - lcStep mStep; - lcModelActionAddPieceSelectionMode mSelectionMode; -}; - enum class lcModelActionGroupPiecesMode { Group, diff --git a/common/light.cpp b/common/light.cpp index aaf0317f..40eef7e2 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1,6 +1,5 @@ #include "lc_global.h" #include "lc_math.h" -#include "lc_colors.h" #include #include #include @@ -1530,9 +1529,10 @@ void lcLight::RemoveKeyFrames() mPOVRayFadePower.RemoveAllKeys(); } -bool lcLight::SaveUndoData(QDataStream& Stream) const +bool lcLight::SaveUndoData(QDataStream& Stream, const lcModel* Model) const { static_assert(sizeof(lcLight) == 704); + Q_UNUSED(Model); Stream << mName; Stream << mLightType; @@ -1548,8 +1548,10 @@ bool lcLight::SaveUndoData(QDataStream& Stream) const mPOVRayFadePower.SaveUndoData(Stream); } -bool lcLight::LoadUndoData(QDataStream& Stream) +bool lcLight::LoadUndoData(QDataStream& Stream, const lcModel* Model) { + Q_UNUSED(Model); + Stream >> mName; Stream >> mLightType; Stream >> mCastShadow; diff --git a/common/light.h b/common/light.h index b1dd23e9..91497b11 100644 --- a/common/light.h +++ b/common/light.h @@ -220,8 +220,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - bool SaveUndoData(QDataStream& Stream) const override; - bool LoadUndoData(QDataStream& Stream) override; + bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const override; + bool LoadUndoData(QDataStream& Stream, const lcModel* Model) override; void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/object.h b/common/object.h index c71688f3..71aa2c4a 100644 --- a/common/object.h +++ b/common/object.h @@ -107,8 +107,8 @@ public: virtual bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const = 0; virtual bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) = 0; virtual void RemoveKeyFrames() = 0; - virtual bool SaveUndoData(QDataStream& Stream) const = 0; - virtual bool LoadUndoData(QDataStream& Stream) = 0; + virtual bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const = 0; + virtual bool LoadUndoData(QDataStream& Stream, const lcModel* Model) = 0; virtual QString GetName() const = 0; static QString GetCheckpointString(lcObjectPropertyId PropertyId); diff --git a/common/piece.cpp b/common/piece.cpp index 0ce52a9e..4ad10d5a 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -16,6 +16,7 @@ #include "lc_synth.h" #include "lc_traintrack.h" #include "lc_string.h" +#include "lc_model.h" constexpr float LC_PIECE_CONTROL_POINT_SIZE = 10.0f; @@ -934,15 +935,22 @@ void lcPiece::RemoveKeyFrames() mRotation.RemoveAllKeys(); } -bool lcPiece::SaveUndoData(QDataStream& Stream) const +bool lcPiece::SaveUndoData(QDataStream& Stream, const lcModel* Model) const { static_assert(sizeof(lcPiece) == 376); Stream << mFileLine; Stream << mID; - -// lcGroup* mGroup; - + + const std::vector>& Groups = Model->GetGroups(); + uint64_t ParentIndex = UINT64_MAX; + + if (mGroup) + for (ParentIndex = 0; ParentIndex < Groups.size(); ParentIndex++) + if (mGroup == Groups[ParentIndex].get()) + break; + + Stream << ParentIndex; Stream << mColorIndex; Stream << mColorCode; @@ -963,12 +971,10 @@ bool lcPiece::SaveUndoData(QDataStream& Stream) const if (Stream.writeRawData(reinterpret_cast(mControlPoints.data()), DataSize) != DataSize) return false; -// std::vector mTrainTrackConnections; - return mPosition.SaveUndoData(Stream) && mRotation.SaveUndoData(Stream); } -bool lcPiece::LoadUndoData(QDataStream& Stream) +bool lcPiece::LoadUndoData(QDataStream& Stream, const lcModel* Model) { Stream >> mFileLine; Stream >> mID; @@ -977,8 +983,13 @@ bool lcPiece::LoadUndoData(QDataStream& Stream) SetPieceInfo(Info, mID, true, false); -// lcGroup* mGroup; - + const std::vector>& Groups = Model->GetGroups(); + uint64_t ParentIndex; + + Stream >> ParentIndex; + + mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; + Stream >> mColorIndex; Stream >> mColorCode; diff --git a/common/piece.h b/common/piece.h index 1410dcdb..7523a06f 100644 --- a/common/piece.h +++ b/common/piece.h @@ -116,8 +116,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - bool SaveUndoData(QDataStream& Stream) const override; - bool LoadUndoData(QDataStream& Stream) override; + bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const override; + bool LoadUndoData(QDataStream& Stream, const lcModel* Model) override; void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const; void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const; From 11d51c95d17394e81951d198bb8ba165268a6462 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Wed, 31 Dec 2025 10:07:25 -0300 Subject: [PATCH 39/93] Don't allow duplicate group names. --- common/lc_groupdialog.cpp | 15 ++++++++++++--- common/lc_groupdialog.h | 3 ++- common/lc_model.cpp | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/common/lc_groupdialog.cpp b/common/lc_groupdialog.cpp index fbe0ed77..fd4cf056 100644 --- a/common/lc_groupdialog.cpp +++ b/common/lc_groupdialog.cpp @@ -3,8 +3,8 @@ #include "ui_lc_groupdialog.h" #include "group.h" -lcGroupDialog::lcGroupDialog(QWidget* Parent, const QString& Name) - : QDialog(Parent), ui(new Ui::lcGroupDialog) +lcGroupDialog::lcGroupDialog(QWidget* Parent, const QString& Name, const std::vector>& Groups) + : QDialog(Parent), mGroups(Groups), ui(new Ui::lcGroupDialog) { ui->setupUi(this); @@ -25,7 +25,16 @@ void lcGroupDialog::accept() QMessageBox::information(this, "LeoCAD", tr("Name cannot be empty.")); return; } - + + for (const std::unique_ptr& Group : mGroups) + { + if (Group->mName == Name) + { + QMessageBox::information(this, "LeoCAD", tr("A group with this name already exists.")); + return; + } + } + mName = Name; QDialog::accept(); diff --git a/common/lc_groupdialog.h b/common/lc_groupdialog.h index 0968626a..5de6b576 100644 --- a/common/lc_groupdialog.h +++ b/common/lc_groupdialog.h @@ -11,7 +11,7 @@ class lcGroupDialog : public QDialog Q_OBJECT public: - explicit lcGroupDialog(QWidget* Parent, const QString& Name); + explicit lcGroupDialog(QWidget* Parent, const QString& Name, const std::vector>& Groups); ~lcGroupDialog(); QString mName; @@ -20,5 +20,6 @@ public slots: void accept() override; private: + const std::vector>& mGroups; Ui::lcGroupDialog *ui; }; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index d3460f24..bfeb8851 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2227,7 +2227,7 @@ void lcModel::GroupSelection() return; } - lcGroupDialog Dialog(gMainWindow, GetGroupName(tr("Group #"))); + lcGroupDialog Dialog(gMainWindow, GetGroupName(tr("Group #")), mGroups); if (Dialog.exec() != QDialog::Accepted) return; From 75ac6fe0cb012fecc91c12bbdda0b67c8dfafe4d Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 3 Jan 2026 10:14:45 -0300 Subject: [PATCH 40/93] Removed unused SetSelected override. --- common/camera.h | 27 --------------------------- common/lc_model.cpp | 6 +----- common/light.h | 10 ---------- common/object.h | 1 - common/piece.h | 10 ---------- 5 files changed, 1 insertion(+), 53 deletions(-) diff --git a/common/camera.h b/common/camera.h index faada241..f9d82f70 100644 --- a/common/camera.h +++ b/common/camera.h @@ -126,33 +126,6 @@ public: mState &= ~(LC_CAMERA_SELECTION_MASK | LC_CAMERA_FOCUS_MASK); } - void SetSelected(quint32 Section, bool Selected) override - { - switch (Section) - { - case LC_CAMERA_SECTION_POSITION: - if (Selected) - mState |= LC_CAMERA_POSITION_SELECTED; - else - mState &= ~(LC_CAMERA_POSITION_SELECTED | LC_CAMERA_POSITION_FOCUSED); - break; - - case LC_CAMERA_SECTION_TARGET: - if (Selected) - mState |= LC_CAMERA_TARGET_SELECTED; - else - mState &= ~(LC_CAMERA_TARGET_SELECTED | LC_CAMERA_TARGET_FOCUSED); - break; - - case LC_CAMERA_SECTION_UPVECTOR: - if (Selected) - mState |= LC_CAMERA_UPVECTOR_SELECTED; - else - mState &= ~(LC_CAMERA_UPVECTOR_SELECTED | LC_CAMERA_UPVECTOR_FOCUSED); - break; - } - } - bool IsFocused() const override { return (mState & LC_CAMERA_FOCUS_MASK) != 0; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index bfeb8851..9119050f 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -4569,11 +4569,7 @@ void lcModel::RemoveFromSelection(const lcObjectSection& ObjectSection) const bool WasSelected = SelectedObject->IsSelected(); - if (SelectedObject->IsFocused(ObjectSection.Section)) - SelectedObject->SetSelected(ObjectSection.Section, false); - else - SelectedObject->SetSelected(false); - + SelectedObject->SetSelected(false); if (SelectedObject->IsPiece() && WasSelected) { diff --git a/common/light.h b/common/light.h index 91497b11..4ad7f45f 100644 --- a/common/light.h +++ b/common/light.h @@ -96,16 +96,6 @@ public: mFocusedSection = LC_LIGHT_SECTION_INVALID; } - void SetSelected(quint32 Section, bool Selected) override - { - Q_UNUSED(Section); - - mSelected = Selected; - - if (!Selected) - mFocusedSection = LC_LIGHT_SECTION_INVALID; - } - bool IsFocused() const override { return mFocusedSection != LC_LIGHT_SECTION_INVALID; diff --git a/common/object.h b/common/object.h index 71aa2c4a..27e189d3 100644 --- a/common/object.h +++ b/common/object.h @@ -90,7 +90,6 @@ public: virtual bool IsSelected() const = 0; virtual bool IsSelected(quint32 Section) const = 0; virtual void SetSelected(bool Selected) = 0; - virtual void SetSelected(quint32 Section, bool Selected) = 0; virtual bool IsFocused() const = 0; virtual bool IsFocused(quint32 Section) const = 0; virtual void SetFocused(quint32 Section, bool Focused) = 0; diff --git a/common/piece.h b/common/piece.h index 7523a06f..476c1fb0 100644 --- a/common/piece.h +++ b/common/piece.h @@ -56,16 +56,6 @@ public: mFocusedSection = LC_PIECE_SECTION_INVALID; } - void SetSelected(quint32 Section, bool Selected) override - { - Q_UNUSED(Section); - - mSelected = Selected; - - if (!Selected) - mFocusedSection = LC_PIECE_SECTION_INVALID; - } - bool IsFocused() const override { return mFocusedSection != LC_PIECE_SECTION_INVALID; From f69166cf3d49060e9e8a206f14e2cae704a1c2aa Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 10 Jan 2026 11:00:39 -0800 Subject: [PATCH 41/93] Undo some selection actions. --- common/lc_mainwindow.cpp | 4 +- common/lc_model.cpp | 150 ++++++++++++++++++++++++++------------ common/lc_model.h | 11 +-- common/lc_modelaction.cpp | 4 +- common/lc_modelaction.h | 16 +++- common/lc_view.cpp | 2 +- 6 files changed, 127 insertions(+), 60 deletions(-) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 63a83647..c9ba555b 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2784,12 +2784,12 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_EDIT_SELECT_NONE: if (ActiveModel) - ActiveModel->ClearSelection(true); + ActiveModel->ClearSelection(); break; case LC_EDIT_SELECT_INVERT: if (ActiveModel) - ActiveModel->InvertSelection(); + ActiveModel->InvertPieceSelection(); break; case LC_EDIT_SELECT_BY_NAME: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 9119050f..e50aff96 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1734,12 +1734,10 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode) { - std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode); + std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode, mCurrentStep); ModelActionSelection->SetSelection(mPieces, mCameras, mLights); - RunSelectionAction(ModelActionSelection.get(), true); - mActionSequence.emplace_back(std::move(ModelActionSelection)); } @@ -1757,9 +1755,31 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect switch (ModelActionSelection->GetMode()) { - case lcModelActionSelectionMode::Clear: + case lcModelActionSelectionMode::ClearSelection: if (Apply) - ClearSelection(true); + DeselectAllObjects(); + else + LoadSelection(); + break; + + case lcModelActionSelectionMode::SelectAllPieces: + if (Apply) + { + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsVisible(ModelActionSelection->GetStep())) + Piece->SetSelected(true); + } + else + LoadSelection(); + break; + + case lcModelActionSelectionMode::InvertPieceSelection: + if (Apply) + { + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsVisible(ModelActionSelection->GetStep())) + Piece->SetSelected(!Piece->IsSelected()); + } else LoadSelection(); break; @@ -1824,8 +1844,6 @@ void lcModel::RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const Q { std::unique_ptr ModelActionGroupPieces = std::make_unique(Mode, GroupName); - RunGroupPiecesAction(ModelActionGroupPieces.get(), true); - mActionSequence.emplace_back(std::move(ModelActionGroupPieces)); } @@ -1901,12 +1919,18 @@ void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGr gMainWindow->UpdateSelectedObjects(true); } -void lcModel::PerformActionSequence(const std::vector>& ActionSequence, bool Apply) +void lcModel::RunActionSequence(const std::vector>& ActionSequence, bool Apply) { - auto PerformAction=[this](const lcModelAction* ModelAction, bool Apply) + bool SelectionChanged = false; + + auto RunAction=[this, &SelectionChanged](const lcModelAction* ModelAction, bool Apply) { if (const lcModelActionSelection* ModelActionSelection = dynamic_cast(ModelAction)) + { RunSelectionAction(ModelActionSelection, Apply); + + SelectionChanged = true; + } else if (const lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(ModelAction)) RunObjectEditAction(ModelActionObjectEdit, Apply); else if (const lcModelActionGroupPieces* ModelActionGroupPieces = dynamic_cast(ModelAction)) @@ -1916,13 +1940,16 @@ void lcModel::PerformActionSequence(const std::vectorget(), true); + RunAction(ModelAction->get(), true); } else { for (auto ModelAction = ActionSequence.rbegin(); ModelAction != ActionSequence.rend(); ++ModelAction) - PerformAction(ModelAction->get(), false); + RunAction(ModelAction->get(), false); } + + if (SelectionChanged) + gMainWindow->UpdateSelectedObjects(true); UpdateAllViews(); } @@ -1934,6 +1961,11 @@ void lcModel::BeginActionSequence() void lcModel::EndActionSequence(const QString& Description) { + if (mActionSequence.empty()) + return; + + RunActionSequence(mActionSequence, true); + std::unique_ptr ModelHistoryEntry = std::make_unique(lcModelHistoryEntry()); ModelHistoryEntry->Description = Description; @@ -1953,7 +1985,7 @@ void lcModel::DiscardActionSequence() void lcModel::RevertActionSequence() { - PerformActionSequence(mActionSequence, false); + RunActionSequence(mActionSequence, false); mActionSequence.clear(); } @@ -1985,7 +2017,7 @@ void lcModel::LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply) { if (!CheckPoint->ModelActions.empty()) { - PerformActionSequence(CheckPoint->ModelActions, Apply); + RunActionSequence(CheckPoint->ModelActions, Apply); return; } @@ -2362,7 +2394,8 @@ void lcModel::ShowEditGroupsDialog() if (Modified) { - ClearSelection(true); + DeselectAllObjects(); + gMainWindow->UpdateSelectedObjects(true); SaveCheckpoint(tr("Editing Groups")); } } @@ -4373,22 +4406,68 @@ std::vector lcModel::GetSelectionModePieces(const lcPiece* SelectedPi return Pieces; } -void lcModel::ClearSelection(bool UpdateInterface) +void lcModel::ClearSelection() +{ + if (!AnyObjectsSelected()) + return; + + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelection); + EndActionSequence(tr("Selection")); +} + +void lcModel::SelectAllPieces() +{ + bool UnselectedPieces = false; + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsVisible(mCurrentStep) && !Piece->IsSelected()) + { + UnselectedPieces = true; + break; + } + } + + if (!UnselectedPieces) + return; + + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::SelectAllPieces); + EndActionSequence(tr("Selection")); +} + +void lcModel::InvertPieceSelection() +{ + bool VisiblePieces = false; + + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsVisible(mCurrentStep)) + { + VisiblePieces = true; + break; + } + } + + if (!VisiblePieces) + return; + + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::InvertPieceSelection); + EndActionSequence(tr("Selection")); +} + +void lcModel::DeselectAllObjects() { for (const std::unique_ptr& Piece : mPieces) Piece->SetSelected(false); - + for (const std::unique_ptr& Camera : mCameras) Camera->SetSelected(false); - + for (const std::unique_ptr& Light : mLights) Light->SetSelected(false); - - if (UpdateInterface) - { - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - } } void lcModel::SelectGroup(lcGroup* TopGroup, bool Select) @@ -4448,7 +4527,7 @@ void lcModel::FocusOrDeselectObject(const lcObjectSection& ObjectSection) void lcModel::ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool EnableSelectionMode) { - ClearSelection(false); + DeselectAllObjects(); if (Object) { @@ -4479,7 +4558,7 @@ void lcModel::ClearSelectionAndSetFocus(const lcObjectSection& ObjectSection, bo void lcModel::SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode) { - ClearSelection(false); + DeselectAllObjects(); if (Focus) { @@ -4596,27 +4675,6 @@ void lcModel::RemoveFromSelection(const lcObjectSection& ObjectSection) UpdateAllViews(); } -void lcModel::SelectAllPieces() -{ - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(true); - - if (!mIsPreview) - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); -} - -void lcModel::InvertSelection() -{ - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(!Piece->IsSelected()); - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); -} - void lcModel::HideSelectedPieces() { BeginActionSequence(); diff --git a/common/lc_model.h b/common/lc_model.h index cf699d3d..bd38ce8f 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -323,17 +323,17 @@ public: void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector& ModelParts) const; void GetSelectionInformation(int* Flags, std::vector& Selection, lcObject** Focus) const; std::vector GetSelectionModePieces(const lcPiece* SelectedPiece) const; - + + void ClearSelection(); + void SelectAllPieces(); + void InvertPieceSelection(); void FocusOrDeselectObject(const lcObjectSection& ObjectSection); - void ClearSelection(bool UpdateInterface); void ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool EnableSelectionMode); void ClearSelectionAndSetFocus(const lcObjectSection& ObjectSection, bool EnableSelectionMode); void SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode); void AddToSelection(const std::vector& Objects, bool EnableSelectionMode, bool UpdateInterface); void RemoveFromSelection(const std::vector& Objects); void RemoveFromSelection(const lcObjectSection& ObjectSection); - void SelectAllPieces(); - void InvertSelection(); void HideSelectedPieces(); void HideUnselectedPieces(); @@ -415,7 +415,7 @@ protected: void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); - void PerformActionSequence(const std::vector>& ActionSequence, bool Apply); + void RunActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); void EndActionSequence(const QString& Description); void DiscardActionSequence(); @@ -429,6 +429,7 @@ protected: bool RemoveSelectedObjects(); void RemoveCameraFromViews(lcCamera* Camera); + void DeselectAllObjects(); void SelectGroup(lcGroup* TopGroup, bool Select); size_t AddPiece(lcPiece* Piece); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index f85660ef..7ecdc9f2 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -182,8 +182,8 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, return true; } -lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode) - : mMode(Mode) +lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode, lcStep Step) + : mMode(Mode), mStep(Step) { } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 96d17c04..2268d30d 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -20,7 +20,9 @@ protected: enum class lcModelActionSelectionMode { - Clear, + ClearSelection, + SelectAllPieces, + InvertPieceSelection, Set, Save, Restore @@ -29,14 +31,19 @@ enum class lcModelActionSelectionMode class lcModelActionSelection : public lcModelAction { public: - lcModelActionSelection(lcModelActionSelectionMode Mode); + lcModelActionSelection(lcModelActionSelectionMode Mode, lcStep Step); virtual ~lcModelActionSelection() = default; lcModelActionSelectionMode GetMode() const { return mMode; } - + + lcStep GetStep() const + { + return mStep; + } + void SetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights); std::tuple, lcObject*, uint32_t> GetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) const; @@ -47,7 +54,8 @@ protected: size_t mFocusIndex = SIZE_MAX; uint32_t mFocusSection = 0; lcObjectType mFocusType = (lcObjectType)0; - lcModelActionSelectionMode mMode = lcModelActionSelectionMode::Clear; + lcModelActionSelectionMode mMode; + lcStep mStep; }; enum class lcModelActionObjectEditMode diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 76702dd6..bafd34bb 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2494,7 +2494,7 @@ void lcView::CancelTrackingOrClearSelection() { lcModel* ActiveModel = GetActiveModel(); if (ActiveModel) - ActiveModel->ClearSelection(true); + ActiveModel->ClearSelection(); } } From a018b166c5fc09e27fc5e06cbd4e1538778952fc Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 10 Jan 2026 20:06:16 -0800 Subject: [PATCH 42/93] Added action for ClearSelectionAndSetFocus. --- common/lc_model.cpp | 206 ++++++++++++++++++------------------ common/lc_model.h | 13 +-- common/lc_modelaction.cpp | 215 +++++++++++++++++++++++++++++++++----- common/lc_modelaction.h | 40 +++++-- common/lc_view.cpp | 6 +- 5 files changed, 330 insertions(+), 150 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index e50aff96..23fe8f1d 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1230,7 +1230,8 @@ void lcModel::Paste(bool PasteToCurrentStep) SaveCheckpoint(tr("Pasting")); if (SelectedObjects.size() == 1) - ClearSelectionAndSetFocus(SelectedObjects[0], LC_PIECE_SECTION_POSITION, false); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); +// ClearSelectionAndSetFocus(SelectedObjects[0], LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); else SetSelectionAndFocus(SelectedObjects, nullptr, 0, false); @@ -1732,13 +1733,12 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v Piece->SubModelAddBoundingBoxPoints(WorldMatrix, Points); } -void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode) +void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) { std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode, mCurrentStep); - ModelActionSelection->SetSelection(mPieces, mCameras, mLights); - - mActionSequence.emplace_back(std::move(ModelActionSelection)); + if (ModelActionSelection->Initialize(this, FocusObject, FocusSection, SelectionMode)) + mActionSequence.emplace_back(std::move(ModelActionSelection)); } void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply) @@ -1752,7 +1752,9 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); }; - + + lcStep Step = ModelActionSelection->GetStep(); + switch (ModelActionSelection->GetMode()) { case lcModelActionSelectionMode::ClearSelection: @@ -1761,12 +1763,38 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect else LoadSelection(); break; + + case lcModelActionSelectionMode::ClearSelectionAndSetFocus: + if (Apply) + { + DeselectAllObjects(); + + lcObject* NewFocusObject = ModelActionSelection->GetNewFocusObject(this); + + if (NewFocusObject) + { + NewFocusObject->SetFocused(ModelActionSelection->GetNewFocusSection(), true); + + if (NewFocusObject->IsPiece()) + { + lcPiece* Piece = dynamic_cast(NewFocusObject); + + SelectGroup(Piece->GetTopGroup(), Step, true); + + std::vector Pieces = GetSelectionModePieces(ModelActionSelection->GetSelectionMode(), Piece, Step); + SelectObjects(Pieces, Step); + } + } + } + else + LoadSelection(); + break; case lcModelActionSelectionMode::SelectAllPieces: if (Apply) { for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(ModelActionSelection->GetStep())) + if (Piece->IsVisible(Step)) Piece->SetSelected(true); } else @@ -1777,7 +1805,7 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect if (Apply) { for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(ModelActionSelection->GetStep())) + if (Piece->IsVisible(Step)) Piece->SetSelected(!Piece->IsSelected()); } else @@ -2088,7 +2116,7 @@ void lcModel::CalculateStep(lcStep Step) if (!Piece->IsVisible(Step)) Piece->SetSelected(false); else - SelectGroup(Piece->GetTopGroup(), true); + SelectGroup(Piece->GetTopGroup(), Step, true); } } @@ -2266,9 +2294,9 @@ void lcModel::GroupSelection() BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordSelectionAction(lcModelActionSelectionMode::Restore, nullptr, 0, lcSelectionMode::Single); RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, Dialog.mName); - RecordSelectionAction(lcModelActionSelectionMode::Save); + RecordSelectionAction(lcModelActionSelectionMode::Save, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Group")); } @@ -2300,9 +2328,9 @@ void lcModel::UngroupSelection() BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore); + RecordSelectionAction(lcModelActionSelectionMode::Restore, nullptr, 0, lcSelectionMode::Single); RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Ungroup, QString()); - RecordSelectionAction(lcModelActionSelectionMode::Save); + RecordSelectionAction(lcModelActionSelectionMode::Save, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Ungroup")); } @@ -2628,7 +2656,8 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) } gMainWindow->UpdateTimeline(false, false); - ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, false); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); +// ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); SaveCheckpoint(tr("Adding Piece")); @@ -3186,7 +3215,8 @@ void lcModel::MoveSelectionToModel(lcModel* Model) SaveCheckpoint(tr("New Model")); gMainWindow->UpdateTimeline(false, false); - ClearSelectionAndSetFocus(ModelPiece, LC_PIECE_SECTION_POSITION, false); +// ClearSelectionAndSetFocus(ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); } void lcModel::InlineSelectedModels() @@ -4373,32 +4403,32 @@ void lcModel::GetSelectionInformation(int* Flags, std::vector& Select } } -std::vector lcModel::GetSelectionModePieces(const lcPiece* SelectedPiece) const +std::vector lcModel::GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece, lcStep Step) const { const PieceInfo* Info = SelectedPiece->mPieceInfo; const int ColorIndex = SelectedPiece->GetColorIndex(); std::vector Pieces; - switch (gMainWindow->GetSelectionMode()) + switch (SelectionMode) { case lcSelectionMode::Single: break; case lcSelectionMode::Piece: for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep) && Piece->mPieceInfo == Info && Piece.get() != SelectedPiece) + if (Piece->IsVisible(Step) && Piece->mPieceInfo == Info && Piece.get() != SelectedPiece) Pieces.emplace_back(Piece.get()); break; case lcSelectionMode::Color: for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep) && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) + if (Piece->IsVisible(Step) && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) Pieces.emplace_back(Piece.get()); break; case lcSelectionMode::PieceColor: for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep) && Piece->mPieceInfo == Info && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) + if (Piece->IsVisible(Step) && Piece->mPieceInfo == Info && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) Pieces.emplace_back(Piece.get()); break; } @@ -4408,53 +4438,29 @@ std::vector lcModel::GetSelectionModePieces(const lcPiece* SelectedPi void lcModel::ClearSelection() { - if (!AnyObjectsSelected()) - return; - BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelection); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelection, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } +void lcModel::ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, lcSelectionMode SelectionMode) +{ + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Object, Section, SelectionMode); + EndActionSequence(tr("Selection")); +} + void lcModel::SelectAllPieces() { - bool UnselectedPieces = false; - - for (const std::unique_ptr& Piece : mPieces) - { - if (Piece->IsVisible(mCurrentStep) && !Piece->IsSelected()) - { - UnselectedPieces = true; - break; - } - } - - if (!UnselectedPieces) - return; - BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::SelectAllPieces); + RecordSelectionAction(lcModelActionSelectionMode::SelectAllPieces, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } void lcModel::InvertPieceSelection() { - bool VisiblePieces = false; - - for (const std::unique_ptr& Piece : mPieces) - { - if (Piece->IsVisible(mCurrentStep)) - { - VisiblePieces = true; - break; - } - } - - if (!VisiblePieces) - return; - BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::InvertPieceSelection); + RecordSelectionAction(lcModelActionSelectionMode::InvertPieceSelection, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } @@ -4470,13 +4476,28 @@ void lcModel::DeselectAllObjects() Light->SetSelected(false); } -void lcModel::SelectGroup(lcGroup* TopGroup, bool Select) +void lcModel::SelectObjects(const std::vector& Objects, lcStep Step) +{ + for (lcObject* Object : Objects) + { + const bool WasSelected = Object->IsSelected(); + Object->SetSelected(true); + + if (Object->IsPiece()) + { + if (!WasSelected) + SelectGroup(((lcPiece*)Object)->GetTopGroup(), Step, true); + } + } +} + +void lcModel::SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select) { if (!TopGroup) return; for (const std::unique_ptr& Piece : mPieces) - if (!Piece->IsSelected() && Piece->IsVisible(mCurrentStep) && (Piece->GetTopGroup() == TopGroup)) + if (!Piece->IsSelected() && Piece->IsVisible(Step) && (Piece->GetTopGroup() == TopGroup)) Piece->SetSelected(Select); } @@ -4507,10 +4528,10 @@ void lcModel::FocusOrDeselectObject(const lcObjectSection& ObjectSection) lcPiece* Piece = (lcPiece*)Object; if (gMainWindow->GetSelectionMode() == lcSelectionMode::Single) - SelectGroup(Piece->GetTopGroup(), IsSelected); + SelectGroup(Piece->GetTopGroup(), mCurrentStep, IsSelected); else { - std::vector Pieces = GetSelectionModePieces(Piece); + std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), Piece, mCurrentStep); AddToSelection(Pieces, false, false); } } @@ -4525,37 +4546,6 @@ void lcModel::FocusOrDeselectObject(const lcObjectSection& ObjectSection) UpdateAllViews(); } -void lcModel::ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool EnableSelectionMode) -{ - DeselectAllObjects(); - - if (Object) - { - Object->SetFocused(Section, true); - - if (Object->IsPiece()) - { - lcPiece* Piece = dynamic_cast(Object); - - SelectGroup(Piece->GetTopGroup(), true); - - if (EnableSelectionMode) - { - std::vector Pieces = GetSelectionModePieces(Piece); - AddToSelection(Pieces, false, false); - } - } - } - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); -} - -void lcModel::ClearSelectionAndSetFocus(const lcObjectSection& ObjectSection, bool EnableSelectionMode) -{ - ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, EnableSelectionMode); -} - void lcModel::SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode) { DeselectAllObjects(); @@ -4566,11 +4556,11 @@ void lcModel::SetSelectionAndFocus(const std::vector& Selection, lcOb if (Focus->IsPiece()) { - SelectGroup(((lcPiece*)Focus)->GetTopGroup(), true); + SelectGroup(((lcPiece*)Focus)->GetTopGroup(), mCurrentStep, true); if (EnableSelectionMode) { - std::vector Pieces = GetSelectionModePieces((lcPiece*)Focus); + std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), dynamic_cast(Focus), mCurrentStep); AddToSelection(Pieces, false, false); } } @@ -4589,11 +4579,11 @@ void lcModel::AddToSelection(const std::vector& Objects, bool EnableS if (Object->IsPiece()) { if (!WasSelected) - SelectGroup(((lcPiece*)Object)->GetTopGroup(), true); + SelectGroup(((lcPiece*)Object)->GetTopGroup(), mCurrentStep, true); if (EnableSelectionMode) { - std::vector Pieces = GetSelectionModePieces((lcPiece*)Object); + std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), dynamic_cast(Object), mCurrentStep); AddToSelection(Pieces, false, false); } } @@ -4618,17 +4608,17 @@ void lcModel::RemoveFromSelection(const std::vector& Objects) lcPiece* Piece = (lcPiece*)SelectedObject; if (gMainWindow->GetSelectionMode() == lcSelectionMode::Single) - SelectGroup(Piece->GetTopGroup(), false); + SelectGroup(Piece->GetTopGroup(), mCurrentStep, false); else { - std::vector Pieces = GetSelectionModePieces(Piece); + std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), Piece, mCurrentStep); for (lcObject* Object : Pieces) { if (Object->IsSelected()) { Object->SetSelected(false); - SelectGroup(((lcPiece*)Object)->GetTopGroup(), false); + SelectGroup(((lcPiece*)Object)->GetTopGroup(), mCurrentStep, false); } } } @@ -4655,17 +4645,17 @@ void lcModel::RemoveFromSelection(const lcObjectSection& ObjectSection) lcPiece* Piece = (lcPiece*)SelectedObject; if (gMainWindow->GetSelectionMode() == lcSelectionMode::Single) - SelectGroup(Piece->GetTopGroup(), false); + SelectGroup(Piece->GetTopGroup(), mCurrentStep, false); else { - std::vector Pieces = GetSelectionModePieces(Piece); + std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), Piece, mCurrentStep); for (lcObject* Object : Pieces) { if (Object->IsSelected()) { Object->SetSelected(false); - SelectGroup(((lcPiece*)Object)->GetTopGroup(), false); + SelectGroup(((lcPiece*)Object)->GetTopGroup(), mCurrentStep, false); } } } @@ -4912,7 +4902,8 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) if (FindAll) SetSelectionAndFocus(Selection, nullptr, 0, false); else - ClearSelectionAndSetFocus(Focus, LC_PIECE_SECTION_POSITION, false); +// ClearSelectionAndSetFocus(Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); if (ReplacedCount) { @@ -5100,13 +5091,14 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece } EndObjectEditAction(std::move(PieceIndices)); + + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + EndActionSequence(tr("Add Piece")); gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateInUseCategory(); - ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, false); - UpdateTrainTrackConnections(Piece, false); } @@ -5121,9 +5113,10 @@ void lcModel::InsertCameraToolClicked(const lcVector3& Position) mCameras.emplace_back(Camera); EndObjectEditAction({ mCameras.size() - 1 }); - EndActionSequence(tr("Add Camera")); - ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_POSITION, false); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); + + EndActionSequence(tr("Add Camera")); } void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType) @@ -5161,9 +5154,10 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh mLights.emplace_back(Light); EndObjectEditAction({ mLights.size() - 1 }); - EndActionSequence(ActionName); - ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); + + EndActionSequence(ActionName); } void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag) diff --git a/common/lc_model.h b/common/lc_model.h index bd38ce8f..79f60fb7 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -322,14 +322,13 @@ public: void GetPartsListForStep(lcStep Step, int DefaultColorIndex, lcPartsList& PartsList, bool Cumulative) const; void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector& ModelParts) const; void GetSelectionInformation(int* Flags, std::vector& Selection, lcObject** Focus) const; - std::vector GetSelectionModePieces(const lcPiece* SelectedPiece) const; void ClearSelection(); + void ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, lcSelectionMode SelectionMode); void SelectAllPieces(); void InvertPieceSelection(); + // to update: void FocusOrDeselectObject(const lcObjectSection& ObjectSection); - void ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool EnableSelectionMode); - void ClearSelectionAndSetFocus(const lcObjectSection& ObjectSection, bool EnableSelectionMode); void SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode); void AddToSelection(const std::vector& Objects, bool EnableSelectionMode, bool UpdateInterface); void RemoveFromSelection(const std::vector& Objects); @@ -407,7 +406,7 @@ public: protected: void DeleteModel(); - void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode); + void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); void EndObjectEditAction(std::vector&& ObjectIndices = std::vector(), std::vector&& GroupIndices = std::vector()); @@ -428,9 +427,11 @@ protected: void RemoveEmptyGroups(); bool RemoveSelectedObjects(); void RemoveCameraFromViews(lcCamera* Camera); - + + std::vector GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece, lcStep Step) const; void DeselectAllObjects(); - void SelectGroup(lcGroup* TopGroup, bool Select); + void SelectObjects(const std::vector& Objects, lcStep Step); + void SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select); size_t AddPiece(lcPiece* Piece); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 7ecdc9f2..e38a81a3 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -187,11 +187,80 @@ lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode, { } -void lcModelActionSelection::SetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) +bool lcModelActionSelection::Initialize(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) { - mSelectedPieces.clear(); - mSelectedCameras.clear(); - mSelectedLights.clear(); + if (!HasChanges(Model, FocusObject, FocusSection)) + return false; + + mSelectionMode = SelectionMode; + + SaveSelection(Model); + SaveNewFocusObject(Model, FocusObject, FocusSection); + + return true; +} + +bool lcModelActionSelection::HasChanges(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection) const +{ + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + + switch (mMode) + { + case lcModelActionSelectionMode::ClearSelection: + return Model->AnyObjectsSelected(); + + case lcModelActionSelectionMode::ClearSelectionAndSetFocus: + if (FocusObject && !FocusObject->IsFocused(FocusSection)) + return true; + + for (const std::unique_ptr& Piece : Pieces) + if (Piece->IsSelected() && Piece.get() != FocusObject) + return true; + + for (const std::unique_ptr& Camera : Cameras) + if (Camera->IsSelected() && Camera.get() != FocusObject) + return true; + + for (const std::unique_ptr& Light : Lights) + if (Light->IsSelected() && Light.get() != FocusObject) + return true; + + return false; + + case lcModelActionSelectionMode::SelectAllPieces: + for (const std::unique_ptr& Piece : Pieces) + if (Piece->IsVisible(mStep) && !Piece->IsSelected()) + return true; + + return false; + + case lcModelActionSelectionMode::InvertPieceSelection: + for (const std::unique_ptr& Piece : Pieces) + if (Piece->IsVisible(mStep)) + return true; + + return false; + + case lcModelActionSelectionMode::Set: + case lcModelActionSelectionMode::Save: + case lcModelActionSelectionMode::Restore: + break; + } + + return true; +} + +void lcModelActionSelection::SaveSelection(const lcModel* Model) +{ + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + + mPreviousSelectedPieces.clear(); + mPreviousSelectedCameras.clear(); + mPreviousSelectedLights.clear(); for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) { @@ -200,13 +269,13 @@ void lcModelActionSelection::SetSelection(const std::vectorIsSelected()) continue; - mSelectedPieces.push_back(PieceIndex); + mPreviousSelectedPieces.push_back(PieceIndex); if (Piece->IsFocused()) { - mFocusIndex = PieceIndex; - mFocusSection = Piece->GetFocusSection(); - mFocusType = lcObjectType::Piece; + mPreviousFocusIndex = PieceIndex; + mPreviousFocusSection = Piece->GetFocusSection(); + mPreviousFocusObjectType = lcObjectType::Piece; } } @@ -217,13 +286,13 @@ void lcModelActionSelection::SetSelection(const std::vectorIsSelected()) continue; - mSelectedCameras.push_back(CameraIndex); + mPreviousSelectedCameras.push_back(CameraIndex); if (Camera->IsFocused()) { - mFocusIndex = CameraIndex; - mFocusSection = Camera->GetFocusSection(); - mFocusType = lcObjectType::Camera; + mPreviousFocusIndex = CameraIndex; + mPreviousFocusSection = Camera->GetFocusSection(); + mPreviousFocusObjectType = lcObjectType::Camera; } } @@ -236,50 +305,142 @@ void lcModelActionSelection::SetSelection(const std::vectorIsFocused()) { - mFocusIndex = LightIndex; - mFocusSection = Light->GetFocusSection(); - mFocusType = lcObjectType::Light; + mPreviousFocusIndex = LightIndex; + mPreviousFocusSection = Light->GetFocusSection(); + mPreviousFocusObjectType = lcObjectType::Light; } } } +void lcModelActionSelection::SaveNewFocusObject(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection) +{ + if (!FocusObject) + return; + + mNewFocusSection = FocusSection; + mNewFocusObjectType = FocusObject->GetType(); + + switch (FocusObject->GetType()) + { + case lcObjectType::Piece: + { + const std::vector>& Pieces = Model->GetPieces(); + + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + { + if (Pieces[PieceIndex].get() == FocusObject) + { + mNewFocusIndex = PieceIndex; + break; + } + } + } + break; + + case lcObjectType::Camera: + { + const std::vector>& Cameras = Model->GetCameras(); + + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + { + if (Cameras[CameraIndex].get() == FocusObject) + { + mNewFocusIndex = CameraIndex; + break; + } + } + } + break; + + case lcObjectType::Light: + { + const std::vector>& Lights = Model->GetLights(); + + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + { + if (Lights[LightIndex].get() == FocusObject) + { + mNewFocusIndex = LightIndex; + break; + } + } + } + break; + } +} + +lcObject* lcModelActionSelection::GetNewFocusObject(const lcModel* Model) const +{ + switch (mNewFocusObjectType) + { + case lcObjectType::Piece: + { + const std::vector>& Pieces = Model->GetPieces(); + + if (mNewFocusIndex < Pieces.size()) + return Pieces[mNewFocusIndex].get(); + } + break; + + case lcObjectType::Camera: + { + const std::vector>& Cameras = Model->GetCameras(); + + if (mNewFocusIndex < Cameras.size()) + return Cameras[mNewFocusIndex].get(); + } + break; + + case lcObjectType::Light: + { + const std::vector>& Lights = Model->GetLights(); + + if (mNewFocusIndex < Lights.size()) + return Lights[mNewFocusIndex].get(); + } + break; + } + + return nullptr; +} + std::tuple, lcObject*, uint32_t> lcModelActionSelection::GetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) const { std::vector SelectedObjects; lcObject* FocusObject = nullptr; - for (size_t PieceIndex : mSelectedPieces) + for (size_t PieceIndex : mPreviousSelectedPieces) if (PieceIndex < Pieces.size()) SelectedObjects.push_back(Pieces[PieceIndex].get()); - for (size_t CameraIndex : mSelectedCameras) + for (size_t CameraIndex : mPreviousSelectedCameras) if (CameraIndex < Cameras.size()) SelectedObjects.push_back(Cameras[CameraIndex].get()); - for (size_t LightIndex : mSelectedLights) + for (size_t LightIndex : mPreviousSelectedLights) if (LightIndex < Lights.size()) SelectedObjects.push_back(Lights[LightIndex].get()); - if (mFocusIndex != SIZE_MAX) + if (mPreviousFocusIndex != SIZE_MAX) { - switch (mFocusType) + switch (mPreviousFocusObjectType) { case lcObjectType::Piece: - if (mFocusIndex < Pieces.size()) - FocusObject = Pieces[mFocusIndex].get(); + if (mPreviousFocusIndex < Pieces.size()) + FocusObject = Pieces[mPreviousFocusIndex].get(); break; case lcObjectType::Camera: - if (mFocusIndex < Cameras.size()) - FocusObject = Cameras[mFocusIndex].get(); + if (mPreviousFocusIndex < Cameras.size()) + FocusObject = Cameras[mPreviousFocusIndex].get(); break; case lcObjectType::Light: - if (mFocusIndex < Lights.size()) - FocusObject = Lights[mFocusIndex].get(); + if (mPreviousFocusIndex < Lights.size()) + FocusObject = Lights[mPreviousFocusIndex].get(); break; } } - return { SelectedObjects, FocusObject, mFocusSection }; + return { SelectedObjects, FocusObject, mPreviousFocusSection }; } lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mode) diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 2268d30d..d406600e 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -1,6 +1,7 @@ #pragma once enum class lcObjectType; +enum class lcSelectionMode; class lcModelAction { @@ -21,6 +22,7 @@ protected: enum class lcModelActionSelectionMode { ClearSelection, + ClearSelectionAndSetFocus, SelectAllPieces, InvertPieceSelection, Set, @@ -33,7 +35,9 @@ class lcModelActionSelection : public lcModelAction public: lcModelActionSelection(lcModelActionSelectionMode Mode, lcStep Step); virtual ~lcModelActionSelection() = default; - + + bool Initialize(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + lcModelActionSelectionMode GetMode() const { return mMode; @@ -44,16 +48,36 @@ public: return mStep; } - void SetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights); + lcSelectionMode GetSelectionMode() const + { + return mSelectionMode; + } + + uint32_t GetNewFocusSection() const + { + return mNewFocusSection; + } + + lcObject* GetNewFocusObject(const lcModel* Model) const; std::tuple, lcObject*, uint32_t> GetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) const; protected: - std::vector mSelectedPieces; - std::vector mSelectedCameras; - std::vector mSelectedLights; - size_t mFocusIndex = SIZE_MAX; - uint32_t mFocusSection = 0; - lcObjectType mFocusType = (lcObjectType)0; + bool HasChanges(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection) const; + void SaveSelection(const lcModel* Model); + void SaveNewFocusObject(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection); + + std::vector mPreviousSelectedPieces; + std::vector mPreviousSelectedCameras; + std::vector mPreviousSelectedLights; + size_t mPreviousFocusIndex = SIZE_MAX; + uint32_t mPreviousFocusSection = 0; + lcObjectType mPreviousFocusObjectType = (lcObjectType)0; + + size_t mNewFocusIndex = SIZE_MAX; + uint32_t mNewFocusSection = 0; + lcObjectType mNewFocusObjectType = (lcObjectType)0; + lcSelectionMode mSelectionMode = (lcSelectionMode)0; + lcModelActionSelectionMode mMode; lcStep mStep; }; diff --git a/common/lc_view.cpp b/common/lc_view.cpp index bafd34bb..6789891a 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2577,7 +2577,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) else if (mMouseModifiers & Qt::ShiftModifier) ActiveModel->RemoveFromSelection(ObjectSection); else - ActiveModel->ClearSelectionAndSetFocus(ObjectSection, true); + ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); StartTracking(TrackButton); } @@ -2643,7 +2643,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) ObjectSection.Object = Focus; ObjectSection.Section = mTrackToolSection; - ActiveModel->ClearSelectionAndSetFocus(ObjectSection, true); + ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); } break; @@ -2741,7 +2741,7 @@ void lcView::OnLeftButtonDoubleClick() else if (mMouseModifiers & Qt::ShiftModifier) ActiveModel->RemoveFromSelection(ObjectSection); else - ActiveModel->ClearSelectionAndSetFocus(ObjectSection, true); + ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); } void lcView::OnMiddleButtonDown() From 8342e147cf4a8a2c00dc256376286ea832d28355 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 10 Jan 2026 21:34:21 -0800 Subject: [PATCH 43/93] Added RemoveFromSelection action. --- common/camera.cpp | 6 +- common/camera.h | 19 ----- common/lc_model.cpp | 166 +++++++++++++++----------------------- common/lc_model.h | 9 +-- common/lc_modelaction.cpp | 157 ++++++++++++++++++++++------------- common/lc_modelaction.h | 13 ++- common/lc_view.cpp | 12 ++- common/light.cpp | 4 +- common/light.h | 7 -- common/object.h | 1 - common/piece.h | 7 -- 11 files changed, 192 insertions(+), 209 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 97dbcb69..0f90296a 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -594,7 +594,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const } else { - if (IsSelected(LC_CAMERA_SECTION_POSITION)) + if (IsSelected()) { Context->SetLineWidth(2.0f * LineWidth); if (IsFocused(LC_CAMERA_SECTION_POSITION)) @@ -610,7 +610,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const Context->DrawIndexedPrimitives(GL_LINES, 40, GL_UNSIGNED_SHORT, 0); - if (IsSelected(LC_CAMERA_SECTION_TARGET)) + if (IsSelected()) { Context->SetLineWidth(2.0f * LineWidth); if (IsFocused(LC_CAMERA_SECTION_TARGET)) @@ -626,7 +626,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 40 * 2); - if (IsSelected(LC_CAMERA_SECTION_UPVECTOR)) + if (IsSelected()) { Context->SetLineWidth(2.0f * LineWidth); if (IsFocused(LC_CAMERA_SECTION_UPVECTOR)) diff --git a/common/camera.h b/common/camera.h index f9d82f70..c99192e6 100644 --- a/common/camera.h +++ b/common/camera.h @@ -99,25 +99,6 @@ public: return (mState & LC_CAMERA_SELECTION_MASK) != 0; } - bool IsSelected(quint32 Section) const override - { - switch (Section) - { - case LC_CAMERA_SECTION_POSITION: - return (mState & LC_CAMERA_POSITION_SELECTED) != 0; - break; - - case LC_CAMERA_SECTION_TARGET: - return (mState & LC_CAMERA_TARGET_SELECTED) != 0; - break; - - case LC_CAMERA_SECTION_UPVECTOR: - return (mState & LC_CAMERA_UPVECTOR_SELECTED) != 0; - break; - } - return false; - } - void SetSelected(bool Selected) override { if (Selected) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 23fe8f1d..8ee98140 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1230,7 +1230,7 @@ void lcModel::Paste(bool PasteToCurrentStep) SaveCheckpoint(tr("Pasting")); if (SelectedObjects.size() == 1) - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); // ClearSelectionAndSetFocus(SelectedObjects[0], LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); else SetSelectionAndFocus(SelectedObjects, nullptr, 0, false); @@ -1733,11 +1733,11 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v Piece->SubModelAddBoundingBoxPoints(WorldMatrix, Points); } -void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) +void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) { std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode, mCurrentStep); - if (ModelActionSelection->Initialize(this, FocusObject, FocusSection, SelectionMode)) + if (ModelActionSelection->Initialize(this, Objects, FocusObject, FocusSection, SelectionMode)) mActionSequence.emplace_back(std::move(ModelActionSelection)); } @@ -1748,7 +1748,7 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect auto LoadSelection = [this, ModelActionSelection]() { - auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetSelection(mPieces, mCameras, mLights); + auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetPreviousSelection(this); SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); }; @@ -1782,7 +1782,7 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect SelectGroup(Piece->GetTopGroup(), Step, true); std::vector Pieces = GetSelectionModePieces(ModelActionSelection->GetSelectionMode(), Piece, Step); - SelectObjects(Pieces, Step); + SelectObjects(Pieces, Step, true); } } } @@ -1811,7 +1811,34 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect else LoadSelection(); break; - + + case lcModelActionSelectionMode::RemoveFromSelection: + if (Apply) + { + std::vector Objects = ModelActionSelection->GetNewObjects(this); + + for (lcObject* Object : Objects) + { + if (!Object->IsSelected()) + continue; + + Object->SetSelected(false); + + if (Object->IsPiece()) + { + lcPiece* Piece = dynamic_cast(Object); + + SelectGroup(Piece->GetTopGroup(), Step, false); + + std::vector Pieces = GetSelectionModePieces(ModelActionSelection->GetSelectionMode(), Piece, Step); + SelectObjects(Pieces, Step, false); + } + } + } + else + LoadSelection(); + break; + case lcModelActionSelectionMode::Set: LoadSelection(); break; @@ -2294,9 +2321,9 @@ void lcModel::GroupSelection() BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore, nullptr, 0, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::Restore, std::vector(), nullptr, 0, lcSelectionMode::Single); RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, Dialog.mName); - RecordSelectionAction(lcModelActionSelectionMode::Save, nullptr, 0, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::Save, std::vector(), nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Group")); } @@ -2328,9 +2355,9 @@ void lcModel::UngroupSelection() BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore, nullptr, 0, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::Restore, std::vector(), nullptr, 0, lcSelectionMode::Single); RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Ungroup, QString()); - RecordSelectionAction(lcModelActionSelectionMode::Save, nullptr, 0, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::Save, std::vector(), nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Ungroup")); } @@ -2656,7 +2683,7 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) } gMainWindow->UpdateTimeline(false, false); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); // ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); SaveCheckpoint(tr("Adding Piece")); @@ -3216,7 +3243,7 @@ void lcModel::MoveSelectionToModel(lcModel* Model) SaveCheckpoint(tr("New Model")); gMainWindow->UpdateTimeline(false, false); // ClearSelectionAndSetFocus(ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); } void lcModel::InlineSelectedModels() @@ -4439,28 +4466,35 @@ std::vector lcModel::GetSelectionModePieces(lcSelectionMode Selection void lcModel::ClearSelection() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelection, nullptr, 0, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelection, std::vector(), nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } void lcModel::ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, lcSelectionMode SelectionMode) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Object, Section, SelectionMode); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Object, Section, SelectionMode); EndActionSequence(tr("Selection")); } void lcModel::SelectAllPieces() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::SelectAllPieces, nullptr, 0, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::SelectAllPieces, std::vector(), nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } void lcModel::InvertPieceSelection() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::InvertPieceSelection, nullptr, 0, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::InvertPieceSelection, std::vector(), nullptr, 0, lcSelectionMode::Single); + EndActionSequence(tr("Selection")); +} + +void lcModel::RemoveFromSelection(const std::vector& Objects, lcSelectionMode SelectionMode) +{ + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::RemoveFromSelection, Objects, nullptr, 0, SelectionMode); EndActionSequence(tr("Selection")); } @@ -4476,19 +4510,18 @@ void lcModel::DeselectAllObjects() Light->SetSelected(false); } -void lcModel::SelectObjects(const std::vector& Objects, lcStep Step) +void lcModel::SelectObjects(const std::vector& Objects, lcStep Step, bool Select) { - for (lcObject* Object : Objects) - { - const bool WasSelected = Object->IsSelected(); - Object->SetSelected(true); - - if (Object->IsPiece()) - { - if (!WasSelected) - SelectGroup(((lcPiece*)Object)->GetTopGroup(), Step, true); - } - } + for (lcObject* Object : Objects) + { + if (Object->IsSelected() == Select) + continue; + + Object->SetSelected(Select); + + if (Object->IsPiece()) + SelectGroup(dynamic_cast(Object)->GetTopGroup(), Step, Select); + } } void lcModel::SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select) @@ -4596,75 +4629,6 @@ void lcModel::AddToSelection(const std::vector& Objects, bool EnableS } } -void lcModel::RemoveFromSelection(const std::vector& Objects) -{ - for (lcObject* SelectedObject : Objects) - { - const bool WasSelected = SelectedObject->IsSelected(); - SelectedObject->SetSelected(false); - - if (WasSelected && SelectedObject->IsPiece()) - { - lcPiece* Piece = (lcPiece*)SelectedObject; - - if (gMainWindow->GetSelectionMode() == lcSelectionMode::Single) - SelectGroup(Piece->GetTopGroup(), mCurrentStep, false); - else - { - std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), Piece, mCurrentStep); - - for (lcObject* Object : Pieces) - { - if (Object->IsSelected()) - { - Object->SetSelected(false); - SelectGroup(((lcPiece*)Object)->GetTopGroup(), mCurrentStep, false); - } - } - } - } - } - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); -} - -void lcModel::RemoveFromSelection(const lcObjectSection& ObjectSection) -{ - lcObject* SelectedObject = ObjectSection.Object; - - if (!SelectedObject) - return; - - const bool WasSelected = SelectedObject->IsSelected(); - - SelectedObject->SetSelected(false); - - if (SelectedObject->IsPiece() && WasSelected) - { - lcPiece* Piece = (lcPiece*)SelectedObject; - - if (gMainWindow->GetSelectionMode() == lcSelectionMode::Single) - SelectGroup(Piece->GetTopGroup(), mCurrentStep, false); - else - { - std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), Piece, mCurrentStep); - - for (lcObject* Object : Pieces) - { - if (Object->IsSelected()) - { - Object->SetSelected(false); - SelectGroup(((lcPiece*)Object)->GetTopGroup(), mCurrentStep, false); - } - } - } - } - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); -} - void lcModel::HideSelectedPieces() { BeginActionSequence(); @@ -4903,7 +4867,7 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) SetSelectionAndFocus(Selection, nullptr, 0, false); else // ClearSelectionAndSetFocus(Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); if (ReplacedCount) { @@ -5092,7 +5056,7 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece EndObjectEditAction(std::move(PieceIndices)); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Add Piece")); @@ -5114,7 +5078,7 @@ void lcModel::InsertCameraToolClicked(const lcVector3& Position) EndObjectEditAction({ mCameras.size() - 1 }); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Add Camera")); } @@ -5155,7 +5119,7 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh EndObjectEditAction({ mLights.size() - 1 }); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(ActionName); } diff --git a/common/lc_model.h b/common/lc_model.h index 79f60fb7..6da1b7b5 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -327,12 +327,11 @@ public: void ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, lcSelectionMode SelectionMode); void SelectAllPieces(); void InvertPieceSelection(); - // to update: + void RemoveFromSelection(const std::vector& Objects, lcSelectionMode SelectionMode); + // to update: void FocusOrDeselectObject(const lcObjectSection& ObjectSection); void SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode); void AddToSelection(const std::vector& Objects, bool EnableSelectionMode, bool UpdateInterface); - void RemoveFromSelection(const std::vector& Objects); - void RemoveFromSelection(const lcObjectSection& ObjectSection); void HideSelectedPieces(); void HideUnselectedPieces(); @@ -406,7 +405,7 @@ public: protected: void DeleteModel(); - void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); void EndObjectEditAction(std::vector&& ObjectIndices = std::vector(), std::vector&& GroupIndices = std::vector()); @@ -430,7 +429,7 @@ protected: std::vector GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece, lcStep Step) const; void DeselectAllObjects(); - void SelectObjects(const std::vector& Objects, lcStep Step); + void SelectObjects(const std::vector& Objects, lcStep Step, bool Select); void SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select); size_t AddPiece(lcPiece* Piece); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index e38a81a3..347942a6 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -173,13 +173,13 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, return false; const std::unique_ptr& Light = Lights[LightIndex]; - + if (!Light->LoadUndoData(Stream, Model)) return false; } - } - - return true; + } + + return true; } lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode, lcStep Step) @@ -187,25 +187,64 @@ lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode, { } -bool lcModelActionSelection::Initialize(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) +bool lcModelActionSelection::Initialize(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) { - if (!HasChanges(Model, FocusObject, FocusSection)) + if (!HasChanges(Model, Objects, FocusObject, FocusSection)) return false; - + mSelectionMode = SelectionMode; - SaveSelection(Model); + SavePreviousSelection(Model); + SaveNewObjects(Objects, Model); SaveNewFocusObject(Model, FocusObject, FocusSection); return true; } -bool lcModelActionSelection::HasChanges(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection) const +size_t lcModelActionSelection::GetObjectIndex(const lcObject* Object, const lcModel* Model) +{ + switch (Object->GetType()) + { + case lcObjectType::Piece: + { + const std::vector>& Pieces = Model->GetPieces(); + + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + if (Pieces[PieceIndex].get() == Object) + return PieceIndex; + } + break; + + case lcObjectType::Camera: + { + const std::vector>& Cameras = Model->GetCameras(); + + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + if (Cameras[CameraIndex].get() == Object) + return CameraIndex; + } + break; + + case lcObjectType::Light: + { + const std::vector>& Lights = Model->GetLights(); + + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + if (Lights[LightIndex].get() == Object) + return LightIndex; + } + break; + } + + return SIZE_T_MAX; +} + +bool lcModelActionSelection::HasChanges(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection) const { const std::vector>& Pieces = Model->GetPieces(); const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - + switch (mMode) { case lcModelActionSelectionMode::ClearSelection: @@ -243,16 +282,23 @@ bool lcModelActionSelection::HasChanges(const lcModel* Model, lcObject* FocusObj return false; + case lcModelActionSelectionMode::RemoveFromSelection: + for (lcObject* Object : Objects) + if (Object->IsSelected()) + return true; + + return false; + case lcModelActionSelectionMode::Set: case lcModelActionSelectionMode::Save: case lcModelActionSelectionMode::Restore: break; } - return true; + return true; } -void lcModelActionSelection::SaveSelection(const lcModel* Model) +void lcModelActionSelection::SavePreviousSelection(const lcModel* Model) { const std::vector>& Pieces = Model->GetPieces(); const std::vector>& Cameras = Model->GetCameras(); @@ -312,61 +358,54 @@ void lcModelActionSelection::SaveSelection(const lcModel* Model) } } +void lcModelActionSelection::SaveNewObjects(const std::vector& Objects, const lcModel* Model) +{ + mNewObjects.clear(); + mNewObjects.reserve(Objects.size()); + + for (lcObject* Object : Objects) + mNewObjects.emplace_back(GetObjectIndex(Object, Model), Object->GetType()); +} + void lcModelActionSelection::SaveNewFocusObject(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection) { if (!FocusObject) return; - + mNewFocusSection = FocusSection; mNewFocusObjectType = FocusObject->GetType(); + mNewFocusIndex = GetObjectIndex(FocusObject, Model); +} + +std::vector lcModelActionSelection::GetNewObjects(const lcModel* Model) const +{ + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + std::vector Objects; - switch (FocusObject->GetType()) + for (auto [ObjectIndex, ObjectType] : mNewObjects) { - case lcObjectType::Piece: + switch (ObjectType) { - const std::vector>& Pieces = Model->GetPieces(); - - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - { - if (Pieces[PieceIndex].get() == FocusObject) - { - mNewFocusIndex = PieceIndex; - break; - } - } + case lcObjectType::Piece: + if (ObjectIndex < Pieces.size()) + Objects.push_back(Pieces[ObjectIndex].get()); + break; + + case lcObjectType::Camera: + if (ObjectIndex < Cameras.size()) + Objects.push_back(Cameras[ObjectIndex].get()); + break; + + case lcObjectType::Light: + if (ObjectIndex < Lights.size()) + Objects.push_back(Lights[ObjectIndex].get()); + break; } - break; - - case lcObjectType::Camera: - { - const std::vector>& Cameras = Model->GetCameras(); - - for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) - { - if (Cameras[CameraIndex].get() == FocusObject) - { - mNewFocusIndex = CameraIndex; - break; - } - } - } - break; - - case lcObjectType::Light: - { - const std::vector>& Lights = Model->GetLights(); - - for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) - { - if (Lights[LightIndex].get() == FocusObject) - { - mNewFocusIndex = LightIndex; - break; - } - } - } - break; } + + return Objects; } lcObject* lcModelActionSelection::GetNewFocusObject(const lcModel* Model) const @@ -404,8 +443,12 @@ lcObject* lcModelActionSelection::GetNewFocusObject(const lcModel* Model) const return nullptr; } -std::tuple, lcObject*, uint32_t> lcModelActionSelection::GetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) const +std::tuple, lcObject*, uint32_t> lcModelActionSelection::GetPreviousSelection(const lcModel* Model) const { + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + std::vector SelectedObjects; lcObject* FocusObject = nullptr; diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index d406600e..0fa507cd 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -25,6 +25,7 @@ enum class lcModelActionSelectionMode ClearSelectionAndSetFocus, SelectAllPieces, InvertPieceSelection, + RemoveFromSelection, Set, Save, Restore @@ -36,7 +37,7 @@ public: lcModelActionSelection(lcModelActionSelectionMode Mode, lcStep Step); virtual ~lcModelActionSelection() = default; - bool Initialize(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + bool Initialize(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); lcModelActionSelectionMode GetMode() const { @@ -58,12 +59,15 @@ public: return mNewFocusSection; } + std::vector GetNewObjects(const lcModel* Model) const; lcObject* GetNewFocusObject(const lcModel* Model) const; - std::tuple, lcObject*, uint32_t> GetSelection(const std::vector>& Pieces, const std::vector>& Cameras, const std::vector>& Lights) const; + std::tuple, lcObject*, uint32_t> GetPreviousSelection(const lcModel* Model) const; protected: - bool HasChanges(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection) const; - void SaveSelection(const lcModel* Model); + static size_t GetObjectIndex(const lcObject* Object, const lcModel* Model); + bool HasChanges(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection) const; + void SavePreviousSelection(const lcModel* Model); + void SaveNewObjects(const std::vector& Objects, const lcModel* Model); void SaveNewFocusObject(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection); std::vector mPreviousSelectedPieces; @@ -73,6 +77,7 @@ protected: uint32_t mPreviousFocusSection = 0; lcObjectType mPreviousFocusObjectType = (lcObjectType)0; + std::vector> mNewObjects; size_t mNewFocusIndex = SIZE_MAX; uint32_t mNewFocusSection = 0; lcObjectType mNewFocusObjectType = (lcObjectType)0; diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 6789891a..a997a32f 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2423,7 +2423,7 @@ void lcView::StopTracking(bool Accept) if (mMouseModifiers & Qt::ControlModifier) ActiveModel->AddToSelection(Objects, true, true); else if (mMouseModifiers & Qt::ShiftModifier) - ActiveModel->RemoveFromSelection(Objects); + ActiveModel->RemoveFromSelection(Objects, lcSelectionMode::Single); else ActiveModel->SetSelectionAndFocus(Objects, nullptr, 0, true); } @@ -2575,7 +2575,10 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) if (mMouseModifiers & Qt::ControlModifier) ActiveModel->FocusOrDeselectObject(ObjectSection); else if (mMouseModifiers & Qt::ShiftModifier) - ActiveModel->RemoveFromSelection(ObjectSection); + { + if (ObjectSection.Object) + ActiveModel->RemoveFromSelection({ ObjectSection.Object }, gMainWindow->GetSelectionMode()); + } else ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); @@ -2739,7 +2742,10 @@ void lcView::OnLeftButtonDoubleClick() if (mMouseModifiers & Qt::ControlModifier) ActiveModel->FocusOrDeselectObject(ObjectSection); else if (mMouseModifiers & Qt::ShiftModifier) - ActiveModel->RemoveFromSelection(ObjectSection); + { + if (ObjectSection.Object) + ActiveModel->RemoveFromSelection({ ObjectSection.Object }, gMainWindow->GetSelectionMode()); + } else ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); } diff --git a/common/light.cpp b/common/light.cpp index 40eef7e2..5c4666d4 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -905,7 +905,7 @@ void lcLight::SetupLightMatrix(lcContext* Context) const const lcPreferences& Preferences = lcGetPreferences(); const float LineWidth = Preferences.mLineWidth; - if (IsSelected(LC_LIGHT_SECTION_POSITION)) + if (IsSelected()) { const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); @@ -1066,7 +1066,7 @@ void lcLight::DrawTarget(lcContext* Context) const const lcPreferences& Preferences = lcGetPreferences(); const float LineWidth = Preferences.mLineWidth; - if (IsSelected(LC_LIGHT_SECTION_TARGET)) + if (IsSelected()) { const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor); const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor); diff --git a/common/light.h b/common/light.h index 4ad7f45f..9db0056c 100644 --- a/common/light.h +++ b/common/light.h @@ -81,13 +81,6 @@ public: return mSelected; } - bool IsSelected(quint32 Section) const override - { - Q_UNUSED(Section); - - return mSelected; - } - void SetSelected(bool Selected) override { mSelected = Selected; diff --git a/common/object.h b/common/object.h index 27e189d3..652c9640 100644 --- a/common/object.h +++ b/common/object.h @@ -88,7 +88,6 @@ public: } virtual bool IsSelected() const = 0; - virtual bool IsSelected(quint32 Section) const = 0; virtual void SetSelected(bool Selected) = 0; virtual bool IsFocused() const = 0; virtual bool IsFocused(quint32 Section) const = 0; diff --git a/common/piece.h b/common/piece.h index 476c1fb0..1db62daf 100644 --- a/common/piece.h +++ b/common/piece.h @@ -41,13 +41,6 @@ public: return mSelected; } - bool IsSelected(quint32 Section) const override - { - Q_UNUSED(Section); - - return mSelected; - } - void SetSelected(bool Selected) override { mSelected = Selected; From 96bc1dc700e4b6e6021f3ced882619ebabf014a0 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 12 Jan 2026 14:42:09 -0800 Subject: [PATCH 44/93] Added remaining selection actions. --- common/lc_model.cpp | 278 +++++++++++++++++++---------------- common/lc_model.h | 9 +- common/lc_modelaction.cpp | 68 ++++++++- common/lc_modelaction.h | 3 + common/lc_timelinewidget.cpp | 2 +- common/lc_view.cpp | 8 +- 6 files changed, 229 insertions(+), 139 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 8ee98140..bf8ecfbb 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1233,7 +1233,8 @@ void lcModel::Paste(bool PasteToCurrentStep) RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); // ClearSelectionAndSetFocus(SelectedObjects[0], LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); else - SetSelectionAndFocus(SelectedObjects, nullptr, 0, false); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, SelectedObjects, nullptr, 0, lcSelectionMode::Single); +// SetSelectionAndFocus(SelectedObjects, nullptr, 0, false); CalculateStep(mCurrentStep); gMainWindow->UpdateTimeline(false, false); @@ -1310,10 +1311,12 @@ void lcModel::DuplicateSelectedPieces() } EndObjectEditAction(std::move(PieceIndices)); + + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, NewPieces, Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + EndActionSequence(tr("Duplicate")); gMainWindow->UpdateTimeline(false, false); - SetSelectionAndFocus(NewPieces, Focus, LC_PIECE_SECTION_POSITION, false); } void lcModel::PaintSelectedPieces() @@ -1745,49 +1748,114 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect { if (!ModelActionSelection) return; - - auto LoadSelection = [this, ModelActionSelection]() + + lcStep Step = ModelActionSelection->GetStep(); + + auto AddToSelection=[this](const std::vector& Objects, lcSelectionMode SelectionMode, lcStep Step) + { + for (lcObject* Object : Objects) + { + if (Object->IsSelected()) + continue; + + Object->SetSelected(true); + + if (Object->IsPiece()) + { + lcPiece* Piece = dynamic_cast(Object); + + SelectGroup(Piece->GetTopGroup(), Step, true); + + std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); + SelectObjects(Pieces, Step, true); + } + } + }; + + auto SetSelectionAndFocus=[this, &AddToSelection](const std::vector& Objects, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode, lcStep Step) + { + DeselectAllObjects(); + + if (Focus) + { + Focus->SetFocused(Section, true); + + if (Focus->IsPiece()) + { + lcPiece* Piece = dynamic_cast(Focus); + + SelectGroup(Piece->GetTopGroup(), Step, true); + + std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); + SelectObjects(Pieces, Step, true); + } + } + + AddToSelection(Objects, SelectionMode, Step); + }; + + auto LoadPreviousSelection = [this, ModelActionSelection, Step, &SetSelectionAndFocus]() { auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetPreviousSelection(this); - SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, false); + SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, lcSelectionMode::Single, Step); }; - lcStep Step = ModelActionSelection->GetStep(); - switch (ModelActionSelection->GetMode()) { case lcModelActionSelectionMode::ClearSelection: if (Apply) DeselectAllObjects(); else - LoadSelection(); + LoadPreviousSelection(); break; case lcModelActionSelectionMode::ClearSelectionAndSetFocus: + case lcModelActionSelectionMode::SetSelectionAndFocus: if (Apply) { - DeselectAllObjects(); + std::vector Objects = ModelActionSelection->GetNewObjects(this); + lcObject* Focus = ModelActionSelection->GetNewFocusObject(this); + uint32_t Section = ModelActionSelection->GetNewFocusSection(); + lcSelectionMode SelectionMode = ModelActionSelection->GetSelectionMode(); - lcObject* NewFocusObject = ModelActionSelection->GetNewFocusObject(this); + SetSelectionAndFocus(Objects, Focus, Section, SelectionMode, Step); + } + else + LoadPreviousSelection(); + break; + + case lcModelActionSelectionMode::SetFocus: + if (Apply) + { + lcObject* Focus = ModelActionSelection->GetNewFocusObject(this); + uint32_t Section = ModelActionSelection->GetNewFocusSection(); + lcSelectionMode SelectionMode = ModelActionSelection->GetSelectionMode(); - if (NewFocusObject) + lcObject* PreviousFocus = GetFocusObject(); + + if (PreviousFocus && PreviousFocus != Focus) + PreviousFocus->SetFocused(PreviousFocus->GetFocusSection(), false); + + if (Focus) { - NewFocusObject->SetFocused(ModelActionSelection->GetNewFocusSection(), true); + const bool WasSelected = Focus->IsSelected(); - if (NewFocusObject->IsPiece()) + Focus->SetFocused(Section, true); + + if (Focus->IsPiece() && !WasSelected) { - lcPiece* Piece = dynamic_cast(NewFocusObject); + lcPiece* Piece = dynamic_cast(Focus); SelectGroup(Piece->GetTopGroup(), Step, true); - std::vector Pieces = GetSelectionModePieces(ModelActionSelection->GetSelectionMode(), Piece, Step); + std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); SelectObjects(Pieces, Step, true); - } + } } } else - LoadSelection(); + LoadPreviousSelection(); break; case lcModelActionSelectionMode::SelectAllPieces: @@ -1798,7 +1866,7 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect Piece->SetSelected(true); } else - LoadSelection(); + LoadPreviousSelection(); break; case lcModelActionSelectionMode::InvertPieceSelection: @@ -1809,9 +1877,21 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect Piece->SetSelected(!Piece->IsSelected()); } else - LoadSelection(); + LoadPreviousSelection(); break; + case lcModelActionSelectionMode::AddToSelection: + if (Apply) + { + std::vector Objects = ModelActionSelection->GetNewObjects(this); + lcSelectionMode SelectionMode = ModelActionSelection->GetSelectionMode(); + + AddToSelection(Objects, SelectionMode, Step); + } + else + LoadPreviousSelection(); + break; + case lcModelActionSelectionMode::RemoveFromSelection: if (Apply) { @@ -1836,21 +1916,21 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect } } else - LoadSelection(); + LoadPreviousSelection(); break; case lcModelActionSelectionMode::Set: - LoadSelection(); + LoadPreviousSelection(); break; case lcModelActionSelectionMode::Save: if (!Apply) - LoadSelection(); + LoadPreviousSelection(); break; case lcModelActionSelectionMode::Restore: if (Apply) - LoadSelection(); + LoadPreviousSelection(); break; } } @@ -3294,10 +3374,11 @@ void lcModel::InlineSelectedModels() QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("No models selected.")); return; } + + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, NewPieces, nullptr, 0, lcSelectionMode::Single); SaveCheckpoint(tr("Inlining")); gMainWindow->UpdateTimeline(false, false); - SetSelectionAndFocus(NewPieces, nullptr, 0, false); } void lcModel::RemoveCameraFromViews(lcCamera* Camera) @@ -4470,13 +4551,39 @@ void lcModel::ClearSelection() EndActionSequence(tr("Selection")); } -void lcModel::ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, lcSelectionMode SelectionMode) +void lcModel::ClearSelectionAndSetFocus(lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Object, Section, SelectionMode); + RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Focus, Section, SelectionMode); EndActionSequence(tr("Selection")); } +void lcModel::SetSelectionAndFocus(const std::vector& Objects, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode) +{ + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, Objects, Focus, Section, SelectionMode); + EndActionSequence(tr("Selection")); +} + +void lcModel::FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelectionMode SelectionMode) +{ + BeginActionSequence(); + + if (Object) + { + if (!Object->IsFocused(Section)) + RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), Object, Section, SelectionMode); + else + RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), nullptr, 0, SelectionMode); + } + else + { + RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), nullptr, 0, SelectionMode); + } + + EndActionSequence(tr("Selection")); +} + void lcModel::SelectAllPieces() { BeginActionSequence(); @@ -4491,6 +4598,13 @@ void lcModel::InvertPieceSelection() EndActionSequence(tr("Selection")); } +void lcModel::AddToSelection(const std::vector& Objects, lcSelectionMode SelectionMode) +{ + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::AddToSelection, Objects, nullptr, 0, SelectionMode); + EndActionSequence(tr("Selection")); +} + void lcModel::RemoveFromSelection(const std::vector& Objects, lcSelectionMode SelectionMode) { BeginActionSequence(); @@ -4534,101 +4648,6 @@ void lcModel::SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select) Piece->SetSelected(Select); } -void lcModel::FocusOrDeselectObject(const lcObjectSection& ObjectSection) -{ - lcObject* FocusObject = GetFocusObject(); - lcObject* Object = ObjectSection.Object; - const quint32 Section = ObjectSection.Section; - - if (Object) - { - const bool WasSelected = Object->IsSelected(); - - if (!Object->IsFocused(Section)) - { - if (FocusObject) - FocusObject->SetFocused(FocusObject->GetFocusSection(), false); - - Object->SetFocused(Section, true); - } - else - Object->SetFocused(Section, false); - - const bool IsSelected = Object->IsSelected(); - - if (Object->IsPiece() && (WasSelected != IsSelected)) - { - lcPiece* Piece = (lcPiece*)Object; - - if (gMainWindow->GetSelectionMode() == lcSelectionMode::Single) - SelectGroup(Piece->GetTopGroup(), mCurrentStep, IsSelected); - else - { - std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), Piece, mCurrentStep); - AddToSelection(Pieces, false, false); - } - } - } - else - { - if (FocusObject) - FocusObject->SetFocused(FocusObject->GetFocusSection(), false); - } - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); -} - -void lcModel::SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode) -{ - DeselectAllObjects(); - - if (Focus) - { - Focus->SetFocused(Section, true); - - if (Focus->IsPiece()) - { - SelectGroup(((lcPiece*)Focus)->GetTopGroup(), mCurrentStep, true); - - if (EnableSelectionMode) - { - std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), dynamic_cast(Focus), mCurrentStep); - AddToSelection(Pieces, false, false); - } - } - } - - AddToSelection(Selection, EnableSelectionMode, true); -} - -void lcModel::AddToSelection(const std::vector& Objects, bool EnableSelectionMode, bool UpdateInterface) -{ - for (lcObject* Object : Objects) - { - const bool WasSelected = Object->IsSelected(); - Object->SetSelected(true); - - if (Object->IsPiece()) - { - if (!WasSelected) - SelectGroup(((lcPiece*)Object)->GetTopGroup(), mCurrentStep, true); - - if (EnableSelectionMode) - { - std::vector Pieces = GetSelectionModePieces(gMainWindow->GetSelectionMode(), dynamic_cast(Object), mCurrentStep); - AddToSelection(Pieces, false, false); - } - } - } - - if (UpdateInterface) - { - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - } -} - void lcModel::HideSelectedPieces() { BeginActionSequence(); @@ -4864,7 +4883,8 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) } if (FindAll) - SetSelectionAndFocus(Selection, nullptr, 0, false); +// SetSelectionAndFocus(Selection, nullptr, 0, false); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, Selection, nullptr, 0, lcSelectionMode::Single); else // ClearSelectionAndSetFocus(Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); @@ -5499,7 +5519,7 @@ void lcModel::ShowSelectByNameDialog() if (Dialog.exec() != QDialog::Accepted) return; - SetSelectionAndFocus(Dialog.mObjects, nullptr, 0, false); + SetSelectionAndFocus(Dialog.mObjects, nullptr, 0, lcSelectionMode::Single); } void lcModel::ShowArrayDialog() @@ -5577,9 +5597,11 @@ void lcModel::ShowArrayDialog() } EndObjectEditAction(std::move(PieceIndices)); + + RecordSelectionAction(lcModelActionSelectionMode::AddToSelection, NewPieces, nullptr, 0, lcSelectionMode::Single); + EndActionSequence(tr("Piece Array")); - AddToSelection(NewPieces, false, true); gMainWindow->UpdateTimeline(false, false); } @@ -5619,10 +5641,12 @@ void lcModel::ShowMinifigDialog() Pieces.emplace_back(Piece); } - EndObjectEditAction(std::move(PieceIndices), { mGroups.size() - 1}); + EndObjectEditAction(std::move(PieceIndices), { mGroups.size() - 1}); + + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, Pieces, nullptr, 0, lcSelectionMode::Single); + EndActionSequence(tr("Add Minifig")); - SetSelectionAndFocus(Pieces, nullptr, 0, false); gMainWindow->UpdateTimeline(false, false); } @@ -5647,8 +5671,6 @@ void lcModel::SetMinifig(const lcMinifig& Minifig) Pieces.emplace_back(Piece); } - - SetSelectionAndFocus(Pieces, nullptr, 0, false); } void lcModel::SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex) diff --git a/common/lc_model.h b/common/lc_model.h index 6da1b7b5..2db436ec 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -324,14 +324,13 @@ public: void GetSelectionInformation(int* Flags, std::vector& Selection, lcObject** Focus) const; void ClearSelection(); - void ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, lcSelectionMode SelectionMode); + void ClearSelectionAndSetFocus(lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode); + void SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode); + void FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelectionMode SelectionMode); void SelectAllPieces(); void InvertPieceSelection(); + void AddToSelection(const std::vector& Objects, lcSelectionMode SelectionMode); void RemoveFromSelection(const std::vector& Objects, lcSelectionMode SelectionMode); - // to update: - void FocusOrDeselectObject(const lcObjectSection& ObjectSection); - void SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode); - void AddToSelection(const std::vector& Objects, bool EnableSelectionMode, bool UpdateInterface); void HideSelectedPieces(); void HideUnselectedPieces(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 347942a6..67de0532 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -244,7 +244,34 @@ bool lcModelActionSelection::HasChanges(const lcModel* Model, const std::vector< const std::vector>& Pieces = Model->GetPieces(); const std::vector>& Cameras = Model->GetCameras(); const std::vector>& Lights = Model->GetLights(); - + + auto HasSelectionChanges=[&Objects, FocusObject, FocusSection](lcObject* CheckObject) + { + if (CheckObject->IsFocused()) + { + if (CheckObject != FocusObject || CheckObject->GetFocusSection() != FocusSection) + return true; + } + else + { + if (CheckObject == FocusObject) + return true; + } + + if (CheckObject == FocusObject || std::find(Objects.begin(), Objects.end(), CheckObject) != Objects.end()) + { + if (!CheckObject->IsSelected()) + return true; + } + else + { + if (CheckObject->IsSelected()) + return true; + } + + return false; + }; + switch (mMode) { case lcModelActionSelectionMode::ClearSelection: @@ -268,6 +295,38 @@ bool lcModelActionSelection::HasChanges(const lcModel* Model, const std::vector< return false; + case lcModelActionSelectionMode::SetFocus: + if (FocusObject) + { + if (!FocusObject->IsFocused(FocusSection)) + return true; + } + else + { + if (Model->GetFocusObject()) + return true; + } + + return false; + + case lcModelActionSelectionMode::SetSelectionAndFocus: + if (FocusObject && !FocusObject->IsFocused(FocusSection)) + return true; + + for (const std::unique_ptr& Piece : Pieces) + if (HasSelectionChanges(Piece.get())) + return true; + + for (const std::unique_ptr& Camera : Cameras) + if (HasSelectionChanges(Camera.get())) + return true; + + for (const std::unique_ptr& Light : Lights) + if (HasSelectionChanges(Light.get())) + return true; + + return false; + case lcModelActionSelectionMode::SelectAllPieces: for (const std::unique_ptr& Piece : Pieces) if (Piece->IsVisible(mStep) && !Piece->IsSelected()) @@ -282,6 +341,13 @@ bool lcModelActionSelection::HasChanges(const lcModel* Model, const std::vector< return false; + case lcModelActionSelectionMode::AddToSelection: + for (lcObject* Object : Objects) + if (!Object->IsSelected()) + return true; + + return false; + case lcModelActionSelectionMode::RemoveFromSelection: for (lcObject* Object : Objects) if (Object->IsSelected()) diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 0fa507cd..edf1de8a 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -23,8 +23,11 @@ enum class lcModelActionSelectionMode { ClearSelection, ClearSelectionAndSetFocus, + SetFocus, + SetSelectionAndFocus, SelectAllPieces, InvertPieceSelection, + AddToSelection, RemoveFromSelection, Set, Save, diff --git a/common/lc_timelinewidget.cpp b/common/lc_timelinewidget.cpp index c01c46c8..50e3ee39 100644 --- a/common/lc_timelinewidget.cpp +++ b/common/lc_timelinewidget.cpp @@ -552,7 +552,7 @@ void lcTimelineWidget::ItemSelectionChanged() UpdateCurrentStepItem(); } - Model->SetSelectionAndFocus(Selection, CurrentPiece, LC_PIECE_SECTION_POSITION, false); + Model->SetSelectionAndFocus(Selection, CurrentPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); mIgnoreUpdates = false; blockSignals(Blocked); } diff --git a/common/lc_view.cpp b/common/lc_view.cpp index a997a32f..9990278c 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2421,11 +2421,11 @@ void lcView::StopTracking(bool Accept) std::vector Objects = FindObjectsInBox(mMouseDownX, mMouseDownY, mMouseX, mMouseY); if (mMouseModifiers & Qt::ControlModifier) - ActiveModel->AddToSelection(Objects, true, true); + ActiveModel->AddToSelection(Objects, lcSelectionMode::Single); else if (mMouseModifiers & Qt::ShiftModifier) ActiveModel->RemoveFromSelection(Objects, lcSelectionMode::Single); else - ActiveModel->SetSelectionAndFocus(Objects, nullptr, 0, true); + ActiveModel->SetSelectionAndFocus(Objects, nullptr, 0, gMainWindow->GetSelectionMode()); } break; @@ -2573,7 +2573,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) lcObjectSection ObjectSection = FindObjectUnderPointer(false, false); if (mMouseModifiers & Qt::ControlModifier) - ActiveModel->FocusOrDeselectObject(ObjectSection); + ActiveModel->FocusOrDeselectObject(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); else if (mMouseModifiers & Qt::ShiftModifier) { if (ObjectSection.Object) @@ -2740,7 +2740,7 @@ void lcView::OnLeftButtonDoubleClick() lcObjectSection ObjectSection = FindObjectUnderPointer(false, false); if (mMouseModifiers & Qt::ControlModifier) - ActiveModel->FocusOrDeselectObject(ObjectSection); + ActiveModel->FocusOrDeselectObject(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); else if (mMouseModifiers & Qt::ShiftModifier) { if (ObjectSection.Object) From daa51ea7003f5862165124be5a243b590cd0d397 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 24 Jan 2026 17:05:48 -0800 Subject: [PATCH 45/93] Keep selected pieces visible when viewing an earlier step. --- common/lc_model.cpp | 81 +++++++++++---------------------------------- 1 file changed, 20 insertions(+), 61 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index bf8ecfbb..ae913696 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1333,7 +1333,7 @@ void lcModel::GetScene(lcScene* Scene, const lcCamera* ViewCamera, bool AllowHig for (const std::unique_ptr& Piece : mPieces) { - if (Piece->IsVisible(mCurrentStep)) + if (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) { if (Piece->IsFocused()) FocusPiece = Piece.get(); @@ -1660,7 +1660,7 @@ void lcModel::SaveStepImages(const QString& BaseName, bool AddStepSuffix, bool Z void lcModel::RayTest(lcObjectRayTest& ObjectRayTest) const { for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep) && (!ObjectRayTest.IgnoreSelected || !Piece->IsSelected())) + if ((Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) && (!ObjectRayTest.IgnoreSelected || !Piece->IsSelected())) Piece->RayTest(ObjectRayTest); if (ObjectRayTest.PiecesOnly) @@ -1678,7 +1678,7 @@ void lcModel::RayTest(lcObjectRayTest& ObjectRayTest) const void lcModel::BoxTest(lcObjectBoxTest& ObjectBoxTest) const { for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep)) + if (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) Piece->BoxTest(ObjectBoxTest); for (const std::unique_ptr& Camera : mCameras) @@ -1873,7 +1873,7 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect if (Apply) { for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(Step)) + if (Piece->IsSelected() || Piece->IsVisible(Step)) Piece->SetSelected(!Piece->IsSelected()); } else @@ -2215,18 +2215,8 @@ void lcModel::SetActive(bool Active) void lcModel::CalculateStep(lcStep Step) { for (const std::unique_ptr& Piece : mPieces) - { Piece->UpdatePosition(Step); - if (Piece->IsSelected()) - { - if (!Piece->IsVisible(Step)) - Piece->SetSelected(false); - else - SelectGroup(Piece->GetTopGroup(), Step, true); - } - } - for (std::unique_ptr& Camera : mCameras) Camera->UpdatePosition(Step); @@ -2295,12 +2285,7 @@ void lcModel::InsertStep(lcStep Step) BeginObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); for (const std::unique_ptr& Piece : mPieces) - { Piece->InsertTime(Step, 1); - - if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - } for (std::unique_ptr& Camera : mCameras) Camera->InsertTime(Step, 1); @@ -2321,12 +2306,7 @@ void lcModel::RemoveStep(lcStep Step) BeginObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); for (const std::unique_ptr& Piece : mPieces) - { Piece->RemoveTime(Step, 1); - - if (Piece->IsSelected() && !Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - } for (std::unique_ptr& Camera : mCameras) Camera->RemoveTime(Step, 1); @@ -2898,11 +2878,10 @@ void lcModel::FocusNextTrainTrack() ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST; ConnectionIndex = (ConnectionIndex + 1) % TrainTrackInfo->GetConnections().size(); } - - FocusPiece->SetFocused(LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, true); - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); + + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); + EndActionSequence(tr("Selection")); } void lcModel::FocusPreviousTrainTrack() @@ -2926,11 +2905,10 @@ void lcModel::FocusPreviousTrainTrack() ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST; ConnectionIndex = (ConnectionIndex + static_cast(TrainTrackInfo->GetConnections().size()) - 1) % TrainTrackInfo->GetConnections().size(); } - - FocusPiece->SetFocused(LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, true); - - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); + + BeginActionSequence(); + RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); + EndActionSequence(tr("Selection")); } void lcModel::RotateFocusedTrainTrack(int Direction) @@ -3195,11 +3173,9 @@ void lcModel::ShowSelectedPiecesLater() Step++; Piece->SetStepShow(Step); - if (!Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - MovedPieces.emplace_back(PieceIt->release()); PieceIt = mPieces.erase(PieceIt); + continue; } } @@ -3218,7 +3194,7 @@ void lcModel::ShowSelectedPiecesLater() SaveCheckpoint(tr("Modifying")); gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); } @@ -3243,9 +3219,6 @@ void lcModel::SetPieceSteps(const std::vector>& Piec mPieces[PieceIdx] = std::unique_ptr(Piece); Piece->SetStepShow(Step); - if (!Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - Modified = true; } } @@ -3255,7 +3228,7 @@ void lcModel::SetPieceSteps(const std::vector>& Piec SaveCheckpoint(tr("Modifying")); UpdateAllViews(); gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateSelectedObjects(false); } } @@ -3794,7 +3767,6 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) void lcModel::SetSelectedPiecesStepShow(lcStep Step) { std::vector MovedPieces; - bool SelectionChanged = false; for (auto PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ) { @@ -3804,12 +3776,6 @@ void lcModel::SetSelectedPiecesStepShow(lcStep Step) { Piece->SetStepShow(Step); - if (!Piece->IsVisible(mCurrentStep)) - { - Piece->SetSelected(false); - SelectionChanged = true; - } - MovedPieces.emplace_back(PieceIt->release()); PieceIt = mPieces.erase(PieceIt); continue; @@ -3830,13 +3796,12 @@ void lcModel::SetSelectedPiecesStepShow(lcStep Step) SaveCheckpoint(tr("Showing Pieces")); UpdateAllViews(); gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(SelectionChanged); + gMainWindow->UpdateSelectedObjects(false); } void lcModel::SetSelectedPiecesStepHide(lcStep Step) { bool Modified = false; - bool SelectionChanged = false; for (const std::unique_ptr& Piece : mPieces) { @@ -3844,12 +3809,6 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) { Piece->SetStepHide(Step); - if (!Piece->IsVisible(mCurrentStep)) - { - Piece->SetSelected(false); - SelectionChanged = true; - } - Modified = true; } } @@ -3859,7 +3818,7 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) SaveCheckpoint(tr("Hiding Pieces")); UpdateAllViews(); gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(SelectionChanged); + gMainWindow->UpdateSelectedObjects(false); } } @@ -4356,7 +4315,7 @@ bool lcModel::GetVisiblePiecesBoundingBox(lcVector3& Min, lcVector3& Max) const for (const std::unique_ptr& Piece : mPieces) { - if (Piece->IsVisible(mCurrentStep)) + if (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) { Piece->CompareBoundingBox(Min, Max); Valid = true; @@ -4371,7 +4330,7 @@ std::vector lcModel::GetPiecesBoundingBoxPoints() const std::vector Points; for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(mCurrentStep)) + if (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) Piece->SubModelAddBoundingBoxPoints(lcMatrix44Identity(), Points); return Points; @@ -4644,7 +4603,7 @@ void lcModel::SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select) return; for (const std::unique_ptr& Piece : mPieces) - if (!Piece->IsSelected() && Piece->IsVisible(Step) && (Piece->GetTopGroup() == TopGroup)) + if (!Piece->IsSelected() && (Piece->GetTopGroup() == TopGroup)) Piece->SetSelected(Select); } From c627e1608ef051217f59a723acf5b4875cf8f2e7 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 25 Jan 2026 23:01:47 -0800 Subject: [PATCH 46/93] Merged selection/focus code in the lcObject class. --- common/camera.cpp | 2 +- common/camera.h | 95 ++--------------------------------------------- common/light.h | 43 +-------------------- common/object.h | 54 +++++++++++++++++++++++---- common/piece.cpp | 2 +- common/piece.h | 43 +-------------------- 6 files changed, 54 insertions(+), 185 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 0f90296a..813a78c4 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -909,7 +909,7 @@ void lcCamera::RemoveKeyFrames() bool lcCamera::SaveUndoData(QDataStream& Stream, const lcModel* Model) const { - static_assert(sizeof(lcCamera) == 240); + static_assert(sizeof(lcCamera) == 248); Q_UNUSED(Model); Stream << m_fovy; diff --git a/common/camera.h b/common/camera.h index c99192e6..6b54da3a 100644 --- a/common/camera.h +++ b/common/camera.h @@ -3,18 +3,9 @@ #include "object.h" #include "lc_math.h" -#define LC_CAMERA_HIDDEN 0x0001 -#define LC_CAMERA_SIMPLE 0x0002 -#define LC_CAMERA_ORTHO 0x0004 -#define LC_CAMERA_POSITION_SELECTED 0x0010 -#define LC_CAMERA_POSITION_FOCUSED 0x0020 -#define LC_CAMERA_TARGET_SELECTED 0x0040 -#define LC_CAMERA_TARGET_FOCUSED 0x0080 -#define LC_CAMERA_UPVECTOR_SELECTED 0x0100 -#define LC_CAMERA_UPVECTOR_FOCUSED 0x0200 - -#define LC_CAMERA_SELECTION_MASK (LC_CAMERA_POSITION_SELECTED | LC_CAMERA_TARGET_SELECTED | LC_CAMERA_UPVECTOR_SELECTED) -#define LC_CAMERA_FOCUS_MASK (LC_CAMERA_POSITION_FOCUSED | LC_CAMERA_TARGET_FOCUSED | LC_CAMERA_UPVECTOR_FOCUSED) +#define LC_CAMERA_HIDDEN 0x01 +#define LC_CAMERA_SIMPLE 0x02 +#define LC_CAMERA_ORTHO 0x04 enum class lcViewpoint { @@ -37,7 +28,7 @@ enum class lcCameraType enum lcCameraSection : quint32 { - LC_CAMERA_SECTION_INVALID = ~0U, + LC_CAMERA_SECTION_INVALID = LC_OBJECT_SECTION_INVALID, LC_CAMERA_SECTION_POSITION = 0, LC_CAMERA_SECTION_TARGET, LC_CAMERA_SECTION_UPVECTOR @@ -94,84 +85,6 @@ public: mState &= ~LC_CAMERA_ORTHO; } - bool IsSelected() const override - { - return (mState & LC_CAMERA_SELECTION_MASK) != 0; - } - - void SetSelected(bool Selected) override - { - if (Selected) - mState |= LC_CAMERA_SELECTION_MASK; - else - mState &= ~(LC_CAMERA_SELECTION_MASK | LC_CAMERA_FOCUS_MASK); - } - - bool IsFocused() const override - { - return (mState & LC_CAMERA_FOCUS_MASK) != 0; - } - - bool IsFocused(quint32 Section) const override - { - switch (Section) - { - case LC_CAMERA_SECTION_POSITION: - return (mState & LC_CAMERA_POSITION_FOCUSED) != 0; - break; - - case LC_CAMERA_SECTION_TARGET: - return (mState & LC_CAMERA_TARGET_FOCUSED) != 0; - break; - - case LC_CAMERA_SECTION_UPVECTOR: - return (mState & LC_CAMERA_UPVECTOR_FOCUSED) != 0; - break; - } - return false; - } - - void SetFocused(quint32 Section, bool Focus) override - { - switch (Section) - { - case LC_CAMERA_SECTION_POSITION: - if (Focus) - mState |= LC_CAMERA_SELECTION_MASK | LC_CAMERA_POSITION_FOCUSED; - else - mState &= ~LC_CAMERA_POSITION_FOCUSED; - break; - - case LC_CAMERA_SECTION_TARGET: - if (Focus) - mState |= LC_CAMERA_SELECTION_MASK | LC_CAMERA_TARGET_FOCUSED; - else - mState &= ~LC_CAMERA_TARGET_FOCUSED; - break; - - case LC_CAMERA_SECTION_UPVECTOR: - if (Focus) - mState |= LC_CAMERA_SELECTION_MASK | LC_CAMERA_UPVECTOR_FOCUSED; - else - mState &= ~LC_CAMERA_UPVECTOR_FOCUSED; - break; - } - } - - quint32 GetFocusSection() const override - { - if (mState & LC_CAMERA_POSITION_FOCUSED) - return LC_CAMERA_SECTION_POSITION; - - if (mState & LC_CAMERA_TARGET_FOCUSED) - return LC_CAMERA_SECTION_TARGET; - - if (mState & LC_CAMERA_UPVECTOR_FOCUSED) - return LC_CAMERA_SECTION_UPVECTOR; - - return LC_CAMERA_SECTION_INVALID; - } - quint32 GetAllowedTransforms() const override { return LC_OBJECT_TRANSFORM_MOVE_XYZ; diff --git a/common/light.h b/common/light.h index 9db0056c..8a935c0f 100644 --- a/common/light.h +++ b/common/light.h @@ -8,7 +8,7 @@ enum lcLightSection : quint32 { - LC_LIGHT_SECTION_INVALID = ~0U, + LC_LIGHT_SECTION_INVALID = LC_OBJECT_SECTION_INVALID, LC_LIGHT_SECTION_POSITION = 0, LC_LIGHT_SECTION_TARGET }; @@ -76,45 +76,6 @@ public: bool SetLightType(lcLightType LightType); - bool IsSelected() const override - { - return mSelected; - } - - void SetSelected(bool Selected) override - { - mSelected = Selected; - - if (!Selected) - mFocusedSection = LC_LIGHT_SECTION_INVALID; - } - - bool IsFocused() const override - { - return mFocusedSection != LC_LIGHT_SECTION_INVALID; - } - - bool IsFocused(quint32 Section) const override - { - return mFocusedSection == Section; - } - - void SetFocused(quint32 Section, bool Focused) override - { - if (Focused) - { - mFocusedSection = Section; - mSelected = true; - } - else - mFocusedSection = LC_LIGHT_SECTION_INVALID; - } - - quint32 GetFocusSection() const override - { - return mFocusedSection; - } - quint32 GetAllowedTransforms() const override { if (IsPointLight()) @@ -373,8 +334,6 @@ protected: lcObjectProperty mPOVRayAreaGridY = lcObjectProperty(2); quint32 mState = 0; - bool mSelected = false; - quint32 mFocusedSection = LC_LIGHT_SECTION_INVALID; lcVector3 mTargetMovePosition = lcVector3(0.0f, 0.0f, 0.0f); lcMatrix44 mWorldMatrix; diff --git a/common/object.h b/common/object.h index 652c9640..c69330f7 100644 --- a/common/object.h +++ b/common/object.h @@ -55,6 +55,8 @@ struct lcObjectBoxTest #define LC_OBJECT_TRANSFORM_SCALE_Z 0x400 #define LC_OBJECT_TRANSFORM_SCALE_XYZ (LC_OBJECT_TRANSFORM_SCALE_X | LC_OBJECT_TRANSFORM_SCALE_Y | LC_OBJECT_TRANSFORM_SCALE_Z) +#define LC_OBJECT_SECTION_INVALID 0xffffffff + class lcObject { public: @@ -86,14 +88,46 @@ public: { return mObjectType; } - - virtual bool IsSelected() const = 0; - virtual void SetSelected(bool Selected) = 0; - virtual bool IsFocused() const = 0; - virtual bool IsFocused(quint32 Section) const = 0; - virtual void SetFocused(quint32 Section, bool Focused) = 0; - virtual quint32 GetFocusSection() const = 0; - + + bool IsSelected() const + { + return mSelected; + } + + void SetSelected(bool Selected) + { + mSelected = Selected; + + if (!Selected) + mFocusedSection = LC_OBJECT_SECTION_INVALID; + } + + bool IsFocused() const + { + return mFocusedSection != LC_OBJECT_SECTION_INVALID; + } + + bool IsFocused(quint32 Section) const + { + return mFocusedSection == Section; + } + + void SetFocused(quint32 Section, bool Focused) + { + if (Focused) + { + mFocusedSection = Section; + mSelected = true; + } + else + mFocusedSection = LC_OBJECT_SECTION_INVALID; + } + + quint32 GetFocusSection() const + { + return mFocusedSection; + } + virtual void UpdatePosition(lcStep Step) = 0; virtual quint32 GetAllowedTransforms() const = 0; virtual lcVector3 GetSectionPosition(quint32 Section) const = 0; @@ -112,4 +146,8 @@ public: private: lcObjectType mObjectType; + +protected: + bool mSelected = false; + quint32 mFocusedSection = LC_OBJECT_SECTION_INVALID; }; diff --git a/common/piece.cpp b/common/piece.cpp index 4ad10d5a..d4d378a6 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -937,7 +937,7 @@ void lcPiece::RemoveKeyFrames() bool lcPiece::SaveUndoData(QDataStream& Stream, const lcModel* Model) const { - static_assert(sizeof(lcPiece) == 376); + static_assert(sizeof(lcPiece) == 384); Stream << mFileLine; Stream << mID; diff --git a/common/piece.h b/common/piece.h index 1db62daf..6241f029 100644 --- a/common/piece.h +++ b/common/piece.h @@ -10,7 +10,7 @@ class PieceInfo; enum lcPieceSection : quint32 { - LC_PIECE_SECTION_INVALID = ~0U, + LC_PIECE_SECTION_INVALID = LC_OBJECT_SECTION_INVALID, LC_PIECE_SECTION_POSITION = 0, LC_PIECE_SECTION_CONTROL_POINT_FIRST, LC_PIECE_SECTION_CONTROL_POINT_LAST = LC_PIECE_SECTION_CONTROL_POINT_FIRST + LC_MAX_CONTROL_POINTS - 1, @@ -36,45 +36,6 @@ public: void CopyProperties(const lcPiece& Other); - bool IsSelected() const override - { - return mSelected; - } - - void SetSelected(bool Selected) override - { - mSelected = Selected; - - if (!Selected) - mFocusedSection = LC_PIECE_SECTION_INVALID; - } - - bool IsFocused() const override - { - return mFocusedSection != LC_PIECE_SECTION_INVALID; - } - - bool IsFocused(quint32 Section) const override - { - return mFocusedSection == Section; - } - - void SetFocused(quint32 Section, bool Focused) override - { - if (Focused) - { - mFocusedSection = Section; - mSelected = true; - } - else - mFocusedSection = LC_PIECE_SECTION_INVALID; - } - - quint32 GetFocusSection() const override - { - return mFocusedSection; - } - quint32 GetAllowedTransforms() const override; lcVector3 GetSectionPosition(quint32 Section) const override; @@ -315,8 +276,6 @@ protected: bool mPivotPointValid = false; bool mHidden = false; - bool mSelected = false; - quint32 mFocusedSection = LC_PIECE_SECTION_INVALID; std::vector mControlPoints; std::vector mTrainTrackConnections; lcMesh* mMesh = nullptr; From 9b7b88923615dea8d312a9520798af73313eadaa Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 30 Jan 2026 18:08:56 -0800 Subject: [PATCH 47/93] Moved selection state to a separate struct. --- common/lc_blenderpreferences.cpp | 1 + common/lc_model.cpp | 22 +++---- common/lc_model.h | 4 +- common/lc_modelaction.cpp | 98 ++++++++++++++++---------------- common/lc_modelaction.h | 21 ++++--- 5 files changed, 76 insertions(+), 70 deletions(-) diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index dd0f7be6..25292a4d 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -26,6 +26,7 @@ #include "lc_http.h" #include "lc_zipfile.h" #include "lc_file.h" +#include "lc_qutils.h" #include "project.h" #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index ae913696..d9def258 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1764,10 +1764,10 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect { lcPiece* Piece = dynamic_cast(Object); - SelectGroup(Piece->GetTopGroup(), Step, true); + SelectGroup(Piece->GetTopGroup(), true); std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); - SelectObjects(Pieces, Step, true); + SelectObjects(Pieces, true); } } }; @@ -1784,10 +1784,10 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect { lcPiece* Piece = dynamic_cast(Focus); - SelectGroup(Piece->GetTopGroup(), Step, true); + SelectGroup(Piece->GetTopGroup(), true); std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); - SelectObjects(Pieces, Step, true); + SelectObjects(Pieces, true); } } @@ -1847,10 +1847,10 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect { lcPiece* Piece = dynamic_cast(Focus); - SelectGroup(Piece->GetTopGroup(), Step, true); + SelectGroup(Piece->GetTopGroup(), true); std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); - SelectObjects(Pieces, Step, true); + SelectObjects(Pieces, true); } } } @@ -1908,10 +1908,10 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect { lcPiece* Piece = dynamic_cast(Object); - SelectGroup(Piece->GetTopGroup(), Step, false); + SelectGroup(Piece->GetTopGroup(), false); std::vector Pieces = GetSelectionModePieces(ModelActionSelection->GetSelectionMode(), Piece, Step); - SelectObjects(Pieces, Step, false); + SelectObjects(Pieces, false); } } } @@ -4583,7 +4583,7 @@ void lcModel::DeselectAllObjects() Light->SetSelected(false); } -void lcModel::SelectObjects(const std::vector& Objects, lcStep Step, bool Select) +void lcModel::SelectObjects(const std::vector& Objects, bool Select) { for (lcObject* Object : Objects) { @@ -4593,11 +4593,11 @@ void lcModel::SelectObjects(const std::vector& Objects, lcStep Step, Object->SetSelected(Select); if (Object->IsPiece()) - SelectGroup(dynamic_cast(Object)->GetTopGroup(), Step, Select); + SelectGroup(dynamic_cast(Object)->GetTopGroup(), Select); } } -void lcModel::SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select) +void lcModel::SelectGroup(lcGroup* TopGroup, bool Select) { if (!TopGroup) return; diff --git a/common/lc_model.h b/common/lc_model.h index 2db436ec..ec699dff 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -428,8 +428,8 @@ protected: std::vector GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece, lcStep Step) const; void DeselectAllObjects(); - void SelectObjects(const std::vector& Objects, lcStep Step, bool Select); - void SelectGroup(lcGroup* TopGroup, lcStep Step, bool Select); + void SelectObjects(const std::vector& Objects, bool Select); + void SelectGroup(lcGroup* TopGroup, bool Select); size_t AddPiece(lcPiece* Piece); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 67de0532..e8a0a647 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -194,7 +194,7 @@ bool lcModelActionSelection::Initialize(const lcModel* Model, const std::vector< mSelectionMode = SelectionMode; - SavePreviousSelection(Model); + SaveState(mStartState, Model); SaveNewObjects(Objects, Model); SaveNewFocusObject(Model, FocusObject, FocusSection); @@ -236,7 +236,7 @@ size_t lcModelActionSelection::GetObjectIndex(const lcObject* Object, const lcMo break; } - return SIZE_T_MAX; + return SIZE_MAX; } bool lcModelActionSelection::HasChanges(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection) const @@ -364,15 +364,12 @@ bool lcModelActionSelection::HasChanges(const lcModel* Model, const std::vector< return true; } -void lcModelActionSelection::SavePreviousSelection(const lcModel* Model) +void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const lcModel* Model) { + State = lcModelActionSelectionState(); + const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - - mPreviousSelectedPieces.clear(); - mPreviousSelectedCameras.clear(); - mPreviousSelectedLights.clear(); + State.SelectedPieces.resize(Pieces.size(), false); for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) { @@ -381,16 +378,19 @@ void lcModelActionSelection::SavePreviousSelection(const lcModel* Model) if (!Piece->IsSelected()) continue; - mPreviousSelectedPieces.push_back(PieceIndex); + State.SelectedPieces[PieceIndex] = true; if (Piece->IsFocused()) { - mPreviousFocusIndex = PieceIndex; - mPreviousFocusSection = Piece->GetFocusSection(); - mPreviousFocusObjectType = lcObjectType::Piece; + State.FocusIndex = PieceIndex; + State.FocusSection = Piece->GetFocusSection(); + State.FocusObjectType = lcObjectType::Piece; } } + const std::vector>& Cameras = Model->GetCameras(); + State.SelectedCameras.resize(Cameras.size(), false); + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) { lcCamera* Camera = Cameras[CameraIndex].get(); @@ -398,16 +398,19 @@ void lcModelActionSelection::SavePreviousSelection(const lcModel* Model) if (!Camera->IsSelected()) continue; - mPreviousSelectedCameras.push_back(CameraIndex); + State.SelectedCameras[CameraIndex] = true; if (Camera->IsFocused()) { - mPreviousFocusIndex = CameraIndex; - mPreviousFocusSection = Camera->GetFocusSection(); - mPreviousFocusObjectType = lcObjectType::Camera; + State.FocusIndex = CameraIndex; + State.FocusSection = Camera->GetFocusSection(); + State.FocusObjectType = lcObjectType::Camera; } } + const std::vector>& Lights = Model->GetLights(); + State.SelectedLights.resize(Lights.size(), false); + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) { lcLight* Light = Lights[LightIndex].get(); @@ -415,11 +418,13 @@ void lcModelActionSelection::SavePreviousSelection(const lcModel* Model) if (!Light->IsSelected()) continue; + State.SelectedLights[LightIndex] = true; + if (Light->IsFocused()) { - mPreviousFocusIndex = LightIndex; - mPreviousFocusSection = Light->GetFocusSection(); - mPreviousFocusObjectType = lcObjectType::Light; + State.FocusIndex = LightIndex; + State.FocusSection = Light->GetFocusSection(); + State.FocusObjectType = lcObjectType::Light; } } } @@ -518,38 +523,35 @@ std::tuple, lcObject*, uint32_t> lcModelActionSelection:: std::vector SelectedObjects; lcObject* FocusObject = nullptr; - for (size_t PieceIndex : mPreviousSelectedPieces) - if (PieceIndex < Pieces.size()) + for (size_t PieceIndex = 0; PieceIndex < mStartState.SelectedPieces.size(); PieceIndex++) + if (mStartState.SelectedPieces[PieceIndex] && PieceIndex < Pieces.size()) SelectedObjects.push_back(Pieces[PieceIndex].get()); - for (size_t CameraIndex : mPreviousSelectedCameras) - if (CameraIndex < Cameras.size()) + for (size_t CameraIndex = 0; CameraIndex < mStartState.SelectedCameras.size(); CameraIndex++) + if (mStartState.SelectedCameras[CameraIndex] && CameraIndex < Cameras.size()) SelectedObjects.push_back(Cameras[CameraIndex].get()); - for (size_t LightIndex : mPreviousSelectedLights) - if (LightIndex < Lights.size()) + for (size_t LightIndex = 0; LightIndex < mStartState.SelectedLights.size(); LightIndex++) + if (mStartState.SelectedLights[LightIndex] && LightIndex < Lights.size()) SelectedObjects.push_back(Lights[LightIndex].get()); - if (mPreviousFocusIndex != SIZE_MAX) + switch (mStartState.FocusObjectType) { - switch (mPreviousFocusObjectType) - { - case lcObjectType::Piece: - if (mPreviousFocusIndex < Pieces.size()) - FocusObject = Pieces[mPreviousFocusIndex].get(); - break; - case lcObjectType::Camera: - if (mPreviousFocusIndex < Cameras.size()) - FocusObject = Cameras[mPreviousFocusIndex].get(); - break; - case lcObjectType::Light: - if (mPreviousFocusIndex < Lights.size()) - FocusObject = Lights[mPreviousFocusIndex].get(); - break; - } + case lcObjectType::Piece: + if (mStartState.FocusIndex < Pieces.size()) + FocusObject = Pieces[mStartState.FocusIndex].get(); + break; + case lcObjectType::Camera: + if (mStartState.FocusIndex < Cameras.size()) + FocusObject = Cameras[mStartState.FocusIndex].get(); + break; + case lcObjectType::Light: + if (mStartState.FocusIndex < Lights.size()) + FocusObject = Lights[mStartState.FocusIndex].get(); + break; } - return { SelectedObjects, FocusObject, mPreviousFocusSection }; + return { SelectedObjects, FocusObject, mStartState.FocusSection }; } lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mode) @@ -582,27 +584,27 @@ bool lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamer break; case lcModelActionObjectEditMode::EditSelectedObjects: - for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) if (Pieces[PieceIndex]->IsSelected()) mPieceIndices.push_back(PieceIndex); - for (uint64_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) if (Cameras[CameraIndex]->IsSelected()) mCameraIndices.push_back(CameraIndex); - for (uint64_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) if (Lights[LightIndex]->IsSelected()) mLightIndices.push_back(LightIndex); break; case lcModelActionObjectEditMode::EditSelectedPieces: - for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) if (Pieces[PieceIndex]->IsSelected()) mPieceIndices.push_back(PieceIndex); break; case lcModelActionObjectEditMode::EditUnselectedPieces: - for (uint64_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) if (!Pieces[PieceIndex]->IsSelected()) mPieceIndices.push_back(PieceIndex); break; diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index edf1de8a..b68868b3 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -34,6 +34,16 @@ enum class lcModelActionSelectionMode Restore }; +struct lcModelActionSelectionState +{ + std::vector SelectedPieces; + std::vector SelectedCameras; + std::vector SelectedLights; + size_t FocusIndex = SIZE_MAX; + uint32_t FocusSection = 0; + lcObjectType FocusObjectType = static_cast(~0); +}; + class lcModelActionSelection : public lcModelAction { public: @@ -67,18 +77,13 @@ public: std::tuple, lcObject*, uint32_t> GetPreviousSelection(const lcModel* Model) const; protected: + static void SaveState(lcModelActionSelectionState& State, const lcModel* Model); static size_t GetObjectIndex(const lcObject* Object, const lcModel* Model); bool HasChanges(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection) const; - void SavePreviousSelection(const lcModel* Model); void SaveNewObjects(const std::vector& Objects, const lcModel* Model); void SaveNewFocusObject(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection); - std::vector mPreviousSelectedPieces; - std::vector mPreviousSelectedCameras; - std::vector mPreviousSelectedLights; - size_t mPreviousFocusIndex = SIZE_MAX; - uint32_t mPreviousFocusSection = 0; - lcObjectType mPreviousFocusObjectType = (lcObjectType)0; + lcModelActionSelectionState mStartState; std::vector> mNewObjects; size_t mNewFocusIndex = SIZE_MAX; @@ -120,8 +125,6 @@ public: } protected: - void SaveState(QByteArray& Buffer); - lcModelActionObjectEditMode mMode; QByteArray mStartBuffer; QByteArray mEndBuffer; From b7ab094635b1a1f7cd0f02f4ac563baebade1ed0 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 30 Jan 2026 19:17:45 -0800 Subject: [PATCH 48/93] Fixed iterator bug in RemoveLights(). --- common/lc_model.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index d9def258..696b1bf9 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -139,7 +139,7 @@ void lcPOVRayOptions::ParseLDrawLine(QTextStream& LineStream) else if (Token == QLatin1String("EXCLUDE_FLOOR")) ExcludeFloor = true; else if (Token == QLatin1String("EXCLUDE_BACKGROUND")) - ExcludeFloor = true; + ExcludeBackground = true; else if (Token == QLatin1String("NO_REFLECTION")) NoReflection = true; else if (Token == QLatin1String("NO_SHADOWS")) @@ -1741,7 +1741,7 @@ void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelect std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode, mCurrentStep); if (ModelActionSelection->Initialize(this, Objects, FocusObject, FocusSection, SelectionMode)) - mActionSequence.emplace_back(std::move(ModelActionSelection)); + mActionSequence.emplace_back(std::move(ModelActionSelection)); } void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply) @@ -1851,7 +1851,7 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); SelectObjects(Pieces, true); - } + } } } else @@ -2297,7 +2297,7 @@ void lcModel::InsertStep(lcStep Step) EndObjectEditAction(); EndActionSequence(tr("Insert Step")); - SetCurrentStep(mCurrentStep); + SetCurrentStep(mCurrentStep); } void lcModel::RemoveStep(lcStep Step) @@ -2820,13 +2820,13 @@ void lcModel::RemoveCameras(const std::vector& CameraIndices) size_t CameraIndex = *CameraIndicesIt; if (CameraIndex >= mCameras.size()) - continue; + continue; - std::vector>::iterator CameraIt = mCameras.begin() + CameraIndex; - - RemoveCameraFromViews(CameraIt->get()); - - mCameras.erase(CameraIt); + std::vector>::iterator CameraIt = mCameras.begin() + CameraIndex; + + RemoveCameraFromViews(CameraIt->get()); + + mCameras.erase(CameraIt); } gMainWindow->UpdateSelectedObjects(true); @@ -2842,16 +2842,16 @@ void lcModel::AddLight(std::unique_ptr Light, size_t LightIndex) void lcModel::RemoveLights(const std::vector& LightIndices) { - for (auto LightIndicesIt = LightIndices.crbegin(); LightIndicesIt != LightIndices.crbegin(); ++LightIndicesIt) + for (auto LightIndicesIt = LightIndices.crbegin(); LightIndicesIt != LightIndices.crend(); ++LightIndicesIt) { size_t LightIndex = *LightIndicesIt; if (LightIndex >= mLights.size()) - return; + continue; - std::vector>::iterator LightIt = mLights.begin() + LightIndex; + std::vector>::iterator LightIt = mLights.begin() + LightIndex; - mLights.erase(LightIt); + mLights.erase(LightIt); } gMainWindow->UpdateSelectedObjects(true); @@ -4913,8 +4913,8 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::ColorPicker: break; - case lcTool::Pan: - case lcTool::Zoom: + case lcTool::Pan: + case lcTool::Zoom: case lcTool::RotateView: case lcTool::Roll: if (!View->GetCamera()->IsSimple()) From ce206cffe8d4030841effa8ff79131239e0317ea Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 31 Jan 2026 13:38:25 -0800 Subject: [PATCH 49/93] Simplified selection history by storing the states instead of changes. --- common/lc_model.cpp | 360 ++++++++++++++------------------------ common/lc_model.h | 10 +- common/lc_modelaction.cpp | 345 ++++++------------------------------ common/lc_modelaction.h | 57 ++---- common/lc_view.cpp | 14 +- 5 files changed, 223 insertions(+), 563 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 696b1bf9..4ae92658 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1230,11 +1230,9 @@ void lcModel::Paste(bool PasteToCurrentStep) SaveCheckpoint(tr("Pasting")); if (SelectedObjects.size() == 1) - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); -// ClearSelectionAndSetFocus(SelectedObjects[0], LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); else RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, SelectedObjects, nullptr, 0, lcSelectionMode::Single); -// SetSelectionAndFocus(SelectedObjects, nullptr, 0, false); CalculateStep(mCurrentStep); gMainWindow->UpdateTimeline(false, false); @@ -1738,9 +1736,57 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) { - std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode, mCurrentStep); + std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode); + bool ForceAdd = false; - if (ModelActionSelection->Initialize(this, Objects, FocusObject, FocusSection, SelectionMode)) + ModelActionSelection->SaveStartState(this); + + switch (ModelActionSelectionMode) + { + case lcModelActionSelectionMode::ClearSelection: + DeselectAllObjects(); + break; + + case lcModelActionSelectionMode::SetSelectionAndFocus: + DeselectAllObjects(); + SetObjectsSelected(Objects, true); + SetFocusedObject(FocusObject, FocusSection, SelectionMode); + break; + + case lcModelActionSelectionMode::SetFocus: + SetFocusedObject(FocusObject, FocusSection, SelectionMode); + break; + + case lcModelActionSelectionMode::SelectAllPieces: + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsVisible(mCurrentStep)) + Piece->SetSelected(true); + break; + + case lcModelActionSelectionMode::InvertPieceSelection: + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) + Piece->SetSelected(!Piece->IsSelected()); + break; + + case lcModelActionSelectionMode::AddToSelection: + SetObjectsSelected(Objects, true); + break; + + case lcModelActionSelectionMode::RemoveFromSelection: + SetObjectsSelected(Objects, false); + break; + + case lcModelActionSelectionMode::Set: + case lcModelActionSelectionMode::Save: + case lcModelActionSelectionMode::Restore: + ForceAdd = true; + break; + } + + ModelActionSelection->SaveEndState(this); + + if (ForceAdd || ModelActionSelection->StateChanged()) mActionSequence.emplace_back(std::move(ModelActionSelection)); } @@ -1749,188 +1795,33 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect if (!ModelActionSelection) return; - lcStep Step = ModelActionSelection->GetStep(); - - auto AddToSelection=[this](const std::vector& Objects, lcSelectionMode SelectionMode, lcStep Step) - { - for (lcObject* Object : Objects) - { - if (Object->IsSelected()) - continue; - - Object->SetSelected(true); - - if (Object->IsPiece()) - { - lcPiece* Piece = dynamic_cast(Object); - - SelectGroup(Piece->GetTopGroup(), true); - - std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); - SelectObjects(Pieces, true); - } - } - }; - - auto SetSelectionAndFocus=[this, &AddToSelection](const std::vector& Objects, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode, lcStep Step) - { - DeselectAllObjects(); - - if (Focus) - { - Focus->SetFocused(Section, true); - - if (Focus->IsPiece()) - { - lcPiece* Piece = dynamic_cast(Focus); - - SelectGroup(Piece->GetTopGroup(), true); - - std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); - SelectObjects(Pieces, true); - } - } - - AddToSelection(Objects, SelectionMode, Step); - }; - - auto LoadPreviousSelection = [this, ModelActionSelection, Step, &SetSelectionAndFocus]() - { - auto [SelectedObjects, FocusObject, FocusSection] = ModelActionSelection->GetPreviousSelection(this); - - SetSelectionAndFocus(SelectedObjects, FocusObject, FocusSection, lcSelectionMode::Single, Step); - }; - switch (ModelActionSelection->GetMode()) { case lcModelActionSelectionMode::ClearSelection: - if (Apply) - DeselectAllObjects(); - else - LoadPreviousSelection(); - break; - - case lcModelActionSelectionMode::ClearSelectionAndSetFocus: case lcModelActionSelectionMode::SetSelectionAndFocus: - if (Apply) - { - std::vector Objects = ModelActionSelection->GetNewObjects(this); - lcObject* Focus = ModelActionSelection->GetNewFocusObject(this); - uint32_t Section = ModelActionSelection->GetNewFocusSection(); - lcSelectionMode SelectionMode = ModelActionSelection->GetSelectionMode(); - - SetSelectionAndFocus(Objects, Focus, Section, SelectionMode, Step); - } - else - LoadPreviousSelection(); - break; - case lcModelActionSelectionMode::SetFocus: - if (Apply) - { - lcObject* Focus = ModelActionSelection->GetNewFocusObject(this); - uint32_t Section = ModelActionSelection->GetNewFocusSection(); - lcSelectionMode SelectionMode = ModelActionSelection->GetSelectionMode(); - - lcObject* PreviousFocus = GetFocusObject(); - - if (PreviousFocus && PreviousFocus != Focus) - PreviousFocus->SetFocused(PreviousFocus->GetFocusSection(), false); - - if (Focus) - { - const bool WasSelected = Focus->IsSelected(); - - Focus->SetFocused(Section, true); - - if (Focus->IsPiece() && !WasSelected) - { - lcPiece* Piece = dynamic_cast(Focus); - - SelectGroup(Piece->GetTopGroup(), true); - - std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece, Step); - SelectObjects(Pieces, true); - } - } - } - else - LoadPreviousSelection(); - break; - case lcModelActionSelectionMode::SelectAllPieces: - if (Apply) - { - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(Step)) - Piece->SetSelected(true); - } - else - LoadPreviousSelection(); - break; - case lcModelActionSelectionMode::InvertPieceSelection: - if (Apply) - { - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsSelected() || Piece->IsVisible(Step)) - Piece->SetSelected(!Piece->IsSelected()); - } - else - LoadPreviousSelection(); - break; - case lcModelActionSelectionMode::AddToSelection: - if (Apply) - { - std::vector Objects = ModelActionSelection->GetNewObjects(this); - lcSelectionMode SelectionMode = ModelActionSelection->GetSelectionMode(); - - AddToSelection(Objects, SelectionMode, Step); - } - else - LoadPreviousSelection(); - break; - case lcModelActionSelectionMode::RemoveFromSelection: if (Apply) - { - std::vector Objects = ModelActionSelection->GetNewObjects(this); - - for (lcObject* Object : Objects) - { - if (!Object->IsSelected()) - continue; - - Object->SetSelected(false); - - if (Object->IsPiece()) - { - lcPiece* Piece = dynamic_cast(Object); - - SelectGroup(Piece->GetTopGroup(), false); - - std::vector Pieces = GetSelectionModePieces(ModelActionSelection->GetSelectionMode(), Piece, Step); - SelectObjects(Pieces, false); - } - } - } + ModelActionSelection->LoadEndState(this); else - LoadPreviousSelection(); + ModelActionSelection->LoadStartState(this); break; case lcModelActionSelectionMode::Set: - LoadPreviousSelection(); + ModelActionSelection->LoadStartState(this); break; case lcModelActionSelectionMode::Save: if (!Apply) - LoadPreviousSelection(); + ModelActionSelection->LoadStartState(this); break; case lcModelActionSelectionMode::Restore: if (Apply) - LoadPreviousSelection(); + ModelActionSelection->LoadStartState(this); break; } } @@ -2099,8 +1990,6 @@ void lcModel::EndActionSequence(const QString& Description) if (mActionSequence.empty()) return; - RunActionSequence(mActionSequence, true); - std::unique_ptr ModelHistoryEntry = std::make_unique(lcModelHistoryEntry()); ModelHistoryEntry->Description = Description; @@ -2111,6 +2000,8 @@ void lcModel::EndActionSequence(const QString& Description) gMainWindow->UpdateModified(IsModified()); gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); + + UpdateAllViews(); } void lcModel::DiscardActionSequence() @@ -2743,8 +2634,7 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) } gMainWindow->UpdateTimeline(false, false); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); -// ClearSelectionAndSetFocus(Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); SaveCheckpoint(tr("Adding Piece")); @@ -3295,8 +3185,8 @@ void lcModel::MoveSelectionToModel(lcModel* Model) SaveCheckpoint(tr("New Model")); gMainWindow->UpdateTimeline(false, false); -// ClearSelectionAndSetFocus(ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); } void lcModel::InlineSelectedModels() @@ -4470,39 +4360,6 @@ void lcModel::GetSelectionInformation(int* Flags, std::vector& Select } } -std::vector lcModel::GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece, lcStep Step) const -{ - const PieceInfo* Info = SelectedPiece->mPieceInfo; - const int ColorIndex = SelectedPiece->GetColorIndex(); - std::vector Pieces; - - switch (SelectionMode) - { - case lcSelectionMode::Single: - break; - - case lcSelectionMode::Piece: - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(Step) && Piece->mPieceInfo == Info && Piece.get() != SelectedPiece) - Pieces.emplace_back(Piece.get()); - break; - - case lcSelectionMode::Color: - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(Step) && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) - Pieces.emplace_back(Piece.get()); - break; - - case lcSelectionMode::PieceColor: - for (const std::unique_ptr& Piece : mPieces) - if (Piece->IsVisible(Step) && Piece->mPieceInfo == Info && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) - Pieces.emplace_back(Piece.get()); - break; - } - - return Pieces; -} - void lcModel::ClearSelection() { BeginActionSequence(); @@ -4510,13 +4367,6 @@ void lcModel::ClearSelection() EndActionSequence(tr("Selection")); } -void lcModel::ClearSelectionAndSetFocus(lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode) -{ - BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Focus, Section, SelectionMode); - EndActionSequence(tr("Selection")); -} - void lcModel::SetSelectionAndFocus(const std::vector& Objects, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode) { BeginActionSequence(); @@ -4557,20 +4407,53 @@ void lcModel::InvertPieceSelection() EndActionSequence(tr("Selection")); } -void lcModel::AddToSelection(const std::vector& Objects, lcSelectionMode SelectionMode) +void lcModel::AddToSelection(const std::vector& Objects) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::AddToSelection, Objects, nullptr, 0, SelectionMode); + RecordSelectionAction(lcModelActionSelectionMode::AddToSelection, Objects, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } -void lcModel::RemoveFromSelection(const std::vector& Objects, lcSelectionMode SelectionMode) +void lcModel::RemoveFromSelection(const std::vector& Objects) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::RemoveFromSelection, Objects, nullptr, 0, SelectionMode); + RecordSelectionAction(lcModelActionSelectionMode::RemoveFromSelection, Objects, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } +std::vector lcModel::GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece) const +{ + const PieceInfo* Info = SelectedPiece->mPieceInfo; + const int ColorIndex = SelectedPiece->GetColorIndex(); + std::vector Pieces; + + switch (SelectionMode) + { + case lcSelectionMode::Single: + break; + + case lcSelectionMode::Piece: + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsVisible(mCurrentStep) && Piece->mPieceInfo == Info && Piece.get() != SelectedPiece) + Pieces.emplace_back(Piece.get()); + break; + + case lcSelectionMode::Color: + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsVisible(mCurrentStep) && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) + Pieces.emplace_back(Piece.get()); + break; + + case lcSelectionMode::PieceColor: + for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsVisible(mCurrentStep) && Piece->mPieceInfo == Info && Piece->GetColorIndex() == ColorIndex && Piece.get() != SelectedPiece) + Pieces.emplace_back(Piece.get()); + break; + } + + return Pieces; +} + void lcModel::DeselectAllObjects() { for (const std::unique_ptr& Piece : mPieces) @@ -4583,17 +4466,46 @@ void lcModel::DeselectAllObjects() Light->SetSelected(false); } -void lcModel::SelectObjects(const std::vector& Objects, bool Select) +void lcModel::SetFocusedObject(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) +{ + lcObject* PreviousFocus = GetFocusObject(); + + if (PreviousFocus) + PreviousFocus->SetFocused(PreviousFocus->GetFocusSection(), false); + + if (FocusObject) + { + lcPiece* Piece = dynamic_cast(FocusObject); + + if (Piece) + { + if (!Piece->IsSelected()) + SetObjectsSelected({ Piece }, true); + + std::vector Pieces = GetSelectionModePieces(SelectionMode, Piece); + + SetObjectsSelected(Pieces, true); + } + + FocusObject->SetFocused(FocusSection, true); + } +} + +void lcModel::SetObjectsSelected(const std::vector& Objects, bool Selected) { for (lcObject* Object : Objects) { - if (Object->IsSelected() == Select) + if (Object->IsSelected() == Selected) continue; - Object->SetSelected(Select); + Object->SetSelected(Selected); if (Object->IsPiece()) - SelectGroup(dynamic_cast(Object)->GetTopGroup(), Select); + { + lcPiece* Piece = dynamic_cast(Object); + + SelectGroup(Piece->GetTopGroup(), Selected); + } } } @@ -4842,11 +4754,9 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) } if (FindAll) -// SetSelectionAndFocus(Selection, nullptr, 0, false); RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, Selection, nullptr, 0, lcSelectionMode::Single); else -// ClearSelectionAndSetFocus(Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); if (ReplacedCount) { @@ -5035,7 +4945,7 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece EndObjectEditAction(std::move(PieceIndices)); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Add Piece")); @@ -5057,7 +4967,7 @@ void lcModel::InsertCameraToolClicked(const lcVector3& Position) EndObjectEditAction({ mCameras.size() - 1 }); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Add Camera")); } @@ -5098,7 +5008,7 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh EndObjectEditAction({ mLights.size() - 1 }); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelectionAndSetFocus, std::vector(), Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); + RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(ActionName); } diff --git a/common/lc_model.h b/common/lc_model.h index ec699dff..98482d7a 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -324,13 +324,12 @@ public: void GetSelectionInformation(int* Flags, std::vector& Selection, lcObject** Focus) const; void ClearSelection(); - void ClearSelectionAndSetFocus(lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode); void SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode); void FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelectionMode SelectionMode); void SelectAllPieces(); void InvertPieceSelection(); - void AddToSelection(const std::vector& Objects, lcSelectionMode SelectionMode); - void RemoveFromSelection(const std::vector& Objects, lcSelectionMode SelectionMode); + void AddToSelection(const std::vector& Objects); + void RemoveFromSelection(const std::vector& Objects); void HideSelectedPieces(); void HideUnselectedPieces(); @@ -426,9 +425,10 @@ protected: bool RemoveSelectedObjects(); void RemoveCameraFromViews(lcCamera* Camera); - std::vector GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece, lcStep Step) const; + std::vector GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece) const; void DeselectAllObjects(); - void SelectObjects(const std::vector& Objects, bool Select); + void SetFocusedObject(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + void SetObjectsSelected(const std::vector& Objects, bool Selected); void SelectGroup(lcGroup* TopGroup, bool Select); size_t AddPiece(lcPiece* Piece); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index e8a0a647..db3e66d5 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -182,186 +182,34 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, return true; } -lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode, lcStep Step) - : mMode(Mode), mStep(Step) +lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode) + : mMode(Mode) { } -bool lcModelActionSelection::Initialize(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) +void lcModelActionSelection::SaveStartState(const lcModel* Model) { - if (!HasChanges(Model, Objects, FocusObject, FocusSection)) - return false; - - mSelectionMode = SelectionMode; - SaveState(mStartState, Model); - SaveNewObjects(Objects, Model); - SaveNewFocusObject(Model, FocusObject, FocusSection); - - return true; } -size_t lcModelActionSelection::GetObjectIndex(const lcObject* Object, const lcModel* Model) +void lcModelActionSelection::SaveEndState(const lcModel* Model) { - switch (Object->GetType()) - { - case lcObjectType::Piece: - { - const std::vector>& Pieces = Model->GetPieces(); - - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - if (Pieces[PieceIndex].get() == Object) - return PieceIndex; - } - break; - - case lcObjectType::Camera: - { - const std::vector>& Cameras = Model->GetCameras(); - - for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) - if (Cameras[CameraIndex].get() == Object) - return CameraIndex; - } - break; - - case lcObjectType::Light: - { - const std::vector>& Lights = Model->GetLights(); - - for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) - if (Lights[LightIndex].get() == Object) - return LightIndex; - } - break; - } - - return SIZE_MAX; + SaveState(mEndState, Model); } -bool lcModelActionSelection::HasChanges(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection) const +void lcModelActionSelection::LoadStartState(lcModel* Model) const { - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - - auto HasSelectionChanges=[&Objects, FocusObject, FocusSection](lcObject* CheckObject) - { - if (CheckObject->IsFocused()) - { - if (CheckObject != FocusObject || CheckObject->GetFocusSection() != FocusSection) - return true; - } - else - { - if (CheckObject == FocusObject) - return true; - } - - if (CheckObject == FocusObject || std::find(Objects.begin(), Objects.end(), CheckObject) != Objects.end()) - { - if (!CheckObject->IsSelected()) - return true; - } - else - { - if (CheckObject->IsSelected()) - return true; - } - - return false; - }; - - switch (mMode) - { - case lcModelActionSelectionMode::ClearSelection: - return Model->AnyObjectsSelected(); - - case lcModelActionSelectionMode::ClearSelectionAndSetFocus: - if (FocusObject && !FocusObject->IsFocused(FocusSection)) - return true; - - for (const std::unique_ptr& Piece : Pieces) - if (Piece->IsSelected() && Piece.get() != FocusObject) - return true; - - for (const std::unique_ptr& Camera : Cameras) - if (Camera->IsSelected() && Camera.get() != FocusObject) - return true; - - for (const std::unique_ptr& Light : Lights) - if (Light->IsSelected() && Light.get() != FocusObject) - return true; - - return false; - - case lcModelActionSelectionMode::SetFocus: - if (FocusObject) - { - if (!FocusObject->IsFocused(FocusSection)) - return true; - } - else - { - if (Model->GetFocusObject()) - return true; - } - - return false; - - case lcModelActionSelectionMode::SetSelectionAndFocus: - if (FocusObject && !FocusObject->IsFocused(FocusSection)) - return true; + LoadState(mStartState, Model); +} - for (const std::unique_ptr& Piece : Pieces) - if (HasSelectionChanges(Piece.get())) - return true; - - for (const std::unique_ptr& Camera : Cameras) - if (HasSelectionChanges(Camera.get())) - return true; - - for (const std::unique_ptr& Light : Lights) - if (HasSelectionChanges(Light.get())) - return true; - - return false; +void lcModelActionSelection::LoadEndState(lcModel* Model) const +{ + LoadState(mEndState, Model); +} - case lcModelActionSelectionMode::SelectAllPieces: - for (const std::unique_ptr& Piece : Pieces) - if (Piece->IsVisible(mStep) && !Piece->IsSelected()) - return true; - - return false; - - case lcModelActionSelectionMode::InvertPieceSelection: - for (const std::unique_ptr& Piece : Pieces) - if (Piece->IsVisible(mStep)) - return true; - - return false; - - case lcModelActionSelectionMode::AddToSelection: - for (lcObject* Object : Objects) - if (!Object->IsSelected()) - return true; - - return false; - - case lcModelActionSelectionMode::RemoveFromSelection: - for (lcObject* Object : Objects) - if (Object->IsSelected()) - return true; - - return false; - - case lcModelActionSelectionMode::Set: - case lcModelActionSelectionMode::Save: - case lcModelActionSelectionMode::Restore: - break; - } - - return true; +bool lcModelActionSelection::StateChanged() const +{ + return mStartState != mEndState; } void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const lcModel* Model) @@ -369,7 +217,7 @@ void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const State = lcModelActionSelectionState(); const std::vector>& Pieces = Model->GetPieces(); - State.SelectedPieces.resize(Pieces.size(), false); + State.PieceSelection.resize(Pieces.size(), false); for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) { @@ -378,7 +226,7 @@ void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const if (!Piece->IsSelected()) continue; - State.SelectedPieces[PieceIndex] = true; + State.PieceSelection[PieceIndex] = true; if (Piece->IsFocused()) { @@ -389,7 +237,7 @@ void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const } const std::vector>& Cameras = Model->GetCameras(); - State.SelectedCameras.resize(Cameras.size(), false); + State.CameraSelection.resize(Cameras.size(), false); for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) { @@ -398,7 +246,7 @@ void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const if (!Camera->IsSelected()) continue; - State.SelectedCameras[CameraIndex] = true; + State.CameraSelection[CameraIndex] = true; if (Camera->IsFocused()) { @@ -409,7 +257,7 @@ void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const } const std::vector>& Lights = Model->GetLights(); - State.SelectedLights.resize(Lights.size(), false); + State.LightSelection.resize(Lights.size(), false); for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) { @@ -418,7 +266,7 @@ void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const if (!Light->IsSelected()) continue; - State.SelectedLights[LightIndex] = true; + State.LightSelection[LightIndex] = true; if (Light->IsFocused()) { @@ -429,129 +277,50 @@ void lcModelActionSelection::SaveState(lcModelActionSelectionState& State, const } } -void lcModelActionSelection::SaveNewObjects(const std::vector& Objects, const lcModel* Model) +void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, lcModel* Model) { - mNewObjects.clear(); - mNewObjects.reserve(Objects.size()); - - for (lcObject* Object : Objects) - mNewObjects.emplace_back(GetObjectIndex(Object, Model), Object->GetType()); -} + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); -void lcModelActionSelection::SaveNewFocusObject(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection) -{ - if (!FocusObject) + if (Pieces.size() != State.PieceSelection.size() || Cameras.size() != State.CameraSelection.size() || Lights.size() != State.LightSelection.size()) return; - mNewFocusSection = FocusSection; - mNewFocusObjectType = FocusObject->GetType(); - mNewFocusIndex = GetObjectIndex(FocusObject, Model); -} - -std::vector lcModelActionSelection::GetNewObjects(const lcModel* Model) const -{ - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - std::vector Objects; - - for (auto [ObjectIndex, ObjectType] : mNewObjects) + for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) { - switch (ObjectType) - { - case lcObjectType::Piece: - if (ObjectIndex < Pieces.size()) - Objects.push_back(Pieces[ObjectIndex].get()); - break; - - case lcObjectType::Camera: - if (ObjectIndex < Cameras.size()) - Objects.push_back(Cameras[ObjectIndex].get()); - break; - - case lcObjectType::Light: - if (ObjectIndex < Lights.size()) - Objects.push_back(Lights[ObjectIndex].get()); - break; - } - } + lcPiece* Piece = Pieces[PieceIndex].get(); + + Piece->SetSelected(State.PieceSelection[PieceIndex]); - return Objects; -} - -lcObject* lcModelActionSelection::GetNewFocusObject(const lcModel* Model) const -{ - switch (mNewFocusObjectType) - { - case lcObjectType::Piece: - { - const std::vector>& Pieces = Model->GetPieces(); - - if (mNewFocusIndex < Pieces.size()) - return Pieces[mNewFocusIndex].get(); - } - break; - - case lcObjectType::Camera: - { - const std::vector>& Cameras = Model->GetCameras(); - - if (mNewFocusIndex < Cameras.size()) - return Cameras[mNewFocusIndex].get(); - } - break; - - case lcObjectType::Light: - { - const std::vector>& Lights = Model->GetLights(); - - if (mNewFocusIndex < Lights.size()) - return Lights[mNewFocusIndex].get(); - } - break; - } - - return nullptr; -} - -std::tuple, lcObject*, uint32_t> lcModelActionSelection::GetPreviousSelection(const lcModel* Model) const -{ - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - - std::vector SelectedObjects; - lcObject* FocusObject = nullptr; - - for (size_t PieceIndex = 0; PieceIndex < mStartState.SelectedPieces.size(); PieceIndex++) - if (mStartState.SelectedPieces[PieceIndex] && PieceIndex < Pieces.size()) - SelectedObjects.push_back(Pieces[PieceIndex].get()); - - for (size_t CameraIndex = 0; CameraIndex < mStartState.SelectedCameras.size(); CameraIndex++) - if (mStartState.SelectedCameras[CameraIndex] && CameraIndex < Cameras.size()) - SelectedObjects.push_back(Cameras[CameraIndex].get()); - - for (size_t LightIndex = 0; LightIndex < mStartState.SelectedLights.size(); LightIndex++) - if (mStartState.SelectedLights[LightIndex] && LightIndex < Lights.size()) - SelectedObjects.push_back(Lights[LightIndex].get()); - - switch (mStartState.FocusObjectType) - { - case lcObjectType::Piece: - if (mStartState.FocusIndex < Pieces.size()) - FocusObject = Pieces[mStartState.FocusIndex].get(); - break; - case lcObjectType::Camera: - if (mStartState.FocusIndex < Cameras.size()) - FocusObject = Cameras[mStartState.FocusIndex].get(); - break; - case lcObjectType::Light: - if (mStartState.FocusIndex < Lights.size()) - FocusObject = Lights[mStartState.FocusIndex].get(); - break; + if (State.FocusObjectType == lcObjectType::Piece && State.FocusIndex == PieceIndex) + Piece->SetFocused(State.FocusSection, true); + else + Piece->SetFocused(State.FocusSection, false); } - return { SelectedObjects, FocusObject, mStartState.FocusSection }; + for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) + { + lcCamera* Camera = Cameras[CameraIndex].get(); + + Camera->SetSelected(State.CameraSelection[CameraIndex]); + + if (State.FocusObjectType == lcObjectType::Camera && State.FocusIndex == CameraIndex) + Camera->SetFocused(State.FocusSection, true); + else + Camera->SetFocused(State.FocusSection, false); + } + + for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) + { + lcLight* Light = Lights[LightIndex].get(); + + Light->SetSelected(State.LightSelection[LightIndex]); + + if (State.FocusObjectType == lcObjectType::Light && State.FocusIndex == LightIndex) + Light->SetFocused(State.FocusSection, true); + else + Light->SetFocused(State.FocusSection, false); + } } lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mode) diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index b68868b3..7266abcf 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -22,7 +22,6 @@ protected: enum class lcModelActionSelectionMode { ClearSelection, - ClearSelectionAndSetFocus, SetFocus, SetSelectionAndFocus, SelectAllPieces, @@ -36,63 +35,45 @@ enum class lcModelActionSelectionMode struct lcModelActionSelectionState { - std::vector SelectedPieces; - std::vector SelectedCameras; - std::vector SelectedLights; + std::vector PieceSelection; + std::vector CameraSelection; + std::vector LightSelection; size_t FocusIndex = SIZE_MAX; uint32_t FocusSection = 0; lcObjectType FocusObjectType = static_cast(~0); + + bool operator!=(const lcModelActionSelectionState& Other) const + { + return PieceSelection != Other.PieceSelection || CameraSelection != Other.CameraSelection || LightSelection != Other.LightSelection || + FocusIndex != Other.FocusIndex || FocusSection != Other.FocusSection || FocusObjectType != Other.FocusObjectType; + } }; class lcModelActionSelection : public lcModelAction { public: - lcModelActionSelection(lcModelActionSelectionMode Mode, lcStep Step); + lcModelActionSelection(lcModelActionSelectionMode Mode); virtual ~lcModelActionSelection() = default; - - bool Initialize(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); - + lcModelActionSelectionMode GetMode() const { return mMode; } - lcStep GetStep() const - { - return mStep; - } - - lcSelectionMode GetSelectionMode() const - { - return mSelectionMode; - } - - uint32_t GetNewFocusSection() const - { - return mNewFocusSection; - } - - std::vector GetNewObjects(const lcModel* Model) const; - lcObject* GetNewFocusObject(const lcModel* Model) const; - std::tuple, lcObject*, uint32_t> GetPreviousSelection(const lcModel* Model) const; + void SaveStartState(const lcModel* Model); + void SaveEndState(const lcModel* Model); + void LoadStartState(lcModel* Model) const; + void LoadEndState(lcModel* Model) const; + + bool StateChanged() const; protected: static void SaveState(lcModelActionSelectionState& State, const lcModel* Model); - static size_t GetObjectIndex(const lcObject* Object, const lcModel* Model); - bool HasChanges(const lcModel* Model, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection) const; - void SaveNewObjects(const std::vector& Objects, const lcModel* Model); - void SaveNewFocusObject(const lcModel* Model, lcObject* FocusObject, uint32_t FocusSection); + static void LoadState(const lcModelActionSelectionState& State, lcModel* Model); lcModelActionSelectionState mStartState; - - std::vector> mNewObjects; - size_t mNewFocusIndex = SIZE_MAX; - uint32_t mNewFocusSection = 0; - lcObjectType mNewFocusObjectType = (lcObjectType)0; - lcSelectionMode mSelectionMode = (lcSelectionMode)0; - + lcModelActionSelectionState mEndState; lcModelActionSelectionMode mMode; - lcStep mStep; }; enum class lcModelActionObjectEditMode diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 9990278c..eeee97ac 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -2421,9 +2421,9 @@ void lcView::StopTracking(bool Accept) std::vector Objects = FindObjectsInBox(mMouseDownX, mMouseDownY, mMouseX, mMouseY); if (mMouseModifiers & Qt::ControlModifier) - ActiveModel->AddToSelection(Objects, lcSelectionMode::Single); + ActiveModel->AddToSelection(Objects); else if (mMouseModifiers & Qt::ShiftModifier) - ActiveModel->RemoveFromSelection(Objects, lcSelectionMode::Single); + ActiveModel->RemoveFromSelection(Objects); else ActiveModel->SetSelectionAndFocus(Objects, nullptr, 0, gMainWindow->GetSelectionMode()); } @@ -2577,10 +2577,10 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) else if (mMouseModifiers & Qt::ShiftModifier) { if (ObjectSection.Object) - ActiveModel->RemoveFromSelection({ ObjectSection.Object }, gMainWindow->GetSelectionMode()); + ActiveModel->RemoveFromSelection({ ObjectSection.Object }); } else - ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); + ActiveModel->SetSelectionAndFocus(std::vector(), ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); StartTracking(TrackButton); } @@ -2646,7 +2646,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) ObjectSection.Object = Focus; ObjectSection.Section = mTrackToolSection; - ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); + ActiveModel->SetSelectionAndFocus(std::vector(), ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); } break; @@ -2744,10 +2744,10 @@ void lcView::OnLeftButtonDoubleClick() else if (mMouseModifiers & Qt::ShiftModifier) { if (ObjectSection.Object) - ActiveModel->RemoveFromSelection({ ObjectSection.Object }, gMainWindow->GetSelectionMode()); + ActiveModel->RemoveFromSelection({ ObjectSection.Object }); } else - ActiveModel->ClearSelectionAndSetFocus(ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); + ActiveModel->SetSelectionAndFocus(std::vector(), ObjectSection.Object, ObjectSection.Section, gMainWindow->GetSelectionMode()); } void lcView::OnMiddleButtonDown() From 966c7abf555e20eb8c5e65e723bf655a8961b11a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 31 Jan 2026 13:44:20 -0800 Subject: [PATCH 50/93] Removed deprecated selection modes. --- common/lc_model.cpp | 46 +++++---------------------------------- common/lc_modelaction.cpp | 5 ----- common/lc_modelaction.h | 13 ++--------- 3 files changed, 7 insertions(+), 57 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 4ae92658..2b612cc9 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1736,8 +1736,7 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) { - std::unique_ptr ModelActionSelection = std::make_unique(ModelActionSelectionMode); - bool ForceAdd = false; + std::unique_ptr ModelActionSelection = std::make_unique(); ModelActionSelection->SaveStartState(this); @@ -1776,17 +1775,11 @@ void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelect case lcModelActionSelectionMode::RemoveFromSelection: SetObjectsSelected(Objects, false); break; - - case lcModelActionSelectionMode::Set: - case lcModelActionSelectionMode::Save: - case lcModelActionSelectionMode::Restore: - ForceAdd = true; - break; } ModelActionSelection->SaveEndState(this); - if (ForceAdd || ModelActionSelection->StateChanged()) + if (ModelActionSelection->StateChanged()) mActionSequence.emplace_back(std::move(ModelActionSelection)); } @@ -1795,35 +1788,10 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect if (!ModelActionSelection) return; - switch (ModelActionSelection->GetMode()) - { - case lcModelActionSelectionMode::ClearSelection: - case lcModelActionSelectionMode::SetSelectionAndFocus: - case lcModelActionSelectionMode::SetFocus: - case lcModelActionSelectionMode::SelectAllPieces: - case lcModelActionSelectionMode::InvertPieceSelection: - case lcModelActionSelectionMode::AddToSelection: - case lcModelActionSelectionMode::RemoveFromSelection: - if (Apply) - ModelActionSelection->LoadEndState(this); - else - ModelActionSelection->LoadStartState(this); - break; - - case lcModelActionSelectionMode::Set: + if (Apply) + ModelActionSelection->LoadEndState(this); + else ModelActionSelection->LoadStartState(this); - break; - - case lcModelActionSelectionMode::Save: - if (!Apply) - ModelActionSelection->LoadStartState(this); - break; - - case lcModelActionSelectionMode::Restore: - if (Apply) - ModelActionSelection->LoadStartState(this); - break; - } } void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera) @@ -2272,9 +2240,7 @@ void lcModel::GroupSelection() BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore, std::vector(), nullptr, 0, lcSelectionMode::Single); RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, Dialog.mName); - RecordSelectionAction(lcModelActionSelectionMode::Save, std::vector(), nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Group")); } @@ -2306,9 +2272,7 @@ void lcModel::UngroupSelection() BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::Restore, std::vector(), nullptr, 0, lcSelectionMode::Single); RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Ungroup, QString()); - RecordSelectionAction(lcModelActionSelectionMode::Save, std::vector(), nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Ungroup")); } diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index db3e66d5..1cdf8627 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -182,11 +182,6 @@ bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, return true; } -lcModelActionSelection::lcModelActionSelection(lcModelActionSelectionMode Mode) - : mMode(Mode) -{ -} - void lcModelActionSelection::SaveStartState(const lcModel* Model) { SaveState(mStartState, Model); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 7266abcf..132ff7f2 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -27,10 +27,7 @@ enum class lcModelActionSelectionMode SelectAllPieces, InvertPieceSelection, AddToSelection, - RemoveFromSelection, - Set, - Save, - Restore + RemoveFromSelection }; struct lcModelActionSelectionState @@ -52,13 +49,8 @@ struct lcModelActionSelectionState class lcModelActionSelection : public lcModelAction { public: - lcModelActionSelection(lcModelActionSelectionMode Mode); + lcModelActionSelection() = default; virtual ~lcModelActionSelection() = default; - - lcModelActionSelectionMode GetMode() const - { - return mMode; - } void SaveStartState(const lcModel* Model); void SaveEndState(const lcModel* Model); @@ -73,7 +65,6 @@ protected: lcModelActionSelectionState mStartState; lcModelActionSelectionState mEndState; - lcModelActionSelectionMode mMode; }; enum class lcModelActionObjectEditMode From e2a1ada4df972adf15939c2266f8f924f577e608 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 1 Feb 2026 21:48:58 -0800 Subject: [PATCH 51/93] Removed lcModelActionSelectionMode. --- common/lc_model.cpp | 121 ++++++++++++++++++++++------------------ common/lc_model.h | 11 +++- common/lc_modelaction.h | 11 ---- 3 files changed, 77 insertions(+), 66 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2b612cc9..cc8dc9f4 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1230,9 +1230,9 @@ void lcModel::Paste(bool PasteToCurrentStep) SaveCheckpoint(tr("Pasting")); if (SelectedObjects.size() == 1) - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); else - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, SelectedObjects, nullptr, 0, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(SelectedObjects, nullptr, 0, lcSelectionMode::Single); CalculateStep(mCurrentStep); gMainWindow->UpdateTimeline(false, false); @@ -1310,7 +1310,7 @@ void lcModel::DuplicateSelectedPieces() EndObjectEditAction(std::move(PieceIndices)); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, NewPieces, Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(NewPieces, Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Duplicate")); @@ -1734,53 +1734,68 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v Piece->SubModelAddBoundingBoxPoints(WorldMatrix, Points); } -void lcModel::RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) +void lcModel::RecordSelectionAction(std::function Callback) { std::unique_ptr ModelActionSelection = std::make_unique(); - + ModelActionSelection->SaveStartState(this); + + Callback(); + + ModelActionSelection->SaveEndState(this); + + if (ModelActionSelection->StateChanged()) + mActionSequence.emplace_back(std::move(ModelActionSelection)); +} - switch (ModelActionSelectionMode) +void lcModel::RecordClearSelectionAction() +{ + RecordSelectionAction([this](){ DeselectAllObjects(); }); +} + +void lcModel::RecordSetFocusAction(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) +{ + RecordSelectionAction([this, FocusObject, FocusSection, SelectionMode](){ SetFocusedObject(FocusObject, FocusSection, SelectionMode); }); +} + +void lcModel::RecordSetSelectionAndFocusAction(const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode) +{ + RecordSelectionAction([this, &Objects, FocusObject, FocusSection, SelectionMode]() { - case lcModelActionSelectionMode::ClearSelection: - DeselectAllObjects(); - break; - - case lcModelActionSelectionMode::SetSelectionAndFocus: DeselectAllObjects(); SetObjectsSelected(Objects, true); SetFocusedObject(FocusObject, FocusSection, SelectionMode); - break; + }); +} - case lcModelActionSelectionMode::SetFocus: - SetFocusedObject(FocusObject, FocusSection, SelectionMode); - break; - - case lcModelActionSelectionMode::SelectAllPieces: +void lcModel::RecordSelectAllPiecesAction() +{ + RecordSelectionAction([this]() + { for (const std::unique_ptr& Piece : mPieces) if (Piece->IsVisible(mCurrentStep)) Piece->SetSelected(true); - break; + }); +} - case lcModelActionSelectionMode::InvertPieceSelection: +void lcModel::RecordInvertPieceSelectionAction() +{ + RecordSelectionAction([this]() + { for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected() || Piece->IsVisible(mCurrentStep)) Piece->SetSelected(!Piece->IsSelected()); - break; + }); +} - case lcModelActionSelectionMode::AddToSelection: - SetObjectsSelected(Objects, true); - break; +void lcModel::RecordAddToSelectionAction(const std::vector& Objects) +{ + RecordSelectionAction([this, &Objects](){ SetObjectsSelected(Objects, true); }); +} - case lcModelActionSelectionMode::RemoveFromSelection: - SetObjectsSelected(Objects, false); - break; - } - - ModelActionSelection->SaveEndState(this); - - if (ModelActionSelection->StateChanged()) - mActionSequence.emplace_back(std::move(ModelActionSelection)); +void lcModel::RecordRemoveFromSelectionAction(const std::vector& Objects) +{ + RecordSelectionAction([this, &Objects](){ SetObjectsSelected(Objects, false); }); } void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply) @@ -2598,7 +2613,7 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) } gMainWindow->UpdateTimeline(false, false); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); SaveCheckpoint(tr("Adding Piece")); @@ -2734,7 +2749,7 @@ void lcModel::FocusNextTrainTrack() } BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); + RecordSetFocusAction(FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } @@ -2761,7 +2776,7 @@ void lcModel::FocusPreviousTrainTrack() } BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); + RecordSetFocusAction(FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); EndActionSequence(tr("Selection")); } @@ -3150,7 +3165,7 @@ void lcModel::MoveSelectionToModel(lcModel* Model) SaveCheckpoint(tr("New Model")); gMainWindow->UpdateTimeline(false, false); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(std::vector(), ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); } void lcModel::InlineSelectedModels() @@ -3202,7 +3217,7 @@ void lcModel::InlineSelectedModels() return; } - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, NewPieces, nullptr, 0, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(NewPieces, nullptr, 0, lcSelectionMode::Single); SaveCheckpoint(tr("Inlining")); gMainWindow->UpdateTimeline(false, false); @@ -4327,14 +4342,14 @@ void lcModel::GetSelectionInformation(int* Flags, std::vector& Select void lcModel::ClearSelection() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::ClearSelection, std::vector(), nullptr, 0, lcSelectionMode::Single); + RecordClearSelectionAction(); EndActionSequence(tr("Selection")); } void lcModel::SetSelectionAndFocus(const std::vector& Objects, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, Objects, Focus, Section, SelectionMode); + RecordSetSelectionAndFocusAction(Objects, Focus, Section, SelectionMode); EndActionSequence(tr("Selection")); } @@ -4345,13 +4360,13 @@ void lcModel::FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelect if (Object) { if (!Object->IsFocused(Section)) - RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), Object, Section, SelectionMode); + RecordSetFocusAction(Object, Section, SelectionMode); else - RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), nullptr, 0, SelectionMode); + RecordSetFocusAction(nullptr, ~0, SelectionMode); } else { - RecordSelectionAction(lcModelActionSelectionMode::SetFocus, std::vector(), nullptr, 0, SelectionMode); + RecordSetFocusAction(nullptr, 0, SelectionMode); } EndActionSequence(tr("Selection")); @@ -4360,28 +4375,28 @@ void lcModel::FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelect void lcModel::SelectAllPieces() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::SelectAllPieces, std::vector(), nullptr, 0, lcSelectionMode::Single); + RecordSelectAllPiecesAction(); EndActionSequence(tr("Selection")); } void lcModel::InvertPieceSelection() { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::InvertPieceSelection, std::vector(), nullptr, 0, lcSelectionMode::Single); + RecordInvertPieceSelectionAction(); EndActionSequence(tr("Selection")); } void lcModel::AddToSelection(const std::vector& Objects) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::AddToSelection, Objects, nullptr, 0, lcSelectionMode::Single); + RecordAddToSelectionAction(Objects); EndActionSequence(tr("Selection")); } void lcModel::RemoveFromSelection(const std::vector& Objects) { BeginActionSequence(); - RecordSelectionAction(lcModelActionSelectionMode::RemoveFromSelection, Objects, nullptr, 0, lcSelectionMode::Single); + RecordRemoveFromSelectionAction(Objects); EndActionSequence(tr("Selection")); } @@ -4718,9 +4733,9 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) } if (FindAll) - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, Selection, nullptr, 0, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(Selection, nullptr, 0, lcSelectionMode::Single); else - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(std::vector(), Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); if (ReplacedCount) { @@ -4909,7 +4924,7 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece EndObjectEditAction(std::move(PieceIndices)); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Add Piece")); @@ -4931,7 +4946,7 @@ void lcModel::InsertCameraToolClicked(const lcVector3& Position) EndObjectEditAction({ mCameras.size() - 1 }); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(std::vector(), Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Add Camera")); } @@ -4972,7 +4987,7 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh EndObjectEditAction({ mLights.size() - 1 }); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, std::vector(), Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(std::vector(), Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(ActionName); } @@ -5431,7 +5446,7 @@ void lcModel::ShowArrayDialog() EndObjectEditAction(std::move(PieceIndices)); - RecordSelectionAction(lcModelActionSelectionMode::AddToSelection, NewPieces, nullptr, 0, lcSelectionMode::Single); + RecordAddToSelectionAction(NewPieces); EndActionSequence(tr("Piece Array")); @@ -5476,7 +5491,7 @@ void lcModel::ShowMinifigDialog() EndObjectEditAction(std::move(PieceIndices), { mGroups.size() - 1}); - RecordSelectionAction(lcModelActionSelectionMode::SetSelectionAndFocus, Pieces, nullptr, 0, lcSelectionMode::Single); + RecordSetSelectionAndFocusAction(Pieces, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Add Minifig")); diff --git a/common/lc_model.h b/common/lc_model.h index 98482d7a..e3bc4112 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -402,8 +402,15 @@ public: protected: void DeleteModel(); - - void RecordSelectionAction(lcModelActionSelectionMode ModelActionSelectionMode, const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + + void RecordSelectionAction(std::function Callback); + void RecordClearSelectionAction(); + void RecordSetFocusAction(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + void RecordSetSelectionAndFocusAction(const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + void RecordSelectAllPiecesAction(); + void RecordInvertPieceSelectionAction(); + void RecordAddToSelectionAction(const std::vector& Objects); + void RecordRemoveFromSelectionAction(const std::vector& Objects); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); void EndObjectEditAction(std::vector&& ObjectIndices = std::vector(), std::vector&& GroupIndices = std::vector()); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 132ff7f2..e64b3f6c 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -19,17 +19,6 @@ protected: std::vector mLightIndices; }; -enum class lcModelActionSelectionMode -{ - ClearSelection, - SetFocus, - SetSelectionAndFocus, - SelectAllPieces, - InvertPieceSelection, - AddToSelection, - RemoveFromSelection -}; - struct lcModelActionSelectionState { std::vector PieceSelection; From bbd01f3e4ea1bb0afe0379f6d0f206a6bb4d6d5a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 3 Feb 2026 09:29:19 -0800 Subject: [PATCH 52/93] Removed unused variable. --- common/lc_view.cpp | 3 +-- common/lc_view.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/common/lc_view.cpp b/common/lc_view.cpp index eeee97ac..66f182b2 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -74,8 +74,7 @@ lcView::~lcView() if (mLastFocusedView == this) mLastFocusedView = nullptr; - if (mDeleteContext) - delete mContext; + delete mContext; } std::vector lcView::GetModelViews(const lcModel* Model) diff --git a/common/lc_view.h b/common/lc_view.h index c915b622..6d752ba8 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -319,7 +319,6 @@ protected: lcViewWidget* mWidget = nullptr; int mWidth = 1; int mHeight = 1; - bool mDeleteContext = true; lcViewType mViewType; int mMouseX = 0; From 07c80b705fa40449c0ce64008690bb526ed7bb1d Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 3 Feb 2026 09:41:28 -0800 Subject: [PATCH 53/93] Fixed duplicate pieces not grouping correctly. --- common/lc_model.cpp | 17 ++++++++++++++--- common/piece.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index cc8dc9f4..2519bae8 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1287,7 +1287,7 @@ void lcModel::DuplicateSelectedPieces() for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) { - lcPiece* Piece = mPieces[PieceIndex].get(); + const lcPiece* Piece = mPieces[PieceIndex].get(); if (!Piece->IsSelected()) continue; @@ -1305,7 +1305,7 @@ void lcModel::DuplicateSelectedPieces() lcGroup* Group = Piece->GetGroup(); if (Group) - Piece->SetGroup(GetNewGroup(Group)); + NewPiece->SetGroup(GetNewGroup(Group)); } EndObjectEditAction(std::move(PieceIndices)); @@ -1853,6 +1853,8 @@ void lcModel::RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const Q { std::unique_ptr ModelActionGroupPieces = std::make_unique(Mode, GroupName); + RunGroupPiecesAction(ModelActionGroupPieces.get(), true); + mActionSequence.emplace_back(std::move(ModelActionGroupPieces)); } @@ -1984,6 +1986,15 @@ void lcModel::EndActionSequence(const QString& Description) gMainWindow->UpdateModified(IsModified()); gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); + for (const std::unique_ptr& ModelAction : mUndoHistory.front()->ModelActions) + { + if (const lcModelActionSelection* ModelActionSelection = dynamic_cast(ModelAction.get())) + { + gMainWindow->UpdateSelectedObjects(true); + break; + } + } + UpdateAllViews(); } @@ -4362,7 +4373,7 @@ void lcModel::FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelect if (!Object->IsFocused(Section)) RecordSetFocusAction(Object, Section, SelectionMode); else - RecordSetFocusAction(nullptr, ~0, SelectionMode); + RecordSetFocusAction(nullptr, ~0U, SelectionMode); } else { diff --git a/common/piece.h b/common/piece.h index 6241f029..6f7cec52 100644 --- a/common/piece.h +++ b/common/piece.h @@ -152,7 +152,7 @@ public: mGroup = Group; } - lcGroup* GetGroup() + lcGroup* GetGroup() const { return mGroup; } From d41671fff5122e6df9cc41cb6776ac2faf7bc740 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 3 Feb 2026 21:09:58 -0800 Subject: [PATCH 54/93] Cleanup lcModelAction. --- common/lc_model.cpp | 2 +- common/lc_modelaction.cpp | 353 +++++++++++++++++++------------------- common/lc_modelaction.h | 19 +- 3 files changed, 187 insertions(+), 187 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2519bae8..9f4f060a 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1988,7 +1988,7 @@ void lcModel::EndActionSequence(const QString& Description) for (const std::unique_ptr& ModelAction : mUndoHistory.front()->ModelActions) { - if (const lcModelActionSelection* ModelActionSelection = dynamic_cast(ModelAction.get())) + if (dynamic_cast(ModelAction.get())) { gMainWindow->UpdateSelectedObjects(true); break; diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 1cdf8627..48652481 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -6,182 +6,6 @@ #include "light.h" #include "group.h" -bool lcModelAction::SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model) -{ - QDataStream Stream(&Buffer, QIODevice::WriteOnly); - - const std::vector>& Groups = Model->GetGroups(); - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - - uint64_t ObjectCount[4] = { Groups.size(), Pieces.size(), Cameras.size(), Lights.size() }; - - if (Stream.writeRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) - return false; - - for (size_t GroupIndex : mGroupIndices) - { - const lcGroup* Group = Groups[GroupIndex].get(); - uint64_t ParentIndex = UINT64_MAX; - - if (Group->mGroup) - for (ParentIndex = 0; ParentIndex < Groups.size(); ParentIndex++) - if (Group->mGroup == Groups[ParentIndex].get()) - break; - - Stream << Group->mName; - Stream << ParentIndex; - } - - for (size_t PieceIndex : mPieceIndices) - if (!Pieces[PieceIndex]->SaveUndoData(Stream, Model)) - return false; - - for (size_t CameraIndex : mCameraIndices) - if (!Cameras[CameraIndex]->SaveUndoData(Stream, Model)) - return false; - - for (size_t LightIndex : mLightIndices) - if (!Lights[LightIndex]->SaveUndoData(Stream, Model)) - return false; - - return true; -} - -bool lcModelAction::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const -{ - QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); - - const std::vector>& Groups = Model->GetGroups(); - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - - uint64_t ObjectCount[4]; - - if (Stream.readRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) - return false; - - if (CreateObjects) - { - ObjectCount[0] -= mGroupIndices.size(); - ObjectCount[1] -= mPieceIndices.size(); - ObjectCount[2] -= mCameraIndices.size(); - ObjectCount[3] -= mLightIndices.size(); - } - - if (ObjectCount[0] != Groups.size() || ObjectCount[1] != Pieces.size() || ObjectCount[2] != Cameras.size() || ObjectCount[3] != Lights.size()) - return false; - - if (CreateObjects) - { - for (size_t GroupIndex : mGroupIndices) - { - std::unique_ptr Group(new lcGroup()); - QString Name; - uint64_t ParentIndex; - - Stream >> Name; - Stream >> ParentIndex; - - Group->mName = Name; - Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; - - Model->AddGroup(std::move(Group), GroupIndex); - } - - for (size_t PieceIndex : mPieceIndices) - { - if (PieceIndex > Pieces.size()) - return false; - - std::unique_ptr Piece(new lcPiece(nullptr)); - - if (!Piece->LoadUndoData(Stream, Model)) - return false; - - Model->AddPiece(std::move(Piece), PieceIndex); - } - - for (size_t CameraIndex : mCameraIndices) - { - if (CameraIndex > Cameras.size()) - return false; - - std::unique_ptr Camera(new lcCamera(false)); - - if (!Camera->LoadUndoData(Stream, Model)) - return false; - - Model->AddCamera(std::move(Camera), CameraIndex); - } - - for (size_t LightIndex : mLightIndices) - { - if (LightIndex > Lights.size()) - return false; - - std::unique_ptr Light(new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point)); - - if (!Light->LoadUndoData(Stream, Model)) - return false; - - Model->AddLight(std::move(Light), LightIndex); - } - } - else - { - for (size_t GroupIndex : mGroupIndices) - { - lcGroup* Group = Groups[GroupIndex].get(); - QString Name; - uint64_t ParentIndex; - - Stream >> Name; - Stream >> ParentIndex; - - Group->mName = Name; - Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; - } - - for (size_t PieceIndex : mPieceIndices) - { - if (PieceIndex >= Pieces.size()) - return false; - - const std::unique_ptr& Piece = Pieces[PieceIndex]; - - if (!Piece->LoadUndoData(Stream, Model)) - return false; - } - - for (size_t CameraIndex : mCameraIndices) - { - if (CameraIndex >= Cameras.size()) - return false; - - const std::unique_ptr& Camera = Cameras[CameraIndex]; - - if (!Camera->LoadUndoData(Stream, Model)) - return false; - } - - for (size_t LightIndex : mLightIndices) - { - if (LightIndex >= Lights.size()) - return false; - - const std::unique_ptr& Light = Lights[LightIndex]; - - if (!Light->LoadUndoData(Stream, Model)) - return false; - } - } - - return true; -} - void lcModelActionSelection::SaveStartState(const lcModel* Model) { SaveState(mStartState, Model); @@ -323,6 +147,183 @@ lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mod { } + +bool lcModelActionObjectEdit::SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model) +{ + QDataStream Stream(&Buffer, QIODevice::WriteOnly); + + const std::vector>& Groups = Model->GetGroups(); + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + + uint64_t ObjectCount[4] = { Groups.size(), Pieces.size(), Cameras.size(), Lights.size() }; + + if (Stream.writeRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) + return false; + + for (size_t GroupIndex : mGroupIndices) + { + const lcGroup* Group = Groups[GroupIndex].get(); + uint64_t ParentIndex = UINT64_MAX; + + if (Group->mGroup) + for (ParentIndex = 0; ParentIndex < Groups.size(); ParentIndex++) + if (Group->mGroup == Groups[ParentIndex].get()) + break; + + Stream << Group->mName; + Stream << ParentIndex; + } + + for (size_t PieceIndex : mPieceIndices) + if (!Pieces[PieceIndex]->SaveUndoData(Stream, Model)) + return false; + + for (size_t CameraIndex : mCameraIndices) + if (!Cameras[CameraIndex]->SaveUndoData(Stream, Model)) + return false; + + for (size_t LightIndex : mLightIndices) + if (!Lights[LightIndex]->SaveUndoData(Stream, Model)) + return false; + + return true; +} + +bool lcModelActionObjectEdit::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const +{ + QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); + + const std::vector>& Groups = Model->GetGroups(); + const std::vector>& Pieces = Model->GetPieces(); + const std::vector>& Cameras = Model->GetCameras(); + const std::vector>& Lights = Model->GetLights(); + + uint64_t ObjectCount[4]; + + if (Stream.readRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) + return false; + + if (CreateObjects) + { + ObjectCount[0] -= mGroupIndices.size(); + ObjectCount[1] -= mPieceIndices.size(); + ObjectCount[2] -= mCameraIndices.size(); + ObjectCount[3] -= mLightIndices.size(); + } + + if (ObjectCount[0] != Groups.size() || ObjectCount[1] != Pieces.size() || ObjectCount[2] != Cameras.size() || ObjectCount[3] != Lights.size()) + return false; + + if (CreateObjects) + { + for (size_t GroupIndex : mGroupIndices) + { + std::unique_ptr Group(new lcGroup()); + QString Name; + uint64_t ParentIndex; + + Stream >> Name; + Stream >> ParentIndex; + + Group->mName = Name; + Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; + + Model->AddGroup(std::move(Group), GroupIndex); + } + + for (size_t PieceIndex : mPieceIndices) + { + if (PieceIndex > Pieces.size()) + return false; + + std::unique_ptr Piece(new lcPiece(nullptr)); + + if (!Piece->LoadUndoData(Stream, Model)) + return false; + + Model->AddPiece(std::move(Piece), PieceIndex); + } + + for (size_t CameraIndex : mCameraIndices) + { + if (CameraIndex > Cameras.size()) + return false; + + std::unique_ptr Camera(new lcCamera(false)); + + if (!Camera->LoadUndoData(Stream, Model)) + return false; + + Model->AddCamera(std::move(Camera), CameraIndex); + } + + for (size_t LightIndex : mLightIndices) + { + if (LightIndex > Lights.size()) + return false; + + std::unique_ptr Light(new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point)); + + if (!Light->LoadUndoData(Stream, Model)) + return false; + + Model->AddLight(std::move(Light), LightIndex); + } + } + else + { + for (size_t GroupIndex : mGroupIndices) + { + lcGroup* Group = Groups[GroupIndex].get(); + QString Name; + uint64_t ParentIndex; + + Stream >> Name; + Stream >> ParentIndex; + + Group->mName = Name; + Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; + } + + for (size_t PieceIndex : mPieceIndices) + { + if (PieceIndex >= Pieces.size()) + return false; + + const std::unique_ptr& Piece = Pieces[PieceIndex]; + + if (!Piece->LoadUndoData(Stream, Model)) + return false; + } + + for (size_t CameraIndex : mCameraIndices) + { + if (CameraIndex >= Cameras.size()) + return false; + + const std::unique_ptr& Camera = Cameras[CameraIndex]; + + if (!Camera->LoadUndoData(Stream, Model)) + return false; + } + + for (size_t LightIndex : mLightIndices) + { + if (LightIndex >= Lights.size()) + return false; + + const std::unique_ptr& Light = Lights[LightIndex]; + + if (!Light->LoadUndoData(Stream, Model)) + return false; + } + } + + return true; +} + bool lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamera* Camera) { const std::vector>& Pieces = Model->GetPieces(); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index e64b3f6c..755e566d 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -8,15 +8,6 @@ class lcModelAction public: lcModelAction() = default; virtual ~lcModelAction() = default; - -protected: - bool SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model); - bool LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const; - - std::vector mGroupIndices; - std::vector mPieceIndices; - std::vector mCameraIndices; - std::vector mLightIndices; }; struct lcModelActionSelectionState @@ -25,7 +16,7 @@ struct lcModelActionSelectionState std::vector CameraSelection; std::vector LightSelection; size_t FocusIndex = SIZE_MAX; - uint32_t FocusSection = 0; + uint32_t FocusSection = ~0U; lcObjectType FocusObjectType = static_cast(~0); bool operator!=(const lcModelActionSelectionState& Other) const @@ -86,6 +77,14 @@ public: } protected: + bool SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model); + bool LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const; + + std::vector mGroupIndices; + std::vector mPieceIndices; + std::vector mCameraIndices; + std::vector mLightIndices; + lcModelActionObjectEditMode mMode; QByteArray mStartBuffer; QByteArray mEndBuffer; From c8dca012f9a860c55c7299eb8fc950ba597ba0ee Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 3 Feb 2026 21:46:00 -0800 Subject: [PATCH 55/93] Replaced bool Ortho with lcCameraProjection::Orthographic for clarity. --- common/camera.cpp | 86 +++++++++++++++++----------------- common/camera.h | 27 +++-------- common/lc_application.cpp | 2 +- common/lc_mainwindow.cpp | 6 +-- common/lc_model.cpp | 8 ++-- common/lc_model.h | 3 +- common/lc_objectproperty.h | 2 +- common/lc_propertieswidget.cpp | 6 +-- common/lc_view.cpp | 17 +++---- common/lc_view.h | 3 +- common/light.cpp | 12 ++--- common/light.h | 9 ++-- common/object.cpp | 4 +- common/piece.cpp | 8 ++-- 14 files changed, 91 insertions(+), 102 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 813a78c4..378bc29a 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -65,35 +65,35 @@ void lcCamera::CopyProperties(const lcCamera& Other) mPosition = Other.mPosition; mTargetPosition = Other.mTargetPosition; mUpVector = Other.mUpVector; - - SetOrtho(Other.IsOrtho()); + + mProjection = Other.mProjection; } -QString lcCamera::GetCameraTypeString(lcCameraType CameraType) +QString lcCamera::GetCameraProjectionString(lcCameraProjection CameraProjection) { - switch (CameraType) + switch (CameraProjection) { - case lcCameraType::Perspective: - return QT_TRANSLATE_NOOP("Camera Type", "Perspective"); + case lcCameraProjection::Perspective: + return QT_TRANSLATE_NOOP("Camera Projection", "Perspective"); - case lcCameraType::Orthographic: - return QT_TRANSLATE_NOOP("Camera Type", "Orthographic"); + case lcCameraProjection::Orthographic: + return QT_TRANSLATE_NOOP("Camera Projection", "Orthographic"); - case lcCameraType::Count: + case lcCameraProjection::Count: break; } return QString(); } -QStringList lcCamera::GetCameraTypeStrings() +QStringList lcCamera::GetCameraProjectionStrings() { - QStringList CameraType; + QStringList CameraProjections; - for (int CameraTypeIndex = 0; CameraTypeIndex < static_cast(lcCameraType::Count); CameraTypeIndex++) - CameraType.push_back(GetCameraTypeString(static_cast(CameraTypeIndex))); + for (int CameraProjectionIndex = 0; CameraProjectionIndex < static_cast(lcCameraProjection::Count); CameraProjectionIndex++) + CameraProjections.push_back(GetCameraProjectionString(static_cast(CameraProjectionIndex))); - return CameraType; + return CameraProjections; } lcViewpoint lcCamera::GetViewpoint(const QString& ViewpointName) @@ -175,15 +175,15 @@ void lcCamera::CreateName(const std::vector>& Cameras) mName = Prefix + QString::number(MaxCameraNumber + 1); } -bool lcCamera::SetCameraType(lcCameraType CameraType) +bool lcCamera::SetProjection(lcCameraProjection CameraProjection) { - if (static_cast(CameraType) < 0 || CameraType >= lcCameraType::Count) + if (static_cast(CameraProjection) < 0 || CameraProjection >= lcCameraProjection::Count) return false; - if (GetCameraType() == CameraType) + if (GetProjection() == CameraProjection) return false; - - SetOrtho(CameraType == lcCameraType::Orthographic); + + mProjection = CameraProjection; return true; } @@ -203,7 +203,7 @@ void lcCamera::SaveLDraw(QTextStream& Stream) const if (IsHidden()) Stream << QLatin1String("HIDDEN"); - if (IsOrtho()) + if (mProjection == lcCameraProjection::Orthographic) Stream << QLatin1String("ORTHOGRAPHIC "); Stream << QLatin1String("NAME ") << mName << LineEnding; @@ -219,7 +219,7 @@ bool lcCamera::ParseLDrawLine(QTextStream& Stream) if (Token == QLatin1String("HIDDEN")) SetHidden(true); else if (Token == QLatin1String("ORTHOGRAPHIC")) - SetOrtho(true); + SetProjection(lcCameraProjection::Orthographic); else if (Token == QLatin1String("FOV")) Stream >> m_fovy; else if (Token == QLatin1String("ZNEAR")) @@ -494,16 +494,16 @@ void lcCamera::CopyPosition(const lcCamera* Camera) mPosition = Camera->mPosition; mTargetPosition = Camera->mTargetPosition; mUpVector = Camera->mUpVector; - mState |= (Camera->mState & LC_CAMERA_ORTHO); + mProjection = Camera->mProjection; } -void lcCamera::CopySettings(const lcCamera* camera) +void lcCamera::CopySettings(const lcCamera* Camera) { - m_fovy = camera->m_fovy; - m_zNear = camera->m_zNear; - m_zFar = camera->m_zFar; + m_fovy = Camera->m_fovy; + m_zNear = Camera->m_zNear; + m_zFar = Camera->m_zFar; - mState |= (camera->mState & LC_CAMERA_ORTHO); + mProjection = Camera->mProjection; } void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const @@ -670,8 +670,8 @@ QVariant lcCamera::GetPropertyValue(lcObjectPropertyId PropertyId) const case lcObjectPropertyId::CameraName: return GetName(); - case lcObjectPropertyId::CameraType: - return static_cast(GetCameraType()); + case lcObjectPropertyId::CameraProjection: + return static_cast(GetProjection()); case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: @@ -732,8 +732,8 @@ bool lcCamera::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool case lcObjectPropertyId::CameraName: return SetName(Value.toString()); - case lcObjectPropertyId::CameraType: - return SetCameraType(static_cast(Value.toInt())); + case lcObjectPropertyId::CameraProjection: + return SetProjection(static_cast(Value.toInt())); case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: @@ -787,7 +787,7 @@ bool lcCamera::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -848,7 +848,7 @@ bool lcCamera::SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyF case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -916,7 +916,8 @@ bool lcCamera::SaveUndoData(QDataStream& Stream, const lcModel* Model) const Stream << m_zNear; Stream << m_zFar; Stream << mName; - Stream << (mState & (LC_CAMERA_HIDDEN | LC_CAMERA_ORTHO)); + Stream << mProjection; + Stream << (mState & LC_CAMERA_HIDDEN); return mPosition.SaveUndoData(Stream) && mTargetPosition.SaveUndoData(Stream) && mUpVector.SaveUndoData(Stream); } @@ -929,11 +930,12 @@ bool lcCamera::LoadUndoData(QDataStream& Stream, const lcModel* Model) Stream >> m_zNear; Stream >> m_zFar; Stream >> mName; + Stream >> mProjection; quint32 State; Stream >> State; - mState = (mState & ~(LC_CAMERA_HIDDEN | LC_CAMERA_ORTHO)) | State; + mState = (mState & ~LC_CAMERA_HIDDEN) | State; return mPosition.LoadUndoData(Stream) && mTargetPosition.LoadUndoData(Stream) && mUpVector.LoadUndoData(Stream); } @@ -1065,8 +1067,8 @@ void lcCamera::RemoveTime(lcStep Start, lcStep Time) void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std::vector& Points, lcStep Step, bool AddKey) { lcVector3 Position, TargetPosition; - - if (IsOrtho()) + + if (GetProjection() == lcCameraProjection::Orthographic) { float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX; @@ -1125,8 +1127,8 @@ void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std void lcCamera::ZoomRegion(float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey) { lcVector3 NewPosition; - - if (IsOrtho()) + + if (GetProjection() == lcCameraProjection::Orthographic) { float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX; @@ -1175,7 +1177,7 @@ void lcCamera::Zoom(float Distance, lcStep Step, bool AddKey) FrontVector *= -5.0f * Distance; // Don't zoom ortho in if it would cross the ortho focal plane. - if (IsOrtho()) + if (GetProjection() == lcCameraProjection::Orthographic) { if ((Distance > 0) && (lcDot(mPosition + FrontVector - mTargetPosition, mPosition - mTargetPosition) <= 0)) return; @@ -1185,8 +1187,8 @@ void lcCamera::Zoom(float Distance, lcStep Step, bool AddKey) AddKey = false; mPosition.ChangeKey(mPosition + FrontVector, Step, AddKey); - - if (!IsOrtho()) + + if (GetProjection() != lcCameraProjection::Orthographic) mTargetPosition.ChangeKey(mTargetPosition + FrontVector, Step, AddKey); UpdatePosition(Step); diff --git a/common/camera.h b/common/camera.h index 6b54da3a..4fe75b46 100644 --- a/common/camera.h +++ b/common/camera.h @@ -5,7 +5,6 @@ #define LC_CAMERA_HIDDEN 0x01 #define LC_CAMERA_SIMPLE 0x02 -#define LC_CAMERA_ORTHO 0x04 enum class lcViewpoint { @@ -19,7 +18,7 @@ enum class lcViewpoint Count }; -enum class lcCameraType +enum class lcCameraProjection { Perspective, Orthographic, @@ -46,8 +45,8 @@ public: lcCamera& operator=(const lcCamera&) = delete; lcCamera& operator=(lcCamera&&) = delete; - static QString GetCameraTypeString(lcCameraType CameraType); - static QStringList GetCameraTypeStrings(); + static QString GetCameraProjectionString(lcCameraProjection CameraProjection); + static QStringList GetCameraProjectionStrings(); static lcViewpoint GetViewpoint(const QString& ViewpointName); void CopyProperties(const lcCamera& Other); @@ -65,25 +64,12 @@ public: return (mState & LC_CAMERA_SIMPLE) != 0; } - lcCameraType GetCameraType() const + lcCameraProjection GetProjection() const { - return ((mState & LC_CAMERA_ORTHO) == 0) ? lcCameraType::Perspective : lcCameraType::Orthographic; + return mProjection; } - bool SetCameraType(lcCameraType CameraType); - - bool IsOrtho() const - { - return (mState & LC_CAMERA_ORTHO) != 0; - } - - void SetOrtho(bool Ortho) - { - if (Ortho) - mState |= LC_CAMERA_ORTHO; - else - mState &= ~LC_CAMERA_ORTHO; - } + bool SetProjection(lcCameraProjection CameraProjection); quint32 GetAllowedTransforms() const override { @@ -228,4 +214,5 @@ protected: QString mName; quint32 mState; + lcCameraProjection mProjection = lcCameraProjection::Perspective; }; diff --git a/common/lc_application.cpp b/common/lc_application.cpp index 2a4f7a07..c113d580 100644 --- a/common/lc_application.cpp +++ b/common/lc_application.cpp @@ -1059,7 +1059,7 @@ lcStartupMode lcApplication::Initialize(const QList>& Libra ActiveView->SetCamera(Options.CameraName); else { - ActiveView->SetProjection(Options.Orthographic); + ActiveView->SetCameraProjection(Options.Orthographic ? lcCameraProjection::Orthographic : lcCameraProjection::Perspective); if (Options.SetFoV) ActiveView->GetCamera()->m_fovy = Options.FoV; diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index c9ba555b..18462216 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2232,7 +2232,7 @@ void lcMainWindow::ProjectionMenuAboutToShow() if (ActiveView) { - if (ActiveView->GetCamera()->IsOrtho()) + if (ActiveView->GetCamera()->GetProjection() == lcCameraProjection::Orthographic) mActions[LC_VIEW_PROJECTION_ORTHO]->setChecked(true); else mActions[LC_VIEW_PROJECTION_PERSPECTIVE]->setChecked(true); @@ -2885,12 +2885,12 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_VIEW_PROJECTION_PERSPECTIVE: if (ActiveView) - ActiveView->SetProjection(false); + ActiveView->SetCameraProjection(lcCameraProjection::Perspective); break; case LC_VIEW_PROJECTION_ORTHO: if (ActiveView) - ActiveView->SetProjection(true); + ActiveView->SetCameraProjection(lcCameraProjection::Orthographic); break; case LC_VIEW_TOGGLE_VIEW_SPHERE: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 9f4f060a..4567f90b 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3702,9 +3702,9 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) } } -void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) +void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraProjection) { - if (Camera->IsOrtho() == Ortho) + if (Camera->GetProjection() == CameraProjection) return; if (!Camera->IsSimple()) @@ -3713,7 +3713,7 @@ void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); } - Camera->SetOrtho(Ortho); + Camera->SetProjection(CameraProjection); Camera->UpdatePosition(mCurrentStep); if (!Camera->IsSimple()) @@ -3820,7 +3820,7 @@ void lcModel::EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept) case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: break; case lcObjectPropertyId::CameraFOV: diff --git a/common/lc_model.h b/common/lc_model.h index e3bc4112..e85fa68d 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -4,6 +4,7 @@ #include "lc_commands.h" enum class lcObjectPropertyId; +enum class lcCameraProjection; class lcModelAction; class lcModelActionSelection; class lcModelActionObjectEdit; @@ -389,7 +390,7 @@ public: void SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value, bool AddUndo); void EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept); - void SetCameraOrthographic(lcCamera* Camera, bool Ortho); + void SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraProjection); void SetCameraFOV(lcCamera* Camera, float FOV, bool Checkpoint); void SetCameraZNear(lcCamera* Camera, float ZNear, bool Checkpoint); void SetCameraZFar(lcCamera* Camera, float ZFar, bool Checkpoint); diff --git a/common/lc_objectproperty.h b/common/lc_objectproperty.h index 8d572e6d..d2dde646 100644 --- a/common/lc_objectproperty.h +++ b/common/lc_objectproperty.h @@ -7,7 +7,7 @@ enum class lcObjectPropertyId PieceStepShow, PieceStepHide, CameraName, - CameraType, + CameraProjection, CameraFOV, CameraNear, CameraFar, diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index d5b6f7f2..86a103a8 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -493,7 +493,7 @@ void lcPropertiesWidget::UpdateFloat(lcObjectPropertyId PropertyId, float Value) case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: break; case lcObjectPropertyId::CameraFOV: @@ -1159,7 +1159,7 @@ void lcPropertiesWidget::CreateWidgets() AddCategory(CategoryIndex::Camera, tr("Camera")); AddStringProperty(lcObjectPropertyId::CameraName, tr("Name"), tr("Camera name"), false); - AddStringListProperty(lcObjectPropertyId::CameraType, tr("Type"), tr("Camera type"), false, lcCamera::GetCameraTypeStrings()); + AddStringListProperty(lcObjectPropertyId::CameraProjection, tr("Projection"), tr("Camera projection"), false, lcCamera::GetCameraProjectionStrings()); AddSpacing(); @@ -1414,7 +1414,7 @@ void lcPropertiesWidget::SetCamera(const std::vector& Selection, lcOb } UpdateString(lcObjectPropertyId::CameraName); - UpdateStringList(lcObjectPropertyId::CameraType); + UpdateStringList(lcObjectPropertyId::CameraProjection); UpdateFloat(lcObjectPropertyId::CameraFOV, FoV); UpdateFloat(lcObjectPropertyId::CameraNear, ZNear); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 66f182b2..59e27954 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -249,7 +249,7 @@ lcMatrix44 lcView::GetProjectionMatrix() const { float AspectRatio = (float)mWidth / (float)mHeight; - if (mCamera->IsOrtho()) + if (mCamera->GetProjection() == lcCameraProjection::Orthographic) { float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f; float OrthoWidth = OrthoHeight * AspectRatio; @@ -267,8 +267,8 @@ lcMatrix44 lcView::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, in double ImageLeft, ImageRight, ImageBottom, ImageTop, Near, Far; double AspectRatio = (double)ImageWidth / (double)ImageHeight; - - if (mCamera->IsOrtho()) + + if (mCamera->GetProjection() == lcCameraProjection::Orthographic) { float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f; float OrthoWidth = OrthoHeight * AspectRatio; @@ -300,8 +300,8 @@ lcMatrix44 lcView::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, in double Right = Left + (ImageRight - ImageLeft) * CurrentTileWidth / ImageWidth; double Bottom = ImageBottom + (ImageTop - ImageBottom) * (CurrentRow * mHeight) / ImageHeight; double Top = Bottom + (ImageTop - ImageBottom) * CurrentTileHeight / ImageHeight; - - if (mCamera->IsOrtho()) + + if (mCamera->GetProjection() == lcCameraProjection::Orthographic) return lcMatrix44Ortho(Left, Right, Bottom, Top, Near, Far); else return lcMatrix44Frustum(Left, Right, Bottom, Top, Near, Far); @@ -1874,18 +1874,19 @@ void lcView::SetCameraIndex(size_t CameraIndex) Redraw(); } -void lcView::SetProjection(bool Ortho) +void lcView::SetCameraProjection(lcCameraProjection CameraProjection) { if (mCamera->IsSimple()) { - mCamera->SetOrtho(Ortho); + mCamera->SetProjection(CameraProjection); Redraw(); } else { lcModel* ActiveModel = GetActiveModel(); + if (ActiveModel) - ActiveModel->SetCameraOrthographic(mCamera, Ortho); + ActiveModel->SetCameraProjection(mCamera, CameraProjection); } } diff --git a/common/lc_view.h b/common/lc_view.h index 6d752ba8..700a5ebf 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -5,6 +5,7 @@ #include "lc_commands.h" struct lcInsertPieceInfo; +enum class lcCameraProjection; enum class lcDragState { @@ -252,7 +253,7 @@ public: void SetCamera(const QString& CameraName); void SetCameraIndex(size_t CameraIndex); - void SetProjection(bool Ortho); + void SetCameraProjection(lcCameraProjection CameraProjection); void LookAt(); void MoveCamera(const lcVector3& Direction); void Zoom(float Amount); diff --git a/common/light.cpp b/common/light.cpp index 5c4666d4..34fb2efd 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1154,7 +1154,7 @@ QVariant lcLight::GetPropertyValue(lcObjectPropertyId PropertyId) const case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -1245,7 +1245,7 @@ bool lcLight::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -1336,7 +1336,7 @@ bool lcLight::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -1427,7 +1427,7 @@ bool lcLight::SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFr case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -1538,7 +1538,7 @@ bool lcLight::SaveUndoData(QDataStream& Stream, const lcModel* Model) const Stream << mLightType; Stream << mCastShadow; Stream << mAreaShape; - Stream << mState; + Stream << mHidden; return mPosition.SaveUndoData(Stream) && mRotation.SaveUndoData(Stream) && mColor.SaveUndoData(Stream) && mSpotConeAngle.SaveUndoData(Stream) && mSpotPenumbraAngle.SaveUndoData(Stream) && mPOVRaySpotTightness.SaveUndoData(Stream) && @@ -1556,7 +1556,7 @@ bool lcLight::LoadUndoData(QDataStream& Stream, const lcModel* Model) Stream >> mLightType; Stream >> mCastShadow; Stream >> mAreaShape; - Stream >> mState; + Stream >> mHidden; return mPosition.LoadUndoData(Stream) && mRotation.LoadUndoData(Stream) && diff --git a/common/light.h b/common/light.h index 8a935c0f..a42cccc5 100644 --- a/common/light.h +++ b/common/light.h @@ -3,9 +3,6 @@ #include "object.h" #include "lc_math.h" -#define LC_LIGHT_HIDDEN 0x0001 -#define LC_LIGHT_DISABLED 0x0002 - enum lcLightSection : quint32 { LC_LIGHT_SECTION_INVALID = LC_OBJECT_SECTION_INVALID, @@ -172,7 +169,7 @@ public: bool IsVisible() const { - return (mState & LC_LIGHT_HIDDEN) == 0; + return !mHidden; } bool SetColor(const lcVector3& Color, lcStep Step, bool AddKey); @@ -332,8 +329,8 @@ protected: lcObjectProperty mAreaSizeY = lcObjectProperty(250.0f); lcObjectProperty mPOVRayAreaGridX = lcObjectProperty(2); lcObjectProperty mPOVRayAreaGridY = lcObjectProperty(2); - - quint32 mState = 0; + + bool mHidden = false; lcVector3 mTargetMovePosition = lcVector3(0.0f, 0.0f, 0.0f); lcMatrix44 mWorldMatrix; diff --git a/common/object.cpp b/common/object.cpp index 482b93aa..e3f8fa11 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -27,8 +27,8 @@ QString lcObject::GetCheckpointString(lcObjectPropertyId PropertyId) case lcObjectPropertyId::CameraName: return QT_TRANSLATE_NOOP("Checkpoint", "Renaming Camera"); - case lcObjectPropertyId::CameraType: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Camera Type"); + case lcObjectPropertyId::CameraProjection: + return QT_TRANSLATE_NOOP("Checkpoint", "Changing Camera Projection"); case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: diff --git a/common/piece.cpp b/common/piece.cpp index d4d378a6..e598c23d 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -707,7 +707,7 @@ QVariant lcPiece::GetPropertyValue(lcObjectPropertyId PropertyId) const case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -767,7 +767,7 @@ bool lcPiece::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -820,7 +820,7 @@ bool lcPiece::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: @@ -879,7 +879,7 @@ bool lcPiece::SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFr case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraType: + case lcObjectPropertyId::CameraProjection: case lcObjectPropertyId::CameraFOV: case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: From 576f9fe13e3af0796298d571d0e5e03bc54c664f Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 3 Feb 2026 23:02:24 -0800 Subject: [PATCH 56/93] Moved hidden state to lcObject. --- common/camera.cpp | 26 ++++---------------------- common/camera.h | 26 ++++++++++---------------- common/light.h | 1 - common/object.h | 1 + common/piece.h | 1 - 5 files changed, 15 insertions(+), 40 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 378bc29a..94f32f36 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -14,13 +14,9 @@ #define LC_CAMERA_SAVE_VERSION 7 // LeoCAD 0.80 lcCamera::lcCamera(bool Simple) - : lcObject(lcObjectType::Camera) + : lcObject(lcObjectType::Camera), mSimple(Simple) { - Initialize(); - - if (Simple) - mState |= LC_CAMERA_SIMPLE; - else + if (!Simple) { mPosition.SetValue(lcVector3(-250.0f, -250.0f, 75.0f)); mTargetPosition.SetValue(lcVector3(0.0f, 0.0f, 0.0f)); @@ -43,8 +39,6 @@ lcCamera::lcCamera(const lcVector3& Position, const lcVector3& TargetPosition) UpVector = lcCross(SideVector, FrontVector); UpVector.Normalize(); - Initialize(); - mPosition.SetValue(Position); mTargetPosition.SetValue(TargetPosition); mUpVector.SetValue(UpVector); @@ -118,14 +112,6 @@ lcViewpoint lcCamera::GetViewpoint(const QString& ViewpointName) return lcViewpoint::Count; } -void lcCamera::Initialize() -{ - m_fovy = 30.0f; - m_zNear = 25.0f; - m_zFar = 50000.0f; - mState = 0; -} - bool lcCamera::SetName(const QString& Name) { if (mName == Name) @@ -917,7 +903,7 @@ bool lcCamera::SaveUndoData(QDataStream& Stream, const lcModel* Model) const Stream << m_zFar; Stream << mName; Stream << mProjection; - Stream << (mState & LC_CAMERA_HIDDEN); + Stream << mHidden; return mPosition.SaveUndoData(Stream) && mTargetPosition.SaveUndoData(Stream) && mUpVector.SaveUndoData(Stream); } @@ -931,11 +917,7 @@ bool lcCamera::LoadUndoData(QDataStream& Stream, const lcModel* Model) Stream >> m_zFar; Stream >> mName; Stream >> mProjection; - - quint32 State; - Stream >> State; - - mState = (mState & ~LC_CAMERA_HIDDEN) | State; + Stream >> mHidden; return mPosition.LoadUndoData(Stream) && mTargetPosition.LoadUndoData(Stream) && mUpVector.LoadUndoData(Stream); } diff --git a/common/camera.h b/common/camera.h index 4fe75b46..9890a695 100644 --- a/common/camera.h +++ b/common/camera.h @@ -3,9 +3,6 @@ #include "object.h" #include "lc_math.h" -#define LC_CAMERA_HIDDEN 0x01 -#define LC_CAMERA_SIMPLE 0x02 - enum class lcViewpoint { Front, @@ -61,7 +58,7 @@ public: bool IsSimple() const { - return (mState & LC_CAMERA_SIMPLE) != 0; + return mSimple; } lcCameraProjection GetProjection() const @@ -122,19 +119,18 @@ public: public: bool IsVisible() const - { return (mState & LC_CAMERA_HIDDEN) == 0; } + { + return !mHidden; + } bool IsHidden() const { - return (mState & LC_CAMERA_HIDDEN) != 0; + return mHidden; } void SetHidden(bool Hidden) { - if (Hidden) - mState |= LC_CAMERA_HIDDEN; - else - mState &= ~LC_CAMERA_HIDDEN; + mHidden = Hidden; } void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey) @@ -200,9 +196,9 @@ public: void GetAngles(float& Latitude, float& Longitude, float& Distance) const; void SetAngles(float Latitude, float Longitude, float Distance); - float m_fovy; - float m_zNear; - float m_zFar; + float m_fovy = 30.0f; + float m_zNear = 25.0f; + float m_zFar = 50000; lcMatrix44 mWorldView; lcObjectProperty mPosition = lcObjectProperty(lcVector3(0.0f, 0.0f, 0.0f)); @@ -210,9 +206,7 @@ public: lcObjectProperty mUpVector = lcObjectProperty(lcVector3(0.0f, 0.0f, 0.0f)); protected: - void Initialize(); - QString mName; - quint32 mState; + bool mSimple = false; lcCameraProjection mProjection = lcCameraProjection::Perspective; }; diff --git a/common/light.h b/common/light.h index a42cccc5..b766fb12 100644 --- a/common/light.h +++ b/common/light.h @@ -330,7 +330,6 @@ protected: lcObjectProperty mPOVRayAreaGridX = lcObjectProperty(2); lcObjectProperty mPOVRayAreaGridY = lcObjectProperty(2); - bool mHidden = false; lcVector3 mTargetMovePosition = lcVector3(0.0f, 0.0f, 0.0f); lcMatrix44 mWorldMatrix; diff --git a/common/object.h b/common/object.h index c69330f7..83d04bf5 100644 --- a/common/object.h +++ b/common/object.h @@ -148,6 +148,7 @@ private: lcObjectType mObjectType; protected: + bool mHidden = false; bool mSelected = false; quint32 mFocusedSection = LC_OBJECT_SECTION_INVALID; }; diff --git a/common/piece.h b/common/piece.h index 6f7cec52..9cb6309a 100644 --- a/common/piece.h +++ b/common/piece.h @@ -275,7 +275,6 @@ protected: lcStep mStepHide; bool mPivotPointValid = false; - bool mHidden = false; std::vector mControlPoints; std::vector mTrainTrackConnections; lcMesh* mMesh = nullptr; From fb71e545a920ef5ca08e8dc451a4bc2e0bd6e6fc Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Wed, 11 Feb 2026 20:15:26 -0800 Subject: [PATCH 57/93] Saved undo data as structures. --- common/camera.cpp | 58 ++++--- common/camera.h | 31 +++- common/group.cpp | 40 ++++- common/group.h | 34 +++- common/lc_math.h | 5 + common/lc_model.cpp | 52 +++++- common/lc_model.h | 7 +- common/lc_modelaction.cpp | 328 +++-------------------------------- common/lc_modelaction.h | 43 +++-- common/lc_objectproperty.cpp | 43 +---- common/lc_objectproperty.h | 6 +- common/light.cpp | 92 +++++----- common/light.h | 42 ++++- common/object.cpp | 5 +- common/object.h | 12 +- common/piece.cpp | 117 ++++++------- common/piece.h | 47 ++++- 17 files changed, 443 insertions(+), 519 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 94f32f36..fe4cb618 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -13,6 +13,11 @@ #define LC_CAMERA_SAVE_VERSION 7 // LeoCAD 0.80 +lcCamera::lcCamera() + : lcObject(lcObjectType::Camera) +{ +} + lcCamera::lcCamera(bool Simple) : lcObject(lcObjectType::Camera), mSimple(Simple) { @@ -26,8 +31,8 @@ lcCamera::lcCamera(bool Simple) } } -lcCamera::lcCamera(const lcVector3& Position, const lcVector3& TargetPosition) - : lcObject(lcObjectType::Camera) +lcCamera::lcCamera(bool Simple, const lcVector3& Position, const lcVector3& TargetPosition) + : lcObject(lcObjectType::Camera), mSimple(Simple) { // Fix the up vector lcVector3 UpVector(0, 0, 1), FrontVector(Position - TargetPosition), SideVector; @@ -893,33 +898,38 @@ void lcCamera::RemoveKeyFrames() mUpVector.RemoveAllKeys(); } -bool lcCamera::SaveUndoData(QDataStream& Stream, const lcModel* Model) const +lcCameraHistoryState lcCamera::GetHistoryState(const lcModel* Model) const { - static_assert(sizeof(lcCamera) == 248); - Q_UNUSED(Model); + lcCameraHistoryState State; - Stream << m_fovy; - Stream << m_zNear; - Stream << m_zFar; - Stream << mName; - Stream << mProjection; - Stream << mHidden; - - return mPosition.SaveUndoData(Stream) && mTargetPosition.SaveUndoData(Stream) && mUpVector.SaveUndoData(Stream); + State.Id = mId; + State.Hidden = mHidden; + State.Simple = mSimple; + State.Fovy = m_fovy; + State.NearPlane = m_zNear; + State.FarPlane = m_zFar; + State.Projection = mProjection; + State.Position = mPosition; + State.TargetPosition = mTargetPosition; + State.UpVector = mUpVector; + State.Name = mName; + + return State; } -bool lcCamera::LoadUndoData(QDataStream& Stream, const lcModel* Model) +void lcCamera::SetHistoryState(const lcCameraHistoryState& State, const lcModel* Model) { - Q_UNUSED(Model); - - Stream >> m_fovy; - Stream >> m_zNear; - Stream >> m_zFar; - Stream >> mName; - Stream >> mProjection; - Stream >> mHidden; - - return mPosition.LoadUndoData(Stream) && mTargetPosition.LoadUndoData(Stream) && mUpVector.LoadUndoData(Stream); + mId = State.Id; + mHidden = State.Hidden; + mSimple = State.Simple; + m_fovy = State.Fovy; + m_zNear = State.NearPlane; + m_zFar = State.FarPlane; + mProjection = State.Projection; + mPosition = State.Position; + mTargetPosition = State.TargetPosition; + mUpVector = State.UpVector; + mName = State.Name; } void lcCamera::RayTest(lcObjectRayTest& ObjectRayTest) const diff --git a/common/camera.h b/common/camera.h index 9890a695..f0bc2d01 100644 --- a/common/camera.h +++ b/common/camera.h @@ -30,11 +30,34 @@ enum lcCameraSection : quint32 LC_CAMERA_SECTION_UPVECTOR }; +struct lcCameraHistoryState +{ + lcObjectId Id; + bool Hidden; + bool Simple; + float Fovy; + float NearPlane; + float FarPlane; + lcCameraProjection Projection; + lcObjectProperty Position; + lcObjectProperty TargetPosition; + lcObjectProperty UpVector; + QString Name; + + bool operator==(const lcCameraHistoryState& Other) const + { + return Id == Other.Id && Hidden == Other.Hidden && Simple == Other.Simple && Fovy == Other.Fovy && + NearPlane == Other.NearPlane && FarPlane == Other.FarPlane && Projection == Other.Projection && + Position == Other.Position && TargetPosition == Other.TargetPosition && UpVector == Other.UpVector && Name == Other.Name; + } +}; + class lcCamera : public lcObject { public: + lcCamera(); lcCamera(bool Simple); - lcCamera(const lcVector3& Position, const lcVector3& TargetPosition); + lcCamera(bool Simple, const lcVector3& Position, const lcVector3& TargetPosition); virtual ~lcCamera(); lcCamera(const lcCamera&) = delete; @@ -167,8 +190,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const override; - bool LoadUndoData(QDataStream& Stream, const lcModel* Model) override; + lcCameraHistoryState GetHistoryState(const lcModel* Model) const; + void SetHistoryState(const lcCameraHistoryState& State, const lcModel* Model); void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); @@ -207,6 +230,6 @@ public: protected: QString mName; - bool mSimple = false; + bool mSimple = true; lcCameraProjection mProjection = lcCameraProjection::Perspective; }; diff --git a/common/group.cpp b/common/group.cpp index d0ad896c..5f52a21a 100644 --- a/common/group.cpp +++ b/common/group.cpp @@ -1,11 +1,15 @@ #include "lc_global.h" #include #include "group.h" +#include "lc_model.h" #include "lc_file.h" +lcGroupId lcGroup::mNextId; + lcGroup::lcGroup() + : mId(mNextId) { - mGroup = nullptr; + mNextId = static_cast(static_cast(mNextId) + 1); } void lcGroup::FileLoad(lcFile* File) @@ -58,3 +62,37 @@ void lcGroup::CreateName(const std::vector>& Groups) mName = Prefix + QString::number(Max + 1); } + +lcGroupHistoryState lcGroup::GetHistoryState(const lcModel* Model) const +{ + lcGroupHistoryState State; + + State.Id = mId; + State.ParentIndex = ~0; + State.Name = mName; + + if (mGroup) + { + const std::vector>& Groups = Model->GetGroups(); + + for (size_t GroupIndex = 0; GroupIndex < Groups.size(); GroupIndex++) + { + if (Groups[GroupIndex].get() == mGroup) + { + State.ParentIndex = GroupIndex; + break; + } + } + } + + return State; +} + +void lcGroup::SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model) +{ + const std::vector>& Groups = Model->GetGroups(); + + mId = State.Id; + mName = State.Name; + mGroup = (State.ParentIndex < Groups.size()) ? Groups[State.ParentIndex].get() : nullptr; +} diff --git a/common/group.h b/common/group.h index a39534f9..7eb6293d 100644 --- a/common/group.h +++ b/common/group.h @@ -2,6 +2,20 @@ #define LC_MAX_GROUP_NAME 64 +enum class lcGroupId : uint32_t; + +struct lcGroupHistoryState +{ + lcGroupId Id; + uint32_t ParentIndex; + QString Name; + + bool operator==(const lcGroupHistoryState& Other) const + { + return Id == Other.Id && ParentIndex == Other.ParentIndex && Name == Other.Name; + } +}; + class lcGroup { public: @@ -11,11 +25,23 @@ public: { return mGroup ? mGroup->GetTopGroup() : this; } - + + lcGroupId GetId() const + { + return mId; + } + void FileLoad(lcFile* File); void CreateName(const std::vector>& Groups); - - lcGroup* mGroup; + + lcGroupHistoryState GetHistoryState(const lcModel* Model) const; + void SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model); + + lcGroup* mGroup = nullptr; QString mName; + +protected: + lcGroupId mId = static_cast(0); + + static lcGroupId mNextId; }; - diff --git a/common/lc_math.h b/common/lc_math.h index c2ef475f..48503c68 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -464,6 +464,11 @@ inline bool operator==(const lcMatrix33& a, const lcMatrix33& b) return a.r[0] == b.r[0] && a.r[1] == b.r[1] && a.r[2] == b.r[2]; } +inline bool operator==(const lcMatrix44& a, const lcMatrix44& b) +{ + return a.r[0] == b.r[0] && a.r[1] == b.r[1] && a.r[2] == b.r[2] && a.r[3] == b.r[3]; +} + #ifndef QT_NO_DEBUG inline QDebug operator<<(QDebug Debug, const lcVector2& v) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 4567f90b..85f932e7 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1809,6 +1809,49 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect ModelActionSelection->LoadStartState(this); } +template +void lcModel::LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects) +{ + std::vector> NewObjects; + + NewObjects.reserve(ObjectStates.size()); + + for (const StateType& ObjectState : ObjectStates) + { + auto ObjectId = ObjectState.Id; + bool Found = false; + + for (auto ObjectIt = Objects.begin(); ObjectIt != Objects.end(); ++ObjectIt) + { + ObjectType* Object = ObjectIt->get(); + + if (Object->GetId() == ObjectId) + { + NewObjects.emplace_back(std::move(*ObjectIt)); + Objects.erase(ObjectIt); + Found = true; + break; + } + } + + if (!Found) + NewObjects.emplace_back(new ObjectType()); + } + + Objects = std::move(NewObjects); + + for (size_t ObjectIndex = 0; ObjectIndex < Objects.size(); ObjectIndex++) + Objects[ObjectIndex]->SetHistoryState(ObjectStates[ObjectIndex], this); +} + +void lcModel::LoadHistoryState(const lcModelHistoryState& HistoryState) +{ + LoadObjectHistoryState(HistoryState.Groups, mGroups); + LoadObjectHistoryState(HistoryState.Pieces, mPieces); + LoadObjectHistoryState(HistoryState.Cameras, mCameras); + LoadObjectHistoryState(HistoryState.Lights, mLights); +} + void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera) { std::unique_ptr ModelActionObjectEdit = std::make_unique(ModelActionObjectEditMode); @@ -1816,8 +1859,7 @@ void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjec if (!ModelActionObjectEdit) return; - if (!ModelActionObjectEdit->SaveStartState(this, Camera)) - return; + ModelActionObjectEdit->SaveStartState(this, Camera); mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } @@ -1832,7 +1874,9 @@ void lcModel::EndObjectEditAction(std::vector&& ObjectIndices, std::vect if (!ModelActionObjectEdit) return; - if (!ModelActionObjectEdit->SaveEndState(this, std::move(ObjectIndices), std::move(GroupIndices))) + ModelActionObjectEdit->SaveEndState(this, std::move(ObjectIndices), std::move(GroupIndices)); + + if (ModelActionObjectEdit->StateChanged()) mActionSequence.pop_back(); } @@ -4950,7 +4994,7 @@ void lcModel::InsertCameraToolClicked(const lcVector3& Position) BeginActionSequence(); BeginObjectEditAction(lcModelActionObjectEditMode::CreateCamera, nullptr); - lcCamera* Camera = new lcCamera(Position, GetSelectionOrModelCenter()); + lcCamera* Camera = new lcCamera(false, Position, GetSelectionOrModelCenter()); Camera->CreateName(mCameras); mCameras.emplace_back(Camera); diff --git a/common/lc_model.h b/common/lc_model.h index e85fa68d..b9ab73d6 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -5,6 +5,7 @@ enum class lcObjectPropertyId; enum class lcCameraProjection; +struct lcModelHistoryState; class lcModelAction; class lcModelActionSelection; class lcModelActionObjectEdit; @@ -229,7 +230,11 @@ public: void ShowNextStep(); void InsertStep(lcStep Step); void RemoveStep(lcStep Step); - + + template + void LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects); + void LoadHistoryState(const lcModelHistoryState& HistoryState); + lcPiece* AddPiece(PieceInfo* Info, quint32 Section); void AddPiece(std::unique_ptr Piece, size_t PieceIndex); void RemovePieces(const std::vector& PieceIndices); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 48652481..23f27342 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -143,332 +143,60 @@ void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, } lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mode) - : mMode(Mode) { } - -bool lcModelActionObjectEdit::SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model) +void lcModelActionObjectEdit::SaveState(lcModelHistoryState& State, const lcModel* Model) { - QDataStream Stream(&Buffer, QIODevice::WriteOnly); - const std::vector>& Groups = Model->GetGroups(); + + for (const std::unique_ptr& Group : Groups) + State.Groups.emplace_back(Group->GetHistoryState(Model)); + const std::vector>& Pieces = Model->GetPieces(); + + for (const std::unique_ptr& Piece : Pieces) + State.Pieces.emplace_back(Piece->GetHistoryState(Model)); + const std::vector>& Cameras = Model->GetCameras(); + + for (const std::unique_ptr& Camera : Cameras) + State.Cameras.emplace_back(Camera->GetHistoryState(Model)); + const std::vector>& Lights = Model->GetLights(); - uint64_t ObjectCount[4] = { Groups.size(), Pieces.size(), Cameras.size(), Lights.size() }; - - if (Stream.writeRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) - return false; - - for (size_t GroupIndex : mGroupIndices) - { - const lcGroup* Group = Groups[GroupIndex].get(); - uint64_t ParentIndex = UINT64_MAX; - - if (Group->mGroup) - for (ParentIndex = 0; ParentIndex < Groups.size(); ParentIndex++) - if (Group->mGroup == Groups[ParentIndex].get()) - break; - - Stream << Group->mName; - Stream << ParentIndex; - } - - for (size_t PieceIndex : mPieceIndices) - if (!Pieces[PieceIndex]->SaveUndoData(Stream, Model)) - return false; - - for (size_t CameraIndex : mCameraIndices) - if (!Cameras[CameraIndex]->SaveUndoData(Stream, Model)) - return false; - - for (size_t LightIndex : mLightIndices) - if (!Lights[LightIndex]->SaveUndoData(Stream, Model)) - return false; - - return true; + for (const std::unique_ptr& Light : Lights) + State.Lights.emplace_back(Light->GetHistoryState(Model)); } -bool lcModelActionObjectEdit::LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const +void lcModelActionObjectEdit::LoadState(const lcModelHistoryState& State, lcModel* Model) { - QDataStream Stream(const_cast(&Buffer), QIODevice::ReadOnly); - - const std::vector>& Groups = Model->GetGroups(); - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - - uint64_t ObjectCount[4]; - - if (Stream.readRawData(reinterpret_cast(ObjectCount), sizeof(ObjectCount)) != sizeof(ObjectCount)) - return false; - - if (CreateObjects) - { - ObjectCount[0] -= mGroupIndices.size(); - ObjectCount[1] -= mPieceIndices.size(); - ObjectCount[2] -= mCameraIndices.size(); - ObjectCount[3] -= mLightIndices.size(); - } - - if (ObjectCount[0] != Groups.size() || ObjectCount[1] != Pieces.size() || ObjectCount[2] != Cameras.size() || ObjectCount[3] != Lights.size()) - return false; - - if (CreateObjects) - { - for (size_t GroupIndex : mGroupIndices) - { - std::unique_ptr Group(new lcGroup()); - QString Name; - uint64_t ParentIndex; - - Stream >> Name; - Stream >> ParentIndex; - - Group->mName = Name; - Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; - - Model->AddGroup(std::move(Group), GroupIndex); - } - - for (size_t PieceIndex : mPieceIndices) - { - if (PieceIndex > Pieces.size()) - return false; - - std::unique_ptr Piece(new lcPiece(nullptr)); - - if (!Piece->LoadUndoData(Stream, Model)) - return false; - - Model->AddPiece(std::move(Piece), PieceIndex); - } - - for (size_t CameraIndex : mCameraIndices) - { - if (CameraIndex > Cameras.size()) - return false; - - std::unique_ptr Camera(new lcCamera(false)); - - if (!Camera->LoadUndoData(Stream, Model)) - return false; - - Model->AddCamera(std::move(Camera), CameraIndex); - } - - for (size_t LightIndex : mLightIndices) - { - if (LightIndex > Lights.size()) - return false; - - std::unique_ptr Light(new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point)); - - if (!Light->LoadUndoData(Stream, Model)) - return false; - - Model->AddLight(std::move(Light), LightIndex); - } - } - else - { - for (size_t GroupIndex : mGroupIndices) - { - lcGroup* Group = Groups[GroupIndex].get(); - QString Name; - uint64_t ParentIndex; - - Stream >> Name; - Stream >> ParentIndex; - - Group->mName = Name; - Group->mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; - } - - for (size_t PieceIndex : mPieceIndices) - { - if (PieceIndex >= Pieces.size()) - return false; - - const std::unique_ptr& Piece = Pieces[PieceIndex]; - - if (!Piece->LoadUndoData(Stream, Model)) - return false; - } - - for (size_t CameraIndex : mCameraIndices) - { - if (CameraIndex >= Cameras.size()) - return false; - - const std::unique_ptr& Camera = Cameras[CameraIndex]; - - if (!Camera->LoadUndoData(Stream, Model)) - return false; - } - - for (size_t LightIndex : mLightIndices) - { - if (LightIndex >= Lights.size()) - return false; - - const std::unique_ptr& Light = Lights[LightIndex]; - - if (!Light->LoadUndoData(Stream, Model)) - return false; - } - } - - return true; + Model->LoadHistoryState(State); } -bool lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamera* Camera) +void lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamera* Camera) { - const std::vector>& Pieces = Model->GetPieces(); - const std::vector>& Cameras = Model->GetCameras(); - const std::vector>& Lights = Model->GetLights(); - - switch (mMode) - { - case lcModelActionObjectEditMode::EditAllObjects: - mPieceIndices.resize(Pieces.size()); - std::iota(mPieceIndices.begin(), mPieceIndices.end(), 0); - - mCameraIndices.resize(Cameras.size()); - std::iota(mCameraIndices.begin(), mCameraIndices.end(), 0); - - mLightIndices.resize(Lights.size()); - std::iota(mLightIndices.begin(), mLightIndices.end(), 0); - break; - - case lcModelActionObjectEditMode::EditAllPieces: - mPieceIndices.resize(Pieces.size()); - std::iota(mPieceIndices.begin(), mPieceIndices.end(), 0); - break; - - case lcModelActionObjectEditMode::EditSelectedObjects: - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - if (Pieces[PieceIndex]->IsSelected()) - mPieceIndices.push_back(PieceIndex); - - for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) - if (Cameras[CameraIndex]->IsSelected()) - mCameraIndices.push_back(CameraIndex); - - for (size_t LightIndex = 0; LightIndex < Lights.size(); LightIndex++) - if (Lights[LightIndex]->IsSelected()) - mLightIndices.push_back(LightIndex); - break; - - case lcModelActionObjectEditMode::EditSelectedPieces: - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - if (Pieces[PieceIndex]->IsSelected()) - mPieceIndices.push_back(PieceIndex); - break; - - case lcModelActionObjectEditMode::EditUnselectedPieces: - for (size_t PieceIndex = 0; PieceIndex < Pieces.size(); PieceIndex++) - if (!Pieces[PieceIndex]->IsSelected()) - mPieceIndices.push_back(PieceIndex); - break; - - case lcModelActionObjectEditMode::EditCamera: - for (size_t CameraIndex = 0; CameraIndex < Cameras.size(); CameraIndex++) - { - if (Cameras[CameraIndex].get() == Camera) - { - mCameraIndices.push_back(CameraIndex); - break; - } - } - break; - - case lcModelActionObjectEditMode::CreatePieces: - case lcModelActionObjectEditMode::CreateCamera: - case lcModelActionObjectEditMode::CreateLight: - break; - }; - - return SaveHistoryBuffer(mStartBuffer, Model); + SaveState(mStartState, Model); } -bool lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices) +void lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices) { - switch (mMode) - { - case lcModelActionObjectEditMode::EditAllObjects: - case lcModelActionObjectEditMode::EditAllPieces: - case lcModelActionObjectEditMode::EditSelectedObjects: - case lcModelActionObjectEditMode::EditSelectedPieces: - case lcModelActionObjectEditMode::EditUnselectedPieces: - case lcModelActionObjectEditMode::EditCamera: - break; - - case lcModelActionObjectEditMode::CreatePieces: - mPieceIndices = std::move(ObjectIndices); - mGroupIndices = std::move(GroupIndices); - break; - - case lcModelActionObjectEditMode::CreateCamera: - mCameraIndices = std::move(ObjectIndices); - break; - - case lcModelActionObjectEditMode::CreateLight: - mLightIndices = std::move(ObjectIndices); - break; - }; - - return SaveHistoryBuffer(mEndBuffer, Model); + SaveState(mEndState, Model); } void lcModelActionObjectEdit::LoadStartState(lcModel* Model) const { - switch (mMode) - { - case lcModelActionObjectEditMode::EditAllObjects: - case lcModelActionObjectEditMode::EditAllPieces: - case lcModelActionObjectEditMode::EditSelectedObjects: - case lcModelActionObjectEditMode::EditSelectedPieces: - case lcModelActionObjectEditMode::EditUnselectedPieces: - case lcModelActionObjectEditMode::EditCamera: - LoadHistoryBuffer(mStartBuffer, Model, false); - break; - - case lcModelActionObjectEditMode::CreatePieces: - Model->RemovePieces(mPieceIndices); - break; - - case lcModelActionObjectEditMode::CreateCamera: - Model->RemoveCameras(mCameraIndices); - break; - - case lcModelActionObjectEditMode::CreateLight: - Model->RemoveLights(mLightIndices); - break; - }; + LoadState(mStartState, Model); } void lcModelActionObjectEdit::LoadEndState(lcModel* Model) const { - switch (mMode) - { - case lcModelActionObjectEditMode::EditAllObjects: - case lcModelActionObjectEditMode::EditAllPieces: - case lcModelActionObjectEditMode::EditSelectedObjects: - case lcModelActionObjectEditMode::EditSelectedPieces: - case lcModelActionObjectEditMode::EditUnselectedPieces: - case lcModelActionObjectEditMode::EditCamera: - LoadHistoryBuffer(mEndBuffer, Model, false); - break; - - case lcModelActionObjectEditMode::CreatePieces: - case lcModelActionObjectEditMode::CreateCamera: - case lcModelActionObjectEditMode::CreateLight: - LoadHistoryBuffer(mEndBuffer, Model, true); - break; - }; + LoadState(mEndState, Model); +} + +bool lcModelActionObjectEdit::StateChanged() const +{ + return mStartState != mEndState; } lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName) diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 755e566d..ed74692b 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -60,34 +60,43 @@ enum class lcModelActionObjectEditMode CreateLight }; +struct lcGroupHistoryState; +struct lcPieceHistoryState; +struct lcCameraHistoryState; +struct lcLightHistoryState; + +struct lcModelHistoryState +{ + std::vector Groups; + std::vector Pieces; + std::vector Cameras; + std::vector Lights; + + bool operator!=(const lcModelHistoryState& Other) const + { + return Groups != Other.Groups || Pieces != Other.Pieces || Cameras != Other.Cameras || Lights != Other.Lights; + } +}; + class lcModelActionObjectEdit: public lcModelAction { public: lcModelActionObjectEdit(lcModelActionObjectEditMode Mode); virtual ~lcModelActionObjectEdit() = default; - bool SaveStartState(const lcModel* Model, const lcCamera* Camera); - bool SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices); + void SaveStartState(const lcModel* Model, const lcCamera* Camera); + void SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices); void LoadStartState(lcModel* Model) const; void LoadEndState(lcModel* Model) const; - - lcModelActionObjectEditMode GetMode() const - { - return mMode; - } + + bool StateChanged() const; protected: - bool SaveHistoryBuffer(QByteArray& Buffer, const lcModel* Model); - bool LoadHistoryBuffer(const QByteArray& Buffer, lcModel* Model, bool CreateObjects) const; + static void SaveState(lcModelHistoryState& State, const lcModel* Model); + static void LoadState(const lcModelHistoryState& State, lcModel* Model); - std::vector mGroupIndices; - std::vector mPieceIndices; - std::vector mCameraIndices; - std::vector mLightIndices; - - lcModelActionObjectEditMode mMode; - QByteArray mStartBuffer; - QByteArray mEndBuffer; + lcModelHistoryState mStartState; + lcModelHistoryState mEndState; }; enum class lcModelActionGroupPiecesMode diff --git a/common/lc_objectproperty.cpp b/common/lc_objectproperty.cpp index 25ce5987..50958494 100644 --- a/common/lc_objectproperty.cpp +++ b/common/lc_objectproperty.cpp @@ -10,9 +10,7 @@ template bool lcObjectProperty::HasKeyFrame(lcStep Time) const; \ template bool lcObjectProperty::SetKeyFrame(lcStep Time, bool KeyFrame); \ template void lcObjectProperty::Save(QTextStream& Stream, const char* ObjectName, const char* VariableName, bool SaveEmpty) const; \ - template bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const char* VariableName); \ - template bool lcObjectProperty::SaveUndoData(QDataStream& Stream) const; \ - template bool lcObjectProperty::LoadUndoData(QDataStream& Stream); + template bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const char* VariableName); LC_OBJECT_PROPERTY(float) LC_OBJECT_PROPERTY(int) @@ -314,42 +312,3 @@ bool lcObjectProperty::Load(QTextStream& Stream, const QString& Token, const return false; } - -template -bool lcObjectProperty::SaveUndoData(QDataStream& Stream) const -{ - size_t KeyCount = mKeys.size(); - qint64 DataSize = KeyCount * sizeof(lcObjectPropertyKey); - - if (Stream.writeRawData(reinterpret_cast(&mValue), sizeof(mValue)) != sizeof(mValue)) - return false; - - if (Stream.writeRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)) != sizeof(KeyCount)) - return false; - - if (Stream.writeRawData(reinterpret_cast(mKeys.data()), DataSize) != DataSize) - return false; - - return true; -} - -template -bool lcObjectProperty::LoadUndoData(QDataStream& Stream) -{ - if (Stream.readRawData(reinterpret_cast(&mValue), sizeof(mValue)) != sizeof(mValue)) - return false; - - size_t KeyCount; - - if (Stream.readRawData(reinterpret_cast(&KeyCount), sizeof(KeyCount)) != sizeof(KeyCount)) - return false; - - mKeys.resize(KeyCount); - - qsizetype DataSize = KeyCount * sizeof(lcObjectPropertyKey); - - if (Stream.readRawData(reinterpret_cast(mKeys.data()), DataSize) != DataSize) - return false; - - return true; -} diff --git a/common/lc_objectproperty.h b/common/lc_objectproperty.h index d2dde646..071232f2 100644 --- a/common/lc_objectproperty.h +++ b/common/lc_objectproperty.h @@ -67,11 +67,13 @@ template class lcObjectProperty { public: + lcObjectProperty() = default; + explicit lcObjectProperty(const T& DefaultValue) : mValue(DefaultValue) { } - + operator const T& () const { return mValue; @@ -96,8 +98,6 @@ public: void Save(QTextStream& Stream, const char* ObjectName, const char* VariableName, bool SaveEmpty) const; bool Load(QTextStream& Stream, const QString& Token, const char* VariableName); - bool SaveUndoData(QDataStream& Stream) const; - bool LoadUndoData(QDataStream& Stream); protected: T mValue; diff --git a/common/light.cpp b/common/light.cpp index 34fb2efd..4ab16282 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -19,6 +19,11 @@ static const std::array(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") }; static const std::array(lcLightAreaShape::Count)> gLightAreaShapes = { QLatin1String("RECTANGLE"), QLatin1String("SQUARE"), QLatin1String("DISK"), QLatin1String("ELLIPSE") }; +lcLight::lcLight() + : lcObject(lcObjectType::Light) +{ +} + lcLight::lcLight(const lcVector3& Position, lcLightType LightType) : lcObject(lcObjectType::Light), mLightType(LightType) { @@ -1529,49 +1534,58 @@ void lcLight::RemoveKeyFrames() mPOVRayFadePower.RemoveAllKeys(); } -bool lcLight::SaveUndoData(QDataStream& Stream, const lcModel* Model) const +lcLightHistoryState lcLight::GetHistoryState(const lcModel* Model) const { - static_assert(sizeof(lcLight) == 704); - Q_UNUSED(Model); + lcLightHistoryState State; - Stream << mName; - Stream << mLightType; - Stream << mCastShadow; - Stream << mAreaShape; - Stream << mHidden; + State.Id = mId; + State.Hidden = mHidden; + State.Name = mName; + State.LightType = mLightType; + State.CastShadow = mCastShadow; + State.Position = mPosition; + State.Rotation = mRotation; + State.Color = mColor; + State.BlenderPower = mBlenderPower; + State.BlenderRadius = mBlenderRadius; + State.BlenderAngle = mBlenderAngle; + State.POVRayPower = mPOVRayPower; + State.POVRayFadeDistance = mPOVRayFadeDistance; + State.POVRayFadePower = mPOVRayFadePower; + State.SpotConeAngle = mSpotConeAngle; + State.SpotPenumbraAngle = mSpotPenumbraAngle; + State.POVRaySpotTightness = mPOVRaySpotTightness; + State.AreaShape = mAreaShape; + State.AreaSizeX = mAreaSizeX; + State.AreaSizeY = mAreaSizeY; + State.POVRayAreaGridX = mPOVRayAreaGridX; + State.POVRayAreaGridY = mPOVRayAreaGridY; - return mPosition.SaveUndoData(Stream) && mRotation.SaveUndoData(Stream) && mColor.SaveUndoData(Stream) && - mSpotConeAngle.SaveUndoData(Stream) && mSpotPenumbraAngle.SaveUndoData(Stream) && mPOVRaySpotTightness.SaveUndoData(Stream) && - mPOVRayAreaGridX.SaveUndoData(Stream) && mPOVRayAreaGridY.SaveUndoData(Stream) && mBlenderRadius.SaveUndoData(Stream) && - mBlenderAngle.SaveUndoData(Stream) && mAreaSizeX.SaveUndoData(Stream) && mAreaSizeY.SaveUndoData(Stream) && - mBlenderPower.SaveUndoData(Stream) && mPOVRayPower.SaveUndoData(Stream) && mPOVRayFadeDistance.SaveUndoData(Stream) && - mPOVRayFadePower.SaveUndoData(Stream); + return State; } -bool lcLight::LoadUndoData(QDataStream& Stream, const lcModel* Model) +void lcLight::SetHistoryState(const lcLightHistoryState& State, const lcModel* Model) { - Q_UNUSED(Model); - - Stream >> mName; - Stream >> mLightType; - Stream >> mCastShadow; - Stream >> mAreaShape; - Stream >> mHidden; - - return mPosition.LoadUndoData(Stream) && - mRotation.LoadUndoData(Stream) && - mColor.LoadUndoData(Stream) && - mSpotConeAngle.LoadUndoData(Stream) && - mSpotPenumbraAngle.LoadUndoData(Stream) && - mPOVRaySpotTightness.LoadUndoData(Stream) && - mPOVRayAreaGridX.LoadUndoData(Stream) && - mPOVRayAreaGridY.LoadUndoData(Stream) && - mBlenderRadius.LoadUndoData(Stream) && - mBlenderAngle.LoadUndoData(Stream) && - mAreaSizeX.LoadUndoData(Stream) && - mAreaSizeY.LoadUndoData(Stream) && - mBlenderPower.LoadUndoData(Stream) && - mPOVRayPower.LoadUndoData(Stream) && - mPOVRayFadeDistance.LoadUndoData(Stream) && - mPOVRayFadePower.LoadUndoData(Stream); + mId = State.Id; + mHidden = State.Hidden; + mName = State.Name; + mLightType = State.LightType; + mCastShadow = State.CastShadow; + mPosition = State.Position; + mRotation = State.Rotation; + mColor = State.Color; + mBlenderPower = State.BlenderPower; + mBlenderRadius = State.BlenderRadius; + mBlenderAngle = State.BlenderAngle; + mPOVRayPower = State.POVRayPower; + mPOVRayFadeDistance = State.POVRayFadeDistance; + mPOVRayFadePower = State.POVRayFadePower; + mSpotConeAngle = State.SpotConeAngle; + mSpotPenumbraAngle = State.SpotPenumbraAngle; + mPOVRaySpotTightness = State.POVRaySpotTightness; + mAreaShape = State.AreaShape; + mAreaSizeX = State.AreaSizeX; + mAreaSizeY = State.AreaSizeY; + mPOVRayAreaGridX = State.POVRayAreaGridX; + mPOVRayAreaGridY = State.POVRayAreaGridY; } diff --git a/common/light.h b/common/light.h index b766fb12..3344e31f 100644 --- a/common/light.h +++ b/common/light.h @@ -28,9 +28,47 @@ enum class lcLightAreaShape Count }; +struct lcLightHistoryState +{ + lcObjectId Id; + bool Hidden; + QString Name; + lcLightType LightType; + bool CastShadow; + lcObjectProperty Position; + lcObjectProperty Rotation; + lcObjectProperty Color; + lcObjectProperty BlenderPower; + lcObjectProperty BlenderRadius; + lcObjectProperty BlenderAngle; + lcObjectProperty POVRayPower; + lcObjectProperty POVRayFadeDistance; + lcObjectProperty POVRayFadePower; + lcObjectProperty SpotConeAngle; + lcObjectProperty SpotPenumbraAngle; + lcObjectProperty POVRaySpotTightness; + lcLightAreaShape AreaShape; + lcObjectProperty AreaSizeX; + lcObjectProperty AreaSizeY; + lcObjectProperty POVRayAreaGridX; + lcObjectProperty POVRayAreaGridY; + + bool operator==(const lcLightHistoryState& Other) const + { + return Id == Other.Id && Hidden == Other.Hidden && Name == Other.Name && LightType == Other.LightType && + CastShadow == Other.CastShadow && Position == Other.Position && Rotation == Other.Rotation && Color == Other.Color && + BlenderPower == Other.BlenderPower && BlenderRadius == Other.BlenderRadius && BlenderAngle == Other.BlenderAngle && + POVRayPower == Other.POVRayPower && POVRayFadeDistance == Other.POVRayFadeDistance && POVRayFadePower == Other.POVRayFadePower && + SpotConeAngle == Other.SpotConeAngle && SpotPenumbraAngle == Other.SpotPenumbraAngle && + POVRaySpotTightness == Other.POVRaySpotTightness && AreaShape == Other.AreaShape && AreaSizeX == Other.AreaSizeX && + AreaSizeY == Other.AreaSizeY && POVRayAreaGridX == Other.POVRayAreaGridX && POVRayAreaGridY == Other.POVRayAreaGridY; + } +}; + class lcLight : public lcObject { public: + lcLight(); lcLight(const lcVector3& Position, lcLightType LightType); virtual ~lcLight() = default; @@ -161,8 +199,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const override; - bool LoadUndoData(QDataStream& Stream, const lcModel* Model) override; + lcLightHistoryState GetHistoryState(const lcModel* Model) const; + void SetHistoryState(const lcLightHistoryState& State, const lcModel* Model); void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/object.cpp b/common/object.cpp index e3f8fa11..ff818bc7 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -1,9 +1,12 @@ #include "lc_global.h" #include "object.h" +lcObjectId lcObject::mNextId; + lcObject::lcObject(lcObjectType ObjectType) - : mObjectType(ObjectType) + : mObjectType(ObjectType), mId(mNextId) { + mNextId = static_cast(static_cast(mNextId) + 1); } lcObject::~lcObject() diff --git a/common/object.h b/common/object.h index 83d04bf5..7a30339e 100644 --- a/common/object.h +++ b/common/object.h @@ -10,6 +10,8 @@ enum class lcObjectType Light }; +enum class lcObjectId : uint32_t; + struct lcObjectSection { lcObject* Object = nullptr; @@ -89,6 +91,11 @@ public: return mObjectType; } + lcObjectId GetId() const + { + return mId; + } + bool IsSelected() const { return mSelected; @@ -139,8 +146,6 @@ public: virtual bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const = 0; virtual bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) = 0; virtual void RemoveKeyFrames() = 0; - virtual bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const = 0; - virtual bool LoadUndoData(QDataStream& Stream, const lcModel* Model) = 0; virtual QString GetName() const = 0; static QString GetCheckpointString(lcObjectPropertyId PropertyId); @@ -151,4 +156,7 @@ protected: bool mHidden = false; bool mSelected = false; quint32 mFocusedSection = LC_OBJECT_SECTION_INVALID; + lcObjectId mId = static_cast(0); + + static lcObjectId mNextId; }; diff --git a/common/piece.cpp b/common/piece.cpp index e598c23d..6bed4239 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -20,15 +20,17 @@ constexpr float LC_PIECE_CONTROL_POINT_SIZE = 10.0f; +lcPiece::lcPiece() + : lcObject(lcObjectType::Piece) +{ +} + lcPiece::lcPiece(PieceInfo* Info) : lcObject(lcObjectType::Piece) { SetPieceInfo(Info, QString(), true, true); mColorIndex = gDefaultColor; mColorCode = 16; - mStepShow = 1; - mStepHide = LC_STEP_MAX; - mGroup = nullptr; mPivotMatrix = lcMatrix44Identity(); } @@ -935,89 +937,68 @@ void lcPiece::RemoveKeyFrames() mRotation.RemoveAllKeys(); } -bool lcPiece::SaveUndoData(QDataStream& Stream, const lcModel* Model) const +lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const { - static_assert(sizeof(lcPiece) == 384); + lcPieceHistoryState State; - Stream << mFileLine; - Stream << mID; + State.Id = mId; + State.Hidden = mHidden; + State.FileLine = mFileLine; + State.PieceId = mID; + State.GroupIndex = ~0; + State.ColorIndex = mColorIndex; + State.ColorCode = mColorCode; + State.StepShow = mStepShow; + State.StepHide = mStepHide; + State.PivotMatrix = mPivotMatrix; + State.PivotPointValid = mPivotPointValid; + State.ControlPoints = mControlPoints; + State.Position = mPosition; + State.Rotation = mRotation; const std::vector>& Groups = Model->GetGroups(); - uint64_t ParentIndex = UINT64_MAX; if (mGroup) - for (ParentIndex = 0; ParentIndex < Groups.size(); ParentIndex++) - if (mGroup == Groups[ParentIndex].get()) + { + for (size_t GroupIndex = 0; GroupIndex < Groups.size(); GroupIndex++) + { + if (mGroup == Groups[GroupIndex].get()) + { + State.GroupIndex = GroupIndex; break; + } + } + } - Stream << ParentIndex; - Stream << mColorIndex; - Stream << mColorCode; - - Stream << mStepShow; - Stream << mStepHide; - - Stream << mPivotMatrix; - Stream << mPivotPointValid; - - Stream << mHidden; - - size_t ControlPointCount = mControlPoints.size(); - qint64 DataSize = ControlPointCount * sizeof(lcPieceControlPoint); - - if (Stream.writeRawData(reinterpret_cast(&ControlPointCount), sizeof(ControlPointCount)) != sizeof(ControlPointCount)) - return false; - - if (Stream.writeRawData(reinterpret_cast(mControlPoints.data()), DataSize) != DataSize) - return false; - - return mPosition.SaveUndoData(Stream) && mRotation.SaveUndoData(Stream); + return State; } -bool lcPiece::LoadUndoData(QDataStream& Stream, const lcModel* Model) +void lcPiece::SetHistoryState(const lcPieceHistoryState& State, const lcModel* Model) { - Stream >> mFileLine; - Stream >> mID; + const std::vector>& Groups = Model->GetGroups(); + + mId = State.Id; + mHidden = State.Hidden; + mFileLine = State.FileLine; + mID = State.PieceId; + mGroup = (State.GroupIndex < Groups.size()) ? Groups[State.GroupIndex].get() : nullptr;; + mColorIndex = State.ColorIndex; + mColorCode = State.ColorCode; + mStepShow = State.StepShow; + mStepHide = State.StepHide; + mPivotMatrix = State.PivotMatrix; + mPivotPointValid = State.PivotPointValid; + mControlPoints = State.ControlPoints; + mPosition = State.Position; + mRotation = State.Rotation; PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(mID.toLatin1(), nullptr, true, false); SetPieceInfo(Info, mID, true, false); - const std::vector>& Groups = Model->GetGroups(); - uint64_t ParentIndex; - - Stream >> ParentIndex; - - mGroup = ParentIndex < Groups.size() ? Groups[ParentIndex].get() : nullptr; - - Stream >> mColorIndex; - Stream >> mColorCode; - - Stream >> mStepShow; - Stream >> mStepHide; - - Stream >> mPivotMatrix; - Stream >> mPivotPointValid; - - Stream >> mHidden; - - size_t ControlPointCount; - - if (Stream.readRawData(reinterpret_cast(&ControlPointCount), sizeof(ControlPointCount)) != sizeof(ControlPointCount)) - return false; - - mControlPoints.resize(ControlPointCount); - - qsizetype DataSize = ControlPointCount * sizeof(lcPieceControlPoint); - - if (Stream.readRawData(reinterpret_cast(mControlPoints.data()), DataSize) != DataSize) - return false; - UpdateMesh(); -// std::vector mTrainTrackConnections; - - return mPosition.LoadUndoData(Stream) && mRotation.LoadUndoData(Stream); + // std::vector mTrainTrackConnections; } void lcPiece::AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const diff --git a/common/piece.h b/common/piece.h index 9cb6309a..db4f2d30 100644 --- a/common/piece.h +++ b/common/piece.h @@ -21,11 +21,44 @@ struct lcPieceControlPoint { lcMatrix44 Transform; float Scale; + + bool operator==(const lcPieceControlPoint& Other) const + { + return Transform == Other.Transform && Scale == Other.Scale; + } +}; + +struct lcPieceHistoryState +{ + lcObjectId Id; + bool Hidden; + int FileLine; + QString PieceId; + uint32_t GroupIndex; + int ColorIndex; + quint32 ColorCode; + lcStep StepShow; + lcStep StepHide; + lcMatrix44 PivotMatrix; + bool PivotPointValid; + std::vector ControlPoints; + lcObjectProperty Position; + lcObjectProperty Rotation; + + bool operator==(const lcPieceHistoryState& Other) const + { + return Id == Other.Id && Hidden == Other.Hidden && FileLine == Other.FileLine && PieceId == Other.PieceId && + GroupIndex == Other.GroupIndex && ColorIndex == Other.ColorIndex && ColorCode == Other.ColorCode && + StepShow == Other.StepShow && StepHide == Other.StepHide && PivotMatrix == Other.PivotMatrix && + PivotPointValid == Other.PivotPointValid && ControlPoints == Other.ControlPoints && + Position == Other.Position && Rotation == Other.Rotation; + } }; class lcPiece : public lcObject { public: + lcPiece(); lcPiece(PieceInfo* Info); lcPiece(const lcPiece& Other); virtual ~lcPiece(); @@ -60,8 +93,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - bool SaveUndoData(QDataStream& Stream, const lcModel* Model) const override; - bool LoadUndoData(QDataStream& Stream, const lcModel* Model) override; + lcPieceHistoryState GetHistoryState(const lcModel* Model) const; + void SetHistoryState(const lcPieceHistoryState& State, const lcModel* Model); void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const; void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const; @@ -240,10 +273,10 @@ public: } public: - PieceInfo* mPieceInfo; + PieceInfo* mPieceInfo = nullptr; lcMatrix44 mModelWorld; - lcMatrix44 mPivotMatrix; + lcMatrix44 mPivotMatrix = lcMatrix44Identity(); protected: void UpdateMesh(); @@ -266,13 +299,13 @@ protected: int mFileLine = -1; QString mID; - lcGroup* mGroup; + lcGroup* mGroup = nullptr; int mColorIndex; quint32 mColorCode; - lcStep mStepShow; - lcStep mStepHide; + lcStep mStepShow = 1; + lcStep mStepHide = LC_STEP_MAX; bool mPivotPointValid = false; std::vector mControlPoints; From eff97d68411a062277e1e90e7c5bba555392641a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Fri, 13 Feb 2026 23:19:19 -0800 Subject: [PATCH 58/93] Removed unused parameters. --- common/lc_model.cpp | 80 ++++++++++++++++++--------------------- common/lc_model.h | 4 +- common/lc_modelaction.cpp | 8 +--- common/lc_modelaction.h | 19 ++-------- 4 files changed, 43 insertions(+), 68 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 85f932e7..30755b93 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1248,7 +1248,7 @@ void lcModel::DuplicateSelectedPieces() } BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); + BeginObjectEditAction(); std::vector NewPieces; lcPiece* Focus = nullptr; @@ -1282,9 +1282,7 @@ void lcModel::DuplicateSelectedPieces() return NewGroup; } }; - - std::vector PieceIndices; - + for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) { const lcPiece* Piece = mPieces[PieceIndex].get(); @@ -1300,7 +1298,6 @@ void lcModel::DuplicateSelectedPieces() Focus = NewPiece; PieceIndex++; - PieceIndices.push_back(PieceIndex); AddPiece(std::unique_ptr(NewPiece), PieceIndex); lcGroup* Group = Piece->GetGroup(); @@ -1308,7 +1305,7 @@ void lcModel::DuplicateSelectedPieces() NewPiece->SetGroup(GetNewGroup(Group)); } - EndObjectEditAction(std::move(PieceIndices)); + EndObjectEditAction(); RecordSetSelectionAndFocusAction(NewPieces, Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); @@ -1852,19 +1849,19 @@ void lcModel::LoadHistoryState(const lcModelHistoryState& HistoryState) LoadObjectHistoryState(HistoryState.Lights, mLights); } -void lcModel::BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera) +void lcModel::BeginObjectEditAction() { - std::unique_ptr ModelActionObjectEdit = std::make_unique(ModelActionObjectEditMode); + std::unique_ptr ModelActionObjectEdit = std::make_unique(); if (!ModelActionObjectEdit) return; - ModelActionObjectEdit->SaveStartState(this, Camera); + ModelActionObjectEdit->SaveStartState(this); mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); } -void lcModel::EndObjectEditAction(std::vector&& ObjectIndices, std::vector&& GroupIndices) +void lcModel::EndObjectEditAction() { if (mActionSequence.empty()) return; @@ -1874,7 +1871,7 @@ void lcModel::EndObjectEditAction(std::vector&& ObjectIndices, std::vect if (!ModelActionObjectEdit) return; - ModelActionObjectEdit->SaveEndState(this, std::move(ObjectIndices), std::move(GroupIndices)); + ModelActionObjectEdit->SaveEndState(this); if (ModelActionObjectEdit->StateChanged()) mActionSequence.pop_back(); @@ -2211,7 +2208,7 @@ lcStep lcModel::GetLastStep() const void lcModel::InsertStep(lcStep Step) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); + BeginObjectEditAction(); for (const std::unique_ptr& Piece : mPieces) Piece->InsertTime(Step, 1); @@ -2232,7 +2229,7 @@ void lcModel::InsertStep(lcStep Step) void lcModel::RemoveStep(lcStep Step) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditAllObjects, nullptr); + BeginObjectEditAction(); for (const std::unique_ptr& Piece : mPieces) Piece->RemoveTime(Step, 1); @@ -2970,7 +2967,7 @@ void lcModel::DeleteSelectedObjects() void lcModel::ResetSelectedPiecesPivotPoint() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + BeginObjectEditAction(); for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) @@ -2985,7 +2982,7 @@ void lcModel::ResetSelectedPiecesPivotPoint() void lcModel::RemoveSelectedObjectsKeyFrames() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); + BeginObjectEditAction(); for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) @@ -3660,7 +3657,7 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + BeginObjectEditAction(); bool Modified = false; @@ -3754,7 +3751,7 @@ void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraPro if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + BeginObjectEditAction(); } Camera->SetProjection(CameraProjection); @@ -4556,7 +4553,7 @@ void lcModel::SelectGroup(lcGroup* TopGroup, bool Select) void lcModel::HideSelectedPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + BeginObjectEditAction(); bool Modified = false; @@ -4589,7 +4586,7 @@ void lcModel::HideSelectedPieces() void lcModel::HideUnselectedPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditUnselectedPieces, nullptr); + BeginObjectEditAction(); bool Modified = false; @@ -4621,7 +4618,7 @@ void lcModel::HideUnselectedPieces() void lcModel::UnhideSelectedPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedPieces, nullptr); + BeginObjectEditAction(); bool Modified = false; @@ -4653,7 +4650,7 @@ void lcModel::UnhideSelectedPieces() void lcModel::UnhideAllPieces() { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditAllPieces, nullptr); + BeginObjectEditAction(); bool Modified = false; @@ -4849,7 +4846,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::Move: case lcTool::Rotate: BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditSelectedObjects, nullptr); + BeginObjectEditAction(); break; case lcTool::Eraser: @@ -4864,7 +4861,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) if (!View->GetCamera()->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, View->GetCamera()); + BeginObjectEditAction(); } break; @@ -4961,10 +4958,9 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece return; BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); + BeginObjectEditAction(); lcPiece* Piece = nullptr; - std::vector PieceIndices; for (const lcInsertPieceInfo& PieceInfoTransform : PieceInfoTransforms) { @@ -4974,10 +4970,10 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece Piece->SetColorIndex(PieceInfoTransform.ColorIndex); Piece->UpdatePosition(mCurrentStep); - PieceIndices.push_back(AddPiece(Piece)); + AddPiece(Piece); } - EndObjectEditAction(std::move(PieceIndices)); + EndObjectEditAction(); RecordSetSelectionAndFocusAction(std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); @@ -4992,14 +4988,14 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece void lcModel::InsertCameraToolClicked(const lcVector3& Position) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::CreateCamera, nullptr); + BeginObjectEditAction(); lcCamera* Camera = new lcCamera(false, Position, GetSelectionOrModelCenter()); Camera->CreateName(mCameras); mCameras.emplace_back(Camera); - EndObjectEditAction({ mCameras.size() - 1 }); + EndObjectEditAction(); RecordSetSelectionAndFocusAction(std::vector(), Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); @@ -5033,14 +5029,14 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh } BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::CreateLight, nullptr); + BeginObjectEditAction(); lcLight* Light = new lcLight(Position, LightType); Light->CreateName(mLights); mLights.emplace_back(Light); - EndObjectEditAction({ mLights.size() - 1 }); + EndObjectEditAction(); RecordSetSelectionAndFocusAction(std::vector(), Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); @@ -5278,7 +5274,7 @@ void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVec if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + BeginObjectEditAction(); } Camera->ZoomRegion(AspectRatio, Position, TargetPosition, Corners, mCurrentStep, gMainWindow->GetAddKeys()); @@ -5310,7 +5306,7 @@ void lcModel::LookAt(lcCamera* Camera) if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + BeginObjectEditAction(); } Camera->Center(Center, mCurrentStep, gMainWindow->GetAddKeys()); @@ -5357,7 +5353,7 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::EditCamera, Camera); + BeginObjectEditAction(); } Camera->ZoomExtents(Aspect, Center, Points, mCurrentStep, gMainWindow ? gMainWindow->GetAddKeys() : false); @@ -5447,7 +5443,7 @@ void lcModel::ShowArrayDialog() } BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); + BeginObjectEditAction(); std::vector NewPieces; @@ -5490,16 +5486,14 @@ void lcModel::ShowArrayDialog() } } - std::vector PieceIndices; - for (size_t PieceIdx = 0; PieceIdx < NewPieces.size(); PieceIdx++) { lcPiece* Piece = (lcPiece*)NewPieces[PieceIdx]; Piece->UpdatePosition(mCurrentStep); - PieceIndices.push_back(AddPiece(Piece)); + AddPiece(Piece); } - EndObjectEditAction(std::move(PieceIndices)); + EndObjectEditAction(); RecordAddToSelectionAction(NewPieces); @@ -5518,15 +5512,13 @@ void lcModel::ShowMinifigDialog() gMainWindow->GetActiveView()->MakeCurrent(); BeginActionSequence(); - BeginObjectEditAction(lcModelActionObjectEditMode::CreatePieces, nullptr); + BeginObjectEditAction(); lcGroup* Group = AddGroup(tr("Minifig #"), nullptr); std::vector Pieces; - std::vector PieceIndices; lcMinifig& Minifig = Dialog.mMinifigWizard->mMinifig; Pieces.reserve(LC_MFW_NUMITEMS); - PieceIndices.reserve(LC_MFW_NUMITEMS); for (int PartIndex = 0; PartIndex < LC_MFW_NUMITEMS; PartIndex++) { @@ -5538,13 +5530,13 @@ void lcModel::ShowMinifigDialog() Piece->Initialize(Minifig.Matrices[PartIndex], mCurrentStep); Piece->SetColorIndex(Minifig.ColorIndices[PartIndex]); Piece->SetGroup(Group); - PieceIndices.push_back(AddPiece(Piece)); + AddPiece(Piece); Piece->UpdatePosition(mCurrentStep); Pieces.emplace_back(Piece); } - EndObjectEditAction(std::move(PieceIndices), { mGroups.size() - 1}); + EndObjectEditAction(); RecordSetSelectionAndFocusAction(Pieces, nullptr, 0, lcSelectionMode::Single); diff --git a/common/lc_model.h b/common/lc_model.h index b9ab73d6..906a1576 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -418,8 +418,8 @@ protected: void RecordAddToSelectionAction(const std::vector& Objects); void RecordRemoveFromSelectionAction(const std::vector& Objects); void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); - void BeginObjectEditAction(lcModelActionObjectEditMode ModelActionObjectEditMode, const lcCamera* Camera); - void EndObjectEditAction(std::vector&& ObjectIndices = std::vector(), std::vector&& GroupIndices = std::vector()); + void BeginObjectEditAction(); + void EndObjectEditAction(); void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 23f27342..69d113eb 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -142,10 +142,6 @@ void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, } } -lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionObjectEditMode Mode) -{ -} - void lcModelActionObjectEdit::SaveState(lcModelHistoryState& State, const lcModel* Model) { const std::vector>& Groups = Model->GetGroups(); @@ -174,12 +170,12 @@ void lcModelActionObjectEdit::LoadState(const lcModelHistoryState& State, lcMode Model->LoadHistoryState(State); } -void lcModelActionObjectEdit::SaveStartState(const lcModel* Model, const lcCamera* Camera) +void lcModelActionObjectEdit::SaveStartState(const lcModel* Model) { SaveState(mStartState, Model); } -void lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices) +void lcModelActionObjectEdit::SaveEndState(const lcModel* Model) { SaveState(mEndState, Model); } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index ed74692b..9c9b8c4b 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -47,19 +47,6 @@ protected: lcModelActionSelectionState mEndState; }; -enum class lcModelActionObjectEditMode -{ - EditAllObjects, - EditAllPieces, - EditSelectedObjects, - EditSelectedPieces, - EditUnselectedPieces, - EditCamera, - CreatePieces, - CreateCamera, - CreateLight -}; - struct lcGroupHistoryState; struct lcPieceHistoryState; struct lcCameraHistoryState; @@ -81,11 +68,11 @@ struct lcModelHistoryState class lcModelActionObjectEdit: public lcModelAction { public: - lcModelActionObjectEdit(lcModelActionObjectEditMode Mode); + lcModelActionObjectEdit() = default; virtual ~lcModelActionObjectEdit() = default; - void SaveStartState(const lcModel* Model, const lcCamera* Camera); - void SaveEndState(const lcModel* Model, std::vector&& ObjectIndices, std::vector&& GroupIndices); + void SaveStartState(const lcModel* Model); + void SaveEndState(const lcModel* Model); void LoadStartState(lcModel* Model) const; void LoadEndState(lcModel* Model) const; From ce0d7c7be3770731d31607399fc296f13c8b188a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 14 Feb 2026 12:34:29 -0800 Subject: [PATCH 59/93] Removed group action. --- common/camera.cpp | 4 +- common/group.cpp | 4 +- common/lc_model.cpp | 156 ++++++++++++++------------------------ common/lc_model.h | 8 -- common/lc_modelaction.cpp | 5 -- common/lc_modelaction.h | 27 ------- common/light.cpp | 4 +- common/piece.cpp | 14 ++-- 8 files changed, 69 insertions(+), 153 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index fe4cb618..27fde10e 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -898,7 +898,7 @@ void lcCamera::RemoveKeyFrames() mUpVector.RemoveAllKeys(); } -lcCameraHistoryState lcCamera::GetHistoryState(const lcModel* Model) const +lcCameraHistoryState lcCamera::GetHistoryState([[maybe_unused]] const lcModel* Model) const { lcCameraHistoryState State; @@ -917,7 +917,7 @@ lcCameraHistoryState lcCamera::GetHistoryState(const lcModel* Model) const return State; } -void lcCamera::SetHistoryState(const lcCameraHistoryState& State, const lcModel* Model) +void lcCamera::SetHistoryState(const lcCameraHistoryState& State, [[maybe_unused]] const lcModel* Model) { mId = State.Id; mHidden = State.Hidden; diff --git a/common/group.cpp b/common/group.cpp index 5f52a21a..a1df761e 100644 --- a/common/group.cpp +++ b/common/group.cpp @@ -68,7 +68,7 @@ lcGroupHistoryState lcGroup::GetHistoryState(const lcModel* Model) const lcGroupHistoryState State; State.Id = mId; - State.ParentIndex = ~0; + State.ParentIndex = ~0U; State.Name = mName; if (mGroup) @@ -79,7 +79,7 @@ lcGroupHistoryState lcGroup::GetHistoryState(const lcModel* Model) const { if (Groups[GroupIndex].get() == mGroup) { - State.ParentIndex = GroupIndex; + State.ParentIndex = static_cast(GroupIndex); break; } } diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 30755b93..8d0e3863 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -329,15 +329,6 @@ void lcModel::UpdatePieceInfo(std::vector& UpdatedModels) mPieceInfo->SetBoundingBox(Min, Max); } -lcCamera* lcModel::GetCamera(const QString& Name) const -{ - for (const std::unique_ptr& Camera : mCameras) - if (Camera->GetName() == Name) - return Camera.get(); - - return nullptr; -} - void lcModel::SaveLDraw(QTextStream& Stream, bool SelectedOnly, lcStep LastStep) const { const QLatin1String LineEnding("\r\n"); @@ -1873,7 +1864,7 @@ void lcModel::EndObjectEditAction() ModelActionObjectEdit->SaveEndState(this); - if (ModelActionObjectEdit->StateChanged()) + if (!ModelActionObjectEdit->StateChanged()) mActionSequence.pop_back(); } @@ -1890,87 +1881,6 @@ void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObje SetCurrentStep(mCurrentStep); } -void lcModel::RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName) -{ - std::unique_ptr ModelActionGroupPieces = std::make_unique(Mode, GroupName); - - RunGroupPiecesAction(ModelActionGroupPieces.get(), true); - - mActionSequence.emplace_back(std::move(ModelActionGroupPieces)); -} - -void lcModel::RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply) -{ - if (!ModelActionGroupPieces) - return; - - if (Apply == (ModelActionGroupPieces->GetMode() == lcModelActionGroupPiecesMode::Group)) - { - lcGroup* NewGroup = new lcGroup(); - mGroups.emplace_back(NewGroup); - - NewGroup->mName = ModelActionGroupPieces->GetGroupName(); - NewGroup->mGroup = nullptr; - - for (const std::unique_ptr& Piece : mPieces) - { - if (Piece->IsSelected()) - { - lcGroup* TopGroup = Piece->GetTopGroup(); - - if (!TopGroup) - Piece->SetGroup(NewGroup); - else if (TopGroup != NewGroup) - TopGroup->mGroup = NewGroup; - } - } - } - else - { - std::set SelectedGroups; - - for (const std::unique_ptr& Piece : mPieces) - { - if (Piece->IsSelected()) - { - lcGroup* Group = Piece->GetTopGroup(); - - if (SelectedGroups.insert(Group).second) - { - for (std::vector>::iterator GroupIt = mGroups.begin(); GroupIt != mGroups.end(); GroupIt++) - { - if (GroupIt->get() == Group) - { - GroupIt->release(); - mGroups.erase(GroupIt); - break; - } - } - } - } - } - - for (const std::unique_ptr& Piece : mPieces) - { - lcGroup* Group = Piece->GetGroup(); - - if (SelectedGroups.find(Group) != SelectedGroups.end()) - Piece->SetGroup(nullptr); - } - - for (const std::unique_ptr& Group : mGroups) - if (SelectedGroups.find(Group->mGroup) != SelectedGroups.end()) - Group->mGroup = nullptr; - - for (lcGroup* Group : SelectedGroups) - delete Group; - - RemoveEmptyGroups(); - } - - gMainWindow->UpdateSelectedObjects(true); -} - void lcModel::RunActionSequence(const std::vector>& ActionSequence, bool Apply) { bool SelectionChanged = false; @@ -1985,8 +1895,6 @@ void lcModel::RunActionSequence(const std::vector } else if (const lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(ModelAction)) RunObjectEditAction(ModelActionObjectEdit, Apply); - else if (const lcModelActionGroupPieces* ModelActionGroupPieces = dynamic_cast(ModelAction)) - RunGroupPiecesAction(ModelActionGroupPieces, Apply); }; if (Apply) @@ -2306,10 +2214,27 @@ void lcModel::GroupSelection() return; BeginActionSequence(); + BeginObjectEditAction(); - RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Group, Dialog.mName); + lcGroup* NewGroup = GetGroup(Dialog.mName, true); + for (const std::unique_ptr& Piece : mPieces) + { + if (Piece->IsSelected()) + { + lcGroup* Group = Piece->GetTopGroup(); + + if (!Group) + Piece->SetGroup(NewGroup); + else if (Group != NewGroup) + Group->mGroup = NewGroup; + } + } + + EndObjectEditAction(); EndActionSequence(tr("Group")); + + gMainWindow->UpdateSelectedObjects(true); } void lcModel::UngroupSelection() @@ -2320,28 +2245,59 @@ void lcModel::UngroupSelection() return; } - bool FoundGroup = false; + std::set SelectedGroups; for (const std::unique_ptr& Piece : mPieces) { - if (Piece->IsSelected() && Piece->GetGroup()) + if (Piece->IsSelected()) { - FoundGroup = true; - break; + lcGroup* Group = Piece->GetTopGroup(); + + if (SelectedGroups.insert(Group).second) + { + for (std::vector>::iterator GroupIt = mGroups.begin(); GroupIt != mGroups.end(); GroupIt++) + { + if (GroupIt->get() == Group) + { + GroupIt->release(); + mGroups.erase(GroupIt); + break; + } + } + } } } - if (!FoundGroup) + if (!SelectedGroups.empty()) { QMessageBox::information(gMainWindow, tr("Ungroup Selection"), tr("No groups selected.")); return; } BeginActionSequence(); + BeginObjectEditAction(); - RecordGroupPiecesAction(lcModelActionGroupPiecesMode::Ungroup, QString()); + for (const std::unique_ptr& Piece : mPieces) + { + lcGroup* Group = Piece->GetGroup(); + if (SelectedGroups.find(Group) != SelectedGroups.end()) + Piece->SetGroup(nullptr); + } + + for (const std::unique_ptr& Group : mGroups) + if (SelectedGroups.find(Group->mGroup) != SelectedGroups.end()) + Group->mGroup = nullptr; + + for (lcGroup* Group : SelectedGroups) + delete Group; + + RemoveEmptyGroups(); + + EndObjectEditAction(); EndActionSequence(tr("Ungroup")); + + gMainWindow->UpdateSelectedObjects(true); } void lcModel::AddSelectedPiecesToGroup() diff --git a/common/lc_model.h b/common/lc_model.h index 906a1576..ea392eaa 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -9,10 +9,6 @@ struct lcModelHistoryState; class lcModelAction; class lcModelActionSelection; class lcModelActionObjectEdit; -class lcModelActionGroupPieces; -enum class lcModelActionSelectionMode; -enum class lcModelActionObjectEditMode; -enum class lcModelActionGroupPiecesMode; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -164,8 +160,6 @@ public: return mCameras; } - lcCamera* GetCamera(const QString& Name) const; - const std::vector>& GetLights() const { return mLights; @@ -421,8 +415,6 @@ protected: void BeginObjectEditAction(); void EndObjectEditAction(); void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); - void RecordGroupPiecesAction(lcModelActionGroupPiecesMode Mode, const QString& GroupName); - void RunGroupPiecesAction(const lcModelActionGroupPieces* ModelActionGroupPieces, bool Apply); void RunActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 69d113eb..b176c066 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -194,8 +194,3 @@ bool lcModelActionObjectEdit::StateChanged() const { return mStartState != mEndState; } - -lcModelActionGroupPieces::lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName) - : mMode(Mode), mGroupName(GroupName) -{ -} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 9c9b8c4b..a865133d 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -85,30 +85,3 @@ protected: lcModelHistoryState mStartState; lcModelHistoryState mEndState; }; - -enum class lcModelActionGroupPiecesMode -{ - Group, - Ungroup -}; - -class lcModelActionGroupPieces : public lcModelAction -{ -public: - lcModelActionGroupPieces(lcModelActionGroupPiecesMode Mode, const QString& GroupName); - virtual ~lcModelActionGroupPieces() = default; - - lcModelActionGroupPiecesMode GetMode() const - { - return mMode; - } - - const QString& GetGroupName() const - { - return mGroupName; - } - -protected: - lcModelActionGroupPiecesMode mMode; - QString mGroupName; -}; diff --git a/common/light.cpp b/common/light.cpp index 4ab16282..498e9442 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1534,7 +1534,7 @@ void lcLight::RemoveKeyFrames() mPOVRayFadePower.RemoveAllKeys(); } -lcLightHistoryState lcLight::GetHistoryState(const lcModel* Model) const +lcLightHistoryState lcLight::GetHistoryState([[maybe_unused]] const lcModel* Model) const { lcLightHistoryState State; @@ -1564,7 +1564,7 @@ lcLightHistoryState lcLight::GetHistoryState(const lcModel* Model) const return State; } -void lcLight::SetHistoryState(const lcLightHistoryState& State, const lcModel* Model) +void lcLight::SetHistoryState(const lcLightHistoryState& State, [[maybe_unused]] const lcModel* Model) { mId = State.Id; mHidden = State.Hidden; diff --git a/common/piece.cpp b/common/piece.cpp index 6bed4239..19534c7c 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -104,13 +104,13 @@ void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait, bool U else mID.clear(); - mControlPoints.clear(); - - delete mMesh; - mMesh = nullptr; - if (UpdateSynthInfo) { + mControlPoints.clear(); + + delete mMesh; + mMesh = nullptr; + const lcSynthInfo* SynthInfo = mPieceInfo ? mPieceInfo->GetSynthInfo() : nullptr; if (SynthInfo) @@ -945,7 +945,7 @@ lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const State.Hidden = mHidden; State.FileLine = mFileLine; State.PieceId = mID; - State.GroupIndex = ~0; + State.GroupIndex = ~0U; State.ColorIndex = mColorIndex; State.ColorCode = mColorCode; State.StepShow = mStepShow; @@ -964,7 +964,7 @@ lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const { if (mGroup == Groups[GroupIndex].get()) { - State.GroupIndex = GroupIndex; + State.GroupIndex = static_cast(GroupIndex); break; } } From 2d03ba22bcfdc9eac84a0ddab08df008fef7a16d Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 14 Feb 2026 14:53:25 -0800 Subject: [PATCH 60/93] Converted more undo actions. --- common/lc_model.cpp | 225 ++++++++++++++++++++++---------------------- common/lc_model.h | 5 - 2 files changed, 111 insertions(+), 119 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 8d0e3863..52545802 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1165,15 +1165,21 @@ void lcModel::Merge(lcModel* Other) void lcModel::Cut() { + if (!AnyObjectsSelected()) + return; + Copy(); - - if (RemoveSelectedObjects()) - { - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - SaveCheckpoint(tr("Cutting")); - } + + BeginActionSequence(); + BeginObjectEditAction(); + + RemoveSelectedObjects(); + + EndObjectEditAction(); + EndActionSequence(tr("Cut")); + + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateSelectedObjects(true); } void lcModel::Copy() @@ -2332,17 +2338,31 @@ void lcModel::AddSelectedPiecesToGroup() void lcModel::RemoveFocusPieceFromGroup() { + bool Modified = false; + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsFocused()) { Piece->SetGroup(nullptr); + + Modified = true; + break; } } - + + if (!Modified) + { + DiscardActionSequence(); + + return; + } + RemoveEmptyGroups(); - SaveCheckpoint(tr("Ungrouping")); + + EndObjectEditAction(); + EndActionSequence(tr("Ungroup")); } void lcModel::ShowEditGroupsDialog() @@ -2643,26 +2663,6 @@ void lcModel::AddPiece(std::unique_ptr Piece, size_t PieceIndex) mPieces.insert(mPieces.begin() + PieceIndex, std::move(Piece)); } -void lcModel::RemovePieces(const std::vector& PieceIndices) -{ - for (auto PieceIndicesIt = PieceIndices.crbegin(); PieceIndicesIt != PieceIndices.crend(); ++PieceIndicesIt) - { - size_t PieceIndex = *PieceIndicesIt; - - if (PieceIndex >= mPieces.size()) - continue; - - std::vector>::iterator PieceIt = mPieces.begin() + PieceIndex; - - mPieces.erase(PieceIt); - } - - RemoveEmptyGroups(); - - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); -} - size_t lcModel::AddPiece(lcPiece* Piece) { size_t PieceIndex; @@ -2682,58 +2682,6 @@ size_t lcModel::AddPiece(lcPiece* Piece) return PieceIndex; } -void lcModel::AddCamera(std::unique_ptr Camera, size_t CameraIndex) -{ - if (CameraIndex > mCameras.size()) - return; - - mCameras.insert(mCameras.begin() + CameraIndex, std::move(Camera)); -} - -void lcModel::RemoveCameras(const std::vector& CameraIndices) -{ - for (auto CameraIndicesIt = CameraIndices.crbegin(); CameraIndicesIt != CameraIndices.crend(); ++CameraIndicesIt) - { - size_t CameraIndex = *CameraIndicesIt; - - if (CameraIndex >= mCameras.size()) - continue; - - std::vector>::iterator CameraIt = mCameras.begin() + CameraIndex; - - RemoveCameraFromViews(CameraIt->get()); - - mCameras.erase(CameraIt); - } - - gMainWindow->UpdateSelectedObjects(true); -} - -void lcModel::AddLight(std::unique_ptr Light, size_t LightIndex) -{ - if (LightIndex > mLights.size()) - return; - - mLights.insert(mLights.begin() + LightIndex, std::move(Light)); -} - -void lcModel::RemoveLights(const std::vector& LightIndices) -{ - for (auto LightIndicesIt = LightIndices.crbegin(); LightIndicesIt != LightIndices.crend(); ++LightIndicesIt) - { - size_t LightIndex = *LightIndicesIt; - - if (LightIndex >= mLights.size()) - continue; - - std::vector>::iterator LightIt = mLights.begin() + LightIndex; - - mLights.erase(LightIt); - } - - gMainWindow->UpdateSelectedObjects(true); -} - void lcModel::FocusNextTrainTrack() { const lcObject* Focus = GetFocusObject(); @@ -2906,18 +2854,31 @@ void lcModel::UpdateSelectedPiecesTrainTrackConnections() void lcModel::DeleteSelectedObjects() { - if (RemoveSelectedObjects()) + if (mIsPreview) { - if (!mIsPreview) - { - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(true); - gMainWindow->UpdateInUseCategory(); + RemoveSelectedObjects(); - UpdateAllViews(); - SaveCheckpoint(tr("Deleting")); - } + return; } + + BeginActionSequence(); + BeginObjectEditAction(); + + bool Modified = RemoveSelectedObjects(); + + if (!Modified) + { + DiscardActionSequence(); + + return; + } + + EndObjectEditAction(); + EndActionSequence(tr("Delete")); + + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateSelectedObjects(true); + gMainWindow->UpdateInUseCategory(); } void lcModel::ResetSelectedPiecesPivotPoint() @@ -2968,13 +2929,23 @@ void lcModel::InsertControlPoint() lcVector3 Start, End; gMainWindow->GetActiveView()->GetRayUnderPointer(Start, End); - - if (Piece->InsertControlPoint(Start, End)) + + BeginActionSequence(); + BeginObjectEditAction(); + + bool Modified = Piece->InsertControlPoint(Start, End); + + if (!Modified) { - SaveCheckpoint(tr("Modifying")); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - } + DiscardActionSequence(); + + return; + } + + EndObjectEditAction(); + EndActionSequence(tr("Add Control Point")); + + gMainWindow->UpdateSelectedObjects(true); } void lcModel::RemoveFocusedControlPoint() @@ -2984,12 +2955,22 @@ void lcModel::RemoveFocusedControlPoint() if (!Piece) return; - if (Piece->RemoveFocusedControlPoint()) + BeginActionSequence(); + BeginObjectEditAction(); + + bool Modified = Piece->RemoveFocusedControlPoint(); + + if (!Modified) { - SaveCheckpoint(tr("Modifying")); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - } + DiscardActionSequence(); + + return; + } + + EndObjectEditAction(); + EndActionSequence(tr("Remove Control Point")); + + gMainWindow->UpdateSelectedObjects(true); } void lcModel::ShowSelectedPiecesEarlier() @@ -3663,15 +3644,19 @@ void lcModel::SetSelectedPiecesStepShow(lcStep Step) if (MovedPieces.empty()) return; - + + BeginActionSequence(); + BeginObjectEditAction(); + for (lcPiece* Piece : MovedPieces) { Piece->SetFileLine(-1); AddPiece(Piece); } + + EndObjectEditAction(); + EndActionSequence(tr("Set Show Step")); - SaveCheckpoint(tr("Showing Pieces")); - UpdateAllViews(); gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(false); } @@ -3679,7 +3664,10 @@ void lcModel::SetSelectedPiecesStepShow(lcStep Step) void lcModel::SetSelectedPiecesStepHide(lcStep Step) { bool Modified = false; - + + BeginActionSequence(); + BeginObjectEditAction(); + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsSelected() && Piece->GetStepHide() != Step) @@ -3689,14 +3677,19 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) Modified = true; } } - - if (Modified) + + if (!Modified) { - SaveCheckpoint(tr("Hiding Pieces")); - UpdateAllViews(); - gMainWindow->UpdateTimeline(false, false); - gMainWindow->UpdateSelectedObjects(false); + DiscardActionSequence(); + + return; } + + EndObjectEditAction(); + EndActionSequence(tr("Set Hide Step")); + + gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateSelectedObjects(false); } void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraProjection) @@ -5169,11 +5162,15 @@ void lcModel::PaintToolClicked(lcObject* Object) if (Piece->GetColorIndex() != gMainWindow->mColorIndex) { + BeginActionSequence(); + BeginObjectEditAction(); + Piece->SetColorIndex(gMainWindow->mColorIndex); - SaveCheckpoint(tr("Painting")); + EndObjectEditAction(); + EndActionSequence(tr("Paint")); + gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); gMainWindow->UpdateTimeline(false, true); } } diff --git a/common/lc_model.h b/common/lc_model.h index ea392eaa..ecc810af 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -231,11 +231,6 @@ public: lcPiece* AddPiece(PieceInfo* Info, quint32 Section); void AddPiece(std::unique_ptr Piece, size_t PieceIndex); - void RemovePieces(const std::vector& PieceIndices); - void AddCamera(std::unique_ptr Camera, size_t CameraIndex); - void RemoveCameras(const std::vector& CameraIndices); - void AddLight(std::unique_ptr Light, size_t LightIndex); - void RemoveLights(const std::vector& LightIndices); void DeleteSelectedObjects(); void ResetSelectedPiecesPivotPoint(); void RemoveSelectedObjectsKeyFrames(); From 1e40f166ac412d6fc02fee44a8b805717e8ed675 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 14 Feb 2026 16:04:33 -0800 Subject: [PATCH 61/93] Fixed crash when undoing a new camera used in a view. --- common/lc_model.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 52545802..6e1eb532 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1832,6 +1832,10 @@ void lcModel::LoadObjectHistoryState(const std::vector& ObjectStates, NewObjects.emplace_back(new ObjectType()); } + if constexpr(std::is_same_v) + for (const std::unique_ptr& Camera : Objects) + RemoveCameraFromViews(Camera.get()); + Objects = std::move(NewObjects); for (size_t ObjectIndex = 0; ObjectIndex < Objects.size(); ObjectIndex++) From 069ed47ee9b151d5e2c6620ad77f5a92811ee0e2 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 14 Feb 2026 16:51:49 -0800 Subject: [PATCH 62/93] Fixed text scale on retina displays. --- common/lc_profile.cpp | 4 ++-- common/lc_view.cpp | 7 ++++++- common/lc_view.h | 3 ++- common/lc_viewmanipulator.cpp | 2 +- common/lc_viewwidget.h | 4 ++-- common/texfont.cpp | 18 ++++++++++-------- common/texfont.h | 2 +- 7 files changed, 24 insertions(+), 16 deletions(-) diff --git a/common/lc_profile.cpp b/common/lc_profile.cpp index 53770c94..af149607 100644 --- a/common/lc_profile.cpp +++ b/common/lc_profile.cpp @@ -72,8 +72,8 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] = lcProfileEntry("Settings", "GradientColorBottom", LC_RGB(49, 52, 55)), // LC_PROFILE_GRADIENT_COLOR_BOTTOM lcProfileEntry("Settings", "DrawAxes", 0), // LC_PROFILE_DRAW_AXES lcProfileEntry("Settings", "DrawAxesLocation", static_cast(lcAxisIconLocation::BottomLeft)), // LC_PROFILE_DRAW_AXES_LOCATION - lcProfileEntry("Settings", "AxesColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_AXES_COLOR - lcProfileEntry("Settings", "TextColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_TEXT_COLOR + lcProfileEntry("Settings", "AxesColor", LC_RGBA(160, 160, 160, 255)), // LC_PROFILE_AXES_COLOR + lcProfileEntry("Settings", "TextColor", LC_RGBA(160, 160, 160, 255)), // LC_PROFILE_TEXT_COLOR lcProfileEntry("Settings", "MarqueeBorderColor", LC_RGBA(64, 64, 255, 255)), // LC_PROFILE_MARQUEE_BORDER_COLOR lcProfileEntry("Settings", "MarqueeFillColor", LC_RGBA(64, 64, 255, 64)), // LC_PROFILE_MARQUEE_FILL_COLOR lcProfileEntry("Settings", "OverlayColor", LC_RGBA(0, 0, 0, 255)), // LC_PROFILE_OVERLAY_COLOR diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 59e27954..aa8ef01a 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -1181,7 +1181,7 @@ void lcView::DrawViewport() const mContext->EnableColorBlend(true); - gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, CameraName.toLatin1().constData()); + gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, GetUIScale(), CameraName.toLatin1().constData()); mContext->EnableColorBlend(false); } @@ -1698,6 +1698,11 @@ lcTrackTool lcView::GetOverrideTrackTool(Qt::MouseButton Button) const return TrackToolFromTool[static_cast(OverrideTool)]; } +float lcView::GetUIScale() const +{ + return mWidget ? mWidget->GetDeviceScale() : 1.0f; +} + float lcView::GetOverlayScale() const { lcVector3 OverlayCenter; diff --git a/common/lc_view.h b/common/lc_view.h index 700a5ebf..4f087bc6 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -263,7 +263,8 @@ public: void ShowContextMenu() const; bool CloseFindReplaceDialog(); void ShowFindReplaceWidget(bool Replace); - + + float GetUIScale() const; float GetOverlayScale() const; lcVector3 GetMoveDirection(const lcVector3& Direction) const; void UpdatePiecePreview(); diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index 2a154162..6b5f83f3 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -896,7 +896,7 @@ void lcViewManipulator::DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackT gTexFont.GetStringDimensions(&cx, &cy, buf); Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f); - gTexFont.PrintText(Context, ScreenPos[0] - (cx / 2), ScreenPos[1] + (cy / 2), 0.0f, buf); + gTexFont.PrintText(Context, ScreenPos[0] - (cx / 2), ScreenPos[1] + (cy / 2), 0.0f, mView->GetUIScale(), buf); Context->EnableColorBlend(false); } diff --git a/common/lc_viewwidget.h b/common/lc_viewwidget.h index d5473189..ab905b5d 100644 --- a/common/lc_viewwidget.h +++ b/common/lc_viewwidget.h @@ -15,7 +15,6 @@ public: QSize sizeHint() const override; -protected: float GetDeviceScale() const { #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) @@ -24,7 +23,8 @@ protected: return devicePixelRatio(); #endif } - + +protected: void initializeGL() override; void resizeGL(int Width, int Height) override; void paintGL() override; diff --git a/common/texfont.cpp b/common/texfont.cpp index a05a9183..97d740fd 100644 --- a/common/texfont.cpp +++ b/common/texfont.cpp @@ -162,7 +162,7 @@ void TexFont::GetStringDimensions(int* cx, int* cy, const char* Text) const } } -void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, const char* Text) const +void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, float Scale, const char* Text) const { const size_t Length = strlen(Text); @@ -175,6 +175,8 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons while (*Text) { int ch = *Text; + float Right = Left + mGlyphs[ch].width * Scale; + float Bottom = Top - mFontHeight * Scale; *CurVert++ = Left; *CurVert++ = Top; @@ -183,24 +185,24 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons *CurVert++ = mGlyphs[ch].top; *CurVert++ = Left; - *CurVert++ = Top - mFontHeight; + *CurVert++ = Bottom; *CurVert++ = Z; *CurVert++ = mGlyphs[ch].left; *CurVert++ = mGlyphs[ch].bottom; - *CurVert++ = Left + mGlyphs[ch].width; - *CurVert++ = Top - mFontHeight; + *CurVert++ = Right; + *CurVert++ = Bottom; *CurVert++ = Z; *CurVert++ = mGlyphs[ch].right; *CurVert++ = mGlyphs[ch].bottom; - *CurVert++ = Left + mGlyphs[ch].width; - *CurVert++ = Top - mFontHeight; + *CurVert++ = Right; + *CurVert++ = Bottom; *CurVert++ = Z; *CurVert++ = mGlyphs[ch].right; *CurVert++ = mGlyphs[ch].bottom; - *CurVert++ = Left + mGlyphs[ch].width; + *CurVert++ = Right; *CurVert++ = Top; *CurVert++ = Z; *CurVert++ = mGlyphs[ch].right; @@ -212,7 +214,7 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons *CurVert++ = mGlyphs[ch].left; *CurVert++ = mGlyphs[ch].top; - Left += mGlyphs[ch].width; + Left = Right; Text++; } diff --git a/common/texfont.h b/common/texfont.h index 9dddf466..297d034f 100644 --- a/common/texfont.h +++ b/common/texfont.h @@ -18,7 +18,7 @@ public: bool Initialize(lcContext* Context); void Reset(); - void PrintText(lcContext* Context, float Left, float Top, float Z, const char* Text) const; + void PrintText(lcContext* Context, float Left, float Top, float Z, float Scale, const char* Text) const; void GetTriangles(const lcMatrix44& Transform, const char* Text, float* Buffer) const; void GetGlyphTriangles(float Left, float Top, float Z, int Glyph, float* Buffer) const; void GetStringDimensions(int* cx, int* cy, const char* Text) const; From 3ddeb8cfbd3393241983d87b7f6efd46282aaff9 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 16 Feb 2026 15:19:56 -0800 Subject: [PATCH 63/93] Use the part picker widget on the replace widget. --- common/lc_findreplacewidget.cpp | 45 ++++++++++++++++++++----------- common/lc_findreplacewidget.h | 6 +++-- common/lc_model.cpp | 15 ++++++++--- common/lc_partselectionwidget.cpp | 20 +++++++++++++- 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/common/lc_findreplacewidget.cpp b/common/lc_findreplacewidget.cpp index 8e4cefc6..a260fcf8 100644 --- a/common/lc_findreplacewidget.cpp +++ b/common/lc_findreplacewidget.cpp @@ -2,6 +2,7 @@ #include "lc_findreplacewidget.h" #include "lc_colorpicker.h" #include "lc_mainwindow.h" +#include "lc_partselectionpopup.h" #include "pieceinf.h" #include "piece.h" #include "lc_model.h" @@ -37,8 +38,8 @@ lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool R Layout->addWidget(FindNextButton, 0, 3); QToolButton* FindAllButton = new QToolButton(this); - FindAllButton ->setAutoRaise(true); - FindAllButton ->setDefaultAction(gMainWindow->mActions[LC_EDIT_FIND_ALL]); + FindAllButton->setAutoRaise(true); + FindAllButton->setDefaultAction(gMainWindow->mActions[LC_EDIT_FIND_ALL]); Layout->addWidget(FindAllButton, 0, 4); connect(FindColorPicker, &lcColorPicker::ColorChanged, this, &lcFindReplaceWidget::FindColorIndexChanged); @@ -55,10 +56,22 @@ lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool R ReplaceColorPicker = new lcColorPicker(this, true); ReplaceColorPicker->setToolTip(tr("Replacement Color")); Layout->addWidget(ReplaceColorPicker, 1, 1); - - mReplacePartComboBox = new QComboBox(this); - mReplacePartComboBox->setToolTip(tr("Replacement Part")); - Layout->addWidget(mReplacePartComboBox, 1, 2); + + QPixmap Pixmap(1, 1); + Pixmap.fill(QColor::fromRgba64(0, 0, 0, 0)); + + mReplacePartButton = new lcElidableToolButton(this); + mReplacePartButton->setToolTip(tr("Replacement Part")); + + QSizePolicy PieceButtonSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + PieceButtonSizePolicy.setHorizontalStretch(2); + PieceButtonSizePolicy.setVerticalStretch(0); + mReplacePartButton->setSizePolicy(PieceButtonSizePolicy); + + mReplacePartButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + mReplacePartButton->setIcon(Pixmap); + + Layout->addWidget(mReplacePartButton, 1, 2); QToolButton* ReplaceNextButton = new QToolButton(this); ReplaceNextButton->setAutoRaise(true); @@ -71,15 +84,10 @@ lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool R Layout->addWidget(ReplaceAllButton, 1, 4); connect(ReplaceColorPicker, &lcColorPicker::ColorChanged, this, &lcFindReplaceWidget::ReplaceColorIndexChanged); - connect(mReplacePartComboBox, static_cast(&QComboBox::activated), this, &lcFindReplaceWidget::ReplaceActivated); - - mReplacePartComboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); - mReplacePartComboBox->setMinimumContentsLength(1); - - mReplacePartComboBox->setModel(new lcPieceIdStringModel(gMainWindow->GetActiveModel(), mReplacePartComboBox)); + connect(mReplacePartButton, &lcElidableToolButton::clicked, this, &lcFindReplaceWidget::ReplaceButtonClicked); ReplaceColorPicker->SetCurrentColor(lcGetColorIndex(LC_COLOR_NOCOLOR)); - mReplacePartComboBox->setCurrentIndex(0); + mReplacePartButton->setText(tr("None")); } QToolButton* CloseButton = new QToolButton(this); @@ -152,9 +160,16 @@ void lcFindReplaceWidget::ReplaceColorIndexChanged(int ColorIndex) Params.ReplaceColorIndex = ColorIndex; } -void lcFindReplaceWidget::ReplaceActivated(int Index) +void lcFindReplaceWidget::ReplaceButtonClicked() { lcFindReplaceParams& Params = lcView::GetFindReplaceParams(); - Params.ReplacePieceInfo = (PieceInfo*)mReplacePartComboBox->itemData(Index).value(); + std::optional Result = lcShowPartSelectionPopup(Params.ReplacePieceInfo, std::vector>(), + gDefaultColor, mReplacePartButton, mReplacePartButton->mapToGlobal(mReplacePartButton->rect().bottomLeft())); + + if (!Result.has_value()) + return; + + Params.ReplacePieceInfo = Result.value(); + mReplacePartButton->setText(Result.value()->m_strDescription); } diff --git a/common/lc_findreplacewidget.h b/common/lc_findreplacewidget.h index 19b5bdd9..20be54bd 100644 --- a/common/lc_findreplacewidget.h +++ b/common/lc_findreplacewidget.h @@ -1,5 +1,7 @@ #pragma once +class lcElidableToolButton; + class lcFindReplaceWidget : public QWidget { Q_OBJECT @@ -12,9 +14,9 @@ protected slots: void FindTextEdited(const QString& Text); void FindActivated(int Index); void ReplaceColorIndexChanged(int ColorIndex); - void ReplaceActivated(int Index); + void ReplaceButtonClicked(); protected: QComboBox* mFindPartComboBox = nullptr; - QComboBox* mReplacePartComboBox = nullptr; + lcElidableToolButton* mReplacePartButton = nullptr; }; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 6e1eb532..52a5ada6 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -4667,7 +4667,10 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) size_t StartIndex = mPieces.size() - 1; int ReplacedCount = 0; - + + BeginActionSequence(); + BeginObjectEditAction(); + if (!FindAll) { // We have to find the currently focused piece, in order to find next/prev match and (optionally) to replace it @@ -4736,7 +4739,9 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) if (CurrentIndex == StartIndex) break; } - + + EndObjectEditAction(); + if (FindAll) RecordSetSelectionAndFocusAction(Selection, nullptr, 0, lcSelectionMode::Single); else @@ -4744,11 +4749,13 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) if (ReplacedCount) { - SaveCheckpoint(tr("Replacing Piece(s)", "", ReplacedCount)); + EndActionSequence(tr("Replace Piece(s)", "", ReplacedCount)); + gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); gMainWindow->UpdateTimeline(false, true); } + else + EndActionSequence(tr("Selection")); } void lcModel::UndoAction() diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp index cecb3d09..267094a5 100644 --- a/common/lc_partselectionwidget.cpp +++ b/common/lc_partselectionwidget.cpp @@ -986,7 +986,25 @@ void lcPartSelectionWidget::SetCurrentPart(PieceInfo* Info) void lcPartSelectionWidget::SetCategory(lcPartCategoryType Type, int Index) { - mPartsWidget->SetCategory(Type, Index); + for (int Row = 0; Row < mCategoriesWidget->topLevelItemCount(); Row++) + { + QTreeWidgetItem* Item = mCategoriesWidget->topLevelItem(Row); + lcPartCategoryType ItemType = static_cast(Item->data(0, static_cast(lcPartCategoryRole::Type)).toInt()); + + if (ItemType != Type) + continue; + + if (Type == lcPartCategoryType::Palette || Type == lcPartCategoryType::Category) + { + int ItemIndex = Item->data(0, static_cast(lcPartCategoryRole::Index)).toInt(); + + if (ItemIndex != Index) + continue; + } + + mCategoriesWidget->setCurrentItem(Item); + break; + } } void lcPartSelectionWidget::SetCustomParts(const std::vector>& Parts, int ColorIndex) From da9c8e9f9cfe0fe6de52eeaadc17cbc4548e03f5 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 16 Feb 2026 18:03:02 -0800 Subject: [PATCH 64/93] Rewrote the Edit Groups Dialog. --- common/lc_model.cpp | 75 +++++----- qt/lc_qeditgroupsdialog.cpp | 285 +++++++++++++++++++++--------------- qt/lc_qeditgroupsdialog.h | 50 +++---- qt/lc_qeditgroupsdialog.ui | 8 +- 4 files changed, 234 insertions(+), 184 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 52a5ada6..fb5a6f3a 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2371,50 +2371,57 @@ void lcModel::RemoveFocusPieceFromGroup() void lcModel::ShowEditGroupsDialog() { - QMap PieceParents; - QMap GroupParents; - - for (const std::unique_ptr& Piece : mPieces) - PieceParents[Piece.get()] = Piece->GetGroup(); - - for (const std::unique_ptr& Group : mGroups) - GroupParents[Group.get()] = Group->mGroup; - - lcQEditGroupsDialog Dialog(gMainWindow, PieceParents, GroupParents, this); + lcQEditGroupsDialog Dialog(gMainWindow, this); if (Dialog.exec() != QDialog::Accepted) return; - - bool Modified = Dialog.mNewGroups.isEmpty(); - - for (const std::unique_ptr& Piece : mPieces) + + BeginActionSequence(); + BeginObjectEditAction(); + + std::function UpdateGroups=[this, &UpdateGroups](const lcQEditGroupsDialog::GroupInfo& GroupInfo, lcGroup* ParentGroup) { - lcGroup* ParentGroup = Dialog.mPieceParents.value(Piece.get()); - - if (ParentGroup != Piece->GetGroup()) + lcGroup* Group = GroupInfo.Group; + + if (!Group) { - Piece->SetGroup(ParentGroup); - Modified = true; + Group = new lcGroup(); + mGroups.emplace_back(Group); } - } + + Group->mName = GroupInfo.Name; + Group->mGroup = ParentGroup; + + for (const lcQEditGroupsDialog::GroupInfo& ChildGroupInfo : GroupInfo.ChildGroups) + UpdateGroups(ChildGroupInfo, Group); + + for (lcPiece* Piece : GroupInfo.ChildPieces) + Piece->SetGroup(Group); + }; + + lcQEditGroupsDialog::GroupInfo GroupInfo = Dialog.GetGroups(); + + for (const lcQEditGroupsDialog::GroupInfo& ChildGroupInfo : GroupInfo.ChildGroups) + UpdateGroups(ChildGroupInfo, nullptr); + + for (lcPiece* Piece : GroupInfo.ChildPieces) + Piece->SetGroup(nullptr); + + RemoveEmptyGroups(); - for (const std::unique_ptr& Group : mGroups) + EndObjectEditAction(); + + if (mActionSequence.empty()) { - lcGroup* ParentGroup = Dialog.mGroupParents.value(Group.get()); - - if (ParentGroup != Group->mGroup) - { - Group->mGroup = ParentGroup; - Modified = true; - } + DiscardActionSequence(); + return; } + + RecordClearSelectionAction(); + + EndActionSequence(tr("Edit Groups")); - if (Modified) - { - DeselectAllObjects(); - gMainWindow->UpdateSelectedObjects(true); - SaveCheckpoint(tr("Editing Groups")); - } + gMainWindow->UpdateSelectedObjects(true); } QString lcModel::GetGroupName(const QString& Prefix) diff --git a/qt/lc_qeditgroupsdialog.cpp b/qt/lc_qeditgroupsdialog.cpp index 1fb28e30..6ddd289f 100644 --- a/qt/lc_qeditgroupsdialog.cpp +++ b/qt/lc_qeditgroupsdialog.cpp @@ -1,28 +1,52 @@ #include "lc_global.h" #include "lc_qeditgroupsdialog.h" #include "ui_lc_qeditgroupsdialog.h" -#include "lc_application.h" #include "lc_model.h" #include "piece.h" #include "group.h" -lcQEditGroupsDialog::lcQEditGroupsDialog(QWidget* Parent, const QMap& PieceParents, const QMap& GroupParents, lcModel* Model) - : QDialog(Parent), mPieceParents(PieceParents), mGroupParents(GroupParents) +constexpr uintptr_t LC_GROUPDIALOG_NEW_GROUP = ~0; + +class lcEditGroupsDialogDelegate : public QItemDelegate +{ +public: + lcEditGroupsDialogDelegate(QObject* Parent) + : QItemDelegate(Parent) + { + } + + void setModelData(QWidget* Editor, QAbstractItemModel* Model, const QModelIndex& Index) const + { + QLineEdit* LineEdit = qobject_cast(Editor); + + if (!LineEdit->isModified()) + return; + + QString Text = LineEdit->text().trimmed(); + + lcQEditGroupsDialog* Dialog = qobject_cast(parent()); + + if (Dialog && !Dialog->CanRenameGroup(Text)) + return; + + QItemDelegate::setModelData(Editor, Model, Index); + } +}; + +lcQEditGroupsDialog::lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model) + : QDialog(Parent), mModel(Model) { - mLastItemClicked = nullptr; - mModel = Model; ui = new Ui::lcQEditGroupsDialog; ui->setupUi(this); + + QPushButton* NewGroup = ui->buttonBox->addButton(tr("&New Group"), QDialogButtonBox::ActionRole); - connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &lcQEditGroupsDialog::onItemClicked); - connect(ui->treeWidget, &QTreeWidget::itemDoubleClicked, this, &lcQEditGroupsDialog::onItemDoubleClicked); + connect(NewGroup, &QPushButton::clicked, this, &lcQEditGroupsDialog::NewGroupClicked); - QPushButton *newGroup = ui->buttonBox->addButton(tr("New Group"), QDialogButtonBox::ActionRole); - - connect(newGroup, &QPushButton::clicked, this, &lcQEditGroupsDialog::on_newGroup_clicked); - - AddChildren(ui->treeWidget->invisibleRootItem(), nullptr); + PopulateTree(); + + ui->treeWidget->setItemDelegate(new lcEditGroupsDialogDelegate(this)); ui->treeWidget->expandAll(); } @@ -31,139 +55,164 @@ lcQEditGroupsDialog::~lcQEditGroupsDialog() delete ui; } -void lcQEditGroupsDialog::accept() +bool lcQEditGroupsDialog::CanRenameGroup(const QString& Text) const { - UpdateParents(ui->treeWidget->invisibleRootItem(), nullptr); - - QDialog::accept(); + if (Text.isEmpty()) + return false; + + std::function ScanGroups = [&ScanGroups, &Text](QTreeWidgetItem* ParentItem) + { + for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++) + { + QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex); + + if (ChildItem->data(0, GroupRole).value()) + { + if (ChildItem->text(0) == Text || !ScanGroups(ChildItem)) + return false; + } + } + + return true; + }; + + return ScanGroups(ui->treeWidget->invisibleRootItem()); } -void lcQEditGroupsDialog::reject() -{ - for (int GroupIdx = 0; GroupIdx < mNewGroups.size(); GroupIdx++) - mModel->RemoveGroup(mNewGroups[GroupIdx]); - - QDialog::reject(); -} - -void lcQEditGroupsDialog::on_newGroup_clicked() +void lcQEditGroupsDialog::NewGroupClicked() { QTreeWidgetItem* CurrentItem = ui->treeWidget->currentItem(); - + if (CurrentItem && CurrentItem->data(0, PieceRole).value()) CurrentItem = CurrentItem->parent(); - + if (!CurrentItem) CurrentItem = ui->treeWidget->invisibleRootItem(); - - lcGroup* ParentGroup = (lcGroup*)CurrentItem->data(0, GroupRole).value(); - - lcGroup* NewGroup = mModel->AddGroup(tr("Group #"), ParentGroup); - mGroupParents[NewGroup] = ParentGroup; - mNewGroups.append(NewGroup); - - QTreeWidgetItem* GroupItem = new QTreeWidgetItem(CurrentItem, QStringList(NewGroup->mName)); + + QString Prefix = tr("Group #"); + int MaxIndex = 0; + + std::function ScanGroups = [&ScanGroups, &Prefix, &MaxIndex](QTreeWidgetItem* ParentItem) + { + for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++) + { + QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex); + + if (ChildItem->data(0, GroupRole).value()) + { + QString Name = ChildItem->text(0); + + if (Name.startsWith(Prefix)) + { + bool Ok = false; + int GroupNumber = Name.mid(Prefix.length()).toInt(&Ok); + + if (Ok && GroupNumber > MaxIndex) + MaxIndex = GroupNumber; + } + + ScanGroups(ChildItem); + } + } + }; + + ScanGroups(ui->treeWidget->invisibleRootItem()); + + QString Name = Prefix + QString::number(MaxIndex + 1); + + QTreeWidgetItem* GroupItem = new QTreeWidgetItem(CurrentItem, QStringList(Name)); GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); - GroupItem->setData(0, GroupRole, QVariant::fromValue((uintptr_t)NewGroup)); + GroupItem->setData(0, GroupRole, QVariant::fromValue(LC_GROUPDIALOG_NEW_GROUP)); + GroupItem->setExpanded(true); } -void lcQEditGroupsDialog::onItemClicked(QTreeWidgetItem *item, int column) +lcQEditGroupsDialog::GroupInfo lcQEditGroupsDialog::GetGroupInfo(QTreeWidgetItem* ParentItem) const { - Q_UNUSED(column); - - if (item->flags() & Qt::ItemIsEditable) + lcQEditGroupsDialog::GroupInfo GroupInfo; + + GroupInfo.Name = ParentItem->text(0); + + uintptr_t GroupPointer = ParentItem->data(0, GroupRole).value(); + GroupInfo.Group = (GroupPointer == LC_GROUPDIALOG_NEW_GROUP) ? nullptr : reinterpret_cast(GroupPointer); + + for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++) { - mClickTimer.stop(); - - if (mLastItemClicked != item) - { - mLastItemClicked = item; - mEditableDoubleClicked = false; - } + QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex); + + if (ChildItem->data(0, GroupRole).value()) + GroupInfo.ChildGroups.emplace_back(GetGroupInfo(ChildItem)); else { - mClickTimer.start(QApplication::doubleClickInterval() + 50, this); + lcPiece* Piece = reinterpret_cast(ChildItem->data(0, PieceRole).value()); + + if (Piece) + GroupInfo.ChildPieces.push_back(Piece); } - } + } + + return GroupInfo; } -void lcQEditGroupsDialog::onItemDoubleClicked(QTreeWidgetItem *item, int column) +lcQEditGroupsDialog::GroupInfo lcQEditGroupsDialog::GetGroups() const { - Q_UNUSED(column); - - if (item->flags() & Qt::ItemIsEditable) - { - mEditableDoubleClicked = true; - } + return GetGroupInfo(ui->treeWidget->invisibleRootItem()); } -void lcQEditGroupsDialog::timerEvent(QTimerEvent *event) +void lcQEditGroupsDialog::PopulateTree() { - Q_UNUSED(event); - - mClickTimer.stop(); - if (!mEditableDoubleClicked) + const std::vector>& Groups = mModel->GetGroups(); + std::unordered_map AddedGroups; + std::vector GroupsToAdd; + + AddedGroups[nullptr] = ui->treeWidget->invisibleRootItem(); + + auto CreateGroupItem = [&AddedGroups](lcGroup* Group) { - ui->treeWidget->editItem(mLastItemClicked); - } - - mEditableDoubleClicked = false; -} - -void lcQEditGroupsDialog::UpdateParents(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup) -{ - for (int ChildIdx = 0; ChildIdx < ParentItem->childCount(); ChildIdx++) - { - QTreeWidgetItem* ChildItem = ParentItem->child(ChildIdx); - - lcPiece* Piece = (lcPiece*)ChildItem->data(0, PieceRole).value(); - - if (Piece) - { - mPieceParents[Piece] = ParentGroup; - } - else - { - lcGroup* Group = (lcGroup*)ChildItem->data(0, GroupRole).value(); - - // todo: validate unique group name - if (Group) - Group->mName = ChildItem->text(0); - - mGroupParents[Group] = ParentGroup; - - UpdateParents(ChildItem, Group); - } - } -} - -void lcQEditGroupsDialog::AddChildren(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup) -{ - for (QMap::const_iterator it = mGroupParents.constBegin(); it != mGroupParents.constEnd(); it++) - { - lcGroup* Group = it.key(); - lcGroup* Parent = it.value(); - - if (Parent != ParentGroup) - continue; - + QTreeWidgetItem* ParentItem = AddedGroups.find(Group->mGroup)->second; + + if (!ParentItem) + return false; + QTreeWidgetItem* GroupItem = new QTreeWidgetItem(ParentItem, QStringList(Group->mName)); GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); GroupItem->setData(0, GroupRole, QVariant::fromValue((uintptr_t)Group)); - - AddChildren(GroupItem, Group); - } - - for (QMap::const_iterator it = mPieceParents.constBegin(); it != mPieceParents.constEnd(); it++) + + AddedGroups[Group] = GroupItem; + + return true; + }; + + for (const std::unique_ptr& Group : Groups) + if (!CreateGroupItem(Group.get())) + GroupsToAdd.push_back(Group.get()); + + while (!GroupsToAdd.empty()) { - lcPiece* Piece = it.key(); - lcGroup* Parent = it.value(); - - if (Parent != ParentGroup) - continue; - - QTreeWidgetItem* PieceItem = new QTreeWidgetItem(ParentItem, QStringList(Piece->GetName())); - PieceItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); - PieceItem->setData(0, PieceRole, QVariant::fromValue((uintptr_t)Piece)); + size_t GroupCount = GroupsToAdd.size(); + + for (auto GroupIt = GroupsToAdd.begin(); GroupIt != GroupsToAdd.end();) + { + if (CreateGroupItem(*GroupIt)) + GroupIt = GroupsToAdd.erase(GroupIt); + else + ++GroupIt; + } + + if (GroupCount == GroupsToAdd.size()) + break; + } + + const std::vector>& Pieces = mModel->GetPieces(); + + for (const std::unique_ptr& Piece : Pieces) + { + QTreeWidgetItem* ParentItem = AddedGroups.find(Piece->GetGroup())->second; + + if (ParentItem) + { + QTreeWidgetItem* PieceItem = new QTreeWidgetItem(ParentItem, QStringList(Piece->GetName())); + PieceItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled); + PieceItem->setData(0, PieceRole, QVariant::fromValue((uintptr_t)Piece.get())); + } } } diff --git a/qt/lc_qeditgroupsdialog.h b/qt/lc_qeditgroupsdialog.h index b05dca2c..b4f7286a 100644 --- a/qt/lc_qeditgroupsdialog.h +++ b/qt/lc_qeditgroupsdialog.h @@ -1,7 +1,5 @@ #pragma once -#include - namespace Ui { class lcQEditGroupsDialog; } @@ -11,37 +9,33 @@ class lcQEditGroupsDialog : public QDialog Q_OBJECT public: - lcQEditGroupsDialog(QWidget* Parent, const QMap& PieceParents, const QMap& GroupParents, lcModel* Model); - ~lcQEditGroupsDialog(); + lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model); + virtual ~lcQEditGroupsDialog(); - QMap mPieceParents; - QMap mGroupParents; - QList mNewGroups; - //QList mDeletedGroups; // todo: support deleting groups in the edit groups dialog + struct GroupInfo + { + QString Name; + lcGroup* Group; + std::vector ChildGroups; + std::vector ChildPieces; + }; + + GroupInfo GetGroups() const; + bool CanRenameGroup(const QString& Text) const; + +protected slots: + void NewGroupClicked(); +protected: enum { PieceRole = Qt::UserRole, GroupRole }; - -public slots: - void accept() override; - void reject() override; - void on_newGroup_clicked(); - void onItemClicked(QTreeWidgetItem* Item, int Column); - void onItemDoubleClicked(QTreeWidgetItem* Item, int Column); - -private: - Ui::lcQEditGroupsDialog *ui; - - void UpdateParents(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup); - void AddChildren(QTreeWidgetItem* ParentItem, lcGroup* ParentGroup); - - void timerEvent(QTimerEvent* Event) override; - - lcModel* mModel; - QTreeWidgetItem* mLastItemClicked; - bool mEditableDoubleClicked; - QBasicTimer mClickTimer; + + GroupInfo GetGroupInfo(QTreeWidgetItem* ParentItem) const; + void PopulateTree(); + + Ui::lcQEditGroupsDialog* ui = nullptr; + const lcModel* mModel = nullptr; }; diff --git a/qt/lc_qeditgroupsdialog.ui b/qt/lc_qeditgroupsdialog.ui index 522be73a..d2b58f15 100644 --- a/qt/lc_qeditgroupsdialog.ui +++ b/qt/lc_qeditgroupsdialog.ui @@ -17,13 +17,13 @@ - QAbstractItemView::NoEditTriggers + QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed|QAbstractItemView::EditTrigger::SelectedClicked true - QAbstractItemView::InternalMove + QAbstractItemView::DragDropMode::InternalMove true @@ -41,10 +41,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok From 416d51ae6453eae3690ea8ffc7ac91ecfb603413 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Wed, 18 Feb 2026 22:10:27 -0800 Subject: [PATCH 65/93] Updated more actions. --- common/lc_model.cpp | 109 +++++++++++++++++++++++++++++++------------- common/lc_model.h | 2 +- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index fb5a6f3a..b1d0587d 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1123,7 +1123,7 @@ bool lcModel::LoadInventory(const QByteArray& Inventory) return true; } -void lcModel::Merge(lcModel* Other) +void lcModel::Merge(std::unique_ptr Other) { for (std::unique_ptr& Piece : Other->mPieces) { @@ -1158,8 +1158,6 @@ void lcModel::Merge(lcModel* Other) Other->mGroups.clear(); - delete Other; - gMainWindow->UpdateTimeline(false, false); } @@ -1197,7 +1195,7 @@ void lcModel::Paste(bool PasteToCurrentStep) if (gApplication->mClipboard.isEmpty()) return; - lcModel* Model = new lcModel(QString(), nullptr, false); + std::unique_ptr Model(new lcModel(QString(), nullptr, false)); QBuffer Buffer(&gApplication->mClipboard); Buffer.open(QIODevice::ReadOnly); @@ -1222,18 +1220,27 @@ void lcModel::Paste(bool PasteToCurrentStep) SelectedObjects.emplace_back(Piece.get()); } } - - Merge(Model); - SaveCheckpoint(tr("Pasting")); + + if (PastedPieces.empty()) + return; + + BeginActionSequence(); + BeginObjectEditAction(); + + Merge(std::move(Model)); + + CalculateStep(mCurrentStep); + + EndObjectEditAction(); if (SelectedObjects.size() == 1) RecordSetSelectionAndFocusAction(std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); else RecordSetSelectionAndFocusAction(SelectedObjects, nullptr, 0, lcSelectionMode::Single); - - CalculateStep(mCurrentStep); + + EndActionSequence(tr("Paste")); + gMainWindow->UpdateTimeline(false, false); - UpdateAllViews(); } void lcModel::DuplicateSelectedPieces() @@ -2323,21 +2330,28 @@ void lcModel::AddSelectedPiecesToGroup() break; } } - - if (Group) + + if (!Group) + return; + + BeginActionSequence(); + BeginObjectEditAction(); + + for (const std::unique_ptr& Piece : mPieces) { - for (const std::unique_ptr& Piece : mPieces) + if (Piece->IsFocused()) { - if (Piece->IsFocused()) - { - Piece->SetGroup(Group); - break; - } + Piece->SetGroup(Group); + break; } } RemoveEmptyGroups(); - SaveCheckpoint(tr("Grouping")); + + EndObjectEditAction(); + EndActionSequence(tr("Group")); + + gMainWindow->UpdateSelectedObjects(false); } void lcModel::RemoveFocusPieceFromGroup() @@ -2611,7 +2625,10 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) Piece->SetColorIndex(ColorIndex); AddPiece(Piece); }; - + + BeginActionSequence(); + BeginObjectEditAction(); + if (Last) { std::vector TrainTracks; @@ -2650,11 +2667,21 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) CreatePiece(Info, WorldMatrix, gMainWindow->mColorIndex); } - - gMainWindow->UpdateTimeline(false, false); + + if (!Piece) + { + DiscardActionSequence(); + + return nullptr; + } + + EndObjectEditAction(); + RecordSetSelectionAndFocusAction(std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - SaveCheckpoint(tr("Adding Piece")); + EndActionSequence(tr("Add Piece")); + + gMainWindow->UpdateTimeline(false, false); return Piece; } @@ -2796,17 +2823,23 @@ void lcModel::RotateFocusedTrainTrack(int Direction) if (!Transform) return; - - if ((FocusSection != LC_PIECE_SECTION_INVALID && FocusSection != LC_PIECE_SECTION_POSITION) || !TracksConnected) - FocusPiece->SetFocused(LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + NewConnectionIndex, true); - + + BeginActionSequence(); + + BeginObjectEditAction(); + FocusPiece->SetPosition(Transform.value().GetTranslation(), mCurrentStep, gMainWindow->GetAddKeys()); FocusPiece->SetRotation(lcMatrix33(Transform.value()), mCurrentStep, gMainWindow->GetAddKeys()); FocusPiece->UpdatePosition(mCurrentStep); - + + EndObjectEditAction(); + + if ((FocusSection != LC_PIECE_SECTION_INVALID && FocusSection != LC_PIECE_SECTION_POSITION) || !TracksConnected) + RecordSetFocusAction(FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + NewConnectionIndex, lcSelectionMode::Single); + + EndActionSequence(tr("Rotate")); + gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - SaveCheckpoint(tr("Rotating")); } void lcModel::UpdateTrainTrackConnections(lcPiece* TrackPiece, bool IgnoreSelected) const @@ -3170,7 +3203,11 @@ void lcModel::MoveSelectionToModel(lcModel* Model) void lcModel::InlineSelectedModels() { + BeginActionSequence(); + BeginObjectEditAction(); + std::vector NewPieces; + bool Modified = false; for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); ) { @@ -3186,6 +3223,8 @@ void lcModel::InlineSelectedModels() mPieces.erase(mPieces.begin() + PieceIndex); lcModel* Model = Piece->mPieceInfo->GetModel(); + + Modified = true; for (const std::unique_ptr& ModelPiece : Model->mPieces) { @@ -3211,15 +3250,21 @@ void lcModel::InlineSelectedModels() delete Piece; } - if (!NewPieces.size()) + if (!Modified) { QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("No models selected.")); + + DiscardActionSequence(); + return; } + EndObjectEditAction(); + RecordSetSelectionAndFocusAction(NewPieces, nullptr, 0, lcSelectionMode::Single); - SaveCheckpoint(tr("Inlining")); + EndActionSequence(tr("Inline Model")); + gMainWindow->UpdateTimeline(false, false); } diff --git a/common/lc_model.h b/common/lc_model.h index ecc810af..cc8b360a 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -263,7 +263,7 @@ public: bool LoadLDD(const QString& FileData); bool LoadInventory(const QByteArray& Inventory); int SplitMPD(QIODevice& Device); - void Merge(lcModel* Other); + void Merge(std::unique_ptr Other); void SetSaved() { From 186cc59d62bd91414397208f99fac67758dabb06 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 19 Feb 2026 22:07:56 -0800 Subject: [PATCH 66/93] Updated more actions. --- common/lc_model.cpp | 87 ++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index b1d0587d..246d5a71 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2936,8 +2936,6 @@ void lcModel::ResetSelectedPiecesPivotPoint() EndObjectEditAction(); EndActionSequence(tr("Reset Pivot Point")); - - UpdateAllViews(); } void lcModel::RemoveSelectedObjectsKeyFrames() @@ -2959,8 +2957,6 @@ void lcModel::RemoveSelectedObjectsKeyFrames() EndObjectEditAction(); EndActionSequence(tr("Remove Key Frames")); - - UpdateAllViews(); } void lcModel::InsertControlPoint() @@ -3019,6 +3015,9 @@ void lcModel::RemoveFocusedControlPoint() void lcModel::ShowSelectedPiecesEarlier() { + BeginActionSequence(); + BeginObjectEditAction(); + std::vector MovedPieces; for (auto PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ) @@ -3044,22 +3043,30 @@ void lcModel::ShowSelectedPiecesEarlier() } if (MovedPieces.empty()) + { + DiscardActionSequence(); + return; + } for (lcPiece* Piece : MovedPieces) { Piece->SetFileLine(-1); AddPiece(Piece); } - - SaveCheckpoint(tr("Modifying")); + + EndObjectEditAction(); + EndActionSequence(tr("Show Earlier")); + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); } void lcModel::ShowSelectedPiecesLater() { + BeginActionSequence(); + BeginObjectEditAction(); + std::vector MovedPieces; for (auto PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ) @@ -3086,25 +3093,33 @@ void lcModel::ShowSelectedPiecesLater() } if (MovedPieces.empty()) + { + DiscardActionSequence(); + return; + } for (lcPiece* Piece : MovedPieces) { Piece->SetFileLine(-1); AddPiece(Piece); } - - SaveCheckpoint(tr("Modifying")); + + EndObjectEditAction(); + EndActionSequence(tr("Show Later")); + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); } void lcModel::SetPieceSteps(const std::vector>& PieceSteps) { if (PieceSteps.size() != mPieces.size()) return; - + + BeginActionSequence(); + BeginObjectEditAction(); + bool Modified = false; for (size_t PieceIdx = 0; PieceIdx < PieceSteps.size(); PieceIdx++) @@ -3127,11 +3142,16 @@ void lcModel::SetPieceSteps(const std::vector>& Piec if (Modified) { - SaveCheckpoint(tr("Modifying")); - UpdateAllViews(); + EndObjectEditAction(); + EndActionSequence(tr("Change Step")); + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(false); } + else + { + DiscardActionSequence(); + } } void lcModel::RenamePiece(PieceInfo* Info) @@ -3631,6 +3651,9 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObjectPropertyId PropertyId, bool KeyFrame) { + BeginActionSequence(); + BeginObjectEditAction(); + bool Modified = false; for (lcObject* Object : Objects) @@ -3641,9 +3664,14 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject if (Modified) { - SaveCheckpoint(tr("Changing Key Frame")); + EndObjectEditAction(); + EndActionSequence(KeyFrame ? tr("Add KeyFrame") : tr("Remove KeyFrame")); + gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); + } + else + { + DiscardActionSequence(); } } @@ -3669,7 +3697,6 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) EndActionSequence(tr("Paint")); gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); gMainWindow->UpdateTimeline(false, true); } else @@ -4585,7 +4612,6 @@ void lcModel::HideSelectedPieces() gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); } void lcModel::HideUnselectedPieces() @@ -4617,7 +4643,6 @@ void lcModel::HideUnselectedPieces() gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); } void lcModel::UnhideSelectedPieces() @@ -4649,7 +4674,6 @@ void lcModel::UnhideSelectedPieces() gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); } void lcModel::UnhideAllPieces() @@ -4681,7 +4705,6 @@ void lcModel::UnhideAllPieces() gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); } void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) @@ -5164,15 +5187,20 @@ void lcModel::EraserToolClicked(lcObject* Object) { if (!Object) return; - + + BeginActionSequence(); + BeginObjectEditAction(); + switch (Object->GetType()) { case lcObjectType::Piece: - if (auto PieceIt = std::find_if(mPieces.begin(), mPieces.end(), [Object](const std::unique_ptr& CheckPiece) { return CheckPiece.get() == Object; }); PieceIt != mPieces.end()) - { - mPieces.erase(PieceIt); - RemoveEmptyGroups(); - } + for (auto PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ++PieceIt) + if (PieceIt->get() == Object) + { + mPieces.erase(PieceIt); + RemoveEmptyGroups(); + break; + } break; case lcObjectType::Camera: @@ -5209,11 +5237,12 @@ void lcModel::EraserToolClicked(lcObject* Object) } break; } - + + EndObjectEditAction(); + EndActionSequence(tr("Delete")); + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - SaveCheckpoint(tr("Deleting")); } void lcModel::PaintToolClicked(lcObject* Object) From 28ffe3be35a6efe552be7557086aa6ac36605baf Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 21 Feb 2026 19:54:00 -0800 Subject: [PATCH 67/93] Added model properties action. --- common/lc_model.cpp | 47 +++++++++++++++++++++++++++++++------ common/lc_model.h | 9 +++++++ common/lc_modelaction.cpp | 35 +++++++++++++++++++++++++++ common/lc_modelaction.h | 23 ++++++++++++++++++ qt/lc_qeditgroupsdialog.cpp | 2 +- 5 files changed, 108 insertions(+), 8 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 246d5a71..91501a13 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1898,6 +1898,38 @@ void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObje SetCurrentStep(mCurrentStep); } +void lcModel::SetModelProperties(const lcModelProperties& ModelProperties) +{ + mProperties = ModelProperties; + + if (gMainWindow) + gMainWindow->GetPreviewWidget()->UpdatePreview(); +} + +void lcModel::RecordModelPropertiesAction(const lcModelProperties& ModelProperties) +{ + std::unique_ptr ModelActionProperties = std::make_unique(); + ModelActionProperties->SaveStartState(this); + + SetModelProperties(ModelProperties); + + ModelActionProperties->SaveEndState(this); + + if (ModelActionProperties->StateChanged()) + mActionSequence.emplace_back(std::move(ModelActionProperties)); +} + +void lcModel::RunModelPropertiesAction(const lcModelActionProperties* ModelActionProperties, bool Apply) +{ + if (!ModelActionProperties) + return; + + if (Apply) + ModelActionProperties->LoadEndState(this); + else + ModelActionProperties->LoadStartState(this); +} + void lcModel::RunActionSequence(const std::vector>& ActionSequence, bool Apply) { bool SelectionChanged = false; @@ -1912,6 +1944,8 @@ void lcModel::RunActionSequence(const std::vector } else if (const lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(ModelAction)) RunObjectEditAction(ModelActionObjectEdit, Apply); + else if (const lcModelActionProperties* ModelActionProperties = dynamic_cast(ModelAction)) + RunModelPropertiesAction(ModelActionProperties, Apply); }; if (Apply) @@ -3286,6 +3320,7 @@ void lcModel::InlineSelectedModels() EndActionSequence(tr("Inline Model")); gMainWindow->UpdateTimeline(false, false); + gMainWindow->UpdateInUseCategory(); } void lcModel::RemoveCameraFromViews(lcCamera* Camera) @@ -4667,8 +4702,8 @@ void lcModel::UnhideSelectedPieces() DiscardActionSequence(); return; - } - + } + EndObjectEditAction(); EndActionSequence(tr("Unhide Pieces")); @@ -5443,11 +5478,9 @@ void lcModel::ShowPropertiesDialog() if (mProperties == Options.Properties) return; - mProperties = Options.Properties; - - gMainWindow->GetPreviewWidget()->UpdatePreview(); - - SaveCheckpoint(tr("Changing Properties")); + BeginActionSequence(); + RecordModelPropertiesAction(Options.Properties); + EndActionSequence(tr("Change Model Properties")); } void lcModel::ShowSelectByNameDialog() diff --git a/common/lc_model.h b/common/lc_model.h index cc8b360a..c68e7829 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -9,6 +9,7 @@ struct lcModelHistoryState; class lcModelAction; class lcModelActionSelection; class lcModelActionObjectEdit; +class lcModelActionProperties; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -70,6 +71,11 @@ public: return true; } + bool operator!=(const lcModelProperties& Properties) const + { + return !(*this == Properties); + } + void SaveLDraw(QTextStream& Stream) const; bool ParseLDrawHeader(QString Line, bool FirstLine); void ParseLDrawLine(QTextStream& Stream); @@ -228,6 +234,7 @@ public: template void LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects); void LoadHistoryState(const lcModelHistoryState& HistoryState); + void SetModelProperties(const lcModelProperties& ModelProperties); lcPiece* AddPiece(PieceInfo* Info, quint32 Section); void AddPiece(std::unique_ptr Piece, size_t PieceIndex); @@ -410,6 +417,8 @@ protected: void BeginObjectEditAction(); void EndObjectEditAction(); void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); + void RecordModelPropertiesAction(const lcModelProperties& ModelProperties); + void RunModelPropertiesAction(const lcModelActionProperties* ModelActionProperties, bool Apply); void RunActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index b176c066..38de364a 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -194,3 +194,38 @@ bool lcModelActionObjectEdit::StateChanged() const { return mStartState != mEndState; } + +void lcModelActionProperties::SaveStartState(const lcModel* Model) +{ + SaveState(mStartState, Model); +} + +void lcModelActionProperties::SaveEndState(const lcModel* Model) +{ + SaveState(mEndState, Model); +} + +void lcModelActionProperties::LoadStartState(lcModel* Model) const +{ + LoadState(mStartState, Model); +} + +void lcModelActionProperties::LoadEndState(lcModel* Model) const +{ + LoadState(mEndState, Model); +} + +bool lcModelActionProperties::StateChanged() const +{ + return mStartState != mEndState; +} + +void lcModelActionProperties::SaveState(lcModelProperties& State, const lcModel* Model) +{ + State = Model->GetProperties(); +} + +void lcModelActionProperties::LoadState(const lcModelProperties& State, lcModel* Model) +{ + Model->SetModelProperties(State); +} diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index a865133d..ca34d574 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -1,5 +1,7 @@ #pragma once +#include "lc_model.h" + enum class lcObjectType; enum class lcSelectionMode; @@ -85,3 +87,24 @@ protected: lcModelHistoryState mStartState; lcModelHistoryState mEndState; }; + +class lcModelActionProperties : public lcModelAction +{ +public: + lcModelActionProperties() = default; + virtual ~lcModelActionProperties() = default; + + void SaveStartState(const lcModel* Model); + void SaveEndState(const lcModel* Model); + void LoadStartState(lcModel* Model) const; + void LoadEndState(lcModel* Model) const; + + bool StateChanged() const; + +protected: + static void SaveState(lcModelProperties& State, const lcModel* Model); + static void LoadState(const lcModelProperties& State, lcModel* Model); + + lcModelProperties mStartState; + lcModelProperties mEndState; +}; diff --git a/qt/lc_qeditgroupsdialog.cpp b/qt/lc_qeditgroupsdialog.cpp index 6ddd289f..3a4f2a5d 100644 --- a/qt/lc_qeditgroupsdialog.cpp +++ b/qt/lc_qeditgroupsdialog.cpp @@ -5,7 +5,7 @@ #include "piece.h" #include "group.h" -constexpr uintptr_t LC_GROUPDIALOG_NEW_GROUP = ~0; +constexpr uintptr_t LC_GROUPDIALOG_NEW_GROUP = ~0U; class lcEditGroupsDialogDelegate : public QItemDelegate { From c42d34ff985157a39e1d5757091ec92c137123a3 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 22 Feb 2026 11:38:43 -0800 Subject: [PATCH 68/93] Removed special case camera property functions. --- common/camera.cpp | 36 +++++++++++++++++++++++++ common/camera.h | 3 +++ common/lc_model.cpp | 42 ----------------------------- common/lc_model.h | 3 --- common/lc_propertieswidget.cpp | 17 ++++-------- common/object.cpp | 48 +++++++++++++++++++--------------- 6 files changed, 71 insertions(+), 78 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 27fde10e..2b0cce5c 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -179,6 +179,36 @@ bool lcCamera::SetProjection(lcCameraProjection CameraProjection) return true; } +bool lcCamera::SetFOV(float Fovy) +{ + if (m_fovy == Fovy) + return false; + + m_fovy = Fovy; + + return true; +} + +bool lcCamera::SetNearPlane(float NearPlane) +{ + if (m_zNear == NearPlane) + return false; + + m_zNear = NearPlane; + + return true; +} + +bool lcCamera::SetFarPlane(float FarPlane) +{ + if (m_zFar == FarPlane) + return false; + + m_zFar = FarPlane; + + return true; +} + void lcCamera::SaveLDraw(QTextStream& Stream) const { const QLatin1String LineEnding("\r\n"); @@ -727,8 +757,14 @@ bool lcCamera::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool return SetProjection(static_cast(Value.toInt())); case lcObjectPropertyId::CameraFOV: + return SetFOV(Value.toFloat()); + case lcObjectPropertyId::CameraNear: + return SetNearPlane(Value.toFloat()); + case lcObjectPropertyId::CameraFar: + return SetFarPlane(Value.toFloat()); + case lcObjectPropertyId::CameraPositionX: case lcObjectPropertyId::CameraPositionY: case lcObjectPropertyId::CameraPositionZ: diff --git a/common/camera.h b/common/camera.h index f0bc2d01..f19b6435 100644 --- a/common/camera.h +++ b/common/camera.h @@ -90,6 +90,9 @@ public: } bool SetProjection(lcCameraProjection CameraProjection); + bool SetFOV(float Fovy); + bool SetNearPlane(float NearPlane); + bool SetFarPlane(float FarPlane); quint32 GetAllowedTransforms() const override { diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 91501a13..2277dcbb 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3834,48 +3834,6 @@ void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraPro gMainWindow->UpdateSelectedObjects(false); } -void lcModel::SetCameraFOV(lcCamera* Camera, float FOV, bool Checkpoint) -{ - if (Camera->m_fovy == FOV) - return; - - Camera->m_fovy = FOV; - Camera->UpdatePosition(mCurrentStep); - - if (Checkpoint) - SaveCheckpoint(tr("Changing FOV")); - - UpdateAllViews(); -} - -void lcModel::SetCameraZNear(lcCamera* Camera, float ZNear, bool Checkpoint) -{ - if (Camera->m_zNear == ZNear) - return; - - Camera->m_zNear = ZNear; - Camera->UpdatePosition(mCurrentStep); - - if (Checkpoint) - SaveCheckpoint(tr("Editing Camera")); - - UpdateAllViews(); -} - -void lcModel::SetCameraZFar(lcCamera* Camera, float ZFar, bool Checkpoint) -{ - if (Camera->m_zFar == ZFar) - return; - - Camera->m_zFar = ZFar; - Camera->UpdatePosition(mCurrentStep); - - if (Checkpoint) - SaveCheckpoint(tr("Editing Camera")); - - UpdateAllViews(); -} - void lcModel::SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value, bool AddUndo) { bool Modified = false; diff --git a/common/lc_model.h b/common/lc_model.h index c68e7829..e2b143c2 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -392,9 +392,6 @@ public: void EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept); void SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraProjection); - void SetCameraFOV(lcCamera* Camera, float FOV, bool Checkpoint); - void SetCameraZNear(lcCamera* Camera, float ZNear, bool Checkpoint); - void SetCameraZFar(lcCamera* Camera, float ZFar, bool Checkpoint); void ShowPropertiesDialog(); void ShowSelectByNameDialog(); diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index 86a103a8..9223b2e1 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -287,6 +287,7 @@ void lcPropertiesWidget::FloatChanged(const QString& TextValue) float Value = lcParseValueLocalized(TextValue); ChangeFloatValue(PropertyId, Value, true); + qDebug() << Value; } void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float Value, bool Dragging) @@ -461,17 +462,9 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V } else if (Camera) { - if (PropertyId == lcObjectPropertyId::CameraFOV) + if (PropertyId == lcObjectPropertyId::CameraFOV || PropertyId == lcObjectPropertyId::CameraNear || PropertyId == lcObjectPropertyId::CameraFar) { - Model->SetCameraFOV(Camera, Value, !Dragging); - } - else if (PropertyId == lcObjectPropertyId::CameraNear) - { - Model->SetCameraZNear(Camera, Value, !Dragging); - } - else if (PropertyId == lcObjectPropertyId::CameraFar) - { - Model->SetCameraZFar(Camera, Value, !Dragging); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value, !Dragging); } } @@ -1164,8 +1157,8 @@ void lcPropertiesWidget::CreateWidgets() AddSpacing(); AddFloatProperty(lcObjectPropertyId::CameraFOV, tr("FOV"), tr("Field of view in degrees"), false, 0.1f, 179.9f); - AddFloatProperty(lcObjectPropertyId::CameraNear, tr("Near"), tr("Near clipping distance"), false, 0.001f, FLT_MAX); - AddFloatProperty(lcObjectPropertyId::CameraFar, tr("Far"), tr("Far clipping distance"), false, 0.001f, FLT_MAX); + AddFloatProperty(lcObjectPropertyId::CameraNear, tr("Near"), tr("Near clipping distance"), false, 0.1f, FLT_MAX); + AddFloatProperty(lcObjectPropertyId::CameraFar, tr("Far"), tr("Far clipping distance"), false, 0.1f, FLT_MAX); AddSpacing(); diff --git a/common/object.cpp b/common/object.cpp index ff818bc7..78269738 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -18,24 +18,30 @@ QString lcObject::GetCheckpointString(lcObjectPropertyId PropertyId) switch (PropertyId) { case lcObjectPropertyId::PieceId: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Piece Id"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Piece"); case lcObjectPropertyId::PieceColor: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Piece Color"); + return QT_TRANSLATE_NOOP("Checkpoint", "Chang Piece Color"); case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: break; case lcObjectPropertyId::CameraName: - return QT_TRANSLATE_NOOP("Checkpoint", "Renaming Camera"); + return QT_TRANSLATE_NOOP("Checkpoint", "Rename Camera"); case lcObjectPropertyId::CameraProjection: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Camera Projection"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera Projection"); case lcObjectPropertyId::CameraFOV: + return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera FOV"); + case lcObjectPropertyId::CameraNear: + return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera Near Plane"); + case lcObjectPropertyId::CameraFar: + return QT_TRANSLATE_NOOP("Checkpoint", "Change Camera Far Plane"); + case lcObjectPropertyId::CameraPositionX: case lcObjectPropertyId::CameraPositionY: case lcObjectPropertyId::CameraPositionZ: @@ -48,56 +54,56 @@ QString lcObject::GetCheckpointString(lcObjectPropertyId PropertyId) break; case lcObjectPropertyId::LightName: - return QT_TRANSLATE_NOOP("Checkpoint", "Renaming Light"); + return QT_TRANSLATE_NOOP("Checkpoint", "Rename Light"); case lcObjectPropertyId::LightType: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Type"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Type"); case lcObjectPropertyId::LightColor: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Color"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Color"); case lcObjectPropertyId::LightBlenderPower: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Blender Power"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Blender Power"); case lcObjectPropertyId::LightPOVRayPower: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light POV-Ray Power"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light POV-Ray Power"); case lcObjectPropertyId::LightCastShadow: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Shadow"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Shadow"); case lcObjectPropertyId::LightPOVRayFadeDistance: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light POV-Ray Fade Distance"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light POV-Ray Fade Distance"); case lcObjectPropertyId::LightPOVRayFadePower: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light POV-Ray Fade Power"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light POV-Ray Fade Power"); case lcObjectPropertyId::LightBlenderRadius: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Blender Radius"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Blender Radius"); case lcObjectPropertyId::LightBlenderAngle: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Light Blender Angle"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Light Blender Angle"); case lcObjectPropertyId::LightAreaSizeX: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light X Size"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light X Size"); case lcObjectPropertyId::LightAreaSizeY: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light Y Size"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light Y Size"); case lcObjectPropertyId::LightSpotConeAngle: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Spot Light Cone Angle"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Spot Light Cone Angle"); case lcObjectPropertyId::LightSpotPenumbraAngle: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Spot Light Penumbra Angle"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Spot Light Penumbra Angle"); case lcObjectPropertyId::LightPOVRaySpotTightness: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Spot Light POV-Ray Tightness"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Spot Light POV-Ray Tightness"); case lcObjectPropertyId::LightAreaShape: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light Shape"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light Shape"); case lcObjectPropertyId::LightPOVRayAreaGridX: case lcObjectPropertyId::LightPOVRayAreaGridY: - return QT_TRANSLATE_NOOP("Checkpoint", "Changing Area Light POV-Ray Grid"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Area Light POV-Ray Grid"); case lcObjectPropertyId::ObjectPositionX: case lcObjectPropertyId::ObjectPositionY: From e6fa3a249f72ce4277b1141651e72b15493daa18 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 22 Feb 2026 17:02:24 -0800 Subject: [PATCH 69/93] Removed dead code. --- common/lc_model.cpp | 32 +++++++++++++++++--------------- common/lc_model.h | 2 +- common/lc_propertieswidget.cpp | 1 - 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2277dcbb..7c5b73ce 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3632,7 +3632,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool } } -void lcModel::ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoint) +void lcModel::ScaleSelectedPieces(const float Scale) { if (Scale < 0.001f) return; @@ -3648,14 +3648,6 @@ void lcModel::ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoin { const int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST; Piece->SetControlPointScale(ControlPointIndex, Scale); - - if (Update) - { - UpdateAllViews(); - if (Checkpoint) - SaveCheckpoint(tr("Scaling")); - gMainWindow->UpdateSelectedObjects(false); - } } } @@ -3837,6 +3829,12 @@ void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraPro void lcModel::SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value, bool AddUndo) { bool Modified = false; + + if (AddUndo) + { + BeginActionSequence(); + BeginObjectEditAction(); + } for (lcObject* Object : Objects) { @@ -3850,10 +3848,17 @@ void lcModel::SetObjectsProperty(const std::vector& Objects, lcObject } if (!Modified) + { + DiscardActionSequence(); + return; + } if (AddUndo) - SaveCheckpoint(lcObject::GetCheckpointString(PropertyId)); + { + EndObjectEditAction(); + EndActionSequence(lcObject::GetCheckpointString(PropertyId)); + } gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); @@ -3890,12 +3895,9 @@ void lcModel::EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept) break; case lcObjectPropertyId::CameraFOV: - SaveCheckpoint(tr("Changing FOV")); - break; - case lcObjectPropertyId::CameraNear: case lcObjectPropertyId::CameraFar: - SaveCheckpoint(tr("Editing Camera")); + SaveCheckpoint(lcObject::GetCheckpointString(PropertyId)); break; case lcObjectPropertyId::CameraPositionX: @@ -5170,7 +5172,7 @@ void lcModel::UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag void lcModel::UpdateScaleTool(const float Scale) { - ScaleSelectedPieces(Scale, true, false); + ScaleSelectedPieces(Scale); gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); diff --git a/common/lc_model.h b/common/lc_model.h index e2b143c2..b420d80d 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -381,7 +381,7 @@ public: void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove); void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint); - void ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoint); + void ScaleSelectedPieces(const float Scale); void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform); void SetObjectsKeyFrame(const std::vector& Objects, lcObjectPropertyId PropertyId, bool KeyFrame); void SetSelectedPiecesColorIndex(int ColorIndex); diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index 9223b2e1..f9b30582 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -287,7 +287,6 @@ void lcPropertiesWidget::FloatChanged(const QString& TextValue) float Value = lcParseValueLocalized(TextValue); ChangeFloatValue(PropertyId, Value, true); - qDebug() << Value; } void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float Value, bool Dragging) From d1575c2ceb12be14933804413e40aa26c4b723d8 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 23 Feb 2026 21:49:22 -0800 Subject: [PATCH 70/93] Fixed arrow keys not working in spin boxes. --- common/lc_doublespinbox.cpp | 19 ++++++++++++++++++- common/lc_propertieswidget.cpp | 7 +++---- common/lc_propertieswidget.h | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/common/lc_doublespinbox.cpp b/common/lc_doublespinbox.cpp index b45345ee..e061c421 100644 --- a/common/lc_doublespinbox.cpp +++ b/common/lc_doublespinbox.cpp @@ -216,7 +216,24 @@ bool lcDoubleSpinBox::event(QEvent* Event) return true; } } - + else if (Event->type() == QEvent::ShortcutOverride) + { + QKeyEvent* KeyEvent = static_cast(Event); + + switch (KeyEvent->key()) + { + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_PageUp: + case Qt::Key_PageDown: + Event->accept(); + return true; + + default: + break; + } + } + return QDoubleSpinBox::event(Event); } diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index f9b30582..93552a3f 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -280,11 +280,10 @@ void lcPropertiesWidget::FloatEditingCanceled() Model->EndPropertyEdit(PropertyId, false); } -void lcPropertiesWidget::FloatChanged(const QString& TextValue) +void lcPropertiesWidget::FloatChanged(double Value) { lcDoubleSpinBox* Widget = qobject_cast(sender()); lcObjectPropertyId PropertyId = GetEditorWidgetPropertyId(Widget); - float Value = lcParseValueLocalized(TextValue); ChangeFloatValue(PropertyId, Value, true); } @@ -572,9 +571,9 @@ void lcPropertiesWidget::AddFloatProperty(lcObjectPropertyId PropertyId, const Q connect(Widget, &lcDoubleSpinBox::EditingFinished, this, &lcPropertiesWidget::FloatEditingFinished); #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) - connect(Widget, QOverload::of(&lcDoubleSpinBox::valueChanged), this, &lcPropertiesWidget::FloatChanged); + connect(Widget, QOverload::of(&lcDoubleSpinBox::valueChanged), this, &lcPropertiesWidget::FloatChanged); #else - connect(Widget, &lcDoubleSpinBox::textChanged, this, &lcPropertiesWidget::FloatChanged); + connect(Widget, &lcDoubleSpinBox::valueChanged, this, &lcPropertiesWidget::FloatChanged); #endif mLayout->addWidget(Widget, mLayoutRow, 2); diff --git a/common/lc_propertieswidget.h b/common/lc_propertieswidget.h index 93f20e4a..6430b7ff 100644 --- a/common/lc_propertieswidget.h +++ b/common/lc_propertieswidget.h @@ -20,7 +20,7 @@ protected slots: void BoolChanged(); void FloatEditingFinished(); void FloatEditingCanceled(); - void FloatChanged(const QString& TextValue); + void FloatChanged(double Value); void IntegerChanged(); void StepNumberChanged(); void StringChanged(); From a6c5cdde2bd1bcba82cbfde0d324129124e5366c Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 23 Feb 2026 22:42:33 -0800 Subject: [PATCH 71/93] Fixed selection marking files modified. --- common/lc_model.cpp | 24 ++++++++++++++++++++++++ common/lc_model.h | 23 +++++++---------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 7c5b73ce..c6cf9f08 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2010,6 +2010,30 @@ void lcModel::RevertActionSequence() mActionSequence.clear(); } +bool lcModel::IsModified() const +{ + const lcModelHistoryEntry* FirstModifyAction = GetFirstUndoChange(); + + if (!FirstModifyAction) + return mSavedHistory != nullptr; + else + return mSavedHistory != FirstModifyAction; +} + +void lcModel::SetSaved() +{ + mSavedHistory = GetFirstUndoChange(); +} + +const lcModelHistoryEntry* lcModel::GetFirstUndoChange() const +{ + for (const std::unique_ptr& UndoEntry : mUndoHistory) + if (UndoEntry->ModelActions.size() != 1 || !dynamic_cast(UndoEntry->ModelActions.front().get())) + return UndoEntry.get(); + + return nullptr; +} + void lcModel::SaveCheckpoint(const QString& ) { /* diff --git a/common/lc_model.h b/common/lc_model.h index b420d80d..b0a11900 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -131,19 +131,14 @@ public: return mProject; } - bool IsModified() const - { - if (mUndoHistory.empty()) - return mSavedHistory != nullptr; - else - return mSavedHistory != mUndoHistory.front().get(); - } - bool IsActive() const { return mActive; } - + + bool IsModified() const; + void SetSaved(); + bool GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const; bool IncludesModel(const lcModel* Model) const; void CreatePieceInfo(Project* Project); @@ -271,12 +266,7 @@ public: bool LoadInventory(const QByteArray& Inventory); int SplitMPD(QIODevice& Device); void Merge(std::unique_ptr Other); - - void SetSaved() - { - mSavedHistory = mUndoHistory.empty() ? nullptr : mUndoHistory.front().get(); - } - + void SetMinifig(const lcMinifig& Minifig); void SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex); @@ -422,6 +412,7 @@ protected: void EndActionSequence(const QString& Description); void DiscardActionSequence(); void RevertActionSequence(); + const lcModelHistoryEntry* GetFirstUndoChange() const; void SaveCheckpoint(const QString& Description); void LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply); @@ -457,7 +448,7 @@ protected: QStringList mFileLines; std::vector> mActionSequence; - lcModelHistoryEntry* mSavedHistory; + const lcModelHistoryEntry* mSavedHistory = nullptr; std::vector> mUndoHistory; std::vector> mRedoHistory; From 076c7f6e593221810e6925034af60d59c66808b5 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 24 Feb 2026 22:31:17 -0800 Subject: [PATCH 72/93] Fixed timeline selection getting out of sync with model selection. --- common/lc_timelinewidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/lc_timelinewidget.cpp b/common/lc_timelinewidget.cpp index 50e3ee39..f3122dc8 100644 --- a/common/lc_timelinewidget.cpp +++ b/common/lc_timelinewidget.cpp @@ -553,8 +553,11 @@ void lcTimelineWidget::ItemSelectionChanged() } Model->SetSelectionAndFocus(Selection, CurrentPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + mIgnoreUpdates = false; blockSignals(Blocked); + + UpdateSelection(); } void lcTimelineWidget::dropEvent(QDropEvent* Event) From b7d28e26e9e40edff984f8af02f23ff63d189ae6 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 24 Feb 2026 22:36:51 -0800 Subject: [PATCH 73/93] Fixed ungroup action. --- common/lc_model.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index c6cf9f08..7a39b2b5 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2322,6 +2322,9 @@ void lcModel::UngroupSelection() std::set SelectedGroups; + BeginActionSequence(); + BeginObjectEditAction(); + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsSelected()) @@ -2343,15 +2346,15 @@ void lcModel::UngroupSelection() } } - if (!SelectedGroups.empty()) + if (SelectedGroups.empty()) { + DiscardActionSequence(); + QMessageBox::information(gMainWindow, tr("Ungroup Selection"), tr("No groups selected.")); + return; } - BeginActionSequence(); - BeginObjectEditAction(); - for (const std::unique_ptr& Piece : mPieces) { lcGroup* Group = Piece->GetGroup(); From 8adef907c869d9ed53158050ed5baf4bcf373a5e Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 24 Feb 2026 22:47:15 -0800 Subject: [PATCH 74/93] Fixed Hide Selected undo. --- common/lc_model.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 7a39b2b5..111b71a6 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -4616,7 +4616,6 @@ void lcModel::HideSelectedPieces() if (Piece->IsSelected() && !Piece->IsHidden()) { Piece->SetHidden(true); - Piece->SetSelected(false); Modified = true; } @@ -4629,7 +4628,10 @@ void lcModel::HideSelectedPieces() return; } - EndObjectEditAction(); + EndObjectEditAction(); + + RecordClearSelectionAction(); + EndActionSequence(tr("Hide Pieces")); gMainWindow->UpdateTimeline(false, true); From afa5b14283fd330cfd2cb1fc54adaf5d4ce8ba40 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 24 Feb 2026 22:56:13 -0800 Subject: [PATCH 75/93] Update timeline after undo. --- common/lc_model.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 111b71a6..47bb1a4a 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1963,6 +1963,7 @@ void lcModel::RunActionSequence(const std::vector gMainWindow->UpdateSelectedObjects(true); UpdateAllViews(); + gMainWindow->UpdateTimeline(true, false); } void lcModel::BeginActionSequence() @@ -1996,6 +1997,7 @@ void lcModel::EndActionSequence(const QString& Description) } UpdateAllViews(); + gMainWindow->UpdateTimeline(true, false); } void lcModel::DiscardActionSequence() @@ -4626,7 +4628,7 @@ void lcModel::HideSelectedPieces() DiscardActionSequence(); return; - } + } EndObjectEditAction(); From 58357c72358a72f0a42e19b1df4bab2ffc273ebf Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 28 Feb 2026 13:33:35 -0800 Subject: [PATCH 76/93] Removed RunAction functions. --- common/lc_model.cpp | 58 ++++++++++++----------------------------- common/lc_model.h | 13 ++++----- common/lc_modelaction.h | 29 ++++++++++++--------- 3 files changed, 38 insertions(+), 62 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 47bb1a4a..f44bf705 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1799,17 +1799,6 @@ void lcModel::RecordRemoveFromSelectionAction(const std::vector& Obje RecordSelectionAction([this, &Objects](){ SetObjectsSelected(Objects, false); }); } -void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply) -{ - if (!ModelActionSelection) - return; - - if (Apply) - ModelActionSelection->LoadEndState(this); - else - ModelActionSelection->LoadStartState(this); -} - template void lcModel::LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects) { @@ -1885,19 +1874,6 @@ void lcModel::EndObjectEditAction() mActionSequence.pop_back(); } -void lcModel::RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply) -{ - if (!ModelActionObjectEdit) - return; - - if (Apply) - ModelActionObjectEdit->LoadEndState(this); - else - ModelActionObjectEdit->LoadStartState(this); - - SetCurrentStep(mCurrentStep); -} - void lcModel::SetModelProperties(const lcModelProperties& ModelProperties) { mProperties = ModelProperties; @@ -1919,33 +1895,31 @@ void lcModel::RecordModelPropertiesAction(const lcModelProperties& ModelProperti mActionSequence.emplace_back(std::move(ModelActionProperties)); } -void lcModel::RunModelPropertiesAction(const lcModelActionProperties* ModelActionProperties, bool Apply) -{ - if (!ModelActionProperties) - return; - - if (Apply) - ModelActionProperties->LoadEndState(this); - else - ModelActionProperties->LoadStartState(this); -} - void lcModel::RunActionSequence(const std::vector>& ActionSequence, bool Apply) { bool SelectionChanged = false; auto RunAction=[this, &SelectionChanged](const lcModelAction* ModelAction, bool Apply) { - if (const lcModelActionSelection* ModelActionSelection = dynamic_cast(ModelAction)) + if (!ModelAction) + return; + + if (Apply) + ModelAction->LoadEndState(this); + else + ModelAction->LoadStartState(this); + + if (dynamic_cast(ModelAction)) { - RunSelectionAction(ModelActionSelection, Apply); - SelectionChanged = true; } - else if (const lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(ModelAction)) - RunObjectEditAction(ModelActionObjectEdit, Apply); - else if (const lcModelActionProperties* ModelActionProperties = dynamic_cast(ModelAction)) - RunModelPropertiesAction(ModelActionProperties, Apply); + else if (dynamic_cast(ModelAction)) + { + SetCurrentStep(mCurrentStep); + } + else if (dynamic_cast(ModelAction)) + { + } }; if (Apply) diff --git a/common/lc_model.h b/common/lc_model.h index b0a11900..eac39e2f 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -395,17 +395,14 @@ protected: void RecordSelectionAction(std::function Callback); void RecordClearSelectionAction(); void RecordSetFocusAction(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); - void RecordSetSelectionAndFocusAction(const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); - void RecordSelectAllPiecesAction(); - void RecordInvertPieceSelectionAction(); - void RecordAddToSelectionAction(const std::vector& Objects); - void RecordRemoveFromSelectionAction(const std::vector& Objects); - void RunSelectionAction(const lcModelActionSelection* ModelActionSelection, bool Apply); + void RecordSetSelectionAndFocusAction(const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); + void RecordSelectAllPiecesAction(); + void RecordInvertPieceSelectionAction(); + void RecordAddToSelectionAction(const std::vector& Objects); + void RecordRemoveFromSelectionAction(const std::vector& Objects); void BeginObjectEditAction(); void EndObjectEditAction(); - void RunObjectEditAction(const lcModelActionObjectEdit* ModelActionObjectEdit, bool Apply); void RecordModelPropertiesAction(const lcModelProperties& ModelProperties); - void RunModelPropertiesAction(const lcModelActionProperties* ModelActionProperties, bool Apply); void RunActionSequence(const std::vector>& ActionSequence, bool Apply); void BeginActionSequence(); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index ca34d574..b8145962 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -10,6 +10,11 @@ class lcModelAction public: lcModelAction() = default; virtual ~lcModelAction() = default; + + virtual void SaveStartState(const lcModel* Model) = 0; + virtual void SaveEndState(const lcModel* Model) = 0; + virtual void LoadStartState(lcModel* Model) const = 0; + virtual void LoadEndState(lcModel* Model) const = 0; }; struct lcModelActionSelectionState @@ -34,10 +39,10 @@ public: lcModelActionSelection() = default; virtual ~lcModelActionSelection() = default; - void SaveStartState(const lcModel* Model); - void SaveEndState(const lcModel* Model); - void LoadStartState(lcModel* Model) const; - void LoadEndState(lcModel* Model) const; + void SaveStartState(const lcModel* Model) override; + void SaveEndState(const lcModel* Model) override; + void LoadStartState(lcModel* Model) const override; + void LoadEndState(lcModel* Model) const override; bool StateChanged() const; @@ -73,10 +78,10 @@ public: lcModelActionObjectEdit() = default; virtual ~lcModelActionObjectEdit() = default; - void SaveStartState(const lcModel* Model); - void SaveEndState(const lcModel* Model); - void LoadStartState(lcModel* Model) const; - void LoadEndState(lcModel* Model) const; + void SaveStartState(const lcModel* Model) override; + void SaveEndState(const lcModel* Model) override; + void LoadStartState(lcModel* Model) const override; + void LoadEndState(lcModel* Model) const override; bool StateChanged() const; @@ -94,10 +99,10 @@ public: lcModelActionProperties() = default; virtual ~lcModelActionProperties() = default; - void SaveStartState(const lcModel* Model); - void SaveEndState(const lcModel* Model); - void LoadStartState(lcModel* Model) const; - void LoadEndState(lcModel* Model) const; + void SaveStartState(const lcModel* Model) override; + void SaveEndState(const lcModel* Model) override; + void LoadStartState(lcModel* Model) const override; + void LoadEndState(lcModel* Model) const override; bool StateChanged() const; From 8c641bf5a5950d811d00b5ecab6af5861e5d4226 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 5 Mar 2026 15:36:33 -0800 Subject: [PATCH 77/93] Removed unused function parameter. --- common/lc_mainwindow.cpp | 24 +++++++++---------- common/lc_model.cpp | 44 +++++++++++++++++++++------------- common/lc_model.h | 8 +++---- common/lc_propertieswidget.cpp | 10 ++++---- 4 files changed, 49 insertions(+), 37 deletions(-) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 18462216..12bc8256 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2966,62 +2966,62 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_PIECE_MOVE_PLUSX: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true); break; case LC_PIECE_MOVE_MINUSX: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true); break; case LC_PIECE_MOVE_PLUSY: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true); break; case LC_PIECE_MOVE_MINUSY: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true); break; case LC_PIECE_MOVE_PLUSZ: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true); break; case LC_PIECE_MOVE_MINUSZ: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true); break; case LC_PIECE_ROTATE_PLUSX: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true); break; case LC_PIECE_ROTATE_MINUSX: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true); break; case LC_PIECE_ROTATE_PLUSY: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true); break; case LC_PIECE_ROTATE_MINUSY: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true); break; case LC_PIECE_ROTATE_PLUSZ: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true); break; case LC_PIECE_ROTATE_MINUSZ: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true); break; case LC_PIECE_MINIFIG_WIZARD: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index f44bf705..5eb7c497 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3387,7 +3387,7 @@ bool lcModel::RemoveSelectedObjects() return RemovedPiece || RemovedCamera || RemovedLight; } -void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove) +void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove) { bool Moved = false; lcMatrix33 RelativeRotation; @@ -3455,7 +3455,7 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector } } - if (Moved && Update) + if (Moved) { UpdateAllViews(); @@ -3466,11 +3466,17 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector } } -void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint) +void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint) { if (Angles.LengthSquared() < 0.001f) return; + if (Checkpoint) + { + BeginActionSequence(); + BeginObjectEditAction(); + } + lcMatrix33 RotationMatrix = lcMatrix33Identity(); bool Rotated = false; @@ -3626,13 +3632,22 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool } } - if (Rotated && Update) + if (!Rotated) { - UpdateAllViews(); if (Checkpoint) - SaveCheckpoint(tr("Rotating")); - gMainWindow->UpdateSelectedObjects(false); + DiscardActionSequence(); + + return; } + + if (Checkpoint) + { + EndObjectEditAction(); + EndActionSequence(tr("Rotate")); + } + + UpdateAllViews(); + gMainWindow->UpdateSelectedObjects(false); } void lcModel::ScaleSelectedPieces(const float Scale) @@ -3659,19 +3674,19 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe switch (TransformType) { case lcTransformType::AbsoluteTranslation: - MoveSelectedObjects(Transform, false, false, true, true, true); + MoveSelectedObjects(Transform, false, false, true, true); break; case lcTransformType::RelativeTranslation: - MoveSelectedObjects(Transform, true, false, true, true, true); + MoveSelectedObjects(Transform, true, false, true, true); break; case lcTransformType::AbsoluteRotation: - RotateSelectedObjects(Transform, false, false, true, true); + RotateSelectedObjects(Transform, false, false, true); break; case lcTransformType::RelativeRotation: - RotateSelectedObjects(Transform, true, false, true, true); + RotateSelectedObjects(Transform, true, false, true); break; case lcTransformType::Count: @@ -5083,7 +5098,7 @@ void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool const lcVector3 PieceDistance = SnapPosition(Distance) - SnapPosition(mMouseToolDistance); const lcVector3 ObjectDistance = Distance - mMouseToolDistance; - MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, true, false, mMouseToolFirstMove); + MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, false, mMouseToolFirstMove); mMouseToolDistance = Distance; mMouseToolFirstMove = false; @@ -5166,13 +5181,10 @@ void lcModel::UpdateFreeMoveTool(lcPiece* MousePiece, const lcMatrix44& StartTra void lcModel::UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag) { const lcVector3 Delta = SnapRotation(Angles) - SnapRotation(mMouseToolDistance); - RotateSelectedObjects(Delta, true, AlternateButtonDrag, false, false); + RotateSelectedObjects(Delta, true, AlternateButtonDrag, false); mMouseToolDistance = Angles; mMouseToolFirstMove = false; - - gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); } void lcModel::UpdateScaleTool(const float Scale) diff --git a/common/lc_model.h b/common/lc_model.h index eac39e2f..dcec3fa7 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -364,13 +364,13 @@ public: void ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& WorldMatrix); void Zoom(lcCamera* Camera, float Amount); - void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove) + void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove) { - MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Update, Checkpoint, FirstMove); + MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Checkpoint, FirstMove); } - void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove); - void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint); + void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove); + void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint); void ScaleSelectedPieces(const float Scale); void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform); void SetObjectsKeyFrame(const std::vector& Objects, lcObjectPropertyId PropertyId, bool KeyFrame); diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index 93552a3f..b8917ee2 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -320,7 +320,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = Position - Center; - Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); } else if (PropertyId == lcObjectPropertyId::ObjectRotationX || PropertyId == lcObjectPropertyId::ObjectRotationY || PropertyId == lcObjectPropertyId::ObjectRotationZ) { @@ -340,7 +340,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V else if (PropertyId == lcObjectPropertyId::ObjectRotationZ) Rotation[2] = Value; - Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, !Dragging); + Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, !Dragging); } else if (Piece || Light) { @@ -376,7 +376,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = End - Start; - Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); if (Camera) { @@ -413,7 +413,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = End - Start; - Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); if (Camera) { @@ -450,7 +450,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = End - Start; - Model->MoveSelectedObjects(Distance, false, false, true, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); if (Camera) { From f7fb61b30454cb310c4e5a1e17f22b6d7ea5b54b Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 5 Mar 2026 15:53:54 -0800 Subject: [PATCH 78/93] Fixed rotating in the properties widget without a focus object. --- common/lc_propertieswidget.cpp | 5 +++++ common/lc_propertieswidget.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index b8917ee2..9a9596a5 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -330,6 +330,8 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD; else if (Light) InitialRotation = lcMatrix44ToEulerAngles(Light->GetWorldMatrix()) * LC_RTOD; + else + InitialRotation = mLastRotation; lcVector3 Rotation = InitialRotation; @@ -341,6 +343,8 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V Rotation[2] = Value; Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, !Dragging); + + mLastRotation = Rotation; } else if (Piece || Light) { @@ -1566,6 +1570,7 @@ void lcPropertiesWidget::Update(const std::vector& Selection, lcObjec if (mDisableUpdates) return; + mLastRotation = lcVector3(0.0f, 0.0f, 0.0f); mFocusObject = nullptr; mSelection.clear(); diff --git a/common/lc_propertieswidget.h b/common/lc_propertieswidget.h index 6430b7ff..46776518 100644 --- a/common/lc_propertieswidget.h +++ b/common/lc_propertieswidget.h @@ -1,6 +1,7 @@ #pragma once #include "lc_objectproperty.h" +#include "lc_math.h" class lcCollapsibleWidgetButton; class lcKeyFrameWidget; @@ -131,6 +132,7 @@ protected: std::vector mSelection; lcObject* mFocusObject = nullptr; bool mDisableUpdates = false; + lcVector3 mLastRotation = lcVector3(0.0f, 0.0f, 0.0f); std::array(lcObjectPropertyId::Count)> mPropertyWidgets = {}; std::array(CategoryIndex::Count)> mCategoryWidgets = {}; From a8ccd4b5aa71eecd4b81ef07f75f7cb04369ecb6 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 5 Mar 2026 16:42:11 -0800 Subject: [PATCH 79/93] Merge sequential rotation actions. --- common/lc_mainwindow.cpp | 13 ++-- common/lc_model.cpp | 127 +++++++++++++++++++-------------- common/lc_model.h | 5 +- common/lc_modelaction.cpp | 29 ++++++++ common/lc_modelaction.h | 33 +++++++-- common/lc_propertieswidget.cpp | 3 +- 6 files changed, 140 insertions(+), 70 deletions(-) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 12bc8256..95fb8944 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -24,6 +24,7 @@ #include "lc_library.h" #include "lc_colors.h" #include "lc_previewwidget.h" +#include "lc_modelaction.h" #if LC_ENABLE_GAMEPAD #include @@ -2996,32 +2997,32 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_PIECE_ROTATE_PLUSX: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate); break; case LC_PIECE_ROTATE_MINUSX: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate); break; case LC_PIECE_ROTATE_PLUSY: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate); break; case LC_PIECE_ROTATE_MINUSY: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, lcModelActionEditMerge::KeyboardRotate); break; case LC_PIECE_ROTATE_PLUSZ: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, lcModelActionEditMerge::KeyboardRotate); break; case LC_PIECE_ROTATE_MINUSZ: if (ActiveModel) - ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true); + ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, lcModelActionEditMerge::KeyboardRotate); break; case LC_PIECE_MINIFIG_WIZARD: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 5eb7c497..41621729 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1169,7 +1169,7 @@ void lcModel::Cut() Copy(); BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); RemoveSelectedObjects(); @@ -1225,7 +1225,7 @@ void lcModel::Paste(bool PasteToCurrentStep) return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); Merge(std::move(Model)); @@ -1252,7 +1252,7 @@ void lcModel::DuplicateSelectedPieces() } BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); std::vector NewPieces; lcPiece* Focus = nullptr; @@ -1846,9 +1846,9 @@ void lcModel::LoadHistoryState(const lcModelHistoryState& HistoryState) LoadObjectHistoryState(HistoryState.Lights, mLights); } -void lcModel::BeginObjectEditAction() +void lcModel::BeginObjectEditAction(lcModelActionEditMerge ModelActionEditMerge) { - std::unique_ptr ModelActionObjectEdit = std::make_unique(); + std::unique_ptr ModelActionObjectEdit = std::make_unique(ModelActionEditMerge); if (!ModelActionObjectEdit) return; @@ -1950,12 +1950,31 @@ void lcModel::EndActionSequence(const QString& Description) if (mActionSequence.empty()) return; - std::unique_ptr ModelHistoryEntry = std::make_unique(lcModelHistoryEntry()); + bool CanMerge = false; - ModelHistoryEntry->Description = Description; - ModelHistoryEntry->ModelActions = std::move(mActionSequence); + if (mActionSequence.size() == 1 && !mUndoHistory.empty() && mUndoHistory.front()->ModelActions.size() == 1) + CanMerge = mActionSequence.front()->CanMergeWith(mUndoHistory.front()->ModelActions.front().get()); + + if (!CanMerge) + { + std::unique_ptr ModelHistoryEntry = std::make_unique(lcModelHistoryEntry()); + + ModelHistoryEntry->Description = Description; + ModelHistoryEntry->ModelActions = std::move(mActionSequence); + + mUndoHistory.insert(mUndoHistory.begin(), std::move(ModelHistoryEntry)); + } + else + { + lcModelActionObjectEdit* ModelActionEdit = dynamic_cast(mActionSequence.front().get()); + lcModelHistoryEntry* LastHistoryEntry = mUndoHistory.front().get(); + lcModelActionObjectEdit* LastModelActionEdit = dynamic_cast(LastHistoryEntry->ModelActions.front().get()); + + LastModelActionEdit->MergeWith(ModelActionEdit); + + mActionSequence.clear(); + } - mUndoHistory.insert(mUndoHistory.begin(), std::move(ModelHistoryEntry)); mRedoHistory.clear(); gMainWindow->UpdateModified(IsModified()); @@ -2167,7 +2186,7 @@ lcStep lcModel::GetLastStep() const void lcModel::InsertStep(lcStep Step) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (const std::unique_ptr& Piece : mPieces) Piece->InsertTime(Step, 1); @@ -2188,7 +2207,7 @@ void lcModel::InsertStep(lcStep Step) void lcModel::RemoveStep(lcStep Step) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (const std::unique_ptr& Piece : mPieces) Piece->RemoveTime(Step, 1); @@ -2265,7 +2284,7 @@ void lcModel::GroupSelection() return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); lcGroup* NewGroup = GetGroup(Dialog.mName, true); @@ -2299,7 +2318,7 @@ void lcModel::UngroupSelection() std::set SelectedGroups; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (const std::unique_ptr& Piece : mPieces) { @@ -2372,7 +2391,7 @@ void lcModel::AddSelectedPiecesToGroup() return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (const std::unique_ptr& Piece : mPieces) { @@ -2428,7 +2447,7 @@ void lcModel::ShowEditGroupsDialog() return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); std::function UpdateGroups=[this, &UpdateGroups](const lcQEditGroupsDialog::GroupInfo& GroupInfo, lcGroup* ParentGroup) { @@ -2664,7 +2683,7 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) }; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); if (Last) { @@ -2863,7 +2882,7 @@ void lcModel::RotateFocusedTrainTrack(int Direction) BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); FocusPiece->SetPosition(Transform.value().GetTranslation(), mCurrentStep, gMainWindow->GetAddKeys()); FocusPiece->SetRotation(lcMatrix33(Transform.value()), mCurrentStep, gMainWindow->GetAddKeys()); @@ -2943,7 +2962,7 @@ void lcModel::DeleteSelectedObjects() } BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = RemoveSelectedObjects(); @@ -2965,7 +2984,7 @@ void lcModel::DeleteSelectedObjects() void lcModel::ResetSelectedPiecesPivotPoint() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) @@ -2978,7 +2997,7 @@ void lcModel::ResetSelectedPiecesPivotPoint() void lcModel::RemoveSelectedObjectsKeyFrames() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) @@ -3008,7 +3027,7 @@ void lcModel::InsertControlPoint() gMainWindow->GetActiveView()->GetRayUnderPointer(Start, End); BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = Piece->InsertControlPoint(Start, End); @@ -3033,7 +3052,7 @@ void lcModel::RemoveFocusedControlPoint() return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = Piece->RemoveFocusedControlPoint(); @@ -3053,7 +3072,7 @@ void lcModel::RemoveFocusedControlPoint() void lcModel::ShowSelectedPiecesEarlier() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); std::vector MovedPieces; @@ -3102,7 +3121,7 @@ void lcModel::ShowSelectedPiecesEarlier() void lcModel::ShowSelectedPiecesLater() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); std::vector MovedPieces; @@ -3155,7 +3174,7 @@ void lcModel::SetPieceSteps(const std::vector>& Piec return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = false; @@ -3261,7 +3280,7 @@ void lcModel::MoveSelectionToModel(lcModel* Model) void lcModel::InlineSelectedModels() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); std::vector NewPieces; bool Modified = false; @@ -3466,7 +3485,7 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector } } -void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint) +void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint, lcModelActionEditMerge ModelActionEditMerge) { if (Angles.LengthSquared() < 0.001f) return; @@ -3474,7 +3493,7 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool if (Checkpoint) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(ModelActionEditMerge); } lcMatrix33 RotationMatrix = lcMatrix33Identity(); @@ -3682,11 +3701,11 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe break; case lcTransformType::AbsoluteRotation: - RotateSelectedObjects(Transform, false, false, true); + RotateSelectedObjects(Transform, false, false, true, lcModelActionEditMerge::None); break; case lcTransformType::RelativeRotation: - RotateSelectedObjects(Transform, true, false, true); + RotateSelectedObjects(Transform, true, false, true, lcModelActionEditMerge::None); break; case lcTransformType::Count: @@ -3697,7 +3716,7 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObjectPropertyId PropertyId, bool KeyFrame) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = false; @@ -3723,7 +3742,7 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = false; @@ -3774,7 +3793,7 @@ void lcModel::SetSelectedPiecesStepShow(lcStep Step) return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (lcPiece* Piece : MovedPieces) { @@ -3794,7 +3813,7 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) bool Modified = false; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); for (const std::unique_ptr& Piece : mPieces) { @@ -3828,7 +3847,7 @@ void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraPro if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); } Camera->SetProjection(CameraProjection); @@ -3851,7 +3870,7 @@ void lcModel::SetObjectsProperty(const std::vector& Objects, lcObject if (AddUndo) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); } for (lcObject* Object : Objects) @@ -4598,7 +4617,7 @@ void lcModel::SelectGroup(lcGroup* TopGroup, bool Select) void lcModel::HideSelectedPieces() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = false; @@ -4632,7 +4651,7 @@ void lcModel::HideSelectedPieces() void lcModel::HideUnselectedPieces() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = false; @@ -4663,7 +4682,7 @@ void lcModel::HideUnselectedPieces() void lcModel::UnhideSelectedPieces() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = false; @@ -4694,7 +4713,7 @@ void lcModel::UnhideSelectedPieces() void lcModel::UnhideAllPieces() { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); bool Modified = false; @@ -4759,7 +4778,7 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) int ReplacedCount = 0; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); if (!FindAll) { @@ -4896,7 +4915,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) case lcTool::Move: case lcTool::Rotate: BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); break; case lcTool::Eraser: @@ -4911,7 +4930,7 @@ void lcModel::BeginMouseTool(lcTool Tool, lcView* View) if (!View->GetCamera()->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); } break; @@ -5008,7 +5027,7 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); lcPiece* Piece = nullptr; @@ -5038,7 +5057,7 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece void lcModel::InsertCameraToolClicked(const lcVector3& Position) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); lcCamera* Camera = new lcCamera(false, Position, GetSelectionOrModelCenter()); @@ -5079,7 +5098,7 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh } BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); lcLight* Light = new lcLight(Position, LightType); @@ -5181,7 +5200,7 @@ void lcModel::UpdateFreeMoveTool(lcPiece* MousePiece, const lcMatrix44& StartTra void lcModel::UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag) { const lcVector3 Delta = SnapRotation(Angles) - SnapRotation(mMouseToolDistance); - RotateSelectedObjects(Delta, true, AlternateButtonDrag, false); + RotateSelectedObjects(Delta, true, AlternateButtonDrag, false, lcModelActionEditMerge::None); mMouseToolDistance = Angles; mMouseToolFirstMove = false; @@ -5201,7 +5220,7 @@ void lcModel::EraserToolClicked(lcObject* Object) return; BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); switch (Object->GetType()) { @@ -5267,7 +5286,7 @@ void lcModel::PaintToolClicked(lcObject* Object) if (Piece->GetColorIndex() != gMainWindow->mColorIndex) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); Piece->SetColorIndex(gMainWindow->mColorIndex); @@ -5331,7 +5350,7 @@ void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVec if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); } Camera->ZoomRegion(AspectRatio, Position, TargetPosition, Corners, mCurrentStep, gMainWindow->GetAddKeys()); @@ -5363,7 +5382,7 @@ void lcModel::LookAt(lcCamera* Camera) if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); } Camera->Center(Center, mCurrentStep, gMainWindow->GetAddKeys()); @@ -5410,7 +5429,7 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl if (!Camera->IsSimple()) { BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); } Camera->ZoomExtents(Aspect, Center, Points, mCurrentStep, gMainWindow ? gMainWindow->GetAddKeys() : false); @@ -5498,7 +5517,7 @@ void lcModel::ShowArrayDialog() } BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); std::vector NewPieces; @@ -5567,7 +5586,7 @@ void lcModel::ShowMinifigDialog() gMainWindow->GetActiveView()->MakeCurrent(); BeginActionSequence(); - BeginObjectEditAction(); + BeginObjectEditAction(lcModelActionEditMerge::None); lcGroup* Group = AddGroup(tr("Minifig #"), nullptr); std::vector Pieces; diff --git a/common/lc_model.h b/common/lc_model.h index dcec3fa7..91bc7855 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -10,6 +10,7 @@ class lcModelAction; class lcModelActionSelection; class lcModelActionObjectEdit; class lcModelActionProperties; +enum class lcModelActionEditMerge; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected @@ -370,7 +371,7 @@ public: } void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove); - void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint); + void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint, lcModelActionEditMerge ModelActionEditMerge); void ScaleSelectedPieces(const float Scale); void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform); void SetObjectsKeyFrame(const std::vector& Objects, lcObjectPropertyId PropertyId, bool KeyFrame); @@ -400,7 +401,7 @@ protected: void RecordInvertPieceSelectionAction(); void RecordAddToSelectionAction(const std::vector& Objects); void RecordRemoveFromSelectionAction(const std::vector& Objects); - void BeginObjectEditAction(); + void BeginObjectEditAction(lcModelActionEditMerge ModelActionEditMerge); void EndObjectEditAction(); void RecordModelPropertiesAction(const lcModelProperties& ModelProperties); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 38de364a..8d698b29 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -142,6 +142,20 @@ void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, } } +bool operator!=(const lcModelHistoryState& a, const lcModelHistoryState& b) +{ + return a.Groups != b.Groups || a.Pieces != b.Pieces || a.Cameras != b.Cameras || a.Lights != b.Lights; +} + +lcModelActionObjectEdit::lcModelActionObjectEdit(lcModelActionEditMerge ModelActionEditMerge) + : mMerge(ModelActionEditMerge) +{ +} + +lcModelActionObjectEdit::~lcModelActionObjectEdit() +{ +} + void lcModelActionObjectEdit::SaveState(lcModelHistoryState& State, const lcModel* Model) { const std::vector>& Groups = Model->GetGroups(); @@ -195,6 +209,21 @@ bool lcModelActionObjectEdit::StateChanged() const return mStartState != mEndState; } +bool lcModelActionObjectEdit::CanMergeWith(const lcModelAction* Other) const +{ + const lcModelActionObjectEdit* OtherModelActionEdit = dynamic_cast(Other); + + return OtherModelActionEdit && mMerge != lcModelActionEditMerge::None && mMerge == OtherModelActionEdit->mMerge; +} + +void lcModelActionObjectEdit::MergeWith(lcModelAction* Other) +{ + lcModelActionObjectEdit* OtherModelActionEdit = dynamic_cast(Other); + + if (OtherModelActionEdit) + mEndState = std::move(OtherModelActionEdit->mEndState); +} + void lcModelActionProperties::SaveStartState(const lcModel* Model) { SaveState(mStartState, Model); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index b8145962..32483727 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -15,6 +15,18 @@ public: virtual void SaveEndState(const lcModel* Model) = 0; virtual void LoadStartState(lcModel* Model) const = 0; virtual void LoadEndState(lcModel* Model) const = 0; + + virtual bool CanMergeWith(const lcModelAction* Other) const + { + Q_UNUSED(Other); + + return false; + } + + virtual void MergeWith(lcModelAction* Other) + { + Q_UNUSED(Other); + } }; struct lcModelActionSelectionState @@ -65,18 +77,22 @@ struct lcModelHistoryState std::vector Pieces; std::vector Cameras; std::vector Lights; - - bool operator!=(const lcModelHistoryState& Other) const - { - return Groups != Other.Groups || Pieces != Other.Pieces || Cameras != Other.Cameras || Lights != Other.Lights; - } +}; + +bool operator!=(const lcModelHistoryState& a, const lcModelHistoryState& b); + +enum class lcModelActionEditMerge +{ + None, + KeyboardRotate, + PropertiesRotate }; class lcModelActionObjectEdit: public lcModelAction { public: - lcModelActionObjectEdit() = default; - virtual ~lcModelActionObjectEdit() = default; + lcModelActionObjectEdit(lcModelActionEditMerge ModelActionEditMerge); + virtual ~lcModelActionObjectEdit(); void SaveStartState(const lcModel* Model) override; void SaveEndState(const lcModel* Model) override; @@ -84,6 +100,8 @@ public: void LoadEndState(lcModel* Model) const override; bool StateChanged() const; + bool CanMergeWith(const lcModelAction* Other) const override; + void MergeWith(lcModelAction* Other) override; protected: static void SaveState(lcModelHistoryState& State, const lcModel* Model); @@ -91,6 +109,7 @@ protected: lcModelHistoryState mStartState; lcModelHistoryState mEndState; + lcModelActionEditMerge mMerge; }; class lcModelActionProperties : public lcModelAction diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index 9a9596a5..ecad38f9 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -12,6 +12,7 @@ #include "lc_colorpicker.h" #include "lc_qutils.h" #include "lc_partselectionpopup.h" +#include "lc_modelaction.h" lcPropertiesWidget::lcPropertiesWidget(QWidget* Parent) : QWidget(Parent) @@ -342,7 +343,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V else if (PropertyId == lcObjectPropertyId::ObjectRotationZ) Rotation[2] = Value; - Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, !Dragging); + Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, lcModelActionEditMerge::PropertiesRotate); mLastRotation = Rotation; } From d80b38a41b05d75753bc997fad5261bedf95e7a9 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 5 Mar 2026 16:44:46 -0800 Subject: [PATCH 80/93] Fixed incremental rotations when dragging in the properties widget. --- common/lc_propertieswidget.cpp | 8 ++++---- common/lc_propertieswidget.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index ecad38f9..cc28ed2c 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -327,12 +327,12 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V { lcVector3 InitialRotation(0.0f, 0.0f, 0.0f); - if (Piece) + if (mLastRotation) + InitialRotation = mLastRotation.value(); + else if (Piece) InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD; else if (Light) InitialRotation = lcMatrix44ToEulerAngles(Light->GetWorldMatrix()) * LC_RTOD; - else - InitialRotation = mLastRotation; lcVector3 Rotation = InitialRotation; @@ -1571,7 +1571,7 @@ void lcPropertiesWidget::Update(const std::vector& Selection, lcObjec if (mDisableUpdates) return; - mLastRotation = lcVector3(0.0f, 0.0f, 0.0f); + mLastRotation.reset(); mFocusObject = nullptr; mSelection.clear(); diff --git a/common/lc_propertieswidget.h b/common/lc_propertieswidget.h index 46776518..82ca61fe 100644 --- a/common/lc_propertieswidget.h +++ b/common/lc_propertieswidget.h @@ -132,7 +132,7 @@ protected: std::vector mSelection; lcObject* mFocusObject = nullptr; bool mDisableUpdates = false; - lcVector3 mLastRotation = lcVector3(0.0f, 0.0f, 0.0f); + std::optional mLastRotation; std::array(lcObjectPropertyId::Count)> mPropertyWidgets = {}; std::array(CategoryIndex::Count)> mCategoryWidgets = {}; From d14b8e3d93a8c8df502e5ab65f58c6ab890706ed Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 7 Mar 2026 13:41:54 -0800 Subject: [PATCH 81/93] Merge repeated move actions. --- common/lc_mainwindow.cpp | 12 ++++++------ common/lc_model.cpp | 31 ++++++++++++++++++++++--------- common/lc_model.h | 6 +++--- common/lc_modelaction.h | 2 ++ common/lc_propertieswidget.cpp | 8 ++++---- 5 files changed, 37 insertions(+), 22 deletions(-) diff --git a/common/lc_mainwindow.cpp b/common/lc_mainwindow.cpp index 95fb8944..558e91c1 100644 --- a/common/lc_mainwindow.cpp +++ b/common/lc_mainwindow.cpp @@ -2967,32 +2967,32 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId) case LC_PIECE_MOVE_PLUSX: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove); break; case LC_PIECE_MOVE_MINUSX: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove); break; case LC_PIECE_MOVE_PLUSY: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove); break; case LC_PIECE_MOVE_MINUSY: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, lcModelActionEditMerge::KeyboardMove); break; case LC_PIECE_MOVE_PLUSZ: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, lcModelActionEditMerge::KeyboardMove); break; case LC_PIECE_MOVE_MINUSZ: if (ActiveModel) - ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true); + ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, lcModelActionEditMerge::KeyboardMove); break; case LC_PIECE_ROTATE_PLUSX: diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 41621729..d67908aa 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3406,8 +3406,14 @@ bool lcModel::RemoveSelectedObjects() return RemovedPiece || RemovedCamera || RemovedLight; } -void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove) +void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove, lcModelActionEditMerge ModelActionEditMerge) { + if (Checkpoint) + { + BeginActionSequence(); + BeginObjectEditAction(ModelActionEditMerge); + } + bool Moved = false; lcMatrix33 RelativeRotation; @@ -3474,15 +3480,22 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector } } - if (Moved) + if (!Moved) { - UpdateAllViews(); - if (Checkpoint) - SaveCheckpoint(tr("Moving")); + DiscardActionSequence(); - gMainWindow->UpdateSelectedObjects(false); + return; } + + if (Checkpoint) + { + EndObjectEditAction(); + EndActionSequence(tr("Move")); + } + + UpdateAllViews(); + gMainWindow->UpdateSelectedObjects(false); } void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint, lcModelActionEditMerge ModelActionEditMerge) @@ -3693,11 +3706,11 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe switch (TransformType) { case lcTransformType::AbsoluteTranslation: - MoveSelectedObjects(Transform, false, false, true, true); + MoveSelectedObjects(Transform, false, false, true, true, lcModelActionEditMerge::None); break; case lcTransformType::RelativeTranslation: - MoveSelectedObjects(Transform, true, false, true, true); + MoveSelectedObjects(Transform, true, false, true, true, lcModelActionEditMerge::None); break; case lcTransformType::AbsoluteRotation: @@ -5117,7 +5130,7 @@ void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool const lcVector3 PieceDistance = SnapPosition(Distance) - SnapPosition(mMouseToolDistance); const lcVector3 ObjectDistance = Distance - mMouseToolDistance; - MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, false, mMouseToolFirstMove); + MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, false, mMouseToolFirstMove, lcModelActionEditMerge::None); mMouseToolDistance = Distance; mMouseToolFirstMove = false; diff --git a/common/lc_model.h b/common/lc_model.h index 91bc7855..ea8ebb15 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -365,12 +365,12 @@ public: void ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& WorldMatrix); void Zoom(lcCamera* Camera, float Amount); - void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove) + void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove, lcModelActionEditMerge ModelActionEditMerge) { - MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Checkpoint, FirstMove); + MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Checkpoint, FirstMove, ModelActionEditMerge); } - void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove); + void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove, lcModelActionEditMerge ModelActionEditMerge); void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint, lcModelActionEditMerge ModelActionEditMerge); void ScaleSelectedPieces(const float Scale); void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 32483727..c39b4f7e 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -84,7 +84,9 @@ bool operator!=(const lcModelHistoryState& a, const lcModelHistoryState& b); enum class lcModelActionEditMerge { None, + KeyboardMove, KeyboardRotate, + PropertiesMove, PropertiesRotate }; diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index cc28ed2c..4eab31ed 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -321,7 +321,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = Position - Center; - Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove); } else if (PropertyId == lcObjectPropertyId::ObjectRotationX || PropertyId == lcObjectPropertyId::ObjectRotationY || PropertyId == lcObjectPropertyId::ObjectRotationZ) { @@ -381,7 +381,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = End - Start; - Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove); if (Camera) { @@ -418,7 +418,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = End - Start; - Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove); if (Camera) { @@ -455,7 +455,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V lcVector3 Distance = End - Start; - Model->MoveSelectedObjects(Distance, false, false, !Dragging, true); + Model->MoveSelectedObjects(Distance, false, false, true, true, lcModelActionEditMerge::PropertiesMove); if (Camera) { From e1dab3286e863598bcc8779d609df3d9c7bd52cd Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 7 Mar 2026 14:03:59 -0800 Subject: [PATCH 82/93] Added undo when using the properties widget. --- common/lc_model.cpp | 19 ++++++------------- common/lc_model.h | 2 +- common/lc_modelaction.h | 3 ++- common/lc_propertieswidget.cpp | 32 ++++++++++++-------------------- common/lc_propertieswidget.h | 2 +- 5 files changed, 22 insertions(+), 36 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index d67908aa..25e002d5 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3876,16 +3876,13 @@ void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraPro gMainWindow->UpdateSelectedObjects(false); } -void lcModel::SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value, bool AddUndo) +void lcModel::SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value) { + BeginActionSequence(); + BeginObjectEditAction(static_cast(static_cast(lcModelActionEditMerge::PropertiesEdit) | static_cast(PropertyId))); + bool Modified = false; - if (AddUndo) - { - BeginActionSequence(); - BeginObjectEditAction(lcModelActionEditMerge::None); - } - for (lcObject* Object : Objects) { bool ObjectModified = Object->SetPropertyValue(PropertyId, mCurrentStep, gMainWindow->GetAddKeys(), Value); @@ -3904,14 +3901,10 @@ void lcModel::SetObjectsProperty(const std::vector& Objects, lcObject return; } - if (AddUndo) - { - EndObjectEditAction(); - EndActionSequence(lcObject::GetCheckpointString(PropertyId)); - } + EndObjectEditAction(); + EndActionSequence(lcObject::GetCheckpointString(PropertyId)); gMainWindow->UpdateSelectedObjects(false); - UpdateAllViews(); // todo: fix hacky timeline update if (PropertyId == lcObjectPropertyId::PieceId || PropertyId == lcObjectPropertyId::PieceColor) diff --git a/common/lc_model.h b/common/lc_model.h index ea8ebb15..151a9f61 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -379,7 +379,7 @@ public: void SetSelectedPiecesStepShow(lcStep Step); void SetSelectedPiecesStepHide(lcStep Step); - void SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value, bool AddUndo); + void SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value); void EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept); void SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraProjection); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index c39b4f7e..9cf10ca8 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -87,7 +87,8 @@ enum class lcModelActionEditMerge KeyboardMove, KeyboardRotate, PropertiesMove, - PropertiesRotate + PropertiesRotate, + PropertiesEdit = 0x40000000 }; class lcModelActionObjectEdit: public lcModelAction diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index 4eab31ed..558ee4ea 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -204,7 +204,7 @@ void lcPropertiesWidget::BoolChanged() return; const bool Value = Widget->isChecked(); - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value, true); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value); } void lcPropertiesWidget::UpdateBool(lcObjectPropertyId PropertyId) @@ -286,10 +286,10 @@ void lcPropertiesWidget::FloatChanged(double Value) lcDoubleSpinBox* Widget = qobject_cast(sender()); lcObjectPropertyId PropertyId = GetEditorWidgetPropertyId(Widget); - ChangeFloatValue(PropertyId, Value, true); + ChangeFloatValue(PropertyId, Value); } -void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float Value, bool Dragging) +void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float Value) { if (PropertyId == lcObjectPropertyId::Count) return; @@ -347,12 +347,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V mLastRotation = Rotation; } - else if (Piece || Light) - { - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value, !Dragging); - } - - if (PropertyId == lcObjectPropertyId::CameraPositionX || PropertyId == lcObjectPropertyId::CameraPositionY || PropertyId == lcObjectPropertyId::CameraPositionZ) + else if (PropertyId == lcObjectPropertyId::CameraPositionX || PropertyId == lcObjectPropertyId::CameraPositionY || PropertyId == lcObjectPropertyId::CameraPositionZ) { quint32 FocusSection = LC_CAMERA_SECTION_INVALID; lcVector3 Start; @@ -463,12 +458,9 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V Camera->SetFocused(FocusSection, true); } } - else if (Camera) + else { - if (PropertyId == lcObjectPropertyId::CameraFOV || PropertyId == lcObjectPropertyId::CameraNear || PropertyId == lcObjectPropertyId::CameraFar) - { - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value, !Dragging); - } + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value); } mDisableUpdates = false; @@ -608,7 +600,7 @@ void lcPropertiesWidget::IntegerChanged() return; const int Value = LineEdit->text().toInt(); - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value, true); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value); } void lcPropertiesWidget::UpdateInteger(lcObjectPropertyId PropertyId) @@ -741,7 +733,7 @@ void lcPropertiesWidget::StringChanged() return; QString Value = LineEdit->text(); - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value, true); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value); } void lcPropertiesWidget::UpdateString(lcObjectPropertyId PropertyId) @@ -805,7 +797,7 @@ void lcPropertiesWidget::StringListChanged(int Value) if (!Model) return; - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value, true); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, Value); } void lcPropertiesWidget::UpdateStringList(lcObjectPropertyId PropertyId) @@ -907,7 +899,7 @@ void lcPropertiesWidget::ColorChanged(QColor Color) return; const lcVector3 FloatColor = lcVector3FromQColor(Color); - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue(FloatColor), true); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue(FloatColor)); } void lcPropertiesWidget::UpdateColor(lcObjectPropertyId PropertyId) @@ -973,7 +965,7 @@ void lcPropertiesWidget::PieceColorChanged(int ColorIndex) if (!Model) return; - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, ColorIndex, true); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, ColorIndex); } void lcPropertiesWidget::PieceColorButtonClicked() @@ -1104,7 +1096,7 @@ void lcPropertiesWidget::PieceIdButtonClicked() if (!Model || !Info) return; - Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue(Info), true); + Model->SetObjectsProperty(mFocusObject ? std::vector{ mFocusObject } : mSelection, PropertyId, QVariant::fromValue(Info)); } } diff --git a/common/lc_propertieswidget.h b/common/lc_propertieswidget.h index 82ca61fe..2c24447e 100644 --- a/common/lc_propertieswidget.h +++ b/common/lc_propertieswidget.h @@ -115,7 +115,7 @@ protected: void UpdatePieceColor(lcObjectPropertyId PropertyId); void UpdatePieceId(lcObjectPropertyId PropertyId); - void ChangeFloatValue(lcObjectPropertyId PropertyId, float Value, bool Dragging); + void ChangeFloatValue(lcObjectPropertyId PropertyId, float Value); void SetEmpty(); void SetPiece(const std::vector& Selection, lcObject* Focus); From f12794e9e0790e7870b9ca1ee4b01147299b260a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 7 Mar 2026 16:11:38 -0800 Subject: [PATCH 83/93] Fixed ui scale on retina displays. --- common/lc_view.cpp | 25 ++++++++++++++++--------- common/lc_viewmanipulator.cpp | 2 +- common/lc_viewsphere.cpp | 8 +++++--- common/lc_viewwidget.cpp | 7 ++----- common/texfont.cpp | 6 +++--- common/texfont.h | 2 +- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/common/lc_view.cpp b/common/lc_view.cpp index aa8ef01a..3972d83b 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -1150,9 +1150,13 @@ void lcView::DrawBackground(int CurrentTileRow, int TotalTileRows, int CurrentTi void lcView::DrawViewport() const { + float Scale = GetUIScale(); + float Width = mWidth / Scale; + float Height = mHeight / Scale; + mContext->SetWorldMatrix(lcMatrix44Identity()); mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0))); - mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f)); + mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, Width, 0.0f, Height, -1.0f, 1.0f)); mContext->SetLineWidth(1.0f); mContext->SetDepthWrite(false); @@ -1165,7 +1169,7 @@ void lcView::DrawViewport() const else mContext->SetColor(lcVector4FromColor(lcGetPreferences().mInactiveViewColor)); - float Verts[8] = { 0.0f, 0.0f, mWidth - 1.0f, 0.0f, mWidth - 1.0f, mHeight - 1.0f, 0.0f, mHeight - 1.0f }; + float Verts[8] = { 0.0f, 0.0f, Width - 1.0f, 0.0f, Width - 1.0f, Height - 1.0f, 0.0f, Height - 1.0f }; mContext->SetVertexBufferPointer(Verts); mContext->SetVertexFormatPosition(2); @@ -1181,7 +1185,7 @@ void lcView::DrawViewport() const mContext->EnableColorBlend(true); - gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, GetUIScale(), CameraName.toLatin1().constData()); + gTexFont.PrintText(mContext, 3.0f, (float)Height - 1.0f - 6.0f, 0.0f, CameraName.toLatin1().constData()); mContext->EnableColorBlend(false); } @@ -1243,26 +1247,28 @@ void lcView::DrawAxes() const }; lcMatrix44 TranslationMatrix; + float Scale = GetUIScale(); switch (Preferences.mAxisIconLocation) { default: case lcAxisIconLocation::BottomLeft: - TranslationMatrix = lcMatrix44Translation(lcVector3(32, 32, 0.0f)); + TranslationMatrix = lcMatrix44Translation(lcVector3(32, 32, 0.0f) / Scale); break; case lcAxisIconLocation::BottomRight: - TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, 32, 0.0f)); + TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, 32, 0.0f) / Scale); break; case lcAxisIconLocation::TopLeft: - TranslationMatrix = lcMatrix44Translation(lcVector3(32, mHeight - 36, 0.0f)); + TranslationMatrix = lcMatrix44Translation(lcVector3(32, mHeight - 36, 0.0f) / Scale); break; case lcAxisIconLocation::TopRight: - TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, mHeight - 36, 0.0f)); + TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, mHeight - 36, 0.0f) / Scale); break; } + lcMatrix44 WorldViewMatrix = mCamera->mWorldView; WorldViewMatrix.SetTranslation(lcVector3(0, 0, 0)); @@ -1270,7 +1276,7 @@ void lcView::DrawAxes() const mContext->SetMaterial(lcMaterialType::UnlitVertexColor); mContext->SetWorldMatrix(lcMatrix44Identity()); mContext->SetViewMatrix(lcMul(WorldViewMatrix, TranslationMatrix)); - mContext->SetProjectionMatrix(lcMatrix44Ortho(0, mWidth, 0, mHeight, -50, 50)); + mContext->SetProjectionMatrix(lcMatrix44Ortho(0, mWidth / Scale, 0, mHeight / Scale, -50, 50)); mContext->SetVertexBufferPointer(Verts); mContext->SetVertexFormat(0, 3, 0, 0, 4, false); @@ -1720,7 +1726,8 @@ float lcView::GetOverlayScale() const lcVector3 Point = UnprojectPoint(ScreenPos); lcVector3 Dist(Point - WorldMatrix.GetTranslation()); - return Dist.Length() * 5.0f; + + return Dist.Length() * 5.0f * GetUIScale(); } void lcView::BeginDrag(lcDragState DragState) diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index 6b5f83f3..2a154162 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -896,7 +896,7 @@ void lcViewManipulator::DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackT gTexFont.GetStringDimensions(&cx, &cy, buf); Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f); - gTexFont.PrintText(Context, ScreenPos[0] - (cx / 2), ScreenPos[1] + (cy / 2), 0.0f, mView->GetUIScale(), buf); + gTexFont.PrintText(Context, ScreenPos[0] - (cx / 2), ScreenPos[1] + (cy / 2), 0.0f, buf); Context->EnableColorBlend(false); } diff --git a/common/lc_viewsphere.cpp b/common/lc_viewsphere.cpp index fd83801c..dcfc941a 100644 --- a/common/lc_viewsphere.cpp +++ b/common/lc_viewsphere.cpp @@ -183,9 +183,10 @@ void lcViewSphere::Draw() return; lcContext* Context = mView->mContext; + const float UIScale = mView->GetUIScale(); const int Width = mView->GetWidth(); const int Height = mView->GetHeight(); - const int ViewportSize = mSize; + const int ViewportSize = mSize * UIScale; const int Left = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize; const int Bottom = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize; Context->SetViewport(Left, Bottom, ViewportSize, ViewportSize); @@ -240,7 +241,7 @@ void lcViewSphere::Draw() Context->EnableCullFace(false); Context->SetDepthFunction(lcDepthFunction::LessEqual); - Context->SetViewport(0, 0, Width, Height); + Context->SetViewport(0, 0, mView->GetWidth(), mView->GetHeight()); } bool lcViewSphere::OnLeftButtonDown() @@ -323,9 +324,10 @@ bool lcViewSphere::IsDragging() const std::bitset<6> lcViewSphere::GetIntersectionFlags(lcVector3& Intersection) const { + const float UIScale = mView->GetUIScale(); const int Width = mView->GetWidth(); const int Height = mView->GetHeight(); - const int ViewportSize = mSize; + const int ViewportSize = mSize * UIScale; const int Left = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize; const int Bottom = (mLocation == lcViewSphereLocation::BottomLeft || mLocation == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize; const int x = mView->GetMouseX() - Left; diff --git a/common/lc_viewwidget.cpp b/common/lc_viewwidget.cpp index 6f92a937..e3bc292d 100644 --- a/common/lc_viewwidget.cpp +++ b/common/lc_viewwidget.cpp @@ -77,11 +77,8 @@ void lcViewWidget::initializeGL() void lcViewWidget::resizeGL(int Width, int Height) { -#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) - const float Scale = devicePixelRatioF(); -#else - const int Scale = devicePixelRatio(); -#endif + const float Scale = GetDeviceScale(); + mView->SetSize(Width * Scale, Height * Scale); } diff --git a/common/texfont.cpp b/common/texfont.cpp index 97d740fd..01bbe9d7 100644 --- a/common/texfont.cpp +++ b/common/texfont.cpp @@ -162,7 +162,7 @@ void TexFont::GetStringDimensions(int* cx, int* cy, const char* Text) const } } -void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, float Scale, const char* Text) const +void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, const char* Text) const { const size_t Length = strlen(Text); @@ -175,8 +175,8 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, floa while (*Text) { int ch = *Text; - float Right = Left + mGlyphs[ch].width * Scale; - float Bottom = Top - mFontHeight * Scale; + float Right = Left + mGlyphs[ch].width; + float Bottom = Top - mFontHeight; *CurVert++ = Left; *CurVert++ = Top; diff --git a/common/texfont.h b/common/texfont.h index 297d034f..9dddf466 100644 --- a/common/texfont.h +++ b/common/texfont.h @@ -18,7 +18,7 @@ public: bool Initialize(lcContext* Context); void Reset(); - void PrintText(lcContext* Context, float Left, float Top, float Z, float Scale, const char* Text) const; + void PrintText(lcContext* Context, float Left, float Top, float Z, const char* Text) const; void GetTriangles(const lcMatrix44& Transform, const char* Text, float* Buffer) const; void GetGlyphTriangles(float Left, float Top, float Z, int Glyph, float* Buffer) const; void GetStringDimensions(int* cx, int* cy, const char* Text) const; From bc9bc3a1b29ca96a1d61af05366aed0a57104775 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 7 Mar 2026 18:01:11 -0800 Subject: [PATCH 84/93] Removed unused code. --- common/camera.cpp | 13 ------------- common/camera.h | 2 -- common/light.cpp | 23 ----------------------- common/light.h | 2 -- common/piece.cpp | 22 ---------------------- common/piece.h | 2 -- 6 files changed, 64 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index 2b0cce5c..ec60c24d 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -55,19 +55,6 @@ lcCamera::~lcCamera() { } -void lcCamera::CopyProperties(const lcCamera& Other) -{ - m_fovy = Other.m_fovy; - m_zNear = Other.m_zNear; - m_zFar = Other.m_zFar; - - mPosition = Other.mPosition; - mTargetPosition = Other.mTargetPosition; - mUpVector = Other.mUpVector; - - mProjection = Other.mProjection; -} - QString lcCamera::GetCameraProjectionString(lcCameraProjection CameraProjection) { switch (CameraProjection) diff --git a/common/camera.h b/common/camera.h index f19b6435..c2101781 100644 --- a/common/camera.h +++ b/common/camera.h @@ -69,8 +69,6 @@ public: static QStringList GetCameraProjectionStrings(); static lcViewpoint GetViewpoint(const QString& ViewpointName); - void CopyProperties(const lcCamera& Other); - QString GetName() const override { return mName; diff --git a/common/light.cpp b/common/light.cpp index 498e9442..7ab89c79 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -35,29 +35,6 @@ lcLight::lcLight(const lcVector3& Position, lcLightType LightType) lcLight::UpdatePosition(1); } -void lcLight::CopyProperties(const lcLight& Other) -{ - mLightType = Other.mLightType; - mCastShadow = Other.mCastShadow; - mPosition = Other.mPosition; - mRotation = Other.mRotation; - mColor = Other.mColor; - mBlenderPower = Other.mBlenderPower; - mBlenderRadius = Other.mBlenderRadius; - mBlenderAngle = Other.mBlenderAngle; - mPOVRayPower = Other.mPOVRayPower; - mPOVRayFadeDistance = Other.mPOVRayFadeDistance; - mPOVRayFadePower = Other.mPOVRayFadePower; - mSpotConeAngle = Other.mSpotConeAngle; - mSpotPenumbraAngle = Other.mSpotPenumbraAngle; - mPOVRaySpotTightness = Other.mPOVRaySpotTightness; - mAreaShape = Other.mAreaShape; - mAreaSizeX = Other.mAreaSizeX; - mAreaSizeY = Other.mAreaSizeY; - mPOVRayAreaGridX = Other.mPOVRayAreaGridX; - mPOVRayAreaGridY = Other.mPOVRayAreaGridY; -} - QString lcLight::GetLightTypeString(lcLightType LightType) { switch (LightType) diff --git a/common/light.h b/common/light.h index 3344e31f..7b0cd8fa 100644 --- a/common/light.h +++ b/common/light.h @@ -82,8 +82,6 @@ public: static QString GetAreaShapeString(lcLightAreaShape LightAreaShape); static QStringList GetAreaShapeStrings(); - void CopyProperties(const lcLight& Other); - bool IsPointLight() const { return mLightType == lcLightType::Point; diff --git a/common/piece.cpp b/common/piece.cpp index 19534c7c..36d6e5cb 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -67,28 +67,6 @@ lcPiece::~lcPiece() delete mMesh; } -void lcPiece::CopyProperties(const lcPiece& Other) -{ - SetPieceInfo(Other.mPieceInfo, Other.mID, true, false); - - mPosition = Other.mPosition; - mRotation = Other.mRotation; - - mColorIndex = Other.mColorIndex; - mColorCode = Other.mColorCode; - - mStepShow = Other.mStepShow; - mStepHide = Other.mStepHide; - - mPivotPointValid = Other.mPivotPointValid; - mPivotMatrix = Other.mPivotMatrix; - - mControlPoints = Other.mControlPoints; - mTrainTrackConnections = Other.mTrainTrackConnections; - - UpdateMesh(); -} - void lcPiece::SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait, bool UpdateSynthInfo) { lcPiecesLibrary* Library = lcGetPiecesLibrary(); diff --git a/common/piece.h b/common/piece.h index db4f2d30..934fe9d4 100644 --- a/common/piece.h +++ b/common/piece.h @@ -67,8 +67,6 @@ public: lcPiece& operator=(const lcPiece&) = delete; lcPiece& operator=(lcPiece&&) = delete; - void CopyProperties(const lcPiece& Other); - quint32 GetAllowedTransforms() const override; lcVector3 GetSectionPosition(quint32 Section) const override; From ce05e20b39faece4b29b28c802de64f3619c3354 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sat, 7 Mar 2026 18:38:35 -0800 Subject: [PATCH 85/93] Fixed empty undo action added when canceling a property widget edit. --- common/lc_model.cpp | 23 +++++++++++++++++++++++ common/lc_model.h | 1 + common/lc_modelaction.h | 11 +++++------ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 25e002d5..f9437642 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2020,6 +2020,21 @@ void lcModel::SetSaved() mSavedHistory = GetFirstUndoChange(); } +void lcModel::RemoveFirstUndoIfUnchanged() +{ + if (mUndoHistory.empty()) + return; + + for (const std::unique_ptr& ModelAction : mUndoHistory.front()->ModelActions) + if (ModelAction->StateChanged()) + return; + + mUndoHistory.erase(mUndoHistory.begin()); + + gMainWindow->UpdateModified(IsModified()); + gMainWindow->UpdateUndoRedo(!mUndoHistory.empty() ? mUndoHistory.front()->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory.front()->Description : nullptr); +} + const lcModelHistoryEntry* lcModel::GetFirstUndoChange() const { for (const std::unique_ptr& UndoEntry : mUndoHistory) @@ -3492,6 +3507,8 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector { EndObjectEditAction(); EndActionSequence(tr("Move")); + + RemoveFirstUndoIfUnchanged(); } UpdateAllViews(); @@ -3676,6 +3693,8 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool { EndObjectEditAction(); EndActionSequence(tr("Rotate")); + + RemoveFirstUndoIfUnchanged(); } UpdateAllViews(); @@ -3904,6 +3923,8 @@ void lcModel::SetObjectsProperty(const std::vector& Objects, lcObject EndObjectEditAction(); EndActionSequence(lcObject::GetCheckpointString(PropertyId)); + RemoveFirstUndoIfUnchanged(); + gMainWindow->UpdateSelectedObjects(false); // todo: fix hacky timeline update @@ -3921,6 +3942,8 @@ void lcModel::SetObjectsProperty(const std::vector& Objects, lcObject void lcModel::EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept) { + // todo: right clicking or pressing esc while dragging the spinbox doesn't cancel + if (!Accept) { RevertActionSequence(); diff --git a/common/lc_model.h b/common/lc_model.h index 151a9f61..03773979 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -410,6 +410,7 @@ protected: void EndActionSequence(const QString& Description); void DiscardActionSequence(); void RevertActionSequence(); + void RemoveFirstUndoIfUnchanged(); const lcModelHistoryEntry* GetFirstUndoChange() const; void SaveCheckpoint(const QString& Description); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 9cf10ca8..3c4eb54d 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -15,6 +15,7 @@ public: virtual void SaveEndState(const lcModel* Model) = 0; virtual void LoadStartState(lcModel* Model) const = 0; virtual void LoadEndState(lcModel* Model) const = 0; + virtual bool StateChanged() const = 0; virtual bool CanMergeWith(const lcModelAction* Other) const { @@ -55,8 +56,7 @@ public: void SaveEndState(const lcModel* Model) override; void LoadStartState(lcModel* Model) const override; void LoadEndState(lcModel* Model) const override; - - bool StateChanged() const; + bool StateChanged() const override; protected: static void SaveState(lcModelActionSelectionState& State, const lcModel* Model); @@ -101,8 +101,8 @@ public: void SaveEndState(const lcModel* Model) override; void LoadStartState(lcModel* Model) const override; void LoadEndState(lcModel* Model) const override; - - bool StateChanged() const; + bool StateChanged() const override; + bool CanMergeWith(const lcModelAction* Other) const override; void MergeWith(lcModelAction* Other) override; @@ -125,8 +125,7 @@ public: void SaveEndState(const lcModel* Model) override; void LoadStartState(lcModel* Model) const override; void LoadEndState(lcModel* Model) const override; - - bool StateChanged() const; + bool StateChanged() const override; protected: static void SaveState(lcModelProperties& State, const lcModel* Model); From 151359d476b26cba143f93b0353a5d7af1f6e428 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 8 Mar 2026 15:37:37 -0700 Subject: [PATCH 86/93] Removed remaining SaveCheckpoint calls. --- common/lc_model.cpp | 150 ++++++++++++---------------------------- common/lc_model.h | 1 - common/lc_modelaction.h | 2 + 3 files changed, 48 insertions(+), 105 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index f9437642..2d4dcf6f 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1950,6 +1950,13 @@ void lcModel::EndActionSequence(const QString& Description) if (mActionSequence.empty()) return; + if (mIsPreview) + { + mActionSequence.clear(); + + return; + } + bool CanMerge = false; if (mActionSequence.size() == 1 && !mUndoHistory.empty() && mUndoHistory.front()->ModelActions.size() == 1) @@ -2044,29 +2051,6 @@ const lcModelHistoryEntry* lcModel::GetFirstUndoChange() const return nullptr; } -void lcModel::SaveCheckpoint(const QString& ) -{ - /* - lcModelHistoryEntry* ModelHistoryEntry = new lcModelHistoryEntry(); - - ModelHistoryEntry->Description = Description; - - QTextStream Stream(&ModelHistoryEntry->File); - SaveLDraw(Stream, false, 0); - - mUndoHistory.insert(mUndoHistory.begin(), ModelHistoryEntry); - for (lcModelHistoryEntry* Entry : mRedoHistory) - delete Entry; - mRedoHistory.clear(); - - if (!Description.isEmpty()) - { - gMainWindow->UpdateModified(IsModified()); - gMainWindow->UpdateUndoRedo(mUndoHistory.size() > 1 ? mUndoHistory[0]->Description : QString(), !mRedoHistory.empty() ? mRedoHistory[0]->Description : QString()); - } - */ -} - void lcModel::LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply) { if (!CheckPoint->ModelActions.empty()) @@ -3236,7 +3220,10 @@ void lcModel::MoveSelectionToModel(lcModel* Model) { if (!Model) return; - + + BeginActionSequence(); + BeginObjectEditAction(lcModelActionEditMerge::None); + std::vector Pieces; lcPiece* ModelPiece = nullptr; lcStep FirstStep = LC_STEP_MAX; @@ -3266,7 +3253,14 @@ void lcModel::MoveSelectionToModel(lcModel* Model) else PieceIndex++; } + + if (Pieces.empty()) + { + DiscardActionSequence(); + return; + } + lcVector3 ModelCenter = (Min + Max) / 2.0f; ModelCenter.z += (Min.z - Max.z) / 2.0f; @@ -3285,11 +3279,14 @@ void lcModel::MoveSelectionToModel(lcModel* Model) ModelPiece->Initialize(lcMatrix44Translation(ModelCenter), FirstStep); ModelPiece->UpdatePosition(mCurrentStep); } - - SaveCheckpoint(tr("New Model")); + + EndObjectEditAction(); + gMainWindow->UpdateTimeline(false, false); RecordSetSelectionAndFocusAction(std::vector(), ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); + + EndActionSequence(tr("Move to Model")); } void lcModel::InlineSelectedModels() @@ -3943,86 +3940,13 @@ void lcModel::SetObjectsProperty(const std::vector& Objects, lcObject void lcModel::EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept) { // todo: right clicking or pressing esc while dragging the spinbox doesn't cancel + // we need to handle the shortcut override and undo the last undo history if it matches the property if (!Accept) { RevertActionSequence(); return; } - - switch (PropertyId) - { - case lcObjectPropertyId::PieceId: - case lcObjectPropertyId::PieceColor: - case lcObjectPropertyId::PieceStepShow: - case lcObjectPropertyId::PieceStepHide: - case lcObjectPropertyId::CameraName: - case lcObjectPropertyId::CameraProjection: - break; - - case lcObjectPropertyId::CameraFOV: - case lcObjectPropertyId::CameraNear: - case lcObjectPropertyId::CameraFar: - SaveCheckpoint(lcObject::GetCheckpointString(PropertyId)); - break; - - case lcObjectPropertyId::CameraPositionX: - case lcObjectPropertyId::CameraPositionY: - case lcObjectPropertyId::CameraPositionZ: - case lcObjectPropertyId::CameraTargetX: - case lcObjectPropertyId::CameraTargetY: - case lcObjectPropertyId::CameraTargetZ: - case lcObjectPropertyId::CameraUpX: - case lcObjectPropertyId::CameraUpY: - case lcObjectPropertyId::CameraUpZ: - SaveCheckpoint(tr("Move")); - break; - - case lcObjectPropertyId::LightName: - case lcObjectPropertyId::LightType: - case lcObjectPropertyId::LightColor: - break; - - case lcObjectPropertyId::LightBlenderPower: - case lcObjectPropertyId::LightPOVRayPower: - SaveCheckpoint(lcObject::GetCheckpointString(PropertyId)); - break; - - case lcObjectPropertyId::LightCastShadow: - break; - - case lcObjectPropertyId::LightPOVRayFadeDistance: - case lcObjectPropertyId::LightPOVRayFadePower: - case lcObjectPropertyId::LightBlenderRadius: - case lcObjectPropertyId::LightBlenderAngle: - case lcObjectPropertyId::LightAreaSizeX: - case lcObjectPropertyId::LightAreaSizeY: - case lcObjectPropertyId::LightSpotConeAngle: - case lcObjectPropertyId::LightSpotPenumbraAngle: - case lcObjectPropertyId::LightPOVRaySpotTightness: - SaveCheckpoint(lcObject::GetCheckpointString(PropertyId)); - break; - - case lcObjectPropertyId::LightAreaShape: - case lcObjectPropertyId::LightPOVRayAreaGridX: - case lcObjectPropertyId::LightPOVRayAreaGridY: - break; - - case lcObjectPropertyId::ObjectPositionX: - case lcObjectPropertyId::ObjectPositionY: - case lcObjectPropertyId::ObjectPositionZ: - SaveCheckpoint(tr("Move")); - break; - - case lcObjectPropertyId::ObjectRotationX: - case lcObjectPropertyId::ObjectRotationY: - case lcObjectPropertyId::ObjectRotationZ: - SaveCheckpoint(tr("Rotate")); - break; - - case lcObjectPropertyId::Count: - break; - } } bool lcModel::AnyPiecesSelected() const @@ -5428,12 +5352,22 @@ void lcModel::LookAt(lcCamera* Camera) void lcModel::MoveCamera(lcCamera* Camera, const lcVector3& Direction) { + if (!Camera->IsSimple()) + { + BeginActionSequence(); + BeginObjectEditAction(lcModelActionEditMerge::KeyboardMoveCamera); + } + Camera->MoveRelative(Direction, mCurrentStep, gMainWindow->GetAddKeys()); + gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); if (!Camera->IsSimple()) - SaveCheckpoint(tr("Moving Camera")); + { + EndObjectEditAction(); + EndActionSequence(tr("Move")); + } } void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& WorldMatrix) @@ -5477,14 +5411,24 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl void lcModel::Zoom(lcCamera* Camera, float Amount) { + if (!Camera->IsSimple()) + { + BeginActionSequence(); + BeginObjectEditAction(lcModelActionEditMerge::KeyboardZoom); + } + Camera->Zoom(Amount, mCurrentStep, gMainWindow->GetAddKeys()); if (!mIsPreview) gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); if (!Camera->IsSimple()) - SaveCheckpoint(tr("Zoom")); + { + EndObjectEditAction(); + EndActionSequence(tr("Zoom")); + } } void lcModel::ShowPropertiesDialog() @@ -5684,8 +5628,6 @@ void lcModel::SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex) mCurrentStep = LC_STEP_MAX; CalculateStep(LC_STEP_MAX); - - SaveCheckpoint(QString()); } void lcModel::UpdateInterface() diff --git a/common/lc_model.h b/common/lc_model.h index 03773979..9a9948ee 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -413,7 +413,6 @@ protected: void RemoveFirstUndoIfUnchanged(); const lcModelHistoryEntry* GetFirstUndoChange() const; - void SaveCheckpoint(const QString& Description); void LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply); QString GetGroupName(const QString& Prefix); diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 3c4eb54d..1d3624bd 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -86,6 +86,8 @@ enum class lcModelActionEditMerge None, KeyboardMove, KeyboardRotate, + KeyboardZoom, + KeyboardMoveCamera, PropertiesMove, PropertiesRotate, PropertiesEdit = 0x40000000 From 62e5bb48676d0457383cd8e7a4ced0fefb9a2a38 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 8 Mar 2026 15:48:09 -0700 Subject: [PATCH 87/93] Removed LoadCheckpoint. --- common/lc_model.cpp | 68 ++++----------------------------------------- common/lc_model.h | 3 -- 2 files changed, 6 insertions(+), 65 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 2d4dcf6f..c99b6452 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1935,9 +1935,11 @@ void lcModel::RunActionSequence(const std::vector if (SelectionChanged) gMainWindow->UpdateSelectedObjects(true); - - UpdateAllViews(); + + gMainWindow->UpdateCurrentStep(); gMainWindow->UpdateTimeline(true, false); + + UpdateAllViews(); } void lcModel::BeginActionSequence() @@ -2051,64 +2053,6 @@ const lcModelHistoryEntry* lcModel::GetFirstUndoChange() const return nullptr; } -void lcModel::LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply) -{ - if (!CheckPoint->ModelActions.empty()) - { - RunActionSequence(CheckPoint->ModelActions, Apply); - - return; - } - - lcPiecesLibrary* Library = lcGetPiecesLibrary(); - std::vector LoadedInfos; - - for (const std::unique_ptr& Piece : mPieces) - { - PieceInfo* Info = Piece->mPieceInfo; - Library->LoadPieceInfo(Info, true, true); - LoadedInfos.push_back(Info); - } - - // Remember the current step - const lcStep CurrentStep = mCurrentStep; - - // Remember the camera names - std::vector Views = lcView::GetModelViews(this); - std::vector CameraNames(Views.size()); - - for (size_t ViewIndex = 0; ViewIndex < Views.size(); ViewIndex++) - { - lcCamera* Camera = Views[ViewIndex]->GetCamera(); - - if (!Camera->IsSimple()) - CameraNames[ViewIndex] = Camera->GetName(); - } - - DeleteModel(); - - QBuffer Buffer(&CheckPoint->File); - Buffer.open(QIODevice::ReadOnly); - LoadLDraw(Buffer, lcGetActiveProject()); - - // Reset the current step - mCurrentStep = CurrentStep; - CalculateStep(CurrentStep); - - // Reset the cameras - for (size_t ViewIndex = 0; ViewIndex < Views.size() && ViewIndex < CameraNames.size(); ViewIndex++) - if (!CameraNames[ViewIndex].isEmpty()) - Views[ViewIndex]->SetCamera(CameraNames[ViewIndex]); - - gMainWindow->UpdateTimeline(true, false); - gMainWindow->UpdateCurrentStep(); - gMainWindow->UpdateSelectedObjects(true); - UpdateAllViews(); - - for (PieceInfo* Info : LoadedInfos) - Library->ReleasePieceInfo(Info); -} - void lcModel::SetActive(bool Active) { CalculateStep(Active ? mCurrentStep : LC_STEP_MAX); @@ -4827,7 +4771,7 @@ void lcModel::UndoAction() std::unique_ptr Undo = std::move(mUndoHistory.front()); - LoadCheckPoint(Undo.get(), false); + RunActionSequence(Undo->ModelActions, false); mUndoHistory.erase(mUndoHistory.begin()); mRedoHistory.insert(mRedoHistory.begin(), std::move(Undo)); @@ -4843,7 +4787,7 @@ void lcModel::RedoAction() std::unique_ptr Redo = std::move(mRedoHistory.front()); - LoadCheckPoint(Redo.get(), true); + RunActionSequence(Redo->ModelActions, true); mRedoHistory.erase(mRedoHistory.begin()); mUndoHistory.insert(mUndoHistory.begin(), std::move(Redo)); diff --git a/common/lc_model.h b/common/lc_model.h index 9a9948ee..6de134d1 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -112,7 +112,6 @@ public: struct lcModelHistoryEntry { std::vector> ModelActions; - QByteArray File; QString Description; }; @@ -413,8 +412,6 @@ protected: void RemoveFirstUndoIfUnchanged(); const lcModelHistoryEntry* GetFirstUndoChange() const; - void LoadCheckPoint(lcModelHistoryEntry* CheckPoint, bool Apply); - QString GetGroupName(const QString& Prefix); void RemoveEmptyGroups(); bool RemoveSelectedObjects(); From da29df623bec220de46268ea31f1b54a504b86ae Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 8 Mar 2026 17:32:23 -0700 Subject: [PATCH 88/93] Fixed race condition where the main thread can upload a texture while it's being loaded. Fixes #1011. --- common/lc_texture.cpp | 14 +++++++++++--- common/lc_texture.h | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/common/lc_texture.cpp b/common/lc_texture.cpp index 819e53e5..1dbd01e2 100644 --- a/common/lc_texture.cpp +++ b/common/lc_texture.cpp @@ -176,9 +176,13 @@ bool lcTexture::Load(const QString& FileName, int Flags) if (!Image.FileLoad(FileName)) return false; - + + mLoading = true; + SetImage(std::move(Image), Flags); + mLoading = false; + return true; } @@ -188,9 +192,13 @@ bool lcTexture::Load(lcMemFile& File, int Flags) if (!Image.FileLoad(File)) return false; - + + mLoading = true; + SetImage(std::move(Image), Flags); - + + mLoading = false; + return true; } diff --git a/common/lc_texture.h b/common/lc_texture.h index 74dbb3ac..4a5e4201 100644 --- a/common/lc_texture.h +++ b/common/lc_texture.h @@ -67,7 +67,7 @@ public: bool NeedsUpload() const { - return mTexture == 0 && !mImages.empty(); + return !mLoading && mTexture == 0 && !mImages.empty(); } int GetFlags() const @@ -99,6 +99,7 @@ protected: QAtomicInt mRefCount; std::vector mImages; int mFlags; + bool mLoading = false; }; lcTexture* lcLoadTexture(const QString& FileName, int Flags); From 4de2c822af9cceb2bf310582d04b1d4801214d20 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 9 Mar 2026 22:19:16 -0700 Subject: [PATCH 89/93] Fixed textures in subparts not working. Fixes #1011. --- common/lc_meshloader.cpp | 20 +++++++++++++++----- common/lc_meshloader.h | 30 +++++++++--------------------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/common/lc_meshloader.cpp b/common/lc_meshloader.cpp index d4b53ca3..34fc6597 100644 --- a/common/lc_meshloader.cpp +++ b/common/lc_meshloader.cpp @@ -369,11 +369,16 @@ void lcMeshLoaderTypeData::AddMeshData(const lcMeshLoaderTypeData& Data, const l if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid) { - lcMeshLoaderTextureMap DstTextureMap = *TextureMap; - + lcMeshLoaderTextureParams DstTextureMap; + + if (TextureMap) + DstTextureMap = *TextureMap; + else + DstTextureMap = *SrcSection->mMaterial; + for (lcVector3& Point : DstTextureMap.Points) Point = lcMul31(Point, Transform); - + DstSection = AddSection(PrimitiveType, mMeshData->GetTexturedMaterial(ColorCode, DstTextureMap)); } else if (TextureMap && SrcSection->mPrimitiveType == LC_MESH_TRIANGLES) @@ -452,7 +457,12 @@ void lcMeshLoaderTypeData::AddMeshDataNoDuplicateCheck(const lcMeshLoaderTypeDat if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid) { - lcMeshLoaderTextureMap DstTextureMap = *TextureMap; + lcMeshLoaderTextureParams DstTextureMap; + + if (TextureMap) + DstTextureMap = *TextureMap; + else + DstTextureMap = *SrcSection->mMaterial; for (lcVector3& Point : DstTextureMap.Points) Point = lcMul31(Point, Transform); @@ -553,7 +563,7 @@ lcMeshLoaderMaterial* lcLibraryMeshData::GetMaterial(quint32 ColorCode) return Material; } -lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureMap& TextureMap) +lcMeshLoaderMaterial* lcLibraryMeshData::GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureParams& TextureMap) { for (const std::unique_ptr& Material : mMaterials) { diff --git a/common/lc_meshloader.h b/common/lc_meshloader.h index b3a24298..ecf1e2fe 100644 --- a/common/lc_meshloader.h +++ b/common/lc_meshloader.h @@ -41,13 +41,17 @@ enum class lcMeshLoaderMaterialType Spherical }; -struct lcMeshLoaderMaterial +struct lcMeshLoaderTextureParams { lcMeshLoaderMaterialType Type = lcMeshLoaderMaterialType::Solid; - quint32 Color = 16; lcVector3 Points[3] = {}; float Angles[2] = {}; - char Name[256] = {}; + char Name[LC_MAXPATH] = {}; +}; + +struct lcMeshLoaderMaterial : public lcMeshLoaderTextureParams +{ + quint32 Color = 16; }; class lcMeshLoaderSection @@ -71,24 +75,8 @@ struct lcMeshLoaderFinalSection char Name[256]; }; -struct lcMeshLoaderTextureMap +struct lcMeshLoaderTextureMap : public lcMeshLoaderTextureParams { - union lcTextureMapParams - { - lcTextureMapParams() - { - } - - struct lcTextureMapSphericalParams - { - } Spherical; - } Params; - - lcMeshLoaderMaterialType Type; - lcVector3 Points[3]; - float Angles[2]; - char Name[LC_MAXPATH]; - bool Fallback = false; bool Next = false; }; @@ -182,7 +170,7 @@ public: void AddMeshDataNoDuplicateCheck(const lcLibraryMeshData& Data, const lcMatrix44& Transform, quint32 CurrentColorCode, bool InvertWinding, bool InvertNormals, lcMeshLoaderTextureMap* TextureMap, lcMeshDataType OverrideDestIndex); lcMeshLoaderMaterial* GetMaterial(quint32 ColorCode); - lcMeshLoaderMaterial* GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureMap& TextureMap); + lcMeshLoaderMaterial* GetTexturedMaterial(quint32 ColorCode, const lcMeshLoaderTextureParams& TextureMap); std::array mData; bool mHasTextures; From 4743368f11d86778b870fbf2cc4f370dac3faecc Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Mon, 9 Mar 2026 23:13:08 -0700 Subject: [PATCH 90/93] Fixed mipmaps not enabled. --- common/lc_library.cpp | 6 +++--- common/lc_texture.cpp | 6 ++---- common/lc_texture.h | 10 +++++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/common/lc_library.cpp b/common/lc_library.cpp index 68775054..2a9cf07c 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -236,7 +236,7 @@ lcTexture* lcPiecesLibrary::FindTexture(const char* TextureName, Project* Curren if (TextureFile.isFile()) { - lcTexture* Texture = lcLoadTexture(TextureFile.absoluteFilePath(), LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV); + lcTexture* Texture = lcLoadTexture(TextureFile.absoluteFilePath(), LC_TEXTURE_MIPMAPS); if (Texture) { @@ -425,7 +425,7 @@ bool lcPiecesLibrary::OpenArchive(std::unique_ptr File, lcZipFileType Zi if ((ZipFileType == lcZipFileType::Official && !memcmp(Name, "LDRAW/PARTS/TEXTURES/", 21)) || (ZipFileType == lcZipFileType::Unofficial && !memcmp(Name, "PARTS/TEXTURES/", 15))) { - lcTexture* Texture = new lcTexture(); + lcTexture* Texture = new lcTexture(LC_TEXTURE_MIPMAPS); mTextures.push_back(Texture); *Dst = 0; @@ -652,7 +652,7 @@ bool lcPiecesLibrary::OpenDirectory(const QDir& LibraryDir, bool ShowProgress) continue; *Dst = 0; - lcTexture* Texture = new lcTexture(); + lcTexture* Texture = new lcTexture(LC_TEXTURE_MIPMAPS); mTextures.push_back(Texture); strncpy(Texture->mName, Name, sizeof(Texture->mName)); diff --git a/common/lc_texture.cpp b/common/lc_texture.cpp index 1dbd01e2..1ea7a055 100644 --- a/common/lc_texture.cpp +++ b/common/lc_texture.cpp @@ -32,11 +32,9 @@ void lcReleaseTexture(lcTexture* Texture) delete Texture; } -lcTexture::lcTexture() +lcTexture::lcTexture(int Flags) + : mFlags(Flags) { - mTexture = 0; - mRefCount = 0; - mTemporary = false; } lcTexture::~lcTexture() diff --git a/common/lc_texture.h b/common/lc_texture.h index 4a5e4201..4f993842 100644 --- a/common/lc_texture.h +++ b/common/lc_texture.h @@ -20,7 +20,7 @@ class lcTexture { public: - lcTexture(); + lcTexture(int Flags = 0); ~lcTexture(); lcTexture(const lcTexture&) = delete; @@ -89,16 +89,16 @@ public: int mHeight; char mName[LC_TEXTURE_NAME_LEN]; QString mFileName; - GLuint mTexture; + GLuint mTexture = 0; protected: bool Load(); bool LoadImages(); - bool mTemporary; - QAtomicInt mRefCount; + bool mTemporary = false; + QAtomicInt mRefCount = 0; std::vector mImages; - int mFlags; + int mFlags = 0; bool mLoading = false; }; From 9e1b8e00324bce30a81860760b2ffa67d06bc541 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 10 Mar 2026 19:55:49 -0700 Subject: [PATCH 91/93] Fixed typos. --- common/object.cpp | 2 +- common/piece.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/object.cpp b/common/object.cpp index 78269738..3a20c30e 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -21,7 +21,7 @@ QString lcObject::GetCheckpointString(lcObjectPropertyId PropertyId) return QT_TRANSLATE_NOOP("Checkpoint", "Change Piece"); case lcObjectPropertyId::PieceColor: - return QT_TRANSLATE_NOOP("Checkpoint", "Chang Piece Color"); + return QT_TRANSLATE_NOOP("Checkpoint", "Change Piece Color"); case lcObjectPropertyId::PieceStepShow: case lcObjectPropertyId::PieceStepHide: diff --git a/common/piece.cpp b/common/piece.cpp index 36d6e5cb..4000ed06 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -959,7 +959,7 @@ void lcPiece::SetHistoryState(const lcPieceHistoryState& State, const lcModel* M mHidden = State.Hidden; mFileLine = State.FileLine; mID = State.PieceId; - mGroup = (State.GroupIndex < Groups.size()) ? Groups[State.GroupIndex].get() : nullptr;; + mGroup = (State.GroupIndex < Groups.size()) ? Groups[State.GroupIndex].get() : nullptr; mColorIndex = State.ColorIndex; mColorCode = State.ColorCode; mStepShow = State.StepShow; From a8e37df8ce9efb31022a68e7b17fef652137755f Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 10 Mar 2026 21:11:40 -0700 Subject: [PATCH 92/93] Whitespace cleanup. --- common/camera.cpp | 30 +- common/camera.h | 2 +- common/group.cpp | 10 +- common/group.h | 14 +- common/lc_aboutdialog.cpp | 4 +- common/lc_blenderpreferences.cpp | 2 +- common/lc_categorydialog.h | 2 +- common/lc_colors.cpp | 2 +- common/lc_doublespinbox.cpp | 6 +- common/lc_filter.cpp | 50 +-- common/lc_findreplacewidget.cpp | 12 +- common/lc_groupdialog.cpp | 6 +- common/lc_instructionsdialog.cpp | 6 +- common/lc_ladderwidget.cpp | 4 +- common/lc_library.cpp | 6 +- common/lc_lxf.cpp | 2 +- common/lc_mesh.cpp | 2 +- common/lc_meshloader.cpp | 10 +- common/lc_minifigdialog.cpp | 8 +- common/lc_model.cpp | 609 +++++++++++++++--------------- common/lc_model.h | 16 +- common/lc_modelaction.cpp | 20 +- common/lc_modelaction.h | 10 +- common/lc_objectproperty.h | 4 +- common/lc_partselectionwidget.cpp | 18 +- common/lc_propertieswidget.cpp | 6 +- common/lc_shortcuts.cpp | 2 +- common/lc_string.cpp | 24 +- common/lc_synth.cpp | 4 +- common/lc_texture.cpp | 14 +- common/lc_thumbnailmanager.cpp | 8 +- common/lc_timelinewidget.cpp | 6 +- common/lc_view.cpp | 42 +-- common/lc_view.h | 2 +- common/lc_viewmanipulator.cpp | 2 +- common/lc_viewwidget.cpp | 2 +- common/lc_viewwidget.h | 2 +- common/light.cpp | 6 +- common/light.h | 4 +- common/minifig.cpp | 2 +- common/object.h | 22 +- common/piece.cpp | 18 +- common/piece.h | 4 +- common/project.cpp | 8 +- qt/lc_qeditgroupsdialog.cpp | 86 ++--- qt/lc_qeditgroupsdialog.h | 12 +- qt/lc_qimagedialog.h | 2 +- qt/lc_qpreferencesdialog.cpp | 4 +- qt/lc_qselectdialog.h | 2 +- qt/lc_qupdatedialog.h | 2 +- qt/lc_qutils.cpp | 16 +- qt/lc_renderdialog.cpp | 2 +- qt/qtmain.cpp | 4 +- 53 files changed, 580 insertions(+), 583 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index ec60c24d..08e3f6b3 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -160,7 +160,7 @@ bool lcCamera::SetProjection(lcCameraProjection CameraProjection) if (GetProjection() == CameraProjection) return false; - + mProjection = CameraProjection; return true; @@ -427,7 +427,7 @@ void lcCamera::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance) { mTargetPosition.ChangeKey(mTargetPosition + Distance, Step, AddKey); } - + if (FocusSection == LC_CAMERA_SECTION_UPVECTOR) { mUpVector.ChangeKey(lcNormalize(mUpVector + Distance), Step, AddKey); @@ -472,7 +472,7 @@ void lcCamera::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix SetTargetPosition(Center + Distance, Step, AddKey); lcVector3 UpVector = mUpVector; - + UpVector = lcMul(UpVector, WorldToLocalMatrix); UpVector = lcMul(UpVector, NewLocalToWorldMatrix); @@ -565,7 +565,7 @@ void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const *CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length; *CurVert++ = 0.0f; *CurVert++ = 25.0f; *CurVert++ = 0.0f; - const GLushort Indices[40 + 24 + 24 + 4 + 16] = + const GLushort Indices[40 + 24 + 24 + 4 + 16] = { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, @@ -924,7 +924,7 @@ void lcCamera::RemoveKeyFrames() lcCameraHistoryState lcCamera::GetHistoryState([[maybe_unused]] const lcModel* Model) const { lcCameraHistoryState State; - + State.Id = mId; State.Hidden = mHidden; State.Simple = mSimple; @@ -936,7 +936,7 @@ lcCameraHistoryState lcCamera::GetHistoryState([[maybe_unused]] const lcModel* M State.TargetPosition = mTargetPosition; State.UpVector = mUpVector; State.Name = mName; - + return State; } @@ -1082,7 +1082,7 @@ void lcCamera::RemoveTime(lcStep Start, lcStep Time) void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std::vector& Points, lcStep Step, bool AddKey) { lcVector3 Position, TargetPosition; - + if (GetProjection() == lcCameraProjection::Orthographic) { float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX; @@ -1096,28 +1096,28 @@ void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std MaxX = lcMax(MaxX, Point.x); MaxY = lcMax(MaxY, Point.y); } - + float Width = fabsf(MaxX - MinX); float Height = fabsf(MaxY - MinY); const lcVector3 ViewCenter = lcMul30(Center, mWorldView); - + float OffsetX = (fabsf(MaxX - ViewCenter.x) - fabsf(ViewCenter.x - MinX)) / 2.0f; float OffsetY = (fabsf(MaxY - ViewCenter.y) - fabsf(ViewCenter.y - MinY)) / 2.0f; lcVector3 ViewOffset(OffsetX, OffsetY, 0.0f); - + lcMatrix44 ViewWorldMatrix = lcMatrix44AffineInverse(mWorldView); ViewWorldMatrix.SetTranslation(lcVector3(0, 0, 0)); - + lcVector3 WorldOffset = lcMul30(ViewOffset, ViewWorldMatrix); - + if (Width > Height * AspectRatio) Height = Width / AspectRatio; const float f = Height / (m_fovy * (LC_PI / 180.0f)); const lcVector3 FrontVector(mTargetPosition - mPosition); - + TargetPosition = Center + WorldOffset; Position = TargetPosition - lcNormalize(FrontVector) * f; } @@ -1142,7 +1142,7 @@ void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std void lcCamera::ZoomRegion(float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey) { lcVector3 NewPosition; - + if (GetProjection() == lcCameraProjection::Orthographic) { float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX; @@ -1202,7 +1202,7 @@ void lcCamera::Zoom(float Distance, lcStep Step, bool AddKey) AddKey = false; mPosition.ChangeKey(mPosition + FrontVector, Step, AddKey); - + if (GetProjection() != lcCameraProjection::Orthographic) mTargetPosition.ChangeKey(mTargetPosition + FrontVector, Step, AddKey); diff --git a/common/camera.h b/common/camera.h index c2101781..f1fdc52a 100644 --- a/common/camera.h +++ b/common/camera.h @@ -43,7 +43,7 @@ struct lcCameraHistoryState lcObjectProperty TargetPosition; lcObjectProperty UpVector; QString Name; - + bool operator==(const lcCameraHistoryState& Other) const { return Id == Other.Id && Hidden == Other.Hidden && Simple == Other.Simple && Fovy == Other.Fovy && diff --git a/common/group.cpp b/common/group.cpp index a1df761e..2517f5c5 100644 --- a/common/group.cpp +++ b/common/group.cpp @@ -66,15 +66,15 @@ void lcGroup::CreateName(const std::vector>& Groups) lcGroupHistoryState lcGroup::GetHistoryState(const lcModel* Model) const { lcGroupHistoryState State; - + State.Id = mId; State.ParentIndex = ~0U; State.Name = mName; - + if (mGroup) { const std::vector>& Groups = Model->GetGroups(); - + for (size_t GroupIndex = 0; GroupIndex < Groups.size(); GroupIndex++) { if (Groups[GroupIndex].get() == mGroup) @@ -84,14 +84,14 @@ lcGroupHistoryState lcGroup::GetHistoryState(const lcModel* Model) const } } } - + return State; } void lcGroup::SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model) { const std::vector>& Groups = Model->GetGroups(); - + mId = State.Id; mName = State.Name; mGroup = (State.ParentIndex < Groups.size()) ? Groups[State.ParentIndex].get() : nullptr; diff --git a/common/group.h b/common/group.h index 7eb6293d..ce758a75 100644 --- a/common/group.h +++ b/common/group.h @@ -9,7 +9,7 @@ struct lcGroupHistoryState lcGroupId Id; uint32_t ParentIndex; QString Name; - + bool operator==(const lcGroupHistoryState& Other) const { return Id == Other.Id && ParentIndex == Other.ParentIndex && Name == Other.Name; @@ -25,23 +25,23 @@ public: { return mGroup ? mGroup->GetTopGroup() : this; } - + lcGroupId GetId() const { return mId; } - + void FileLoad(lcFile* File); void CreateName(const std::vector>& Groups); - + lcGroupHistoryState GetHistoryState(const lcModel* Model) const; void SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model); - + lcGroup* mGroup = nullptr; QString mName; - + protected: lcGroupId mId = static_cast(0); - + static lcGroupId mNextId; }; diff --git a/common/lc_aboutdialog.cpp b/common/lc_aboutdialog.cpp index d16729f2..12d41711 100644 --- a/common/lc_aboutdialog.cpp +++ b/common/lc_aboutdialog.cpp @@ -21,12 +21,12 @@ lcAboutDialog::lcAboutDialog(QWidget* Parent) QOpenGLContext* Context = Widget->context(); QOpenGLFunctions* Functions = Context->functions(); QSurfaceFormat Format = Context->format(); - + int ColorDepth = Format.redBufferSize() + Format.greenBufferSize() + Format.blueBufferSize() + Format.alphaBufferSize(); const QString QtVersionFormat = tr("Qt Version %1 (compiled with %2)\n\n"); const QString QtVersion = QtVersionFormat.arg(qVersion(), QT_VERSION_STR); - + const QString VersionFormat = tr("OpenGL Version %1 (GLSL %2)\n%3 - %4\n\n"); const QString GLVersion(reinterpret_cast(Functions->glGetString(GL_VERSION))); const QString ShaderVersion(reinterpret_cast(Functions->glGetString(GL_SHADING_LANGUAGE_VERSION))); diff --git a/common/lc_blenderpreferences.cpp b/common/lc_blenderpreferences.cpp index 25292a4d..f7993363 100644 --- a/common/lc_blenderpreferences.cpp +++ b/common/lc_blenderpreferences.cpp @@ -2720,7 +2720,7 @@ void lcBlenderPreferences::SaveSettings() lcSetProfileString(LC_PROFILE_BLENDER_VERSION, Value); const QString BlenderConfigDir = QString("%1/Blender/addons/%2/config").arg(gAddonPreferences->mDataDir, LC_BLENDER_ADDON_RENDER_FOLDER); - + Value = lcGetProfileString(LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH); if (!Value.contains(LC_BLENDER_ADDON_RENDER_FOLDER)) { diff --git a/common/lc_categorydialog.h b/common/lc_categorydialog.h index ffcf0cbf..3fb1bac3 100644 --- a/common/lc_categorydialog.h +++ b/common/lc_categorydialog.h @@ -9,7 +9,7 @@ class lcCategoryDialog; class lcCategoryDialog : public QDialog { Q_OBJECT - + public: explicit lcCategoryDialog(QWidget* Parent, lcLibraryCategory* Category); virtual ~lcCategoryDialog(); diff --git a/common/lc_colors.cpp b/common/lc_colors.cpp index 262c5d21..39852d5c 100644 --- a/common/lc_colors.cpp +++ b/common/lc_colors.cpp @@ -422,7 +422,7 @@ QString lcGetColorToolTip(int ColorIndex) QPainter Painter(&Image); Painter.setPen(Qt::darkGray); - + if (Color->Code != LC_COLOR_NOCOLOR) Painter.drawRect(0, 0, Image.width() - 1, Image.height() - 1); else diff --git a/common/lc_doublespinbox.cpp b/common/lc_doublespinbox.cpp index e061c421..c10b9abb 100644 --- a/common/lc_doublespinbox.cpp +++ b/common/lc_doublespinbox.cpp @@ -219,7 +219,7 @@ bool lcDoubleSpinBox::event(QEvent* Event) else if (Event->type() == QEvent::ShortcutOverride) { QKeyEvent* KeyEvent = static_cast(Event); - + switch (KeyEvent->key()) { case Qt::Key_Up: @@ -228,12 +228,12 @@ bool lcDoubleSpinBox::event(QEvent* Event) case Qt::Key_PageDown: Event->accept(); return true; - + default: break; } } - + return QDoubleSpinBox::event(Event); } diff --git a/common/lc_filter.cpp b/common/lc_filter.cpp index a008a820..22b23e72 100644 --- a/common/lc_filter.cpp +++ b/common/lc_filter.cpp @@ -107,41 +107,41 @@ bool lcFilter::Match(const char* String) const } // Copyright 2018 IBM Corporation -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // -// Compares two text strings. Accepts '?' as a single-character wildcard. -// For each '*' wildcard, seeks out a matching sequence of any characters -// beyond it. Otherwise compares the strings a character at a time. +// Compares two text strings. Accepts '?' as a single-character wildcard. +// For each '*' wildcard, seeks out a matching sequence of any characters +// beyond it. Otherwise compares the strings a character at a time. // bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) { const char* WildSequence; // Points to prospective wild string match after '*' const char* TameSequence; // Points to prospective tame string match - + auto NotEquals=[](char a, char b) { // Lowercase the characters to be compared. if (a >= 'A' && a <= 'Z') a += ('a' - 'A'); - + if (b >= 'A' && b <= 'Z') b += ('a' - 'A'); return a != b; }; - // Find a first wildcard, if one exists, and the beginning of any + // Find a first wildcard, if one exists, and the beginning of any // prospectively matching sequence after it. do { @@ -157,7 +157,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) return true; // "ab" matches "ab*". } } - + return false; // "abcd" doesn't match "abc". } else @@ -172,12 +172,12 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) { continue; } - + if (!*Wild) { return true; // "abc*" matches "abcd". } - + // Search for the next prospective match. if (*Wild != '?') { @@ -189,7 +189,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) } } } - + // Keep fallback positions for retry in case of incomplete match. WildSequence = Wild; TameSequence = Tame; @@ -199,11 +199,11 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) { return false; // "abc" doesn't match "abd". } - + ++Wild; // Everything's a match, so far. ++Tame; } while (true); - + // Find any further wildcards and any further matching sequences. do { @@ -214,17 +214,17 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) { continue; } - + if (!*Wild) { return true; // "ab*c*" matches "abcd". } - + if (!*Tame) { return false; // "*bcd*" doesn't match "abc". } - + // Search for the next prospective match. if (*Wild != '?') { @@ -236,7 +236,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) } } } - + // Keep the new fallback positions. WildSequence = Wild; TameSequence = Tame; @@ -248,16 +248,16 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) { return false; // "*bcd" doesn't match "abc". } - + // A fine time for questions. while (*WildSequence == '?') { ++WildSequence; ++TameSequence; } - + Wild = WildSequence; - + // Fall back, but never so far again. while (NotEquals(*Wild, *(++TameSequence))) { @@ -266,10 +266,10 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) return false; // "*a*b" doesn't match "ac". } } - + Tame = TameSequence; } - + // Another check for the end, at the end. if (!*Tame) { @@ -282,7 +282,7 @@ bool lcFilter::FastWildCompare(const char* Tame, const char* Wild) return false; // "*bc" doesn't match "abcd". } } - + ++Wild; // Everything's still a match. ++Tame; } while (true); diff --git a/common/lc_findreplacewidget.cpp b/common/lc_findreplacewidget.cpp index a260fcf8..61afda3e 100644 --- a/common/lc_findreplacewidget.cpp +++ b/common/lc_findreplacewidget.cpp @@ -56,21 +56,21 @@ lcFindReplaceWidget::lcFindReplaceWidget(QWidget* Parent, lcModel* Model, bool R ReplaceColorPicker = new lcColorPicker(this, true); ReplaceColorPicker->setToolTip(tr("Replacement Color")); Layout->addWidget(ReplaceColorPicker, 1, 1); - + QPixmap Pixmap(1, 1); Pixmap.fill(QColor::fromRgba64(0, 0, 0, 0)); - + mReplacePartButton = new lcElidableToolButton(this); mReplacePartButton->setToolTip(tr("Replacement Part")); - + QSizePolicy PieceButtonSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); PieceButtonSizePolicy.setHorizontalStretch(2); PieceButtonSizePolicy.setVerticalStretch(0); mReplacePartButton->setSizePolicy(PieceButtonSizePolicy); - + mReplacePartButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); mReplacePartButton->setIcon(Pixmap); - + Layout->addWidget(mReplacePartButton, 1, 2); QToolButton* ReplaceNextButton = new QToolButton(this); @@ -166,7 +166,7 @@ void lcFindReplaceWidget::ReplaceButtonClicked() std::optional Result = lcShowPartSelectionPopup(Params.ReplacePieceInfo, std::vector>(), gDefaultColor, mReplacePartButton, mReplacePartButton->mapToGlobal(mReplacePartButton->rect().bottomLeft())); - + if (!Result.has_value()) return; diff --git a/common/lc_groupdialog.cpp b/common/lc_groupdialog.cpp index fd4cf056..e1de76ef 100644 --- a/common/lc_groupdialog.cpp +++ b/common/lc_groupdialog.cpp @@ -25,7 +25,7 @@ void lcGroupDialog::accept() QMessageBox::information(this, "LeoCAD", tr("Name cannot be empty.")); return; } - + for (const std::unique_ptr& Group : mGroups) { if (Group->mName == Name) @@ -33,8 +33,8 @@ void lcGroupDialog::accept() QMessageBox::information(this, "LeoCAD", tr("A group with this name already exists.")); return; } - } - + } + mName = Name; QDialog::accept(); diff --git a/common/lc_instructionsdialog.cpp b/common/lc_instructionsdialog.cpp index 8301a381..2e9b5ec6 100644 --- a/common/lc_instructionsdialog.cpp +++ b/common/lc_instructionsdialog.cpp @@ -291,7 +291,7 @@ lcInstructionsPropertiesWidget::lcInstructionsPropertiesWidget(QWidget* Parent, QWidget* CentralWidget = new QWidget(this); setWidget(CentralWidget); setWindowTitle(tr("Properties")); - + QGridLayout* Layout = new QGridLayout(CentralWidget); Layout->setContentsMargins(0, 0, 0, 0); @@ -343,7 +343,7 @@ void lcInstructionsPropertiesWidget::AddColorProperty(lcInstructionsPropertyType Pixmap.fill(Color); ColorButton->setIcon(Pixmap); }; - + UpdateButton(); connect(ColorButton, &QToolButton::clicked, [this, Type, UpdateButton]() @@ -651,7 +651,7 @@ void lcInstructionsDialog::Print(QPrinter* Printer) if (Printer->printerState() == QPrinter::Aborted || Printer->printerState() == QPrinter::Error) { delete Scene; - + return; } diff --git a/common/lc_ladderwidget.cpp b/common/lc_ladderwidget.cpp index fb24083b..9537e891 100644 --- a/common/lc_ladderwidget.cpp +++ b/common/lc_ladderwidget.cpp @@ -40,7 +40,7 @@ void lcLadderWidget::Show() if (Position.y() + HalfHeight > Desktop.bottom()) Position.setY(Desktop.bottom() - HalfHeight); - + move(Position); mLastMousePositionX = mapFromGlobal(QCursor::pos()).x(); @@ -97,7 +97,7 @@ void lcLadderWidget::UpdateMousePosition() { int CellHeight = height() / static_cast(mSteps.size()); int CurrentStep = MousePosition.y() / CellHeight; - + if (CurrentStep != mCurrentStep) { mCurrentStep = CurrentStep; diff --git a/common/lc_library.cpp b/common/lc_library.cpp index 2a9cf07c..5b07783f 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -1281,7 +1281,7 @@ bool lcPiecesLibrary::LoadPieceData(PieceInfo* Info) { char FileName[LC_MAXPATH]; lcDiskFile PieceFile; - + snprintf(FileName, sizeof(FileName), "parts/%s", Info->mFileName); PieceFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); if (PieceFile.Open(QIODevice::ReadOnly)) @@ -1355,7 +1355,7 @@ void lcPiecesLibrary::GetPieceFile(const char* PieceName, std::functionmFileName); IncludeFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String(FileName))); Found = IncludeFile.Open(QIODevice::ReadOnly); @@ -1530,7 +1530,7 @@ bool lcPiecesLibrary::LoadTexture(lcTexture* Texture) if (mZipFiles[static_cast(lcZipFileType::Official)]) { lcMemFile TextureFile; - + snprintf(FileName, sizeof(FileName), "ldraw/parts/textures/%s.png", Texture->mName); if (!mZipFiles[static_cast(lcZipFileType::Official)]->ExtractFile(FileName, TextureFile)) diff --git a/common/lc_lxf.cpp b/common/lc_lxf.cpp index 892e45eb..4299c844 100644 --- a/common/lc_lxf.cpp +++ b/common/lc_lxf.cpp @@ -185,7 +185,7 @@ bool lcImportLXFMLFile(const QString& FileData, std::vector& Pieces, s Pieces.push_back(Piece); NumBrickPieces++; } - + if (NumBrickPieces > 1) { std::vector Group; diff --git a/common/lc_mesh.cpp b/common/lc_mesh.cpp index 2222faa1..87b4e209 100644 --- a/common/lc_mesh.cpp +++ b/common/lc_mesh.cpp @@ -297,7 +297,7 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color { const lcVertex* Verts = GetVertexData(); const IndexType* Indices = (IndexType*)mIndexData + Section->IndexOffset / sizeof(IndexType); - + if (NumSections > 1) File.WriteLine(" mesh {\n"); diff --git a/common/lc_meshloader.cpp b/common/lc_meshloader.cpp index 34fc6597..b302bc95 100644 --- a/common/lc_meshloader.cpp +++ b/common/lc_meshloader.cpp @@ -351,7 +351,7 @@ void lcMeshLoaderTypeData::AddMeshData(const lcMeshLoaderTypeData& Data, const l for (const lcMeshLoaderConditionalVertex& DataVertex : Data.mConditionalVertices) { lcVector3 Position[4]; - + Position[0] = lcMul31(DataVertex.Position[0], Transform); Position[1] = lcMul31(DataVertex.Position[1], Transform); Position[2] = lcMul31(DataVertex.Position[2], Transform); @@ -370,15 +370,15 @@ void lcMeshLoaderTypeData::AddMeshData(const lcMeshLoaderTypeData& Data, const l if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid) { lcMeshLoaderTextureParams DstTextureMap; - + if (TextureMap) DstTextureMap = *TextureMap; else DstTextureMap = *SrcSection->mMaterial; - + for (lcVector3& Point : DstTextureMap.Points) Point = lcMul31(Point, Transform); - + DstSection = AddSection(PrimitiveType, mMeshData->GetTexturedMaterial(ColorCode, DstTextureMap)); } else if (TextureMap && SrcSection->mPrimitiveType == LC_MESH_TRIANGLES) @@ -458,7 +458,7 @@ void lcMeshLoaderTypeData::AddMeshDataNoDuplicateCheck(const lcMeshLoaderTypeDat if (SrcSection->mMaterial->Type != lcMeshLoaderMaterialType::Solid) { lcMeshLoaderTextureParams DstTextureMap; - + if (TextureMap) DstTextureMap = *TextureMap; else diff --git a/common/lc_minifigdialog.cpp b/common/lc_minifigdialog.cpp index 13079adb..8b7bd5e4 100644 --- a/common/lc_minifigdialog.cpp +++ b/common/lc_minifigdialog.cpp @@ -134,9 +134,9 @@ lcMinifigDialog::lcMinifigDialog(QWidget* Parent) mMinifigWizard->Calculate(); mView->GetCamera()->SetViewpoint(lcVector3(0.0f, -270.0f, 90.0f)); mView->ZoomExtents(); - + ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setFocus(); - + connect(ui->TemplateComboBox, &QComboBox::currentTextChanged, this, &lcMinifigDialog::TemplateComboBoxCurrentTextChanged); connect(ui->TemplateSaveButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateSaveButtonClicked); connect(ui->TemplateDeleteButton, &QPushButton::clicked, this, &lcMinifigDialog::TemplateDeleteButtonClicked); @@ -196,7 +196,7 @@ void lcMinifigDialog::TemplateComboBoxCurrentTextChanged(const QString& Template UpdateTemplateCombo(); const lcMinifigTemplate& Template = Position->second; - + mView->MakeCurrent(); mMinifigWizard->LoadTemplate(TemplateName); @@ -387,7 +387,7 @@ void lcMinifigDialog::PieceButtonClicked() return; PieceInfo* NewPiece = Result.value(); - + SetCurrentTemplateModified(); UpdateTemplateCombo(); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index c99b6452..27d84da0 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -1165,17 +1165,17 @@ void lcModel::Cut() { if (!AnyObjectsSelected()) return; - + Copy(); - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + RemoveSelectedObjects(); - + EndObjectEditAction(); EndActionSequence(tr("Cut")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(true); } @@ -1220,26 +1220,26 @@ void lcModel::Paste(bool PasteToCurrentStep) SelectedObjects.emplace_back(Piece.get()); } } - + if (PastedPieces.empty()) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + Merge(std::move(Model)); - + CalculateStep(mCurrentStep); - + EndObjectEditAction(); if (SelectedObjects.size() == 1) RecordSetSelectionAndFocusAction(std::vector(), SelectedObjects.front(), LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); else RecordSetSelectionAndFocusAction(SelectedObjects, nullptr, 0, lcSelectionMode::Single); - + EndActionSequence(tr("Paste")); - + gMainWindow->UpdateTimeline(false, false); } @@ -1253,22 +1253,22 @@ void lcModel::DuplicateSelectedPieces() BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + std::vector NewPieces; lcPiece* Focus = nullptr; std::map GroupMap; - + std::function GetNewGroup = [this, &GroupMap, &GetNewGroup](lcGroup* Group) { const auto GroupIt = GroupMap.find(Group); - + if (GroupIt != GroupMap.end()) return GroupIt->second; else { lcGroup* Parent = Group->mGroup ? GetNewGroup(Group->mGroup) : nullptr; QString GroupName = Group->mName; - + while (!GroupName.isEmpty()) { const QChar Last = GroupName[GroupName.size() - 1]; @@ -1277,44 +1277,44 @@ void lcModel::DuplicateSelectedPieces() else break; } - + if (GroupName.isEmpty()) GroupName = Group->mName; - + lcGroup* NewGroup = AddGroup(GroupName, Parent); GroupMap[Group] = NewGroup; return NewGroup; } }; - + for (size_t PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) { const lcPiece* Piece = mPieces[PieceIndex].get(); - + if (!Piece->IsSelected()) continue; - + lcPiece* NewPiece = new lcPiece(*Piece); NewPiece->UpdatePosition(mCurrentStep); NewPieces.emplace_back(NewPiece); - + if (Piece->IsFocused()) Focus = NewPiece; - + PieceIndex++; AddPiece(std::unique_ptr(NewPiece), PieceIndex); - + lcGroup* Group = Piece->GetGroup(); if (Group) NewPiece->SetGroup(GetNewGroup(Group)); } - + EndObjectEditAction(); - + RecordSetSelectionAndFocusAction(NewPieces, Focus, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - + EndActionSequence(tr("Duplicate")); - + gMainWindow->UpdateTimeline(false, false); } @@ -1738,13 +1738,13 @@ void lcModel::SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::v void lcModel::RecordSelectionAction(std::function Callback) { std::unique_ptr ModelActionSelection = std::make_unique(); - + ModelActionSelection->SaveStartState(this); - - Callback(); - + + Callback(); + ModelActionSelection->SaveEndState(this); - + if (ModelActionSelection->StateChanged()) mActionSequence.emplace_back(std::move(ModelActionSelection)); } @@ -1803,18 +1803,18 @@ template void lcModel::LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects) { std::vector> NewObjects; - + NewObjects.reserve(ObjectStates.size()); - + for (const StateType& ObjectState : ObjectStates) { auto ObjectId = ObjectState.Id; bool Found = false; - + for (auto ObjectIt = Objects.begin(); ObjectIt != Objects.end(); ++ObjectIt) { ObjectType* Object = ObjectIt->get(); - + if (Object->GetId() == ObjectId) { NewObjects.emplace_back(std::move(*ObjectIt)); @@ -1823,17 +1823,17 @@ void lcModel::LoadObjectHistoryState(const std::vector& ObjectStates, break; } } - + if (!Found) NewObjects.emplace_back(new ObjectType()); } - + if constexpr(std::is_same_v) for (const std::unique_ptr& Camera : Objects) RemoveCameraFromViews(Camera.get()); - + Objects = std::move(NewObjects); - + for (size_t ObjectIndex = 0; ObjectIndex < Objects.size(); ObjectIndex++) Objects[ObjectIndex]->SetHistoryState(ObjectStates[ObjectIndex], this); } @@ -1849,10 +1849,7 @@ void lcModel::LoadHistoryState(const lcModelHistoryState& HistoryState) void lcModel::BeginObjectEditAction(lcModelActionEditMerge ModelActionEditMerge) { std::unique_ptr ModelActionObjectEdit = std::make_unique(ModelActionEditMerge); - - if (!ModelActionObjectEdit) - return; - + ModelActionObjectEdit->SaveStartState(this); mActionSequence.emplace_back(std::move(ModelActionObjectEdit)); @@ -1862,14 +1859,14 @@ void lcModel::EndObjectEditAction() { if (mActionSequence.empty()) return; - + lcModelActionObjectEdit* ModelActionObjectEdit = dynamic_cast(mActionSequence.back().get()); - + if (!ModelActionObjectEdit) return; - + ModelActionObjectEdit->SaveEndState(this); - + if (!ModelActionObjectEdit->StateChanged()) mActionSequence.pop_back(); } @@ -1898,7 +1895,7 @@ void lcModel::RecordModelPropertiesAction(const lcModelProperties& ModelProperti void lcModel::RunActionSequence(const std::vector>& ActionSequence, bool Apply) { bool SelectionChanged = false; - + auto RunAction=[this, &SelectionChanged](const lcModelAction* ModelAction, bool Apply) { if (!ModelAction) @@ -1908,7 +1905,7 @@ void lcModel::RunActionSequence(const std::vector ModelAction->LoadEndState(this); else ModelAction->LoadStartState(this); - + if (dynamic_cast(ModelAction)) { SelectionChanged = true; @@ -1932,14 +1929,14 @@ void lcModel::RunActionSequence(const std::vector for (auto ModelAction = ActionSequence.rbegin(); ModelAction != ActionSequence.rend(); ++ModelAction) RunAction(ModelAction->get(), false); } - + if (SelectionChanged) gMainWindow->UpdateSelectedObjects(true); - + gMainWindow->UpdateCurrentStep(); gMainWindow->UpdateTimeline(true, false); - - UpdateAllViews(); + + UpdateAllViews(); } void lcModel::BeginActionSequence() @@ -1951,14 +1948,14 @@ void lcModel::EndActionSequence(const QString& Description) { if (mActionSequence.empty()) return; - + if (mIsPreview) { mActionSequence.clear(); - + return; } - + bool CanMerge = false; if (mActionSequence.size() == 1 && !mUndoHistory.empty() && mUndoHistory.front()->ModelActions.size() == 1) @@ -2017,7 +2014,7 @@ void lcModel::RevertActionSequence() bool lcModel::IsModified() const { const lcModelHistoryEntry* FirstModifyAction = GetFirstUndoChange(); - + if (!FirstModifyAction) return mSavedHistory != nullptr; else @@ -2049,7 +2046,7 @@ const lcModelHistoryEntry* lcModel::GetFirstUndoChange() const for (const std::unique_ptr& UndoEntry : mUndoHistory) if (UndoEntry->ModelActions.size() != 1 || !dynamic_cast(UndoEntry->ModelActions.front().get())) return UndoEntry.get(); - + return nullptr; } @@ -2130,20 +2127,20 @@ void lcModel::InsertStep(lcStep Step) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + for (const std::unique_ptr& Piece : mPieces) Piece->InsertTime(Step, 1); - + for (std::unique_ptr& Camera : mCameras) Camera->InsertTime(Step, 1); - + for (const std::unique_ptr& Light : mLights) Light->InsertTime(Step, 1); - - + + EndObjectEditAction(); EndActionSequence(tr("Insert Step")); - + SetCurrentStep(mCurrentStep); } @@ -2151,19 +2148,19 @@ void lcModel::RemoveStep(lcStep Step) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + for (const std::unique_ptr& Piece : mPieces) Piece->RemoveTime(Step, 1); - + for (std::unique_ptr& Camera : mCameras) Camera->RemoveTime(Step, 1); - + for (const std::unique_ptr& Light : mLights) Light->RemoveTime(Step, 1); - + EndObjectEditAction(); EndActionSequence(tr("Remove Step")); - + SetCurrentStep(mCurrentStep); } @@ -2287,9 +2284,9 @@ void lcModel::UngroupSelection() if (SelectedGroups.empty()) { DiscardActionSequence(); - + QMessageBox::information(gMainWindow, tr("Ungroup Selection"), tr("No groups selected.")); - + return; } @@ -2329,13 +2326,13 @@ void lcModel::AddSelectedPiecesToGroup() break; } } - + if (!Group) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsFocused()) @@ -2346,39 +2343,39 @@ void lcModel::AddSelectedPiecesToGroup() } RemoveEmptyGroups(); - + EndObjectEditAction(); EndActionSequence(tr("Group")); - - gMainWindow->UpdateSelectedObjects(false); + + gMainWindow->UpdateSelectedObjects(false); } void lcModel::RemoveFocusPieceFromGroup() { bool Modified = false; - + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsFocused()) { Piece->SetGroup(nullptr); - + Modified = true; - + break; } } - + if (!Modified) { DiscardActionSequence(); - + return; } - + RemoveEmptyGroups(); - - EndObjectEditAction(); + + EndObjectEditAction(); EndActionSequence(tr("Ungroup")); } @@ -2388,50 +2385,50 @@ void lcModel::ShowEditGroupsDialog() if (Dialog.exec() != QDialog::Accepted) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + std::function UpdateGroups=[this, &UpdateGroups](const lcQEditGroupsDialog::GroupInfo& GroupInfo, lcGroup* ParentGroup) { lcGroup* Group = GroupInfo.Group; - + if (!Group) { Group = new lcGroup(); mGroups.emplace_back(Group); } - + Group->mName = GroupInfo.Name; Group->mGroup = ParentGroup; - + for (const lcQEditGroupsDialog::GroupInfo& ChildGroupInfo : GroupInfo.ChildGroups) UpdateGroups(ChildGroupInfo, Group); - + for (lcPiece* Piece : GroupInfo.ChildPieces) - Piece->SetGroup(Group); + Piece->SetGroup(Group); }; - + lcQEditGroupsDialog::GroupInfo GroupInfo = Dialog.GetGroups(); - + for (const lcQEditGroupsDialog::GroupInfo& ChildGroupInfo : GroupInfo.ChildGroups) UpdateGroups(ChildGroupInfo, nullptr); - + for (lcPiece* Piece : GroupInfo.ChildPieces) Piece->SetGroup(nullptr); - + RemoveEmptyGroups(); EndObjectEditAction(); - + if (mActionSequence.empty()) { DiscardActionSequence(); return; } - + RecordClearSelectionAction(); - + EndActionSequence(tr("Edit Groups")); gMainWindow->UpdateSelectedObjects(true); @@ -2624,10 +2621,10 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) Piece->SetColorIndex(ColorIndex); AddPiece(Piece); }; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + if (Last) { std::vector TrainTracks; @@ -2666,20 +2663,20 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) CreatePiece(Info, WorldMatrix, gMainWindow->mColorIndex); } - + if (!Piece) { DiscardActionSequence(); - + return nullptr; } - + EndObjectEditAction(); - + RecordSetSelectionAndFocusAction(std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); EndActionSequence(tr("Add Piece")); - + gMainWindow->UpdateTimeline(false, false); return Piece; @@ -2688,35 +2685,35 @@ lcPiece* lcModel::AddPiece(PieceInfo* Info, quint32 Section) void lcModel::AddPiece(std::unique_ptr Piece, size_t PieceIndex) { const PieceInfo* Info = Piece->mPieceInfo; - + if (!Info->IsModel()) { const lcMesh* Mesh = Info->GetMesh(); - + if (Mesh && Mesh->mVertexCacheOffset == -1) lcGetPiecesLibrary()->mBuffersDirty = true; } - + mPieces.insert(mPieces.begin() + PieceIndex, std::move(Piece)); } size_t lcModel::AddPiece(lcPiece* Piece) { size_t PieceIndex; - + for (PieceIndex = 0; PieceIndex < mPieces.size(); PieceIndex++) { if (mPieces[PieceIndex]->GetStepShow() > Piece->GetStepShow()) { AddPiece(std::unique_ptr(Piece), PieceIndex); - + return PieceIndex; } } AddPiece(std::unique_ptr(Piece), PieceIndex); - - return PieceIndex; + + return PieceIndex; } void lcModel::FocusNextTrainTrack() @@ -2740,7 +2737,7 @@ void lcModel::FocusNextTrainTrack() ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST; ConnectionIndex = (ConnectionIndex + 1) % TrainTrackInfo->GetConnections().size(); } - + BeginActionSequence(); RecordSetFocusAction(FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); EndActionSequence(tr("Selection")); @@ -2767,7 +2764,7 @@ void lcModel::FocusPreviousTrainTrack() ConnectionIndex = FocusSection - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST; ConnectionIndex = (ConnectionIndex + static_cast(TrainTrackInfo->GetConnections().size()) - 1) % TrainTrackInfo->GetConnections().size(); } - + BeginActionSequence(); RecordSetFocusAction(FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + ConnectionIndex, lcSelectionMode::Single); EndActionSequence(tr("Selection")); @@ -2822,22 +2819,22 @@ void lcModel::RotateFocusedTrainTrack(int Direction) if (!Transform) return; - + BeginActionSequence(); - + BeginObjectEditAction(lcModelActionEditMerge::None); - + FocusPiece->SetPosition(Transform.value().GetTranslation(), mCurrentStep, gMainWindow->GetAddKeys()); FocusPiece->SetRotation(lcMatrix33(Transform.value()), mCurrentStep, gMainWindow->GetAddKeys()); FocusPiece->UpdatePosition(mCurrentStep); - + EndObjectEditAction(); - + if ((FocusSection != LC_PIECE_SECTION_INVALID && FocusSection != LC_PIECE_SECTION_POSITION) || !TracksConnected) RecordSetFocusAction(FocusPiece, LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST + NewConnectionIndex, lcSelectionMode::Single); - + EndActionSequence(tr("Rotate")); - + gMainWindow->UpdateSelectedObjects(true); } @@ -2903,22 +2900,22 @@ void lcModel::DeleteSelectedObjects() return; } - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = RemoveSelectedObjects(); - + if (!Modified) { DiscardActionSequence(); - + return; - } - - EndObjectEditAction(); + } + + EndObjectEditAction(); EndActionSequence(tr("Delete")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(true); gMainWindow->UpdateInUseCategory(); @@ -2928,11 +2925,11 @@ void lcModel::ResetSelectedPiecesPivotPoint() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) Piece->ResetPivotPoint(); - + EndObjectEditAction(); EndActionSequence(tr("Reset Pivot Point")); } @@ -2941,7 +2938,7 @@ void lcModel::RemoveSelectedObjectsKeyFrames() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + for (const std::unique_ptr& Piece : mPieces) if (Piece->IsSelected()) Piece->RemoveKeyFrames(); @@ -2953,7 +2950,7 @@ void lcModel::RemoveSelectedObjectsKeyFrames() for (const std::unique_ptr& Light : mLights) if (Light->IsSelected()) Light->RemoveKeyFrames(); - + EndObjectEditAction(); EndActionSequence(tr("Remove Key Frames")); } @@ -2966,49 +2963,49 @@ void lcModel::InsertControlPoint() return; lcVector3 Start, End; - + gMainWindow->GetActiveView()->GetRayUnderPointer(Start, End); - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = Piece->InsertControlPoint(Start, End); - + if (!Modified) { DiscardActionSequence(); - + return; - } - - EndObjectEditAction(); + } + + EndObjectEditAction(); EndActionSequence(tr("Add Control Point")); - + gMainWindow->UpdateSelectedObjects(true); } void lcModel::RemoveFocusedControlPoint() { lcPiece* Piece = dynamic_cast(GetFocusObject()); - + if (!Piece) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = Piece->RemoveFocusedControlPoint(); - + if (!Modified) { DiscardActionSequence(); - + return; - } - - EndObjectEditAction(); + } + + EndObjectEditAction(); EndActionSequence(tr("Remove Control Point")); - + gMainWindow->UpdateSelectedObjects(true); } @@ -3016,7 +3013,7 @@ void lcModel::ShowSelectedPiecesEarlier() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + std::vector MovedPieces; for (auto PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ) @@ -3053,10 +3050,10 @@ void lcModel::ShowSelectedPiecesEarlier() Piece->SetFileLine(-1); AddPiece(Piece); } - + EndObjectEditAction(); EndActionSequence(tr("Show Earlier")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(true); } @@ -3065,7 +3062,7 @@ void lcModel::ShowSelectedPiecesLater() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + std::vector MovedPieces; for (auto PieceIt = mPieces.begin(); PieceIt != mPieces.end(); ) @@ -3083,7 +3080,7 @@ void lcModel::ShowSelectedPiecesLater() MovedPieces.emplace_back(PieceIt->release()); PieceIt = mPieces.erase(PieceIt); - + continue; } } @@ -3094,7 +3091,7 @@ void lcModel::ShowSelectedPiecesLater() if (MovedPieces.empty()) { DiscardActionSequence(); - + return; } @@ -3103,10 +3100,10 @@ void lcModel::ShowSelectedPiecesLater() Piece->SetFileLine(-1); AddPiece(Piece); } - + EndObjectEditAction(); EndActionSequence(tr("Show Later")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(false); } @@ -3115,10 +3112,10 @@ void lcModel::SetPieceSteps(const std::vector>& Piec { if (PieceSteps.size() != mPieces.size()) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = false; for (size_t PieceIdx = 0; PieceIdx < PieceSteps.size(); PieceIdx++) @@ -3143,7 +3140,7 @@ void lcModel::SetPieceSteps(const std::vector>& Piec { EndObjectEditAction(); EndActionSequence(tr("Change Step")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(false); } @@ -3164,10 +3161,10 @@ void lcModel::MoveSelectionToModel(lcModel* Model) { if (!Model) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + std::vector Pieces; lcPiece* ModelPiece = nullptr; lcStep FirstStep = LC_STEP_MAX; @@ -3197,14 +3194,14 @@ void lcModel::MoveSelectionToModel(lcModel* Model) else PieceIndex++; } - + if (Pieces.empty()) { DiscardActionSequence(); return; } - + lcVector3 ModelCenter = (Min + Max) / 2.0f; ModelCenter.z += (Min.z - Max.z) / 2.0f; @@ -3223,13 +3220,13 @@ void lcModel::MoveSelectionToModel(lcModel* Model) ModelPiece->Initialize(lcMatrix44Translation(ModelCenter), FirstStep); ModelPiece->UpdatePosition(mCurrentStep); } - + EndObjectEditAction(); - + gMainWindow->UpdateTimeline(false, false); RecordSetSelectionAndFocusAction(std::vector(), ModelPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - + EndActionSequence(tr("Move to Model")); } @@ -3237,7 +3234,7 @@ void lcModel::InlineSelectedModels() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + std::vector NewPieces; bool Modified = false; @@ -3255,7 +3252,7 @@ void lcModel::InlineSelectedModels() mPieces.erase(mPieces.begin() + PieceIndex); lcModel* Model = Piece->mPieceInfo->GetModel(); - + Modified = true; for (const std::unique_ptr& ModelPiece : Model->mPieces) @@ -3285,18 +3282,18 @@ void lcModel::InlineSelectedModels() if (!Modified) { QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("No models selected.")); - + DiscardActionSequence(); - + return; } - + EndObjectEditAction(); - + RecordSetSelectionAndFocusAction(NewPieces, nullptr, 0, lcSelectionMode::Single); EndActionSequence(tr("Inline Model")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateInUseCategory(); } @@ -3304,7 +3301,7 @@ void lcModel::InlineSelectedModels() void lcModel::RemoveCameraFromViews(lcCamera* Camera) { std::vector Views = lcView::GetModelViews(this); - + for (lcView* View : Views) if (Camera == View->GetCamera()) View->SetCamera(Camera, true); @@ -3336,7 +3333,7 @@ bool lcModel::RemoveSelectedObjects() if (Camera->IsSelected()) { RemoveCameraFromViews(Camera); - + RemovedCamera = true; CameraIt = mCameras.erase(CameraIt); } @@ -3690,7 +3687,7 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = false; for (lcObject* Object : Objects) @@ -3703,7 +3700,7 @@ void lcModel::SetObjectsKeyFrame(const std::vector& Objects, lcObject { EndObjectEditAction(); EndActionSequence(KeyFrame ? tr("Add KeyFrame") : tr("Remove KeyFrame")); - + gMainWindow->UpdateSelectedObjects(false); } else @@ -3716,7 +3713,7 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = false; for (const std::unique_ptr& Piece : mPieces) @@ -3732,7 +3729,7 @@ void lcModel::SetSelectedPiecesColorIndex(int ColorIndex) { EndObjectEditAction(); EndActionSequence(tr("Paint")); - + gMainWindow->UpdateSelectedObjects(false); gMainWindow->UpdateTimeline(false, true); } @@ -3764,17 +3761,17 @@ void lcModel::SetSelectedPiecesStepShow(lcStep Step) if (MovedPieces.empty()) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + for (lcPiece* Piece : MovedPieces) { Piece->SetFileLine(-1); AddPiece(Piece); } - - EndObjectEditAction(); + + EndObjectEditAction(); EndActionSequence(tr("Set Show Step")); gMainWindow->UpdateTimeline(false, false); @@ -3784,10 +3781,10 @@ void lcModel::SetSelectedPiecesStepShow(lcStep Step) void lcModel::SetSelectedPiecesStepHide(lcStep Step) { bool Modified = false; - + BeginActionSequence(); - BeginObjectEditAction(lcModelActionEditMerge::None); - + BeginObjectEditAction(lcModelActionEditMerge::None); + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsSelected() && Piece->GetStepHide() != Step) @@ -3797,17 +3794,17 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) Modified = true; } } - + if (!Modified) { DiscardActionSequence(); - + return; } - - EndObjectEditAction(); + + EndObjectEditAction(); EndActionSequence(tr("Set Hide Step")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(false); } @@ -3816,22 +3813,22 @@ void lcModel::SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraPro { if (Camera->GetProjection() == CameraProjection) return; - + if (!Camera->IsSimple()) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); } - + Camera->SetProjection(CameraProjection); Camera->UpdatePosition(mCurrentStep); - + if (!Camera->IsSimple()) { EndObjectEditAction(); EndActionSequence(tr("Change Projection")); } - + UpdateAllViews(); gMainWindow->UpdateSelectedObjects(false); } @@ -3842,7 +3839,7 @@ void lcModel::SetObjectsProperty(const std::vector& Objects, lcObject BeginObjectEditAction(static_cast(static_cast(lcModelActionEditMerge::PropertiesEdit) | static_cast(PropertyId))); bool Modified = false; - + for (lcObject* Object : Objects) { bool ObjectModified = Object->SetPropertyValue(PropertyId, mCurrentStep, gMainWindow->GetAddKeys(), Value); @@ -4369,7 +4366,7 @@ void lcModel::SetSelectionAndFocus(const std::vector& Objects, lcObje void lcModel::FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelectionMode SelectionMode) { BeginActionSequence(); - + if (Object) { if (!Object->IsFocused(Section)) @@ -4381,7 +4378,7 @@ void lcModel::FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelect { RecordSetFocusAction(nullptr, 0, SelectionMode); } - + EndActionSequence(tr("Selection")); } @@ -4450,10 +4447,10 @@ void lcModel::DeselectAllObjects() { for (const std::unique_ptr& Piece : mPieces) Piece->SetSelected(false); - + for (const std::unique_ptr& Camera : mCameras) Camera->SetSelected(false); - + for (const std::unique_ptr& Light : mLights) Light->SetSelected(false); } @@ -4464,7 +4461,7 @@ void lcModel::SetFocusedObject(lcObject* FocusObject, uint32_t FocusSection, lcS if (PreviousFocus) PreviousFocus->SetFocused(PreviousFocus->GetFocusSection(), false); - + if (FocusObject) { lcPiece* Piece = dynamic_cast(FocusObject); @@ -4489,9 +4486,9 @@ void lcModel::SetObjectsSelected(const std::vector& Objects, bool Sel { if (Object->IsSelected() == Selected) continue; - + Object->SetSelected(Selected); - + if (Object->IsPiece()) { lcPiece* Piece = dynamic_cast(Object); @@ -4515,32 +4512,32 @@ void lcModel::HideSelectedPieces() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = false; - + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsSelected() && !Piece->IsHidden()) { Piece->SetHidden(true); - + Modified = true; } } - + if (!Modified) { DiscardActionSequence(); - + return; } - + EndObjectEditAction(); - + RecordClearSelectionAction(); - + EndActionSequence(tr("Hide Pieces")); - + gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); } @@ -4549,29 +4546,29 @@ void lcModel::HideUnselectedPieces() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = false; - + for (const std::unique_ptr& Piece : mPieces) { if (!Piece->IsSelected() && !Piece->IsHidden()) { Piece->SetHidden(true); - + Modified = true; } } - + if (!Modified) { DiscardActionSequence(); - + return; - } - - EndObjectEditAction(); + } + + EndObjectEditAction(); EndActionSequence(tr("Hide Pieces")); - + gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); } @@ -4580,29 +4577,29 @@ void lcModel::UnhideSelectedPieces() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = false; - + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsSelected() && Piece->IsHidden()) { Piece->SetHidden(false); - + Modified = true; } } - + if (!Modified) { DiscardActionSequence(); - + return; } - EndObjectEditAction(); + EndObjectEditAction(); EndActionSequence(tr("Unhide Pieces")); - + gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); } @@ -4611,29 +4608,29 @@ void lcModel::UnhideAllPieces() { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + bool Modified = false; - + for (const std::unique_ptr& Piece : mPieces) { if (Piece->IsHidden()) { Piece->SetHidden(false); - + Modified = true; } } - + if (!Modified) { DiscardActionSequence(); - + return; } - - EndObjectEditAction(); + + EndObjectEditAction(); EndActionSequence(tr("Unhide Pieces")); - + gMainWindow->UpdateTimeline(false, true); gMainWindow->UpdateSelectedObjects(true); } @@ -4673,10 +4670,10 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) size_t StartIndex = mPieces.size() - 1; int ReplacedCount = 0; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + if (!FindAll) { // We have to find the currently focused piece, in order to find next/prev match and (optionally) to replace it @@ -4745,9 +4742,9 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) if (CurrentIndex == StartIndex) break; } - + EndObjectEditAction(); - + if (FindAll) RecordSetSelectionAndFocusAction(Selection, nullptr, 0, lcSelectionMode::Single); else @@ -4756,7 +4753,7 @@ void lcModel::FindReplacePiece(bool SearchForward, bool FindAll, bool Replace) if (ReplacedCount) { EndActionSequence(tr("Replace Piece(s)", "", ReplacedCount)); - + gMainWindow->UpdateSelectedObjects(false); gMainWindow->UpdateTimeline(false, true); } @@ -4849,9 +4846,9 @@ void lcModel::EndMouseTool(lcTool Tool, lcView* View, bool Accept) RevertActionSequence(); return; } - + const lcCamera* Camera = View->GetCamera(); - + switch (Tool) { case lcTool::Insert: @@ -4927,27 +4924,27 @@ void lcModel::InsertPieceToolClicked(const std::vector& Piece BeginObjectEditAction(lcModelActionEditMerge::None); lcPiece* Piece = nullptr; - + for (const lcInsertPieceInfo& PieceInfoTransform : PieceInfoTransforms) { Piece = new lcPiece(PieceInfoTransform.Info); - + Piece->Initialize(PieceInfoTransform.Transform, mCurrentStep); Piece->SetColorIndex(PieceInfoTransform.ColorIndex); Piece->UpdatePosition(mCurrentStep); - + AddPiece(Piece); } - + EndObjectEditAction(); - + RecordSetSelectionAndFocusAction(std::vector(), Piece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - + EndActionSequence(tr("Add Piece")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateInUseCategory(); - + UpdateTrainTrackConnections(Piece, false); } @@ -4955,16 +4952,16 @@ void lcModel::InsertCameraToolClicked(const lcVector3& Position) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + lcCamera* Camera = new lcCamera(false, Position, GetSelectionOrModelCenter()); - + Camera->CreateName(mCameras); mCameras.emplace_back(Camera); - + EndObjectEditAction(); - + RecordSetSelectionAndFocusAction(std::vector(), Camera, LC_CAMERA_SECTION_POSITION, lcSelectionMode::Single); - + EndActionSequence(tr("Add Camera")); } @@ -4998,14 +4995,14 @@ void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType Ligh BeginObjectEditAction(lcModelActionEditMerge::None); lcLight* Light = new lcLight(Position, LightType); - + Light->CreateName(mLights); mLights.emplace_back(Light); - + EndObjectEditAction(); - + RecordSetSelectionAndFocusAction(std::vector(), Light, LC_LIGHT_SECTION_POSITION, lcSelectionMode::Single); - + EndActionSequence(ActionName); } @@ -5115,10 +5112,10 @@ void lcModel::EraserToolClicked(lcObject* Object) { if (!Object) return; - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + switch (Object->GetType()) { case lcObjectType::Piece: @@ -5165,10 +5162,10 @@ void lcModel::EraserToolClicked(lcObject* Object) } break; } - + EndObjectEditAction(); EndActionSequence(tr("Delete")); - + gMainWindow->UpdateTimeline(false, false); gMainWindow->UpdateSelectedObjects(true); } @@ -5189,7 +5186,7 @@ void lcModel::PaintToolClicked(lcObject* Object) EndObjectEditAction(); EndActionSequence(tr("Paint")); - + gMainWindow->UpdateSelectedObjects(false); gMainWindow->UpdateTimeline(false, true); } @@ -5243,21 +5240,21 @@ void lcModel::UpdateRollTool(lcCamera* Camera, float Mouse) void lcModel::ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners) { lcCamera* Camera = View->GetCamera(); - + if (!Camera->IsSimple()) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); } - + Camera->ZoomRegion(AspectRatio, Position, TargetPosition, Corners, mCurrentStep, gMainWindow->GetAddKeys()); - + if (!Camera->IsSimple()) { EndObjectEditAction(); EndActionSequence(tr("Zoom")); } - + gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); } @@ -5275,13 +5272,13 @@ void lcModel::LookAt(lcCamera* Camera) else Center = lcVector3(0.0f, 0.0f, 0.0f); } - + if (!Camera->IsSimple()) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); } - + Camera->Center(Center, mCurrentStep, gMainWindow->GetAddKeys()); gMainWindow->UpdateSelectedObjects(false); @@ -5301,9 +5298,9 @@ void lcModel::MoveCamera(lcCamera* Camera, const lcVector3& Direction) BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::KeyboardMoveCamera); } - + Camera->MoveRelative(Direction, mCurrentStep, gMainWindow->GetAddKeys()); - + gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); @@ -5332,18 +5329,18 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& Worl } const lcVector3 Center = (Min + Max) / 2.0f; - + if (!Camera->IsSimple()) { BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); } - + Camera->ZoomExtents(Aspect, Center, Points, mCurrentStep, gMainWindow ? gMainWindow->GetAddKeys() : false); if (!mIsPreview && gMainWindow) gMainWindow->UpdateSelectedObjects(false); - + UpdateAllViews(); if (!Camera->IsSimple()) @@ -5360,12 +5357,12 @@ void lcModel::Zoom(lcCamera* Camera, float Amount) BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::KeyboardZoom); } - + Camera->Zoom(Amount, mCurrentStep, gMainWindow->GetAddKeys()); if (!mIsPreview) gMainWindow->UpdateSelectedObjects(false); - + UpdateAllViews(); if (!Camera->IsSimple()) @@ -5432,12 +5429,12 @@ void lcModel::ShowArrayDialog() QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Array only has 1 element or less, no pieces added.")); return; } - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + std::vector NewPieces; - + for (int Step1 = 0; Step1 < Dialog.mCounts[0]; Step1++) { for (int Step2 = 0; Step2 < Dialog.mCounts[1]; Step2++) @@ -5465,32 +5462,32 @@ void lcModel::ShowArrayDialog() Position = lcVector3(ModelWorld.r[3].x, ModelWorld.r[3].y, ModelWorld.r[3].z); ModelWorld.SetTranslation(Position + Offset); - + lcPiece* NewPiece = new lcPiece(nullptr); NewPiece->SetPieceInfo(Piece->mPieceInfo, Piece->GetID(), true, true); NewPiece->Initialize(ModelWorld, mCurrentStep); NewPiece->SetColorIndex(Piece->GetColorIndex()); - + NewPieces.emplace_back(NewPiece); } } } } - + for (size_t PieceIdx = 0; PieceIdx < NewPieces.size(); PieceIdx++) { lcPiece* Piece = (lcPiece*)NewPieces[PieceIdx]; Piece->UpdatePosition(mCurrentStep); AddPiece(Piece); } - + EndObjectEditAction(); - + RecordAddToSelectionAction(NewPieces); - + EndActionSequence(tr("Piece Array")); - - gMainWindow->UpdateTimeline(false, false); + + gMainWindow->UpdateTimeline(false, false); } void lcModel::ShowMinifigDialog() @@ -5501,38 +5498,38 @@ void lcModel::ShowMinifigDialog() return; gMainWindow->GetActiveView()->MakeCurrent(); - + BeginActionSequence(); BeginObjectEditAction(lcModelActionEditMerge::None); - + lcGroup* Group = AddGroup(tr("Minifig #"), nullptr); std::vector Pieces; lcMinifig& Minifig = Dialog.mMinifigWizard->mMinifig; - + Pieces.reserve(LC_MFW_NUMITEMS); - + for (int PartIndex = 0; PartIndex < LC_MFW_NUMITEMS; PartIndex++) { if (!Minifig.Parts[PartIndex]) continue; - + lcPiece* Piece = new lcPiece(Minifig.Parts[PartIndex]); - + Piece->Initialize(Minifig.Matrices[PartIndex], mCurrentStep); Piece->SetColorIndex(Minifig.ColorIndices[PartIndex]); Piece->SetGroup(Group); AddPiece(Piece); Piece->UpdatePosition(mCurrentStep); - + Pieces.emplace_back(Piece); } - + EndObjectEditAction(); - + RecordSetSelectionAndFocusAction(Pieces, nullptr, 0, lcSelectionMode::Single); - + EndActionSequence(tr("Add Minifig")); - + gMainWindow->UpdateTimeline(false, false); } diff --git a/common/lc_model.h b/common/lc_model.h index 6de134d1..3ff14421 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -135,10 +135,10 @@ public: { return mActive; } - + bool IsModified() const; void SetSaved(); - + bool GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const; bool IncludesModel(const lcModel* Model) const; void CreatePieceInfo(Project* Project); @@ -225,12 +225,12 @@ public: void ShowNextStep(); void InsertStep(lcStep Step); void RemoveStep(lcStep Step); - + template void LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects); void LoadHistoryState(const lcModelHistoryState& HistoryState); void SetModelProperties(const lcModelProperties& ModelProperties); - + lcPiece* AddPiece(PieceInfo* Info, quint32 Section); void AddPiece(std::unique_ptr Piece, size_t PieceIndex); void DeleteSelectedObjects(); @@ -266,7 +266,7 @@ public: bool LoadInventory(const QByteArray& Inventory); int SplitMPD(QIODevice& Device); void Merge(std::unique_ptr Other); - + void SetMinifig(const lcMinifig& Minifig); void SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex); @@ -314,7 +314,7 @@ public: void GetPartsListForStep(lcStep Step, int DefaultColorIndex, lcPartsList& PartsList, bool Cumulative) const; void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector& ModelParts) const; void GetSelectionInformation(int* Flags, std::vector& Selection, lcObject** Focus) const; - + void ClearSelection(); void SetSelectionAndFocus(const std::vector& Selection, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode); void FocusOrDeselectObject(lcObject* Object, uint32_t Section, lcSelectionMode SelectionMode); @@ -391,7 +391,7 @@ public: protected: void DeleteModel(); - + void RecordSelectionAction(std::function Callback); void RecordClearSelectionAction(); void RecordSetFocusAction(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); @@ -416,7 +416,7 @@ protected: void RemoveEmptyGroups(); bool RemoveSelectedObjects(); void RemoveCameraFromViews(lcCamera* Camera); - + std::vector GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece) const; void DeselectAllObjects(); void SetFocusedObject(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); diff --git a/common/lc_modelaction.cpp b/common/lc_modelaction.cpp index 8d698b29..81609e0b 100644 --- a/common/lc_modelaction.cpp +++ b/common/lc_modelaction.cpp @@ -110,7 +110,7 @@ void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, lcPiece* Piece = Pieces[PieceIndex].get(); Piece->SetSelected(State.PieceSelection[PieceIndex]); - + if (State.FocusObjectType == lcObjectType::Piece && State.FocusIndex == PieceIndex) Piece->SetFocused(State.FocusSection, true); else @@ -122,7 +122,7 @@ void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, lcCamera* Camera = Cameras[CameraIndex].get(); Camera->SetSelected(State.CameraSelection[CameraIndex]); - + if (State.FocusObjectType == lcObjectType::Camera && State.FocusIndex == CameraIndex) Camera->SetFocused(State.FocusSection, true); else @@ -134,7 +134,7 @@ void lcModelActionSelection::LoadState(const lcModelActionSelectionState& State, lcLight* Light = Lights[LightIndex].get(); Light->SetSelected(State.LightSelection[LightIndex]); - + if (State.FocusObjectType == lcObjectType::Light && State.FocusIndex == LightIndex) Light->SetFocused(State.FocusSection, true); else @@ -159,22 +159,22 @@ lcModelActionObjectEdit::~lcModelActionObjectEdit() void lcModelActionObjectEdit::SaveState(lcModelHistoryState& State, const lcModel* Model) { const std::vector>& Groups = Model->GetGroups(); - + for (const std::unique_ptr& Group : Groups) State.Groups.emplace_back(Group->GetHistoryState(Model)); - + const std::vector>& Pieces = Model->GetPieces(); - + for (const std::unique_ptr& Piece : Pieces) State.Pieces.emplace_back(Piece->GetHistoryState(Model)); - + const std::vector>& Cameras = Model->GetCameras(); - + for (const std::unique_ptr& Camera : Cameras) State.Cameras.emplace_back(Camera->GetHistoryState(Model)); - + const std::vector>& Lights = Model->GetLights(); - + for (const std::unique_ptr& Light : Lights) State.Lights.emplace_back(Light->GetHistoryState(Model)); } diff --git a/common/lc_modelaction.h b/common/lc_modelaction.h index 1d3624bd..9a00eda7 100644 --- a/common/lc_modelaction.h +++ b/common/lc_modelaction.h @@ -10,7 +10,7 @@ class lcModelAction public: lcModelAction() = default; virtual ~lcModelAction() = default; - + virtual void SaveStartState(const lcModel* Model) = 0; virtual void SaveEndState(const lcModel* Model) = 0; virtual void LoadStartState(lcModel* Model) const = 0; @@ -51,7 +51,7 @@ class lcModelActionSelection : public lcModelAction public: lcModelActionSelection() = default; virtual ~lcModelActionSelection() = default; - + void SaveStartState(const lcModel* Model) override; void SaveEndState(const lcModel* Model) override; void LoadStartState(lcModel* Model) const override; @@ -61,7 +61,7 @@ public: protected: static void SaveState(lcModelActionSelectionState& State, const lcModel* Model); static void LoadState(const lcModelActionSelectionState& State, lcModel* Model); - + lcModelActionSelectionState mStartState; lcModelActionSelectionState mEndState; }; @@ -98,7 +98,7 @@ class lcModelActionObjectEdit: public lcModelAction public: lcModelActionObjectEdit(lcModelActionEditMerge ModelActionEditMerge); virtual ~lcModelActionObjectEdit(); - + void SaveStartState(const lcModel* Model) override; void SaveEndState(const lcModel* Model) override; void LoadStartState(lcModel* Model) const override; @@ -111,7 +111,7 @@ public: protected: static void SaveState(lcModelHistoryState& State, const lcModel* Model); static void LoadState(const lcModelHistoryState& State, lcModel* Model); - + lcModelHistoryState mStartState; lcModelHistoryState mEndState; lcModelActionEditMerge mMerge; diff --git a/common/lc_objectproperty.h b/common/lc_objectproperty.h index 071232f2..432863c5 100644 --- a/common/lc_objectproperty.h +++ b/common/lc_objectproperty.h @@ -68,12 +68,12 @@ class lcObjectProperty { public: lcObjectProperty() = default; - + explicit lcObjectProperty(const T& DefaultValue) : mValue(DefaultValue) { } - + operator const T& () const { return mValue; diff --git a/common/lc_partselectionwidget.cpp b/common/lc_partselectionwidget.cpp index 267094a5..11e1bd48 100644 --- a/common/lc_partselectionwidget.cpp +++ b/common/lc_partselectionwidget.cpp @@ -249,7 +249,7 @@ void lcPartSelectionListModel::SetCustomParts(const std::vectormFileName).contains(FilterRx)); } - + mListView->setRowHidden((int)PartIdx, !Visible); } } @@ -662,7 +662,7 @@ void lcPartSelectionListView::SetCurrentPart(PieceInfo* Info) { setCurrentIndex(Index); scrollTo(Index, QAbstractItemView::EnsureVisible); - } + } } void lcPartSelectionListView::SetNoIcons() @@ -771,13 +771,13 @@ void lcPartSelectionListView::SetIconSize(int Size) { setIconSize(QSize(Size, Size)); lcSetProfileInt(LC_PROFILE_PARTS_LIST_ICONS, Size); - + #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) float DeviceScale = devicePixelRatioF(); #else float DeviceScale = devicePixelRatio(); #endif - + mListModel->SetIconSize(Size, DeviceScale); UpdateViewMode(); @@ -990,18 +990,18 @@ void lcPartSelectionWidget::SetCategory(lcPartCategoryType Type, int Index) { QTreeWidgetItem* Item = mCategoriesWidget->topLevelItem(Row); lcPartCategoryType ItemType = static_cast(Item->data(0, static_cast(lcPartCategoryRole::Type)).toInt()); - + if (ItemType != Type) continue; - + if (Type == lcPartCategoryType::Palette || Type == lcPartCategoryType::Category) { int ItemIndex = Item->data(0, static_cast(lcPartCategoryRole::Index)).toInt(); - + if (ItemIndex != Index) continue; } - + mCategoriesWidget->setCurrentItem(Item); break; } diff --git a/common/lc_propertieswidget.cpp b/common/lc_propertieswidget.cpp index 558ee4ea..1b66da2b 100644 --- a/common/lc_propertieswidget.cpp +++ b/common/lc_propertieswidget.cpp @@ -469,7 +469,7 @@ void lcPropertiesWidget::ChangeFloatValue(lcObjectPropertyId PropertyId, float V void lcPropertiesWidget::UpdateFloat(lcObjectPropertyId PropertyId, float Value) { lcDoubleSpinBox* Widget = qobject_cast(mPropertyWidgets[static_cast(PropertyId)].Editor); - + if (Widget) { QSignalBlocker Blocker(Widget); @@ -1083,7 +1083,7 @@ void lcPropertiesWidget::PieceIdButtonClicked() PieceInfo* Info = Partial ? nullptr : static_cast(Value.value()); std::tie(Value, Partial) = GetUpdateValue(lcObjectPropertyId::PieceColor); - + int ColorIndex = Partial ? gDefaultColor : Value.toInt(); std::optional Result = lcShowPartSelectionPopup(Info, std::vector>(), ColorIndex, PieceIdButton, PieceIdButton->mapToGlobal(PieceIdButton->rect().bottomLeft())); @@ -1314,7 +1314,7 @@ void lcPropertiesWidget::SetPiece(const std::vector& Selection, lcObj if (!Model) return; - + Model->GetMoveRotateTransform(Position, RelativeRotation); UpdateFloat(lcObjectPropertyId::ObjectPositionX, Position[0]); diff --git a/common/lc_shortcuts.cpp b/common/lc_shortcuts.cpp index 2cab2cdb..a23fa732 100644 --- a/common/lc_shortcuts.cpp +++ b/common/lc_shortcuts.cpp @@ -173,7 +173,7 @@ bool lcMouseShortcuts::Save(const QString& FileName) return false; QTextStream Stream(&File); - + for (const QString& Shortcut : std::as_const(Shortcuts)) Stream << Shortcut << QLatin1String("\n"); diff --git a/common/lc_string.cpp b/common/lc_string.cpp index 0e5cfa57..9a9939f9 100644 --- a/common/lc_string.cpp +++ b/common/lc_string.cpp @@ -4,7 +4,7 @@ char* lcstrcasestr(const char* s, const char* find) { char c, sc; - + if ((c = *find++) != 0) { c = tolower((unsigned char)c); @@ -26,7 +26,7 @@ char* lcstrupr(char* string) { for (char* c = string; *c; c++) *c = toupper(*c); - + return string; } @@ -34,19 +34,19 @@ size_t lcstrcpy(char* dest, const char* source, size_t size) { if (size == 0) return 0; - + for (size_t i = 0; i < size; i++) { dest[i] = source[i]; - + if (source[i] == '\0') { return i; } } - + dest[--size] = '\0'; - + return size; } @@ -56,16 +56,16 @@ size_t lcstrcat(char* dest, const char* source, size_t size) const char* s = source; size_t n = size; size_t dlen; - + while (n-- != 0 && *d != '\0') d++; - + dlen = d - dest; n = size - dlen; - + if (n == 0) return(dlen + strlen(s)); - + while (*s != '\0') { if (n != 1) @@ -75,8 +75,8 @@ size_t lcstrcat(char* dest, const char* source, size_t size) } s++; } - + *d = '\0'; - + return (dlen + (s - source)); } diff --git a/common/lc_synth.cpp b/common/lc_synth.cpp index a4429dd3..86c17e5b 100644 --- a/common/lc_synth.cpp +++ b/common/lc_synth.cpp @@ -1187,7 +1187,7 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD char Line[256]; const int NumEdgeParts = 6; - lcMatrix33 EdgeTransforms[6] = + lcMatrix33 EdgeTransforms[6] = { lcMatrix33(lcVector3(-1.0f, 0.0f, 0.0f), lcVector3(0.0f, -5.0f, 0.0f), lcVector3(0.0f, 0.0f, 1.0f)), lcMatrix33(lcVector3( 0.0f, 1.0f, 0.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 0.0f, -1.0f)), @@ -1282,7 +1282,7 @@ void lcSynthInfoFlexibleAxle::AddParts(lcMemFile& File, lcLibraryMeshData& MeshD for (size_t SectionIndex = 1; SectionIndex < Sections.size() - 1; SectionIndex++) { const int Indices[] = { 1, 3, 5, 8, 10, 12, 15, 17, 19, 22, 24, 26 }; - + for (int VertexIdx = 0; VertexIdx < 12; VertexIdx++) { *IndexBuffer++ = BaseLinesVertex + Indices[VertexIdx]; diff --git a/common/lc_texture.cpp b/common/lc_texture.cpp index 1ea7a055..92d91e8e 100644 --- a/common/lc_texture.cpp +++ b/common/lc_texture.cpp @@ -174,13 +174,13 @@ bool lcTexture::Load(const QString& FileName, int Flags) if (!Image.FileLoad(FileName)) return false; - + mLoading = true; - + SetImage(std::move(Image), Flags); mLoading = false; - + return true; } @@ -190,13 +190,13 @@ bool lcTexture::Load(lcMemFile& File, int Flags) if (!Image.FileLoad(File)) return false; - + mLoading = true; - + SetImage(std::move(Image), Flags); - + mLoading = false; - + return true; } diff --git a/common/lc_thumbnailmanager.cpp b/common/lc_thumbnailmanager.cpp index 8d488dfb..b90bda6d 100644 --- a/common/lc_thumbnailmanager.cpp +++ b/common/lc_thumbnailmanager.cpp @@ -121,7 +121,7 @@ void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThum IconName = ":/resources/part_flexible.png"; else if (Info->GetTrainTrackInfo()) IconName = ":/resources/part_traintrack.png"; - + if (IconName) { QPainter Painter(&Image); @@ -146,11 +146,11 @@ void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThum Painter.drawImage(QPoint(0, 0), Icon); Painter.end(); } - + Image.setDevicePixelRatio(Thumbnail.DeviceScale); - + float ScaledSize = Thumbnail.Size * Thumbnail.DeviceScale; - + Thumbnail.Pixmap = QPixmap::fromImage(Image).scaled(ScaledSize, ScaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); mLibrary->ReleasePieceInfo(Info); diff --git a/common/lc_timelinewidget.cpp b/common/lc_timelinewidget.cpp index f3122dc8..cd80eff3 100644 --- a/common/lc_timelinewidget.cpp +++ b/common/lc_timelinewidget.cpp @@ -247,7 +247,7 @@ void lcTimelineWidget::Update(bool Clear, bool UpdateItems) StepItem = topLevelItem(Step - 1); PieceItemIndex = 0; } - + UpdateCurrentStepItem(); blockSignals(Blocked); @@ -553,10 +553,10 @@ void lcTimelineWidget::ItemSelectionChanged() } Model->SetSelectionAndFocus(Selection, CurrentPiece, LC_PIECE_SECTION_POSITION, lcSelectionMode::Single); - + mIgnoreUpdates = false; blockSignals(Blocked); - + UpdateSelection(); } diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 3972d83b..46f96077 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -267,7 +267,7 @@ lcMatrix44 lcView::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, in double ImageLeft, ImageRight, ImageBottom, ImageTop, Near, Far; double AspectRatio = (double)ImageWidth / (double)ImageHeight; - + if (mCamera->GetProjection() == lcCameraProjection::Orthographic) { float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f; @@ -300,7 +300,7 @@ lcMatrix44 lcView::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, in double Right = Left + (ImageRight - ImageLeft) * CurrentTileWidth / ImageWidth; double Bottom = ImageBottom + (ImageTop - ImageBottom) * (CurrentRow * mHeight) / ImageHeight; double Top = Bottom + (ImageTop - ImageBottom) * CurrentTileHeight / ImageHeight; - + if (mCamera->GetProjection() == lcCameraProjection::Orthographic) return lcMatrix44Ortho(Left, Right, Bottom, Top, Near, Far); else @@ -807,7 +807,7 @@ bool lcView::BeginRenderToImage(int Width, int Height) { lcContext* Context = lcContext::GetGlobalOffscreenContext(); GLint MaxTexture; - + Context->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexture); MaxTexture = qMin(MaxTexture, 2048); @@ -1153,7 +1153,7 @@ void lcView::DrawViewport() const float Scale = GetUIScale(); float Width = mWidth / Scale; float Height = mHeight / Scale; - + mContext->SetWorldMatrix(lcMatrix44Identity()); mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0))); mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, Width, 0.0f, Height, -1.0f, 1.0f)); @@ -1268,7 +1268,7 @@ void lcView::DrawAxes() const TranslationMatrix = lcMatrix44Translation(lcVector3(mWidth - 36, mHeight - 36, 0.0f) / Scale); break; } - + lcMatrix44 WorldViewMatrix = mCamera->mWorldView; WorldViewMatrix.SetTranslation(lcVector3(0, 0, 0)); @@ -1523,18 +1523,18 @@ void lcView::DrawGrid() if (Preferences.mDrawGridLines) VertexBufferSize += 2 * (MaxX - MinX + MaxY - MinY + 2) * 3 * sizeof(float); - + float* Verts = nullptr; - + if (VertexBufferSize) { Verts = static_cast(malloc(VertexBufferSize)); - + if (!Verts) return; - + float* CurVert = Verts; - + if (Preferences.mDrawGridStuds) { float Left = MinX * 20.0f * Spacing; @@ -1544,36 +1544,36 @@ void lcView::DrawGrid() float Z = 0; float U = (MaxX - MinX) * Spacing; float V = (MaxY - MinY) * Spacing; - + *CurVert++ = Left; *CurVert++ = Top; *CurVert++ = Z; *CurVert++ = 0.0f; *CurVert++ = V; - + *CurVert++ = Right; *CurVert++ = Top; *CurVert++ = Z; *CurVert++ = U; *CurVert++ = V; - + *CurVert++ = Left; *CurVert++ = Bottom; *CurVert++ = Z; *CurVert++ = 0.0f; *CurVert++ = 0.0f; - + *CurVert++ = Right; *CurVert++ = Bottom; *CurVert++ = Z; *CurVert++ = U; *CurVert++ = 0.0f; } - + if (Preferences.mDrawGridLines) { float LineSpacing = Spacing * 20.0f; - + for (int Step = MinX; Step < MaxX + 1; Step++) { *CurVert++ = Step * LineSpacing; @@ -1583,7 +1583,7 @@ void lcView::DrawGrid() *CurVert++ = MaxY * LineSpacing; *CurVert++ = 0.0f; } - + for (int Step = MinY; Step < MaxY + 1; Step++) { *CurVert++ = MinX * LineSpacing; @@ -1726,7 +1726,7 @@ float lcView::GetOverlayScale() const lcVector3 Point = UnprojectPoint(ScreenPos); lcVector3 Dist(Point - WorldMatrix.GetTranslation()); - + return Dist.Length() * 5.0f * GetUIScale(); } @@ -1896,7 +1896,7 @@ void lcView::SetCameraProjection(lcCameraProjection CameraProjection) else { lcModel* ActiveModel = GetActiveModel(); - + if (ActiveModel) ActiveModel->SetCameraProjection(mCamera, CameraProjection); } @@ -2571,10 +2571,10 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) case lcTrackTool::Camera: { ActiveModel->InsertCameraToolClicked(GetCameraLightInsertPosition()); - + if ((mMouseModifiers & Qt::ControlModifier) == 0) gMainWindow->SetTool(lcTool::Select); - + mToolClicked = true; UpdateTrackTool(); } diff --git a/common/lc_view.h b/common/lc_view.h index 4f087bc6..c1f926ed 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -263,7 +263,7 @@ public: void ShowContextMenu() const; bool CloseFindReplaceDialog(); void ShowFindReplaceWidget(bool Replace); - + float GetUIScale() const; float GetOverlayScale() const; lcVector3 GetMoveDirection(const lcVector3& Direction) const; diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index 2a154162..e64a17b9 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -515,7 +515,7 @@ void lcViewManipulator::DrawTrainTrack(lcPiece* Piece, lcContext* Context, lcTra else if (TrackTool == lcTrackTool::RotateTrainTrackLeft) { Context->DrawIndexedPrimitives(GL_TRIANGLES, 96, GL_UNSIGNED_SHORT, (108 + 360 + 12) * 2); - + if (CanAdd) Context->DrawIndexedPrimitives(GL_TRIANGLES, 72, GL_UNSIGNED_SHORT, (108 + 360 + 12 + 192) * 2); diff --git a/common/lc_viewwidget.cpp b/common/lc_viewwidget.cpp index e3bc292d..823f3bc7 100644 --- a/common/lc_viewwidget.cpp +++ b/common/lc_viewwidget.cpp @@ -78,7 +78,7 @@ void lcViewWidget::initializeGL() void lcViewWidget::resizeGL(int Width, int Height) { const float Scale = GetDeviceScale(); - + mView->SetSize(Width * Scale, Height * Scale); } diff --git a/common/lc_viewwidget.h b/common/lc_viewwidget.h index ab905b5d..af177aad 100644 --- a/common/lc_viewwidget.h +++ b/common/lc_viewwidget.h @@ -23,7 +23,7 @@ public: return devicePixelRatio(); #endif } - + protected: void initializeGL() override; void resizeGL(int Width, int Height) override; diff --git a/common/light.cpp b/common/light.cpp index 7ab89c79..bfc16e03 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -496,7 +496,7 @@ void lcLight::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance, WorldMatrix.Orthonormalize(); SetRotation(WorldMatrix, Step, AddKey); - + mWorldMatrix = lcMatrix44(WorldMatrix, mWorldMatrix.GetTranslation()); } } @@ -1250,7 +1250,7 @@ bool lcLight::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool case lcObjectPropertyId::LightColor: return SetColor(Value.value(), Step, AddKey); - + case lcObjectPropertyId::LightBlenderPower: return SetBlenderPower(Value.toFloat(), Step, AddKey); @@ -1514,7 +1514,7 @@ void lcLight::RemoveKeyFrames() lcLightHistoryState lcLight::GetHistoryState([[maybe_unused]] const lcModel* Model) const { lcLightHistoryState State; - + State.Id = mId; State.Hidden = mHidden; State.Name = mName; diff --git a/common/light.h b/common/light.h index 7b0cd8fa..a5012ae2 100644 --- a/common/light.h +++ b/common/light.h @@ -52,7 +52,7 @@ struct lcLightHistoryState lcObjectProperty AreaSizeY; lcObjectProperty POVRayAreaGridX; lcObjectProperty POVRayAreaGridY; - + bool operator==(const lcLightHistoryState& Other) const { return Id == Other.Id && Hidden == Other.Hidden && Name == Other.Name && LightType == Other.LightType && @@ -365,7 +365,7 @@ protected: lcObjectProperty mAreaSizeY = lcObjectProperty(250.0f); lcObjectProperty mPOVRayAreaGridX = lcObjectProperty(2); lcObjectProperty mPOVRayAreaGridY = lcObjectProperty(2); - + lcVector3 mTargetMovePosition = lcVector3(0.0f, 0.0f, 0.0f); lcMatrix44 mWorldMatrix; diff --git a/common/minifig.cpp b/common/minifig.cpp index 1dc80d5f..fa783c7b 100644 --- a/common/minifig.cpp +++ b/common/minifig.cpp @@ -154,7 +154,7 @@ void MinifigWizard::ParseSettings(lcFile& Settings) int Flags; if (sscanf(NameEnd, "%d %g %g %g %g %g %g %g %g %g %g %g %g", - &Flags, &Mat[0], &Mat[1], &Mat[2], &Mat[3], &Mat[4], &Mat[5], &Mat[6], + &Flags, &Mat[0], &Mat[1], &Mat[2], &Mat[3], &Mat[4], &Mat[5], &Mat[6], &Mat[7], &Mat[8], &Mat[9], &Mat[10], &Mat[11]) != 13) continue; diff --git a/common/object.h b/common/object.h index 7a30339e..7392eb1c 100644 --- a/common/object.h +++ b/common/object.h @@ -90,35 +90,35 @@ public: { return mObjectType; } - + lcObjectId GetId() const { return mId; } - + bool IsSelected() const { return mSelected; } - + void SetSelected(bool Selected) { mSelected = Selected; - + if (!Selected) mFocusedSection = LC_OBJECT_SECTION_INVALID; } - + bool IsFocused() const { return mFocusedSection != LC_OBJECT_SECTION_INVALID; } - + bool IsFocused(quint32 Section) const { return mFocusedSection == Section; } - + void SetFocused(quint32 Section, bool Focused) { if (Focused) @@ -129,12 +129,12 @@ public: else mFocusedSection = LC_OBJECT_SECTION_INVALID; } - + quint32 GetFocusSection() const { return mFocusedSection; } - + virtual void UpdatePosition(lcStep Step) = 0; virtual quint32 GetAllowedTransforms() const = 0; virtual lcVector3 GetSectionPosition(quint32 Section) const = 0; @@ -151,12 +151,12 @@ public: private: lcObjectType mObjectType; - + protected: bool mHidden = false; bool mSelected = false; quint32 mFocusedSection = LC_OBJECT_SECTION_INVALID; lcObjectId mId = static_cast(0); - + static lcObjectId mNextId; }; diff --git a/common/piece.cpp b/common/piece.cpp index 4000ed06..1958825b 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -918,7 +918,7 @@ void lcPiece::RemoveKeyFrames() lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const { lcPieceHistoryState State; - + State.Id = mId; State.Hidden = mHidden; State.FileLine = mFileLine; @@ -933,9 +933,9 @@ lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const State.ControlPoints = mControlPoints; State.Position = mPosition; State.Rotation = mRotation; - + const std::vector>& Groups = Model->GetGroups(); - + if (mGroup) { for (size_t GroupIndex = 0; GroupIndex < Groups.size(); GroupIndex++) @@ -947,14 +947,14 @@ lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const } } } - + return State; } void lcPiece::SetHistoryState(const lcPieceHistoryState& State, const lcModel* Model) { const std::vector>& Groups = Model->GetGroups(); - + mId = State.Id; mHidden = State.Hidden; mFileLine = State.FileLine; @@ -969,13 +969,13 @@ void lcPiece::SetHistoryState(const lcPieceHistoryState& State, const lcModel* M mControlPoints = State.ControlPoints; mPosition = State.Position; mRotation = State.Rotation; - + PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(mID.toLatin1(), nullptr, true, false); - + SetPieceInfo(Info, mID, true, false); - + UpdateMesh(); - + // std::vector mTrainTrackConnections; } diff --git a/common/piece.h b/common/piece.h index 934fe9d4..914bd038 100644 --- a/common/piece.h +++ b/common/piece.h @@ -21,7 +21,7 @@ struct lcPieceControlPoint { lcMatrix44 Transform; float Scale; - + bool operator==(const lcPieceControlPoint& Other) const { return Transform == Other.Transform && Scale == Other.Scale; @@ -44,7 +44,7 @@ struct lcPieceHistoryState std::vector ControlPoints; lcObjectProperty Position; lcObjectProperty Rotation; - + bool operator==(const lcPieceHistoryState& Other) const { return Id == Other.Id && Hidden == Other.Hidden && FileLine == Other.FileLine && PieceId == Other.PieceId && diff --git a/common/project.cpp b/common/project.cpp index 0b2eecf8..02908455 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -268,10 +268,10 @@ lcModel* Project::CreateNewModel(bool ShowModel) SetActiveModel(mModels.back().get(), true); lcView* ActiveView = gMainWindow ? gMainWindow->GetActiveView() : nullptr; - + if (ActiveView) ActiveView->GetCamera()->SetViewpoint(lcViewpoint::Home); - + if (gMainWindow) gMainWindow->UpdateTitle(); } @@ -1182,7 +1182,7 @@ bool Project::Export3DStudio(const QString& FileName) File.WriteU16(0x4130); // CHK_MSH_MAT_GROUP File.WriteU32(6 + MaterialNameLength + 1 + 2 + 2 * Section->NumIndices / 3); - + snprintf(MaterialName, sizeof(MaterialName), "Material%03d", MaterialIndex); File.WriteBuffer(MaterialName, MaterialNameLength + 1); @@ -1900,7 +1900,7 @@ std::pair Project::ExportPOVRay(const QString& FileName) float FloorDiffuse = POVRayOptions.FloorDiffuse; const char* FloorLocation; const char* FloorAxis; - + if (POVRayOptions.FloorAxis == 0) { FloorAxis = "x"; diff --git a/qt/lc_qeditgroupsdialog.cpp b/qt/lc_qeditgroupsdialog.cpp index 3a4f2a5d..1e08715e 100644 --- a/qt/lc_qeditgroupsdialog.cpp +++ b/qt/lc_qeditgroupsdialog.cpp @@ -14,21 +14,21 @@ public: : QItemDelegate(Parent) { } - + void setModelData(QWidget* Editor, QAbstractItemModel* Model, const QModelIndex& Index) const { QLineEdit* LineEdit = qobject_cast(Editor); - + if (!LineEdit->isModified()) return; QString Text = LineEdit->text().trimmed(); - + lcQEditGroupsDialog* Dialog = qobject_cast(parent()); - + if (Dialog && !Dialog->CanRenameGroup(Text)) return; - + QItemDelegate::setModelData(Editor, Model, Index); } }; @@ -39,13 +39,13 @@ lcQEditGroupsDialog::lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model) ui = new Ui::lcQEditGroupsDialog; ui->setupUi(this); - + QPushButton* NewGroup = ui->buttonBox->addButton(tr("&New Group"), QDialogButtonBox::ActionRole); connect(NewGroup, &QPushButton::clicked, this, &lcQEditGroupsDialog::NewGroupClicked); PopulateTree(); - + ui->treeWidget->setItemDelegate(new lcEditGroupsDialogDelegate(this)); ui->treeWidget->expandAll(); } @@ -59,67 +59,67 @@ bool lcQEditGroupsDialog::CanRenameGroup(const QString& Text) const { if (Text.isEmpty()) return false; - + std::function ScanGroups = [&ScanGroups, &Text](QTreeWidgetItem* ParentItem) { for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++) { QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex); - + if (ChildItem->data(0, GroupRole).value()) { if (ChildItem->text(0) == Text || !ScanGroups(ChildItem)) return false; } } - + return true; }; - + return ScanGroups(ui->treeWidget->invisibleRootItem()); } void lcQEditGroupsDialog::NewGroupClicked() { QTreeWidgetItem* CurrentItem = ui->treeWidget->currentItem(); - + if (CurrentItem && CurrentItem->data(0, PieceRole).value()) CurrentItem = CurrentItem->parent(); - + if (!CurrentItem) CurrentItem = ui->treeWidget->invisibleRootItem(); - + QString Prefix = tr("Group #"); int MaxIndex = 0; - + std::function ScanGroups = [&ScanGroups, &Prefix, &MaxIndex](QTreeWidgetItem* ParentItem) { for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++) { QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex); - + if (ChildItem->data(0, GroupRole).value()) { QString Name = ChildItem->text(0); - + if (Name.startsWith(Prefix)) { bool Ok = false; int GroupNumber = Name.mid(Prefix.length()).toInt(&Ok); - + if (Ok && GroupNumber > MaxIndex) MaxIndex = GroupNumber; } - + ScanGroups(ChildItem); } - } + } }; - + ScanGroups(ui->treeWidget->invisibleRootItem()); - + QString Name = Prefix + QString::number(MaxIndex + 1); - + QTreeWidgetItem* GroupItem = new QTreeWidgetItem(CurrentItem, QStringList(Name)); GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); GroupItem->setData(0, GroupRole, QVariant::fromValue(LC_GROUPDIALOG_NEW_GROUP)); @@ -129,27 +129,27 @@ void lcQEditGroupsDialog::NewGroupClicked() lcQEditGroupsDialog::GroupInfo lcQEditGroupsDialog::GetGroupInfo(QTreeWidgetItem* ParentItem) const { lcQEditGroupsDialog::GroupInfo GroupInfo; - + GroupInfo.Name = ParentItem->text(0); - + uintptr_t GroupPointer = ParentItem->data(0, GroupRole).value(); GroupInfo.Group = (GroupPointer == LC_GROUPDIALOG_NEW_GROUP) ? nullptr : reinterpret_cast(GroupPointer); - + for (int ChildIndex = 0; ChildIndex < ParentItem->childCount(); ChildIndex++) { QTreeWidgetItem* ChildItem = ParentItem->child(ChildIndex); - + if (ChildItem->data(0, GroupRole).value()) GroupInfo.ChildGroups.emplace_back(GetGroupInfo(ChildItem)); else { lcPiece* Piece = reinterpret_cast(ChildItem->data(0, PieceRole).value()); - + if (Piece) GroupInfo.ChildPieces.push_back(Piece); } - } - + } + return GroupInfo; } @@ -163,33 +163,33 @@ void lcQEditGroupsDialog::PopulateTree() const std::vector>& Groups = mModel->GetGroups(); std::unordered_map AddedGroups; std::vector GroupsToAdd; - + AddedGroups[nullptr] = ui->treeWidget->invisibleRootItem(); - + auto CreateGroupItem = [&AddedGroups](lcGroup* Group) { QTreeWidgetItem* ParentItem = AddedGroups.find(Group->mGroup)->second; - + if (!ParentItem) return false; - + QTreeWidgetItem* GroupItem = new QTreeWidgetItem(ParentItem, QStringList(Group->mName)); GroupItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); GroupItem->setData(0, GroupRole, QVariant::fromValue((uintptr_t)Group)); - + AddedGroups[Group] = GroupItem; - + return true; }; - + for (const std::unique_ptr& Group : Groups) if (!CreateGroupItem(Group.get())) GroupsToAdd.push_back(Group.get()); - + while (!GroupsToAdd.empty()) { size_t GroupCount = GroupsToAdd.size(); - + for (auto GroupIt = GroupsToAdd.begin(); GroupIt != GroupsToAdd.end();) { if (CreateGroupItem(*GroupIt)) @@ -197,17 +197,17 @@ void lcQEditGroupsDialog::PopulateTree() else ++GroupIt; } - + if (GroupCount == GroupsToAdd.size()) break; } - + const std::vector>& Pieces = mModel->GetPieces(); - + for (const std::unique_ptr& Piece : Pieces) { QTreeWidgetItem* ParentItem = AddedGroups.find(Piece->GetGroup())->second; - + if (ParentItem) { QTreeWidgetItem* PieceItem = new QTreeWidgetItem(ParentItem, QStringList(Piece->GetName())); diff --git a/qt/lc_qeditgroupsdialog.h b/qt/lc_qeditgroupsdialog.h index b4f7286a..11dd7cd8 100644 --- a/qt/lc_qeditgroupsdialog.h +++ b/qt/lc_qeditgroupsdialog.h @@ -7,11 +7,11 @@ class lcQEditGroupsDialog; class lcQEditGroupsDialog : public QDialog { Q_OBJECT - + public: lcQEditGroupsDialog(QWidget* Parent, const lcModel* Model); virtual ~lcQEditGroupsDialog(); - + struct GroupInfo { QString Name; @@ -19,10 +19,10 @@ public: std::vector ChildGroups; std::vector ChildPieces; }; - + GroupInfo GetGroups() const; bool CanRenameGroup(const QString& Text) const; - + protected slots: void NewGroupClicked(); @@ -32,10 +32,10 @@ protected: PieceRole = Qt::UserRole, GroupRole }; - + GroupInfo GetGroupInfo(QTreeWidgetItem* ParentItem) const; void PopulateTree(); - + Ui::lcQEditGroupsDialog* ui = nullptr; const lcModel* mModel = nullptr; }; diff --git a/qt/lc_qimagedialog.h b/qt/lc_qimagedialog.h index 4ef8855e..1cd94144 100644 --- a/qt/lc_qimagedialog.h +++ b/qt/lc_qimagedialog.h @@ -9,7 +9,7 @@ class lcQImageDialog; class lcQImageDialog : public QDialog { Q_OBJECT - + public: lcQImageDialog(QWidget* Parent); ~lcQImageDialog(); diff --git a/qt/lc_qpreferencesdialog.cpp b/qt/lc_qpreferencesdialog.cpp index 0813b6ff..e41346cc 100644 --- a/qt/lc_qpreferencesdialog.cpp +++ b/qt/lc_qpreferencesdialog.cpp @@ -101,7 +101,7 @@ lcQPreferencesDialog::lcQPreferencesDialog(QWidget* Parent, lcPreferencesDialogO ui->ConditionalLinesCheckBox->setChecked(false); ui->ConditionalLinesCheckBox->setEnabled(false); } - + lcViewWidget* Widget = gMainWindow->GetActiveView()->GetWidget(); QOpenGLContext* Context = Widget->context(); QOpenGLFunctions* Functions = Context->functions(); @@ -912,7 +912,7 @@ void lcQPreferencesDialog::updateCommandList() qsizetype pos = identifier.indexOf(QLatin1Char('.')); qsizetype subPos = identifier.indexOf(QLatin1Char('.'), pos + 1); - + if (subPos == -1) subPos = pos; diff --git a/qt/lc_qselectdialog.h b/qt/lc_qselectdialog.h index 63059b25..fbdff6e1 100644 --- a/qt/lc_qselectdialog.h +++ b/qt/lc_qselectdialog.h @@ -9,7 +9,7 @@ class lcQSelectDialog; class lcQSelectDialog : public QDialog { Q_OBJECT - + public: lcQSelectDialog(QWidget* Parent, lcModel* Model); ~lcQSelectDialog(); diff --git a/qt/lc_qupdatedialog.h b/qt/lc_qupdatedialog.h index 1038c91b..a2f4fdd5 100644 --- a/qt/lc_qupdatedialog.h +++ b/qt/lc_qupdatedialog.h @@ -14,7 +14,7 @@ void lcDoInitialUpdateCheck(); class lcQUpdateDialog : public QDialog { Q_OBJECT - + public: explicit lcQUpdateDialog(QWidget* Parent, bool InitialUpdate); ~lcQUpdateDialog(); diff --git a/qt/lc_qutils.cpp b/qt/lc_qutils.cpp index fe003e7d..ee944023 100644 --- a/qt/lc_qutils.cpp +++ b/qt/lc_qutils.cpp @@ -152,14 +152,14 @@ void lcQTreeWidgetColumnStretcher::SectionResized(int LogicalIndex, int OldSize, { Q_UNUSED(OldSize) - if (LogicalIndex == mColumnToStretch) - { - QHeaderView* HeaderView = qobject_cast(parent()); - - if (HeaderView->isVisible()) - mInteractiveResize = true; - - mStretchWidth = NewSize; + if (LogicalIndex == mColumnToStretch) + { + QHeaderView* HeaderView = qobject_cast(parent()); + + if (HeaderView->isVisible()) + mInteractiveResize = true; + + mStretchWidth = NewSize; } } diff --git a/qt/lc_renderdialog.cpp b/qt/lc_renderdialog.cpp index a32411a2..47835910 100644 --- a/qt/lc_renderdialog.cpp +++ b/qt/lc_renderdialog.cpp @@ -175,7 +175,7 @@ bool lcRenderDialog::PromptCancel() { if (!mProcess) return true; - + if (QMessageBox::question(this, tr("Cancel Render"), tr("Are you sure you want to cancel the current render?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return false; diff --git a/qt/qtmain.cpp b/qt/qtmain.cpp index df739ae2..bf59102c 100644 --- a/qt/qtmain.cpp +++ b/qt/qtmain.cpp @@ -27,7 +27,7 @@ static TCHAR gMinidumpPath[_MAX_PATH]; static LONG WINAPI lcSehHandler(PEXCEPTION_POINTERS exceptionPointers) -{ +{ if (IsDebuggerPresent()) return EXCEPTION_CONTINUE_SEARCH; @@ -203,7 +203,7 @@ int main(int argc, char *argv[]) #ifdef LC_LDRAW_LIBRARY_PATH LibraryPaths += qMakePair(QString::fromLatin1(LC_LDRAW_LIBRARY_PATH), false); #endif - + setlocale(LC_NUMERIC, "C"); lcStartupMode StartupMode = Application.Initialize(LibraryPaths); From 1eb9a430c79567f63c205817de5839b44eec1f7a Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Thu, 12 Mar 2026 21:26:43 -0700 Subject: [PATCH 93/93] Removed unused function. --- common/lc_model.cpp | 5 ----- common/lc_model.h | 1 - 2 files changed, 6 deletions(-) diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 27d84da0..a8b62ce5 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2175,11 +2175,6 @@ lcGroup* lcModel::AddGroup(const QString& Prefix, lcGroup* Parent) return Group; } -void lcModel::AddGroup(std::unique_ptr Group, size_t GroupIndex) -{ - mGroups.insert(mGroups.begin() + GroupIndex, std::move(Group)); -} - lcGroup* lcModel::GetGroup(const QString& Name, bool CreateIfMissing) { for (const std::unique_ptr& Group : mGroups) diff --git a/common/lc_model.h b/common/lc_model.h index 3ff14421..32191c10 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -250,7 +250,6 @@ public: void InlineSelectedModels(); lcGroup* AddGroup(const QString& Prefix, lcGroup* Parent); - void AddGroup(std::unique_ptr Group, size_t GroupIndex); lcGroup* GetGroup(const QString& Name, bool CreateIfMissing); void RemoveGroup(lcGroup* Group); void GroupSelection();