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;