diff --git a/common/camera.cpp b/common/camera.cpp index 9f10ea64..1b6b0dd8 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -921,7 +921,7 @@ void lcCamera::RemoveKeyFrames() mUpVector.RemoveAllKeys(); } -lcCameraHistoryState lcCamera::GetHistoryState([[maybe_unused]] const lcModel* Model) const +lcCameraHistoryState lcCamera::GetHistoryState() const { lcCameraHistoryState State; @@ -940,7 +940,7 @@ lcCameraHistoryState lcCamera::GetHistoryState([[maybe_unused]] const lcModel* M return State; } -void lcCamera::SetHistoryState(const lcCameraHistoryState& State, [[maybe_unused]] const lcModel* Model) +void lcCamera::SetHistoryState(const lcCameraHistoryState& State) { mId = State.Id; mHidden = State.Hidden; diff --git a/common/camera.h b/common/camera.h index 82a39528..e8af95d6 100644 --- a/common/camera.h +++ b/common/camera.h @@ -191,8 +191,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - lcCameraHistoryState GetHistoryState(const lcModel* Model) const; - void SetHistoryState(const lcCameraHistoryState& State, const lcModel* Model); + lcCameraHistoryState GetHistoryState() const; + void SetHistoryState(const lcCameraHistoryState& State); void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/group.cpp b/common/group.cpp index 2517f5c5..3ae7125d 100644 --- a/common/group.cpp +++ b/common/group.cpp @@ -1,7 +1,6 @@ #include "lc_global.h" #include #include "group.h" -#include "lc_model.h" #include "lc_file.h" lcGroupId lcGroup::mNextId; @@ -63,36 +62,20 @@ void lcGroup::CreateName(const std::vector>& Groups) mName = Prefix + QString::number(Max + 1); } -lcGroupHistoryState lcGroup::GetHistoryState(const lcModel* Model) const +lcGroupHistoryState lcGroup::GetHistoryState() const { lcGroupHistoryState State; State.Id = mId; - State.ParentIndex = ~0U; + State.ParentId = mGroup ? static_cast(mGroup->GetId()) : LC_GROUP_ID_INVALID; 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 = static_cast(GroupIndex); - break; - } - } - } - return State; } -void lcGroup::SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model) +void lcGroup::SetHistoryState(const lcGroupHistoryState& State, lcGroup* Parent) { - const std::vector>& Groups = Model->GetGroups(); - mId = State.Id; mName = State.Name; - mGroup = (State.ParentIndex < Groups.size()) ? Groups[State.ParentIndex].get() : nullptr; + mGroup = Parent; } diff --git a/common/group.h b/common/group.h index ce758a75..651f7c1e 100644 --- a/common/group.h +++ b/common/group.h @@ -4,15 +4,17 @@ enum class lcGroupId : uint32_t; +constexpr uint32_t LC_GROUP_ID_INVALID = std::numeric_limits::max(); + struct lcGroupHistoryState { lcGroupId Id; - uint32_t ParentIndex; + uint32_t ParentId; QString Name; bool operator==(const lcGroupHistoryState& Other) const { - return Id == Other.Id && ParentIndex == Other.ParentIndex && Name == Other.Name; + return Id == Other.Id && ParentId == Other.ParentId && Name == Other.Name; } }; @@ -34,8 +36,8 @@ public: void FileLoad(lcFile* File); void CreateName(const std::vector>& Groups); - lcGroupHistoryState GetHistoryState(const lcModel* Model) const; - void SetHistoryState(const lcGroupHistoryState& State, const lcModel* Model); + lcGroupHistoryState GetHistoryState() const; + void SetHistoryState(const lcGroupHistoryState& State, lcGroup* Parent); lcGroup* mGroup = nullptr; QString mName; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index dccd95ab..cdf53238 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2262,43 +2262,43 @@ void lcModel::RemoveFromSelection(const std::vector& Objects) AddSelectionHistory([this, &Objects](){ SetObjectsSelected(Objects, false); }); } -template -void lcModel::LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects) -{ - std::vector> NewObjects; - std::unordered_map ObjectIndices; - - NewObjects.reserve(ObjectStates.size()); - ObjectIndices.reserve(Objects.size()); - - for (size_t ObjectIndex = 0; ObjectIndex < Objects.size(); ObjectIndex++) - ObjectIndices.emplace(static_cast(Objects[ObjectIndex]->GetId()), ObjectIndex); - - for (const StateType& ObjectState : ObjectStates) - { - const auto ObjectIt = ObjectIndices.find(static_cast(ObjectState.Id)); - - if (ObjectIt != ObjectIndices.end()) - NewObjects.emplace_back(std::move(Objects[ObjectIt->second])); - else - NewObjects.emplace_back(new ObjectType()); - } - - if constexpr(std::is_same_v) - for (const std::unique_ptr& Camera : Objects) - if (Camera) - RemoveCameraFromViews(Camera.get()); - - Objects = std::move(NewObjects); - - for (size_t ObjectIndex = 0; ObjectIndex < Objects.size(); ObjectIndex++) - Objects[ObjectIndex]->SetHistoryState(ObjectStates[ObjectIndex], this); -} - void lcModel::LoadEditHistoryState(const lcModelHistoryEditState& HistoryState) { - LoadObjectHistoryState(HistoryState.Groups, mGroups); - LoadObjectHistoryState(HistoryState.Pieces, mPieces); + const std::unordered_map GroupsById = RestoreGroups(HistoryState.Groups); + RestorePieces(HistoryState.Pieces, GroupsById); + RestoreCameras(HistoryState.Cameras); + RestoreLights(HistoryState.Lights); +} + +std::unordered_map lcModel::RestoreGroups(const lcObjectHistory& History) +{ + const std::unordered_map GroupsById = History.RestoreObjects(mGroups); + + // The lookup uses saved IDs, so a parent can be linked before its state is restored. + for (const lcGroupHistoryState& State : History.States) + { + const auto Group = GroupsById.find(static_cast(State.Id)); + const auto Parent = GroupsById.find(State.ParentId); + + if (Group != GroupsById.end()) + Group->second->SetHistoryState(State, Parent != GroupsById.end() ? Parent->second : nullptr); + } + + return GroupsById; +} + +void lcModel::RestorePieces(const lcObjectHistory& History, const std::unordered_map& GroupsById) +{ + const std::unordered_map PiecesById = History.RestoreObjects(mPieces); + + for (const lcPieceHistoryState& State : History.States) + { + const auto Piece = PiecesById.find(static_cast(State.Id)); + const auto Group = GroupsById.find(State.GroupId); + + if (Piece != PiecesById.end()) + Piece->second->SetHistoryState(State, mProject, Group != GroupsById.end() ? Group->second : nullptr); + } // Model-list changes are not undoable, but older edit states can still name // a submodel that was replaced. Do not restore references that now recurse. @@ -2306,9 +2306,47 @@ void lcModel::LoadEditHistoryState(const lcModelHistoryEditState& HistoryState) { return Piece->mPieceData && Piece->mPieceData->IncludesModel(this); }), mPieces.end()); +} - LoadObjectHistoryState(HistoryState.Cameras, mCameras); - LoadObjectHistoryState(HistoryState.Lights, mLights); +void lcModel::RestoreCameras(const lcObjectHistory& History) +{ + if (History.IsEmpty()) + return; + + if (History.Order) + { + const std::unordered_set CameraIds(History.Order->begin(), History.Order->end()); + + for (const std::unique_ptr& Camera : mCameras) + if (CameraIds.find(static_cast(Camera->GetId())) == CameraIds.end()) + RemoveCameraFromViews(Camera.get()); + } + + const std::unordered_map CamerasById = History.RestoreObjects(mCameras); + + for (const lcCameraHistoryState& State : History.States) + { + const auto Camera = CamerasById.find(static_cast(State.Id)); + + if (Camera != CamerasById.end()) + Camera->second->SetHistoryState(State); + } +} + +void lcModel::RestoreLights(const lcObjectHistory& History) +{ + if (History.IsEmpty()) + return; + + const std::unordered_map LightsById = History.RestoreObjects(mLights); + + for (const lcLightHistoryState& State : History.States) + { + const auto Light = LightsById.find(static_cast(State.Id)); + + if (Light != LightsById.end()) + Light->second->SetHistoryState(State); + } } void lcModel::BeginEditHistory() diff --git a/common/lc_model.h b/common/lc_model.h index 5d800cc7..c332ef7f 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -15,6 +15,11 @@ enum class lcGeometryBoundsMode enum class lcCameraProjection; struct lcSetInventoryItem; struct lcModelHistoryEditState; +struct lcGroupHistoryState; +struct lcPieceHistoryState; +struct lcCameraHistoryState; +struct lcLightHistoryState; +template struct lcObjectHistory; class lcModelHistory; class lcModelHistorySelect; class lcModelHistoryEdit; @@ -291,8 +296,6 @@ public: void InsertStepAction(lcStep Step); void RemoveStepAction(lcStep Step); - template - void LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects); void LoadEditHistoryState(const lcModelHistoryEditState& HistoryState); void LoadModelPropertiesState(const lcModelProperties& ModelProperties); @@ -478,6 +481,11 @@ protected: void DeleteModel(); + std::unordered_map RestoreGroups(const lcObjectHistory& History); + void RestorePieces(const lcObjectHistory& History, const std::unordered_map& GroupsById); + void RestoreCameras(const lcObjectHistory& History); + void RestoreLights(const lcObjectHistory& History); + void AddSelectionHistory(std::function Callback); void ClearSelection(); void SetFocus(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); diff --git a/common/lc_modelhistory.cpp b/common/lc_modelhistory.cpp index 2f9340c1..4617e1fa 100644 --- a/common/lc_modelhistory.cpp +++ b/common/lc_modelhistory.cpp @@ -142,11 +142,6 @@ void lcModelHistorySelect::LoadState(const lcModelHistorySelectState& State, lcM } } -bool operator!=(const lcModelHistoryEditState& a, const lcModelHistoryEditState& b) -{ - return a.Groups != b.Groups || a.Pieces != b.Pieces || a.Cameras != b.Cameras || a.Lights != b.Lights; -} - lcModelHistoryEdit::lcModelHistoryEdit(lcModelHistoryEditMergeKey MergeKey) : mMergeKey(MergeKey) { @@ -158,25 +153,10 @@ lcModelHistoryEdit::~lcModelHistoryEdit() void lcModelHistoryEdit::SaveState(lcModelHistoryEditState& 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)); + State.Groups.Save(Model->GetGroups()); + State.Pieces.Save(Model->GetPieces()); + State.Cameras.Save(Model->GetCameras()); + State.Lights.Save(Model->GetLights()); } void lcModelHistoryEdit::LoadState(const lcModelHistoryEditState& State, lcModel* Model) @@ -192,6 +172,11 @@ void lcModelHistoryEdit::SaveStartState(const lcModel* Model) void lcModelHistoryEdit::SaveEndState(const lcModel* Model) { SaveState(mEndState, Model); + + lcObjectHistory::Compact(mStartState.Groups, mEndState.Groups); + lcObjectHistory::Compact(mStartState.Pieces, mEndState.Pieces); + lcObjectHistory::Compact(mStartState.Cameras, mEndState.Cameras); + lcObjectHistory::Compact(mStartState.Lights, mEndState.Lights); } void lcModelHistoryEdit::LoadStartState(lcModel* Model) const @@ -206,7 +191,7 @@ void lcModelHistoryEdit::LoadEndState(lcModel* Model) const bool lcModelHistoryEdit::StateChanged() const { - return mStartState != mEndState; + return !mStartState.IsEmpty() || !mEndState.IsEmpty(); } void lcModelHistoryEdit::RenamePieces(const std::vector& Renames, const lcPieceData* ModelPieceData) @@ -215,7 +200,7 @@ void lcModelHistoryEdit::RenamePieces(const std::vector& Ren auto RenamePieceIds = [&Renames](lcModelHistoryEditState& State) { - for (lcPieceHistoryState& Piece : State.Pieces) + for (lcPieceHistoryState& Piece : State.Pieces.States) { for (const lcModelPieceRename& Rename : Renames) { @@ -243,8 +228,13 @@ void lcModelHistoryEdit::MergeWith(lcModelHistory* Other) { lcModelHistoryEdit* OtherModelHistoryEdit = dynamic_cast(Other); - if (OtherModelHistoryEdit) - mEndState = std::move(OtherModelHistoryEdit->mEndState); + if (!OtherModelHistoryEdit) + return; + + lcObjectHistory::Merge(mStartState.Groups, mEndState.Groups, OtherModelHistoryEdit->mStartState.Groups, OtherModelHistoryEdit->mEndState.Groups); + lcObjectHistory::Merge(mStartState.Pieces, mEndState.Pieces, OtherModelHistoryEdit->mStartState.Pieces, OtherModelHistoryEdit->mEndState.Pieces); + lcObjectHistory::Merge(mStartState.Cameras, mEndState.Cameras, OtherModelHistoryEdit->mStartState.Cameras, OtherModelHistoryEdit->mEndState.Cameras); + lcObjectHistory::Merge(mStartState.Lights, mEndState.Lights, OtherModelHistoryEdit->mStartState.Lights, OtherModelHistoryEdit->mEndState.Lights); } void lcModelHistoryProperties::SaveStartState(const lcModel* Model) diff --git a/common/lc_modelhistory.h b/common/lc_modelhistory.h index 36f82413..597087d5 100644 --- a/common/lc_modelhistory.h +++ b/common/lc_modelhistory.h @@ -1,6 +1,7 @@ #pragma once #include "lc_model.h" +#include "lc_objecthistory.h" enum class lcObjectType; enum class lcSelectionMode; @@ -78,13 +79,16 @@ struct lcLightHistoryState; struct lcModelHistoryEditState { - std::vector Groups; - std::vector Pieces; - std::vector Cameras; - std::vector Lights; -}; + lcObjectHistory Groups; + lcObjectHistory Pieces; + lcObjectHistory Cameras; + lcObjectHistory Lights; -bool operator!=(const lcModelHistoryEditState& a, const lcModelHistoryEditState& b); + bool IsEmpty() const + { + return Groups.IsEmpty() && Pieces.IsEmpty() && Cameras.IsEmpty() && Lights.IsEmpty(); + } +}; enum class lcModelHistoryEditMerge { diff --git a/common/lc_objecthistory.h b/common/lc_objecthistory.h new file mode 100644 index 00000000..c96af5e6 --- /dev/null +++ b/common/lc_objecthistory.h @@ -0,0 +1,173 @@ +#pragma once + +// Object states are captured while an edit is in progress, then reduced to the +// changed objects. Ordering is only retained for insertions, deletions or reordering. +template +struct lcObjectHistory +{ + std::vector States; + std::optional> Order; + + template + void Save(const std::vector>& Objects) + { + States.clear(); + States.reserve(Objects.size()); + Order.emplace(); + Order->reserve(Objects.size()); + + for (const std::unique_ptr& Object : Objects) + { + States.emplace_back(Object->GetHistoryState()); + Order->emplace_back(static_cast(Object->GetId())); + } + } + + bool IsEmpty() const + { + return States.empty() && !Order; + } + + static void Compact(lcObjectHistory& Start, lcObjectHistory& End) + { + std::unordered_map StartStates; + std::unordered_map EndStates; + + StartStates.reserve(Start.States.size()); + EndStates.reserve(End.States.size()); + + for (const StateType& State : Start.States) + StartStates.emplace(static_cast(State.Id), &State); + + for (const StateType& State : End.States) + EndStates.emplace(static_cast(State.Id), &State); + + std::unordered_set Changed; + + for (const StateType& State : Start.States) + { + const auto Other = EndStates.find(static_cast(State.Id)); + + if (Other == EndStates.end() || !(State == *Other->second)) + Changed.emplace(static_cast(State.Id)); + } + + for (const StateType& State : End.States) + if (StartStates.find(static_cast(State.Id)) == StartStates.end()) + Changed.emplace(static_cast(State.Id)); + + auto KeepChanges = [&Changed](std::vector& States) + { + std::vector Changes; + Changes.reserve(std::min(States.size(), Changed.size())); + + for (StateType& State : States) + if (Changed.find(static_cast(State.Id)) != Changed.end()) + Changes.emplace_back(std::move(State)); + + States = std::move(Changes); + }; + + KeepChanges(Start.States); + KeepChanges(End.States); + + if (Start.Order == End.Order) + { + Start.Order.reset(); + End.Order.reset(); + } + } + + static void Merge(lcObjectHistory& Start, lcObjectHistory& End, lcObjectHistory& NextStart, lcObjectHistory& NextEnd) + { + std::map Before; + std::map After; + + for (StateType& State : Start.States) + Before.emplace(static_cast(State.Id), std::move(State)); + + for (StateType& State : End.States) + After.emplace(static_cast(State.Id), std::move(State)); + + for (StateType& State : NextStart.States) + { + const uint32_t Id = static_cast(State.Id); + + if (After.find(Id) == After.end()) + Before.emplace(Id, std::move(State)); + } + + for (const StateType& State : NextStart.States) + After.erase(static_cast(State.Id)); + + for (StateType& State : NextEnd.States) + After.insert_or_assign(static_cast(State.Id), std::move(State)); + + Start.States.clear(); + End.States.clear(); + + for (auto& [Id, State] : Before) + Start.States.emplace_back(std::move(State)); + + for (auto& [Id, State] : After) + End.States.emplace_back(std::move(State)); + + if (!Start.Order) + Start.Order = std::move(NextStart.Order); + + if (NextEnd.Order) + End.Order = std::move(NextEnd.Order); + + Compact(Start, End); + } + + template + std::unordered_map RestoreObjects(std::vector>& Objects) const + { + std::unordered_map ObjectsById; + + if (!Order) + { + ObjectsById.reserve(Objects.size()); + + for (const std::unique_ptr& Object : Objects) + ObjectsById.emplace(static_cast(Object->GetId()), Object.get()); + + return ObjectsById; + } + + std::unordered_map ObjectIndices; + ObjectIndices.reserve(Objects.size()); + + for (size_t Index = 0; Index < Objects.size(); Index++) + ObjectIndices.emplace(static_cast(Objects[Index]->GetId()), Index); + + std::unordered_set StateIds; + std::vector> NewObjects; + + for (const StateType& State : States) + StateIds.emplace(static_cast(State.Id)); + + NewObjects.reserve(Order->size()); + ObjectsById.reserve(Order->size()); + + for (uint32_t Id : *Order) + { + const auto Object = ObjectIndices.find(Id); + + if (Object != ObjectIndices.end()) + NewObjects.emplace_back(std::move(Objects[Object->second])); + else if (StateIds.find(Id) != StateIds.end()) + NewObjects.emplace_back(std::make_unique()); + else + continue; // A non-undoable model-list change may have removed it. + + // New objects do not have their saved IDs until their state is restored. + ObjectsById.emplace(Id, NewObjects.back().get()); + } + + Objects = std::move(NewObjects); + + return ObjectsById; + } +}; diff --git a/common/lc_objectproperty.h b/common/lc_objectproperty.h index 432863c5..e9546924 100644 --- a/common/lc_objectproperty.h +++ b/common/lc_objectproperty.h @@ -61,6 +61,11 @@ struct lcObjectPropertyKey { lcStep Step; T Value; + + bool operator==(const lcObjectPropertyKey& Other) const + { + return Step == Other.Step && Value == Other.Value; + } }; template @@ -79,6 +84,11 @@ public: return mValue; } + bool operator==(const lcObjectProperty& Other) const + { + return mValue == Other.mValue && mKeys == Other.mKeys; + } + void SetValue(const T& Value) { mValue = Value; diff --git a/common/light.cpp b/common/light.cpp index 0242b797..37f1360d 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -1511,7 +1511,7 @@ void lcLight::RemoveKeyFrames() mPOVRayFadePower.RemoveAllKeys(); } -lcLightHistoryState lcLight::GetHistoryState([[maybe_unused]] const lcModel* Model) const +lcLightHistoryState lcLight::GetHistoryState() const { lcLightHistoryState State; @@ -1541,7 +1541,7 @@ lcLightHistoryState lcLight::GetHistoryState([[maybe_unused]] const lcModel* Mod return State; } -void lcLight::SetHistoryState(const lcLightHistoryState& State, [[maybe_unused]] const lcModel* Model) +void lcLight::SetHistoryState(const lcLightHistoryState& State) { mId = State.Id; mHidden = State.Hidden; diff --git a/common/light.h b/common/light.h index a5012ae2..73c4add4 100644 --- a/common/light.h +++ b/common/light.h @@ -197,8 +197,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - lcLightHistoryState GetHistoryState(const lcModel* Model) const; - void SetHistoryState(const lcLightHistoryState& State, const lcModel* Model); + lcLightHistoryState GetHistoryState() const; + void SetHistoryState(const lcLightHistoryState& State); void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); diff --git a/common/piece.cpp b/common/piece.cpp index 4135f336..0b5e0c5c 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -988,7 +988,7 @@ void lcPiece::RemoveKeyFrames() mRotation.RemoveAllKeys(); } -lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const +lcPieceHistoryState lcPiece::GetHistoryState() const { lcPieceHistoryState State; @@ -996,7 +996,7 @@ lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const State.Hidden = mHidden; State.FileLine = mFileLine; State.PieceId = mID; - State.GroupIndex = ~0U; + State.GroupId = mGroup ? static_cast(mGroup->GetId()) : LC_GROUP_ID_INVALID; State.ColorIndex = mColorIndex; State.ColorCode = mColorCode; State.StepShow = mStepShow; @@ -1007,32 +1007,16 @@ lcPieceHistoryState lcPiece::GetHistoryState(const lcModel* Model) const State.Position = mPosition; State.Rotation = mRotation; - const std::vector>& Groups = Model->GetGroups(); - - if (mGroup) - { - for (size_t GroupIndex = 0; GroupIndex < Groups.size(); GroupIndex++) - { - if (mGroup == Groups[GroupIndex].get()) - { - State.GroupIndex = static_cast(GroupIndex); - break; - } - } - } - return State; } -void lcPiece::SetHistoryState(const lcPieceHistoryState& State, const lcModel* Model) +void lcPiece::SetHistoryState(const lcPieceHistoryState& State, Project* Project, lcGroup* Group) { - 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; + mGroup = Group; mColorIndex = State.ColorIndex; mColorCode = State.ColorCode; mStepShow = State.StepShow; @@ -1043,7 +1027,7 @@ void lcPiece::SetHistoryState(const lcPieceHistoryState& State, const lcModel* M mPosition = State.Position; mRotation = State.Rotation; - lcPieceDataRef RestoredData = lcGetPiecesLibrary()->AcquirePieceData(mID.toLatin1(), Model->GetProject(), true, true); + lcPieceDataRef RestoredData = lcGetPiecesLibrary()->AcquirePieceData(mID.toLatin1(), Project, true, true); if (mPieceData != RestoredData) { diff --git a/common/piece.h b/common/piece.h index a548fe5d..ee499993 100644 --- a/common/piece.h +++ b/common/piece.h @@ -35,7 +35,7 @@ struct lcPieceHistoryState bool Hidden; int FileLine; QString PieceId; - uint32_t GroupIndex; + uint32_t GroupId; int ColorIndex; quint32 ColorCode; lcStep StepShow; @@ -49,7 +49,7 @@ struct lcPieceHistoryState 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 && + GroupId == Other.GroupId && 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; @@ -95,8 +95,8 @@ public: bool HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const override; bool SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame) override; void RemoveKeyFrames() override; - lcPieceHistoryState GetHistoryState(const lcModel* Model) const; - void SetHistoryState(const lcPieceHistoryState& State, const lcModel* Model); + lcPieceHistoryState GetHistoryState() const; + void SetHistoryState(const lcPieceHistoryState& State, Project* Project, lcGroup* Group); void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const; void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const; diff --git a/leocad.pro b/leocad.pro index 3b2ad939..1a46edbf 100644 --- a/leocad.pro +++ b/leocad.pro @@ -304,6 +304,7 @@ HEADERS += \ common/lc_minifigdialog.h \ common/lc_model.h \ common/lc_modellistdialog.h \ + common/lc_objecthistory.h \ common/lc_objectproperty.h \ common/lc_pagesetupdialog.h \ common/lc_partpalettedialog.h \