Saved undo data as structures.

This commit is contained in:
Leonardo Zide
2026-02-11 20:15:26 -08:00
parent 576f9fe13e
commit fb71e545a9
17 changed files with 443 additions and 519 deletions
+34 -24
View File
@@ -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
+27 -4
View File
@@ -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<lcVector3> Position;
lcObjectProperty<lcVector3> TargetPosition;
lcObjectProperty<lcVector3> 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;
};
+39 -1
View File
@@ -1,11 +1,15 @@
#include "lc_global.h"
#include <stdlib.h>
#include "group.h"
#include "lc_model.h"
#include "lc_file.h"
lcGroupId lcGroup::mNextId;
lcGroup::lcGroup()
: mId(mNextId)
{
mGroup = nullptr;
mNextId = static_cast<lcGroupId>(static_cast<uint32_t>(mNextId) + 1);
}
void lcGroup::FileLoad(lcFile* File)
@@ -58,3 +62,37 @@ void lcGroup::CreateName(const std::vector<std::unique_ptr<lcGroup>>& 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<std::unique_ptr<lcGroup>>& 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<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
mId = State.Id;
mName = State.Name;
mGroup = (State.ParentIndex < Groups.size()) ? Groups[State.ParentIndex].get() : nullptr;
}
+30 -4
View File
@@ -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<std::unique_ptr<lcGroup>>& 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<lcGroupId>(0);
static lcGroupId mNextId;
};
+5
View File
@@ -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)
+48 -4
View File
@@ -1809,6 +1809,49 @@ void lcModel::RunSelectionAction(const lcModelActionSelection* ModelActionSelect
ModelActionSelection->LoadStartState(this);
}
template<typename StateType, typename ObjectType>
void lcModel::LoadObjectHistoryState(const std::vector<StateType>& ObjectStates, std::vector<std::unique_ptr<ObjectType>>& Objects)
{
std::vector<std::unique_ptr<ObjectType>> 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<lcModelActionObjectEdit> ModelActionObjectEdit = std::make_unique<lcModelActionObjectEdit>(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<size_t>&& 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);
+6 -1
View File
@@ -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<typename StateType, typename ObjectType>
void LoadObjectHistoryState(const std::vector<StateType>& ObjectStates, std::vector<std::unique_ptr<ObjectType>>& Objects);
void LoadHistoryState(const lcModelHistoryState& HistoryState);
lcPiece* AddPiece(PieceInfo* Info, quint32 Section);
void AddPiece(std::unique_ptr<lcPiece> Piece, size_t PieceIndex);
void RemovePieces(const std::vector<size_t>& PieceIndices);
+28 -300
View File
@@ -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<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
for (const std::unique_ptr<lcGroup>& Group : Groups)
State.Groups.emplace_back(Group->GetHistoryState(Model));
const std::vector<std::unique_ptr<lcPiece>>& Pieces = Model->GetPieces();
for (const std::unique_ptr<lcPiece>& Piece : Pieces)
State.Pieces.emplace_back(Piece->GetHistoryState(Model));
const std::vector<std::unique_ptr<lcCamera>>& Cameras = Model->GetCameras();
for (const std::unique_ptr<lcCamera>& Camera : Cameras)
State.Cameras.emplace_back(Camera->GetHistoryState(Model));
const std::vector<std::unique_ptr<lcLight>>& Lights = Model->GetLights();
uint64_t ObjectCount[4] = { Groups.size(), Pieces.size(), Cameras.size(), Lights.size() };
if (Stream.writeRawData(reinterpret_cast<const char*>(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<lcLight>& 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<QByteArray*>(&Buffer), QIODevice::ReadOnly);
const std::vector<std::unique_ptr<lcGroup>>& Groups = Model->GetGroups();
const std::vector<std::unique_ptr<lcPiece>>& Pieces = Model->GetPieces();
const std::vector<std::unique_ptr<lcCamera>>& Cameras = Model->GetCameras();
const std::vector<std::unique_ptr<lcLight>>& Lights = Model->GetLights();
uint64_t ObjectCount[4];
if (Stream.readRawData(reinterpret_cast<char*>(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<lcGroup> 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<lcPiece> 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<lcCamera> 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<lcLight> 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<lcPiece>& 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<lcCamera>& 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<lcLight>& 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<std::unique_ptr<lcPiece>>& Pieces = Model->GetPieces();
const std::vector<std::unique_ptr<lcCamera>>& Cameras = Model->GetCameras();
const std::vector<std::unique_ptr<lcLight>>& 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<size_t>&& ObjectIndices, std::vector<size_t>&& GroupIndices)
void lcModelActionObjectEdit::SaveEndState(const lcModel* Model, std::vector<size_t>&& ObjectIndices, std::vector<size_t>&& 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)
+26 -17
View File
@@ -60,34 +60,43 @@ enum class lcModelActionObjectEditMode
CreateLight
};
struct lcGroupHistoryState;
struct lcPieceHistoryState;
struct lcCameraHistoryState;
struct lcLightHistoryState;
struct lcModelHistoryState
{
std::vector<lcGroupHistoryState> Groups;
std::vector<lcPieceHistoryState> Pieces;
std::vector<lcCameraHistoryState> Cameras;
std::vector<lcLightHistoryState> 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<size_t>&& ObjectIndices, std::vector<size_t>&& GroupIndices);
void SaveStartState(const lcModel* Model, const lcCamera* Camera);
void SaveEndState(const lcModel* Model, std::vector<size_t>&& ObjectIndices, std::vector<size_t>&& 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<size_t> mGroupIndices;
std::vector<size_t> mPieceIndices;
std::vector<size_t> mCameraIndices;
std::vector<size_t> mLightIndices;
lcModelActionObjectEditMode mMode;
QByteArray mStartBuffer;
QByteArray mEndBuffer;
lcModelHistoryState mStartState;
lcModelHistoryState mEndState;
};
enum class lcModelActionGroupPiecesMode
+1 -42
View File
@@ -10,9 +10,7 @@
template bool lcObjectProperty<T>::HasKeyFrame(lcStep Time) const; \
template bool lcObjectProperty<T>::SetKeyFrame(lcStep Time, bool KeyFrame); \
template void lcObjectProperty<T>::Save(QTextStream& Stream, const char* ObjectName, const char* VariableName, bool SaveEmpty) const; \
template bool lcObjectProperty<T>::Load(QTextStream& Stream, const QString& Token, const char* VariableName); \
template bool lcObjectProperty<T>::SaveUndoData(QDataStream& Stream) const; \
template bool lcObjectProperty<T>::LoadUndoData(QDataStream& Stream);
template bool lcObjectProperty<T>::Load(QTextStream& Stream, const QString& Token, const char* VariableName);
LC_OBJECT_PROPERTY(float)
LC_OBJECT_PROPERTY(int)
@@ -314,42 +312,3 @@ bool lcObjectProperty<T>::Load(QTextStream& Stream, const QString& Token, const
return false;
}
template<typename T>
bool lcObjectProperty<T>::SaveUndoData(QDataStream& Stream) const
{
size_t KeyCount = mKeys.size();
qint64 DataSize = KeyCount * sizeof(lcObjectPropertyKey<T>);
if (Stream.writeRawData(reinterpret_cast<const char*>(&mValue), sizeof(mValue)) != sizeof(mValue))
return false;
if (Stream.writeRawData(reinterpret_cast<const char*>(&KeyCount), sizeof(KeyCount)) != sizeof(KeyCount))
return false;
if (Stream.writeRawData(reinterpret_cast<const char*>(mKeys.data()), DataSize) != DataSize)
return false;
return true;
}
template<typename T>
bool lcObjectProperty<T>::LoadUndoData(QDataStream& Stream)
{
if (Stream.readRawData(reinterpret_cast<char*>(&mValue), sizeof(mValue)) != sizeof(mValue))
return false;
size_t KeyCount;
if (Stream.readRawData(reinterpret_cast<char*>(&KeyCount), sizeof(KeyCount)) != sizeof(KeyCount))
return false;
mKeys.resize(KeyCount);
qsizetype DataSize = KeyCount * sizeof(lcObjectPropertyKey<T>);
if (Stream.readRawData(reinterpret_cast<char*>(mKeys.data()), DataSize) != DataSize)
return false;
return true;
}
+3 -3
View File
@@ -67,11 +67,13 @@ template<typename T>
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;
+53 -39
View File
@@ -19,6 +19,11 @@
static const std::array<QLatin1String, static_cast<int>(lcLightType::Count)> gLightTypes = { QLatin1String("POINT"), QLatin1String("SPOT"), QLatin1String("DIRECTIONAL"), QLatin1String("AREA") };
static const std::array<QLatin1String, static_cast<int>(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;
}
+40 -2
View File
@@ -28,9 +28,47 @@ enum class lcLightAreaShape
Count
};
struct lcLightHistoryState
{
lcObjectId Id;
bool Hidden;
QString Name;
lcLightType LightType;
bool CastShadow;
lcObjectProperty<lcVector3> Position;
lcObjectProperty<lcMatrix33> Rotation;
lcObjectProperty<lcVector3> Color;
lcObjectProperty<float> BlenderPower;
lcObjectProperty<float> BlenderRadius;
lcObjectProperty<float> BlenderAngle;
lcObjectProperty<float> POVRayPower;
lcObjectProperty<float> POVRayFadeDistance;
lcObjectProperty<float> POVRayFadePower;
lcObjectProperty<float> SpotConeAngle;
lcObjectProperty<float> SpotPenumbraAngle;
lcObjectProperty<float> POVRaySpotTightness;
lcLightAreaShape AreaShape;
lcObjectProperty<float> AreaSizeX;
lcObjectProperty<float> AreaSizeY;
lcObjectProperty<int> POVRayAreaGridX;
lcObjectProperty<int> 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);
+4 -1
View File
@@ -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<lcObjectId>(static_cast<uint32_t>(mNextId) + 1);
}
lcObject::~lcObject()
+10 -2
View File
@@ -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<lcObjectId>(0);
static lcObjectId mNextId;
};
+49 -68
View File
@@ -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<std::unique_ptr<lcGroup>>& 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<const char*>(&ControlPointCount), sizeof(ControlPointCount)) != sizeof(ControlPointCount))
return false;
if (Stream.writeRawData(reinterpret_cast<const char*>(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<std::unique_ptr<lcGroup>>& 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<std::unique_ptr<lcGroup>>& 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<char*>(&ControlPointCount), sizeof(ControlPointCount)) != sizeof(ControlPointCount))
return false;
mControlPoints.resize(ControlPointCount);
qsizetype DataSize = ControlPointCount * sizeof(lcPieceControlPoint);
if (Stream.readRawData(reinterpret_cast<char*>(mControlPoints.data()), DataSize) != DataSize)
return false;
UpdateMesh();
// std::vector<bool> mTrainTrackConnections;
return mPosition.LoadUndoData(Stream) && mRotation.LoadUndoData(Stream);
// std::vector<bool> mTrainTrackConnections;
}
void lcPiece::AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const
+40 -7
View File
@@ -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<lcPieceControlPoint> ControlPoints;
lcObjectProperty<lcVector3> Position;
lcObjectProperty<lcMatrix33> 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<lcPieceControlPoint> mControlPoints;