From 661fa680112e5b0310c122e531af1cff26e4ebac Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 2 Sep 2014 03:44:51 +0000 Subject: [PATCH] Changed the LDraw exporter to include more features in extensions. --- common/camera.cpp | 168 +++++++++++++-- common/camera.h | 20 +- common/lc_global.h | 1 + common/lc_model.cpp | 502 ++++++++++++++++++++++++++++++++++++++++++-- common/lc_model.h | 19 +- common/light.cpp | 4 + common/light.h | 1 + common/object.cpp | 27 +-- common/object.h | 103 ++++++++- common/piece.cpp | 176 ++++++++++++++-- common/piece.h | 9 +- common/project.cpp | 86 ++------ common/project.h | 1 - 13 files changed, 975 insertions(+), 142 deletions(-) diff --git a/common/camera.cpp b/common/camera.cpp index e29790af..d34c8c23 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -78,6 +78,22 @@ void lcCamera::Initialize() void lcCamera::CreateName(const lcArray& Cameras) { + if (m_strName[0]) + { + bool Found = false; + for (int CameraIdx = 0; CameraIdx < Cameras.GetSize(); CameraIdx++) + { + if (!strcmp(Cameras[CameraIdx]->m_strName, m_strName)) + { + Found = true; + break; + } + } + + if (!Found) + return; + } + int i, max = 0; const char* Prefix = "Camera "; @@ -90,40 +106,168 @@ void lcCamera::CreateName(const lcArray& Cameras) sprintf(m_strName, "%s %d", Prefix, max+1); } -QJsonObject lcCamera::Save() +void lcCamera::SaveLDraw(lcFile& File) const +{ + char Line[1024]; + + if (IsHidden()) + { + strcpy(Line, "0 !LEOCAD CAMERA HIDDEN\r\n"); + File.WriteBuffer(Line, strlen(Line)); + } + + if (IsOrtho()) + { + strcpy(Line, "0 !LEOCAD CAMERA ORTHOGRAPHIC\r\n"); + File.WriteBuffer(Line, strlen(Line)); + } + + sprintf(Line, "0 !LEOCAD CAMERA FOV %.2f\r\n", m_fovy); + File.WriteBuffer(Line, strlen(Line)); + + sprintf(Line, "0 !LEOCAD CAMERA ZNEAR %.2f\r\n", m_zNear); + File.WriteBuffer(Line, strlen(Line)); + + sprintf(Line, "0 !LEOCAD CAMERA ZFAR %.2f\r\n", m_zFar); + File.WriteBuffer(Line, strlen(Line)); + + if (mPositionKeys.GetSize() > 1) + SaveKeysLDraw(mPositionKeys, "CAMERA POSITION_KEY", File); + else + { + sprintf(Line, "0 !LEOCAD CAMERA POSITION %.2f %.2f %.2f\r\n", mPosition[0], mPosition[1], mPosition[2]); + File.WriteBuffer(Line, strlen(Line)); + } + + if (mTargetPositionKeys.GetSize() > 1) + SaveKeysLDraw(mTargetPositionKeys, "CAMERA TARGETPOSITION_KEY", File); + else + { + sprintf(Line, "0 !LEOCAD CAMERA TARGETPOSITION %.2f %.2f %.2f\r\n", mTargetPosition[0], mTargetPosition[1], mTargetPosition[2]); + File.WriteBuffer(Line, strlen(Line)); + } + + if (mUpVectorKeys.GetSize() > 1) + SaveKeysLDraw(mUpVectorKeys, "CAMERA UPVECTOR_KEY", File); + else + { + sprintf(Line, "0 !LEOCAD CAMERA UPVECTOR %.2f %.2f %.2f\r\n", mUpVector[0], mUpVector[1], mUpVector[2]); + File.WriteBuffer(Line, strlen(Line)); + } + + sprintf(Line, "0 !LEOCAD CAMERA NAME %s\r\n", m_strName); + File.WriteBuffer(Line, strlen(Line)); +} + +bool lcCamera::ParseLDrawLine(QString& Line) +{ + QRegExp TokenExp("\\s*(\\w+)\\s+(.*)"); + + if (!Line.contains(TokenExp)) + return false; + + QString Token = TokenExp.cap(1); + Line = TokenExp.cap(2); + + if (Token == QStringLiteral("HIDDEN")) + SetHidden(true); + else if (Token == QStringLiteral("ORTHOGRAPHIC")) + SetOrtho(true); + else if (Token == QStringLiteral("FOV")) + m_fovy = Line.toFloat(); + else if (Token == QStringLiteral("ZNEAR")) + m_zNear = Line.toFloat(); + else if (Token == QStringLiteral("ZFAR")) + m_zFar = Line.toFloat(); + else if (Token == QStringLiteral("POSITION")) + QTextStream(&Line) >> mPosition[0] >> mPosition[1] >> mPosition[2]; + else if (Token == QStringLiteral("TARGETPOSITION")) + QTextStream(&Line) >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2]; + else if (Token == QStringLiteral("UPVECTOR")) + QTextStream(&Line) >> mUpVector[0] >> mUpVector[1] >> mUpVector[2]; + else if (Token == QStringLiteral("POSITION_KEY")) + LoadKeyLDraw(mPositionKeys, Line); + else if (Token == QStringLiteral("TARGETPOSITION_KEY")) + LoadKeyLDraw(mTargetPositionKeys, Line); + else if (Token == QStringLiteral("UPVECTOR_KEY")) + LoadKeyLDraw(mUpVectorKeys, Line); + else if (Token == QStringLiteral("NAME")) + { + QByteArray NameUtf = Line.toUtf8(); // todo: replace with qstring + strncpy(m_strName, NameUtf.constData(), sizeof(m_strName)); + m_strName[sizeof(m_strName) - 1] = 0; + return true; + } + + return false; +} + +QJsonObject lcCamera::SaveJson() const { QJsonObject Camera; - Camera[QStringLiteral("FOV")] = QString::number(m_fovy); - Camera[QStringLiteral("ZNear")] = QString::number(m_zNear); - Camera[QStringLiteral("ZFar")] = QString::number(m_zFar); - Camera[QStringLiteral("Name")] = QString::fromLatin1(m_strName); // todo: replace with qstring + Camera[QStringLiteral("FOV")] = m_fovy; + Camera[QStringLiteral("ZNear")] = m_zNear; + Camera[QStringLiteral("ZFar")] = m_zFar; + Camera[QStringLiteral("Name")] = QString::fromUtf8(m_strName); // todo: replace with qstring if (IsHidden()) Camera[QStringLiteral("Hidden")] = QStringLiteral("true"); if (IsOrtho()) Camera[QStringLiteral("Orthographic")] = QStringLiteral("true"); if (mPositionKeys.GetSize() < 2) - Camera[QStringLiteral("Position")] = QStringLiteral("%1 %2 %3").arg(QString::number(mPosition[0]), QString::number(mPosition[1]), QString::number(mPosition[2])); + Camera[QStringLiteral("Position")] = QJsonArray() << mPosition[0] << mPosition[1] << mPosition[2]; else - Camera[QStringLiteral("PositionKeys")] = SaveKeys(mPositionKeys); + Camera[QStringLiteral("PositionKeys")] = SaveKeysJson(mPositionKeys); if (mTargetPositionKeys.GetSize() < 2) - Camera[QStringLiteral("TargetPosition")] = QStringLiteral("%1 %2 %3").arg(QString::number(mTargetPosition[0]), QString::number(mTargetPosition[1]), QString::number(mTargetPosition[2])); + Camera[QStringLiteral("TargetPosition")] = QJsonArray() << mTargetPosition[0] << mTargetPosition[1] << mTargetPosition[2]; else - Camera[QStringLiteral("TargetPositionKeys")] = SaveKeys(mTargetPositionKeys); + Camera[QStringLiteral("TargetPositionKeys")] = SaveKeysJson(mTargetPositionKeys); if (mUpVectorKeys.GetSize() < 2) - Camera[QStringLiteral("UpVector")] = QStringLiteral("%1 %2 %3").arg(QString::number(mUpVector[0]), QString::number(mUpVector[1]), QString::number(mUpVector[2])); + Camera[QStringLiteral("UpVector")] = QJsonArray() << mUpVector[0] << mUpVector[1] << mUpVector[2]; else - Camera[QStringLiteral("UpVectorKeys")] = SaveKeys(mUpVectorKeys); + Camera[QStringLiteral("UpVectorKeys")] = SaveKeysJson(mUpVectorKeys); return Camera; } -void lcCamera::Load(QJsonObject Camera) +bool lcCamera::LoadJson(const QJsonObject& Camera) { + QJsonValue FOV = Camera.value(QStringLiteral("FOV")); + if (!FOV.isUndefined()) + m_fovy = FOV.toDouble(); + QJsonValue ZNear = Camera.value(QStringLiteral("ZNear")); + if (!ZNear.isUndefined()) + m_zNear = ZNear.toDouble(); + + QJsonValue ZFar = Camera.value(QStringLiteral("ZFar")); + if (!ZFar.isUndefined()) + m_zFar = ZFar.toDouble(); + + QJsonValue Name = Camera.value(QStringLiteral("Name")); + if (!Name.isUndefined()) + { + QByteArray NameUtf = Name.toString().toUtf8(); // todo: replace with qstring + strncpy(m_strName, NameUtf.constData(), sizeof(m_strName)); + m_strName[sizeof(m_strName) - 1] = 0; + } + + QJsonValue Hidden = Camera.value(QStringLiteral("Hidden")); + if (!Hidden.isUndefined()) + SetHidden(Hidden.toBool()); + + QJsonValue Ortho = Camera.value(QStringLiteral("Orthographic")); + if (!Ortho.isUndefined()) + SetOrtho(Ortho.toBool()); + + LoadKeysJson(mPositionKeys, Camera.value(QStringLiteral("PositionKeys")), mPosition, Camera.value(QStringLiteral("Position"))); + LoadKeysJson(mTargetPositionKeys, Camera.value(QStringLiteral("TargetPositionKeys")), mTargetPosition, Camera.value(QStringLiteral("TargetPosition"))); + LoadKeysJson(mUpVectorKeys, Camera.value(QStringLiteral("UpVectorKeys")), mUpVector, Camera.value(QStringLiteral("UpVector"))); + + return true; } ///////////////////////////////////////////////////////////////////////////// diff --git a/common/camera.h b/common/camera.h index 5c5dd09d..2cbeabcf 100644 --- a/common/camera.h +++ b/common/camera.h @@ -220,8 +220,11 @@ public: return lcVector3(0.0f, 0.0f, 0.0f); } - QJsonObject Save(); - void Load(QJsonObject Camera); + void SaveLDraw(lcFile& File) const; + bool ParseLDrawLine(QString& Line); + + QJsonObject SaveJson() const; + bool LoadJson(const QJsonObject& Camera); @@ -237,8 +240,19 @@ public: { return m_nType < LC_CAMERA_MAIN; } bool IsVisible() const { return (mState & LC_CAMERA_HIDDEN) == 0; } + bool IsHidden() const - { return (mState & LC_CAMERA_HIDDEN) != 0; } + { + return (mState & LC_CAMERA_HIDDEN) != 0; + } + + void SetHidden(bool Hidden) + { + if (Hidden) + mState |= LC_CAMERA_HIDDEN; + else + mState &= ~LC_CAMERA_HIDDEN; + } void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey) { diff --git a/common/lc_global.h b/common/lc_global.h index 56b799c6..847f0dce 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -10,6 +10,7 @@ #define LC_VERSION_TEXT "0.80.4" // Forward declarations. +class lcModel; class lcObject; class lcPiece; class lcCamera; diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 41a2e1fb..2364e20a 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3,8 +3,10 @@ #include "piece.h" #include "camera.h" #include "light.h" +#include "group.h" #include "lc_mainwindow.h" #include "lc_profile.h" +#include "lc_library.h" void lcModelProperties::LoadDefaults() { @@ -38,18 +40,177 @@ void lcModelProperties::SaveDefaults() lcSetProfileInt(LC_PROFILE_DEFAULT_AMBIENT_COLOR, lcColorFromVector3(mAmbientColor)); } -QJsonObject lcModelProperties::Save() +void lcModelProperties::SaveLDraw(lcFile& File) const +{ + char Line[1024]; + + if (!mName.IsEmpty()) + { + sprintf(Line, "0 !LEOCAD MODEL NAME %s\r\n", mName); + File.WriteBuffer(Line, strlen(Line)); + } + + if (!mAuthor.IsEmpty()) + { + sprintf(Line, "0 !LEOCAD MODEL AUTHOR %s\r\n", mAuthor); + File.WriteBuffer(Line, strlen(Line)); + } + + if (!mDescription.IsEmpty()) + { + sprintf(Line, "0 !LEOCAD MODEL DESCRIPTION %s\r\n", mDescription); + File.WriteBuffer(Line, strlen(Line)); + } + + if (!mComments.IsEmpty()) + { + sprintf(Line, "0 !LEOCAD MODEL COMMENTS %s\r\n", mComments); + File.WriteBuffer(Line, strlen(Line)); + } + + switch (mBackgroundType) + { + case LC_BACKGROUND_SOLID: + strcpy(Line, "0 !LEOCAD MODEL BACKGROUND_TYPE SOLID\r\n"); + File.WriteBuffer(Line, strlen(Line)); + break; + case LC_BACKGROUND_GRADIENT: + strcpy(Line, "0 !LEOCAD MODEL BACKGROUND_TYPE GRADIENT\r\n"); + File.WriteBuffer(Line, strlen(Line)); + break; + case LC_BACKGROUND_IMAGE: + strcpy(Line, "0 !LEOCAD MODEL BACKGROUND_TYPE IMAGE\r\n"); + File.WriteBuffer(Line, strlen(Line)); + break; + } + + sprintf(Line, "0 !LEOCAD MODEL BACKGROUND SOLID_COLOR %.2f %.2f %.2f\r\n", mBackgroundSolidColor[0], mBackgroundSolidColor[1], mBackgroundSolidColor[2]); + File.WriteBuffer(Line, strlen(Line)); + + sprintf(Line, "0 !LEOCAD MODEL BACKGROUND GRADIENT_COLORS %.2f %.2f %.2f %.2f %.2f %.2f\r\n", mBackgroundGradientColor1[0], mBackgroundGradientColor1[1], mBackgroundGradientColor1[2], mBackgroundGradientColor2[0], mBackgroundGradientColor2[1], mBackgroundGradientColor2[2]); + File.WriteBuffer(Line, strlen(Line)); + + if (!mBackgroundImage.IsEmpty()) + { + sprintf(Line, "0 !LEOCAD MODEL BACKGROUND IMAGE_NAME %s\r\n", mBackgroundImage); + File.WriteBuffer(Line, strlen(Line)); + } + + if (mBackgroundImageTile) + { + strcat(Line, "0 !LEOCAD MODEL BACKGROUND IMAGE_TILE\r\n"); + File.WriteBuffer(Line, strlen(Line)); + } + +// bool mFogEnabled; +// float mFogDensity; +// lcVector3 mFogColor; +// lcVector3 mAmbientColor; +} + +void lcModelProperties::ParseLDrawLine(char** Tokens) +{ + if (!Tokens[4]) + return; + + strupr(Tokens[4]); + + if (!strcmp(Tokens[4], "NAME")) + { + if (Tokens[5]) + { + strncpy(mName, Tokens[5], sizeof(mName)); + mName[sizeof(mName) - 1] = 0; + } + else + mName[0] = 0; + } + else if (!strcmp(Tokens[4], "AUTHOR")) + { + if (Tokens[5]) + { + strncpy(mAuthor, Tokens[5], sizeof(mAuthor)); + mAuthor[sizeof(mAuthor) - 1] = 0; + } + else + mAuthor[0] = 0; + } + else if (!strcmp(Tokens[4], "DESCRIPTION")) + { + if (Tokens[5]) + { + strncpy(mDescription, Tokens[5], sizeof(mDescription)); + mDescription[sizeof(mDescription) - 1] = 0; + } + else + mDescription[0] = 0; + } + else if (!strcmp(Tokens[4], "COMMENTS")) + { + if (Tokens[5]) + { + strncpy(mComments, Tokens[5], sizeof(mComments)); + mComments[sizeof(mComments) - 1] = 0; + } + else + mComments[0] = 0; + } + else if (!strcmp(Tokens[4], "BACKGROUND_TYPE")) + { + if (Tokens[5]) + { + strupr(Tokens[5]); + + if (!strcmp(Tokens[5], "SOLID")) + mBackgroundType = LC_BACKGROUND_SOLID; + else if (!strcmp(Tokens[5], "GRADIENT")) + mBackgroundType = LC_BACKGROUND_GRADIENT; + else if (!strcmp(Tokens[5], "IMAGE")) + mBackgroundType = LC_BACKGROUND_IMAGE; + } + } + else if (!strcmp(Tokens[4], "BACKGROUND")) + { + if (Tokens[5]) + { + strupr(Tokens[5]); + + } + } + +/* + sprintf(Line, "0 !LEOCAD MODEL BACKGROUND SOLID_COLOR %.2f %.2f %.2f\r\n", mBackgroundSolidColor[0], mBackgroundSolidColor[1], mBackgroundSolidColor[2]); + File.WriteBuffer(Line, strlen(Line)); + + sprintf(Line, "0 !LEOCAD MODEL BACKGROUND GRADIENT_COLORS %.2f %.2f %.2f %.2f %.2f %.2f\r\n", mBackgroundGradientColor1[0], mBackgroundGradientColor1[1], mBackgroundGradientColor1[2], mBackgroundGradientColor2[0], mBackgroundGradientColor2[1], mBackgroundGradientColor2[2]); + File.WriteBuffer(Line, strlen(Line)); + + if (!mBackgroundImage.IsEmpty()) + { + sprintf(Line, "0 !LEOCAD MODEL BACKGROUND IMAGE_NAME %s\r\n", mBackgroundImage); + File.WriteBuffer(Line, strlen(Line)); + } + + if (mBackgroundImageTile) + { + strcat(Line, "0 !LEOCAD MODEL BACKGROUND IMAGE_TILE\r\n"); + File.WriteBuffer(Line, strlen(Line)); + } +*/ +} + +QJsonObject lcModelProperties::Save() const { QJsonObject Properties; if (!mName.IsEmpty()) - Properties[QStringLiteral("Name")] = QString::fromLatin1(mName.Buffer()); + Properties[QStringLiteral("Name")] = QString::fromLatin1(mName); // todo: qstring if (!mAuthor.IsEmpty()) - Properties[QStringLiteral("Author")] = QString::fromLatin1(mAuthor.Buffer()); + Properties[QStringLiteral("Author")] = QString::fromLatin1(mAuthor); if (!mDescription.IsEmpty()) - Properties[QStringLiteral("Description")] = QString::fromLatin1(mDescription.Buffer()); + Properties[QStringLiteral("Description")] = QString::fromLatin1(mDescription); if (!mComments.IsEmpty()) - Properties[QStringLiteral("Comments")] = QString::fromLatin1(mComments.Buffer()); + Properties[QStringLiteral("Comments")] = QString::fromLatin1(mComments); switch (mBackgroundType) { @@ -68,7 +229,7 @@ QJsonObject lcModelProperties::Save() Properties[QStringLiteral("BackgroundGradientColor1")] = QStringLiteral("%1 %2 %3").arg(QString::number(mBackgroundGradientColor1[0]), QString::number(mBackgroundGradientColor1[1]), QString::number(mBackgroundGradientColor1[2])); Properties[QStringLiteral("BackgroundGradientColor2")] = QStringLiteral("%1 %2 %3").arg(QString::number(mBackgroundGradientColor2[0]), QString::number(mBackgroundGradientColor2[1]), QString::number(mBackgroundGradientColor2[2])); if (!mBackgroundImage.IsEmpty()) - Properties[QStringLiteral("BackgroundImage")] = QString::fromLatin1(mBackgroundImage.Buffer()); + Properties[QStringLiteral("BackgroundImage")] = QString::fromLatin1(mBackgroundImage); // todo: qstring if (mBackgroundImageTile) Properties[QStringLiteral("BackgroundImageTile")] = QStringLiteral("true"); @@ -81,8 +242,9 @@ QJsonObject lcModelProperties::Save() return Properties; } -void lcModelProperties::Load(QJsonObject Properties) +bool lcModelProperties::Load(const QJsonObject& Properties) { + return true; } lcModel::lcModel() @@ -94,21 +256,208 @@ lcModel::~lcModel() { } -QJsonObject lcModel::Save() +void lcModel::SaveLDraw(lcFile& File) const +{ + mProperties.SaveLDraw(File); + + lcStep LastStep = GetLastStep(); + + if (mCurrentStep != LastStep) + { + char Line[1024]; + sprintf(Line, "0 !LEOCAD MODEL CURRENT_STEP %d\r\n", mCurrentStep); + File.WriteBuffer(Line, strlen(Line)); + } + + for (lcStep Step = 1; Step <= LastStep; Step++) + { + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* Piece = mPieces[PieceIdx]; + + if (Piece->GetStepShow() == Step) + Piece->SaveLDraw(File); + } + + if (Step != LastStep) + File.WriteBuffer("0 STEP\r\n", 8); + } + + for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++) + mCameras[CameraIdx]->SaveLDraw(File); + + for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++) + mLights[LightIdx]->SaveLDraw(File); + +// lcArray mGroups; +} + +void lcModel::LoadLDraw(const QStringList& Lines, const lcMatrix44& CurrentTransform, int DefaultColorCode, int& CurrentStep) +{ + QRegExp TokenExp("\\s*(!?\\w+)\\s+(.*)"); + lcPiece* Piece = NULL; + lcCamera* Camera = NULL; + lcLight* Light = NULL; + + for (int LineIdx = 0; LineIdx < Lines.size(); LineIdx++) + { + QString Line = Lines[LineIdx].trimmed(); + + if (!Line.contains(TokenExp)) + continue; + + QString Token = TokenExp.cap(1); + Line = TokenExp.cap(2); + + if (Token == QStringLiteral("0")) + { + if (!Line.contains(TokenExp)) + continue; + + Token = TokenExp.cap(1); + Line = TokenExp.cap(2); + + if (Token == QStringLiteral("STEP")) + { + CurrentStep++; + continue; + } + + if (Token != QStringLiteral("!LEOCAD")) + continue; + + if (!Line.contains(TokenExp)) + continue; + + Token = TokenExp.cap(1); + Line = TokenExp.cap(2); + + if (Token == QStringLiteral("MODEL")) + { +// if (!strcmp(Tokens[3], "CURRENT_STEP") && Tokens[4]) +// mCurrentStep = atoi(Tokens[4]); + +// mProperties.ParseLDrawLine(Tokens); + } + else if (Token == QStringLiteral("PIECE")) + { + if (!Piece) + Piece = new lcPiece(NULL); + + Piece->ParseLDrawLine(Line, this); + } + else if (Token == QStringLiteral("CAMERA")) + { + if (!Camera) + Camera = new lcCamera(false); + + if (Camera->ParseLDrawLine(Line)) + { + Camera->CreateName(mCameras); + mCameras.Add(Camera); + Camera = NULL; + } + } + else if (Token == QStringLiteral("LIGHT")) + { + } + else if (Token == QStringLiteral("GROUP")) + { + } + + continue; + } + else if (Token == QStringLiteral("1")) + { + QTextStream Stream(&Line, QIODevice::ReadOnly); + + int ColorCode; + Stream >> ColorCode; + if (ColorCode == 16) + ColorCode = DefaultColorCode; + + float Matrix[12]; + for (int TokenIdx = 0; TokenIdx < 12; TokenIdx++) + Stream >> Matrix[TokenIdx]; + + lcMatrix44 IncludeTransform(lcVector4(Matrix[3], Matrix[6], Matrix[9], 0.0f), lcVector4(Matrix[4], Matrix[7], Matrix[10], 0.0f), + lcVector4(Matrix[5], Matrix[8], Matrix[11], 0.0f), lcVector4(Matrix[0], Matrix[1], Matrix[2], 1.0f)); + + IncludeTransform = lcMul(IncludeTransform, CurrentTransform); + + QString File; + Stream >> File; + + QString PartID = File.toUpper(); + if (PartID.endsWith(QStringLiteral(".DAT"))) + PartID = PartID.left(PartID.size() - 4); + + if (!Piece) + Piece = new lcPiece(NULL); + + PieceInfo* Info = lcGetPiecesLibrary()->FindPiece(PartID.toLatin1().constData(), false); + if (Info != NULL) + { + float* Matrix = IncludeTransform; + lcMatrix44 Transform(lcVector4(Matrix[0], Matrix[2], -Matrix[1], 0.0f), lcVector4(Matrix[8], Matrix[10], -Matrix[9], 0.0f), + lcVector4(-Matrix[4], -Matrix[6], Matrix[5], 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f)); + + lcVector4 AxisAngle = lcMatrix44ToAxisAngle(Transform); + AxisAngle[3] *= LC_RTOD; + + Piece->SetPieceInfo(Info); + Piece->Initialize(lcVector3(IncludeTransform[3].x, IncludeTransform[3].z, -IncludeTransform[3].y), AxisAngle, CurrentStep); + Piece->SetColorCode(ColorCode); + Piece->CreateName(mPieces); + mPieces.Add(Piece); + Piece = NULL; + continue; + } + + // todo: mpd + // todo: load from disk + + Info = lcGetPiecesLibrary()->FindPiece(PartID.toLatin1().constData(), true); + if (Info != NULL) + { + float* Matrix = IncludeTransform; + lcMatrix44 Transform(lcVector4(Matrix[0], Matrix[2], -Matrix[1], 0.0f), lcVector4(Matrix[8], Matrix[10], -Matrix[9], 0.0f), + lcVector4(-Matrix[4], -Matrix[6], Matrix[5], 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f)); + + lcVector4 AxisAngle = lcMatrix44ToAxisAngle(Transform); + AxisAngle[3] *= LC_RTOD; + + Piece->SetPieceInfo(Info); + Piece->Initialize(lcVector3(IncludeTransform[3].x, IncludeTransform[3].z, -IncludeTransform[3].y), AxisAngle, CurrentStep); + Piece->SetColorCode(ColorCode); + Piece->CreateName(mPieces); + mPieces.Add(Piece); + Piece = NULL; + continue; + } + } + } + + delete Piece; + delete Camera; + delete Light; +} + +QJsonObject lcModel::SaveJson() const { QJsonObject Model; Model["Properties"] = mProperties.Save(); - Model["CurrentStep"] = QString::number(mCurrentStep); + Model["CurrentStep"] = (int)mCurrentStep; QJsonArray Pieces; for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - Pieces.append(mPieces[PieceIdx]->Save()); + Pieces.append(mPieces[PieceIdx]->SaveJson()); Model["Pieces"] = Pieces; QJsonArray Cameras; for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++) - Cameras.append(mCameras[CameraIdx]->Save()); + Cameras.append(mCameras[CameraIdx]->SaveJson()); Model["Cameras"] = Cameras; QJsonArray Lights; @@ -121,9 +470,114 @@ QJsonObject lcModel::Save() return Model; } -void lcModel::Load(QJsonObject Model) +bool lcModel::LoadJson(const QJsonObject& Model) { + QJsonValue Properties = Model.value(QStringLiteral("Properties")); + if (!Properties.isUndefined()) + mProperties.Load(Properties.toObject()); + QJsonValue CurrentStep = Model.value(QStringLiteral("CurrentStep")); + if (!CurrentStep.isUndefined()) + mCurrentStep = CurrentStep.toInt(); + + QJsonValue Pieces = Model.value(QStringLiteral("Pieces")); + if (!Pieces.isUndefined()) + { + QJsonArray PiecesArray = Pieces.toArray(); + + for (int PieceIdx = 0; PieceIdx < PiecesArray.size(); PieceIdx++) + { + lcPiece* Piece = new lcPiece(NULL); + + if (Piece->LoadJson(PiecesArray[PieceIdx].toObject())) + mPieces.Add(Piece); + else + delete Piece; + } + } + + QJsonValue Cameras = Model.value(QStringLiteral("Cameras")); + if (!Cameras.isUndefined()) + { + QJsonArray CamerasArray = Cameras.toArray(); + + for (int CameraIdx = 0; CameraIdx < CamerasArray.size(); CameraIdx++) + { + lcCamera* Camera = new lcCamera(false); + + if (Camera->LoadJson(CamerasArray[CameraIdx].toObject())) + mCameras.Add(Camera); + else + delete Camera; + } + } + + QJsonValue Lights = Model.value(QStringLiteral("Lights")); + if (!Lights.isUndefined()) + { + QJsonArray LightsArray = Lights.toArray(); + + for (int LightIdx = 0; LightIdx < LightsArray.size(); LightIdx++) + { +/* lcLight* Light = new lcLight(); + + if (Light->Load(LightsArray[LightIdx].toObject())) + mLights.Add(Light); + else + delete Light; +*/ } + } + +// groups + + CalculateStep(); +/* + if (!bMerge) + gMainWindow->UpdateFocusObject(GetFocusObject()); + + if (!bMerge) + { + for (int ViewIdx = 0; ViewIdx < Views.GetSize(); ViewIdx++) + { + View* view = Views[ViewIdx]; + + if (!view->mCamera->IsSimple()) + view->SetDefaultCamera(); + } + + if (!bUndo) + ZoomExtents(0, Views.GetSize()); + } +*/ + gMainWindow->UpdateCameraMenu(); + UpdateSelection(); + gMainWindow->UpdateCurrentStep(); + gMainWindow->UpdateAllViews(); + + return true; +} + +void lcModel::CalculateStep() +{ + for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) + { + lcPiece* Piece = mPieces[PieceIdx]; + Piece->UpdatePosition(mCurrentStep); + + if (Piece->IsSelected()) + { + if (!Piece->IsVisible(mCurrentStep)) + Piece->SetSelected(false); + else + SelectGroup(Piece->GetTopGroup(), true); + } + } + + for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++) + mCameras[CameraIdx]->UpdatePosition(mCurrentStep); + + for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++) + mLights[LightIdx]->UpdatePosition(mCurrentStep); } lcStep lcModel::GetLastStep() const @@ -136,6 +590,30 @@ lcStep lcModel::GetLastStep() const return Step; } +lcGroup* lcModel::GetGroup(const char* Name, bool CreateIfMissing) +{ + for (int GroupIdx = 0; GroupIdx < mGroups.GetSize(); GroupIdx++) + { + lcGroup* Group = mGroups[GroupIdx]; + + if (!strcmp(Group->m_strName, Name)) + return Group; + } + + if (CreateIfMissing) + { + lcGroup* Group = new lcGroup(); + mGroups.Add(Group); + + strncpy(Group->m_strName, Name, sizeof(Group->m_strName)); + Group->m_strName[sizeof(Group->m_strName) - 1] = 0; + + return Group; + } + + return NULL; +} + lcObject* lcModel::GetFocusObject() const { for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) diff --git a/common/lc_model.h b/common/lc_model.h index 23697175..6a183d48 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -54,8 +54,11 @@ public: return true; } - QJsonObject Save(); - void Load(QJsonObject Properties); + void SaveLDraw(lcFile& File) const; + void ParseLDrawLine(char** Tokens); + + QJsonObject Save() const; + bool Load(const QJsonObject& Properties); String mName; String mAuthor; @@ -95,7 +98,7 @@ enum lcTool struct lcModelHistoryEntry { - lcMemFile File; + QByteArray File; char Description[64]; }; @@ -137,8 +140,13 @@ public: return mCurrentStep; } - QJsonObject Save(); - void Load(QJsonObject Model); + lcGroup* GetGroup(const char* Name, bool CreateIfMissing); + + void SaveLDraw(lcFile& File) const; + void LoadLDraw(const QStringList& Lines, const lcMatrix44& CurrentTransform, int DefaultColorCode, int& CurrentStep); + + QJsonObject SaveJson() const; + bool LoadJson(const QJsonObject& Model); lcObject* GetFocusObject() const; void FocusOrDeselectObject(const lcObjectSection& ObjectSection); @@ -148,6 +156,7 @@ public: void AddToSelection(const lcArray& ObjectSections); protected: + void CalculateStep(); void UpdateSelection() const; void SelectGroup(lcGroup* TopGroup, bool Select); void ClearSelection(bool UpdateInterface); diff --git a/common/light.cpp b/common/light.cpp index 4939141d..c306cefe 100644 --- a/common/light.cpp +++ b/common/light.cpp @@ -46,6 +46,10 @@ lcLight::~lcLight() { } +void lcLight::SaveLDraw(lcFile& File) const +{ +} + QJsonObject lcLight::Save() { return QJsonObject(); diff --git a/common/light.h b/common/light.h index 318d7a53..ad05cb1c 100644 --- a/common/light.h +++ b/common/light.h @@ -170,6 +170,7 @@ public: return lcVector3(0.0f, 0.0f, 0.0f); } + void SaveLDraw(lcFile& File) const; QJsonObject Save(); void Load(QJsonObject Light); diff --git a/common/object.cpp b/common/object.cpp index 918c7d52..df383f04 100644 --- a/common/object.cpp +++ b/common/object.cpp @@ -1,5 +1,6 @@ #include "lc_global.h" #include "object.h" +#include "lc_file.h" lcObject::lcObject(lcObjectType ObjectType) : mObjectType(ObjectType) @@ -10,36 +11,26 @@ lcObject::~lcObject() { } -QJsonArray lcObject::SaveKeys(const lcArray>& Keys) +void lcObject::SaveKeysLDraw(const lcArray>& Keys, const char* KeyName, lcFile& File) const { - QJsonArray KeyArray; + char Line[1024]; for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++) { lcObjectKey& Key = Keys[KeyIdx]; - QJsonObject KeyObject; - - KeyObject[QStringLiteral("Step")] = QString::number(Key.Step); - KeyObject[QStringLiteral("Value")] = QStringLiteral("%1 %2 %3").arg(QString::number(Key.Value[0]), QString::number(Key.Value[1]), QString::number(Key.Value[2])); - KeyArray.append(KeyObject); + sprintf(Line, "0 !LEOCAD %s %d %f %f %f\r\n", KeyName, Key.Step, Key.Value[0], Key.Value[1], Key.Value[2]); + File.WriteBuffer(Line, strlen(Line)); } - - return KeyArray; } -QJsonArray lcObject::SaveKeys(const lcArray>& Keys) +void lcObject::SaveKeysLDraw(const lcArray>& Keys, const char* KeyName, lcFile& File) const { - QJsonArray KeyArray; + char Line[1024]; for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++) { lcObjectKey& Key = Keys[KeyIdx]; - QJsonObject KeyObject; - - KeyObject[QStringLiteral("Step")] = QString::number(Key.Step); - KeyObject[QStringLiteral("Value")] = QStringLiteral("%1 %2 %3 %4").arg(QString::number(Key.Value[0]), QString::number(Key.Value[1]), QString::number(Key.Value[2]), QString::number(Key.Value[3])); - KeyArray.append(KeyObject); + sprintf(Line, "0 !LEOCAD %s %d %f %f %f %f\r\n", KeyName, Key.Step, Key.Value[0], Key.Value[1], Key.Value[2], Key.Value[3]); + File.WriteBuffer(Line, strlen(Line)); } - - return KeyArray; } diff --git a/common/object.h b/common/object.h index 9d056e18..b64c4e5d 100644 --- a/common/object.h +++ b/common/object.h @@ -87,8 +87,107 @@ public: virtual const char* GetName() const = 0; protected: - QJsonArray SaveKeys(const lcArray>& Keys); - QJsonArray SaveKeys(const lcArray>& Keys); + void SaveKeysLDraw(const lcArray>& Keys, const char* KeyName, lcFile& File) const; + void SaveKeysLDraw(const lcArray>& Keys, const char* KeyName, lcFile& File) const; + + template + void LoadKeyLDraw(lcArray>& Keys, QString& Line) + { + QRegExp TokenExp("\\s*(\\w+)\\s+(.*)"); + + if (!Line.contains(TokenExp)) + return; + + QString Token = TokenExp.cap(1); + Line = TokenExp.cap(2); + + int Step = Token.toInt(); + T Value; + + QTextStream Stream(&Line); + const int Count = sizeof(T) / sizeof(float); + for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++) + Stream >> Value[ValueIdx]; + + lcObjectKey& Key = Keys.Add(); + Key.Step = Step; + Key.Value = Value; + } + + template + QJsonArray SaveKeysJson(const lcArray>& Keys) const + { + const int Count = sizeof(T) / sizeof(float); + QJsonArray KeyArray; + QString StepString = QStringLiteral("Step"); + QString ValueString = QStringLiteral("Value"); + + for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++) + { + lcObjectKey& Key = Keys[KeyIdx]; + + QJsonArray ValueArray; + for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++) + ValueArray << Key.Value[ValueIdx]; + + QJsonObject KeyObject; + KeyObject[StepString] = (int)Key.Step; + KeyObject[ValueString] = ValueArray; + KeyArray.append(KeyObject); + } + + return KeyArray; + } + + template + void LoadKeysJson(lcArray>& Keys, const QJsonValue& KeysValue, T& Single, const QJsonValue& SingleValue) + { + const int Count = sizeof(T) / sizeof(float); + Keys.SetSize(0); + QString StepString = QStringLiteral("Step"); + QString ValueString = QStringLiteral("Value"); + + if (!KeysValue.isUndefined()) + { + QJsonArray KeyArray = KeysValue.toArray(); + Keys.AllocGrow(KeyArray.size()); + + for (int KeyIdx = 0; KeyIdx < KeyArray.size(); KeyIdx++) + { + QJsonObject KeyObject = KeyArray[KeyIdx].toObject(); + + QJsonValue Step = KeyObject.value(StepString); + QJsonValue Value = KeyObject.value(ValueString); + + if (Step.isUndefined() || Value.isUndefined()) + continue; + + lcStep CurrentStep = Step.toInt(); + + if (!Keys.IsEmpty() && Keys[Keys.GetSize() - 1].Step >= CurrentStep) + continue; + + lcObjectKey& Key = Keys.Add(); + Key.Step = CurrentStep; + + QJsonArray ValueArray = Value.toArray(); + if (ValueArray.size() == Count) + for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++) + Single[ValueIdx] = ValueArray[ValueIdx].toDouble(); + } + } + else if (!SingleValue.isUndefined()) + { + QJsonArray ValueArray = SingleValue.toArray(); + + if (ValueArray.size() == Count) + for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++) + Single[ValueIdx] = ValueArray[ValueIdx].toDouble(); + } + + if (Keys.IsEmpty()) + ChangeKey(Keys, Single, 1, true); + } template const T& CalculateKey(const lcArray>& Keys, lcStep Step) diff --git a/common/piece.cpp b/common/piece.cpp index 89df59d9..5974e7c4 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -23,8 +23,8 @@ lcPiece::lcPiece(PieceInfo* pPieceInfo) { mPieceInfo = pPieceInfo; mState = 0; - mColorIndex = 0; - mColorCode = 0; + mColorIndex = gDefaultColor; + mColorCode = 16; mStepShow = 1; mStepHide = LC_STEP_MAX; memset(m_strName, 0, sizeof(m_strName)); @@ -43,35 +43,160 @@ lcPiece::~lcPiece() mPieceInfo->Release(); } -QJsonObject lcPiece::Save() +void lcPiece::SaveLDraw(lcFile& File) const +{ + char Line[1024]; + + if (mStepHide != LC_STEP_MAX) + { + sprintf(Line, "0 !LEOCAD PIECE STEP_HIDE %d\r\n", mStepHide); + File.WriteBuffer(Line, strlen(Line)); + } + + sprintf(Line, "0 !LEOCAD PIECE NAME %s\r\n", m_strName); + File.WriteBuffer(Line, strlen(Line)); + + if (IsHidden()) + { + strcpy(Line, "0 !LEOCAD PIECE HIDDEN\r\n"); + File.WriteBuffer(Line, strlen(Line)); + } + + if (mGroup) + { + sprintf(Line, "0 !LEOCAD PIECE GROUP %s\r\n", mGroup->m_strName); + File.WriteBuffer(Line, strlen(Line)); + } + + if (mPositionKeys.GetSize() > 1) + SaveKeysLDraw(mPositionKeys, "PIECE POSITION_KEY", File); + + if (mRotationKeys.GetSize() > 1) + SaveKeysLDraw(mRotationKeys, "PIECE ROTATION_KEY", File); + + const float* Matrix = mModelWorld; + float Numbers[12] = { Matrix[12], -Matrix[14], Matrix[13], Matrix[0], -Matrix[8], Matrix[4], -Matrix[2], Matrix[10], -Matrix[6], Matrix[1], -Matrix[9], Matrix[5] }; + char Strings[12][32]; + for (int NumberIdx = 0; NumberIdx < 12; NumberIdx++) + { + sprintf(Strings[NumberIdx], "%f", Numbers[NumberIdx]); + char* Dot = strchr(Strings[NumberIdx], '.'); + if (Dot) + { + char* Last; + + for (Last = Dot + strlen(Dot) - 1; *Last == '0'; Last--) + *Last = 0; + + if (Last == Dot) + *Dot = 0; + } + } + + sprintf(Line, "1 %d %s %s %s %s %s %s %s %s %s %s %s %s %s.DAT\r\n", + mColorCode, Strings[0], Strings[1], Strings[2], Strings[3], Strings[4], Strings[5], Strings[6], Strings[7], Strings[8], Strings[9], Strings[10], Strings[11], mPieceInfo->m_strName); + File.WriteBuffer(Line, strlen(Line)); +} + +bool lcPiece::ParseLDrawLine(QString& Line, lcModel* Model) +{ + QRegExp TokenExp("\\s*(\\w+)\\s+(.*)"); + + if (!Line.contains(TokenExp)) + return false; + + QString Token = TokenExp.cap(1); + Line = TokenExp.cap(2); + + if (Token == QStringLiteral("STEP_HIDE")) + mStepHide = Line.toInt(); + else if (Token == QStringLiteral("NAME")) + { + QByteArray NameUtf = Line.toUtf8(); // todo: replace with qstring + strncpy(m_strName, NameUtf.constData(), sizeof(m_strName)); + m_strName[sizeof(m_strName) - 1] = 0; + } + else if (Token == QStringLiteral("HIDDEN")) + SetHidden(true); + else if (Token == QStringLiteral("GROUP")) + mGroup = Model->GetGroup(Line.toUtf8(), true); + else if (Token == QStringLiteral("POSITION_KEY")) + LoadKeyLDraw(mPositionKeys, Line); + else if (Token == QStringLiteral("ROTATION_KEY")) + LoadKeyLDraw(mRotationKeys, Line); + + return false; +} + +QJsonObject lcPiece::SaveJson() const { QJsonObject Piece; Piece[QStringLiteral("ID")] = QString::fromLatin1(mPieceInfo->m_strName); - Piece[QStringLiteral("Color")] = QString::number(mColorCode); - Piece[QStringLiteral("Step")] = QString::number(mStepShow); + Piece[QStringLiteral("Color")] = (int)mColorCode; + Piece[QStringLiteral("Step")] = (int)mStepShow; if (mStepHide != LC_STEP_MAX) - Piece[QStringLiteral("StepHide")] = QString::number(mStepHide); - Piece[QStringLiteral("Name")] = QString::fromLatin1(m_strName); // todo: replace with qstring + Piece[QStringLiteral("StepHide")] = (int)mStepHide; + Piece[QStringLiteral("Name")] = QString::fromUtf8(m_strName); // todo: replace with qstring if (IsHidden()) - Piece[QStringLiteral("Hidden")] = QStringLiteral("true"); + Piece[QStringLiteral("Hidden")] = true; if (mPositionKeys.GetSize() < 2) - Piece[QStringLiteral("Position")] = QStringLiteral("%1 %2 %3").arg(QString::number(mPosition[0]), QString::number(mPosition[1]), QString::number(mPosition[2])); + Piece[QStringLiteral("Position")] = QJsonArray() << mPosition[0] << mPosition[1] << mPosition[2]; else - Piece[QStringLiteral("PositionKeys")] = SaveKeys(mPositionKeys); + Piece[QStringLiteral("PositionKeys")] = SaveKeysJson(mPositionKeys); if (mRotationKeys.GetSize() < 2) - Piece[QStringLiteral("Rotation")] = QStringLiteral("%1 %2 %3 %4").arg(QString::number(mRotation[0]), QString::number(mRotation[1]), QString::number(mRotation[2]), QString::number(mRotation[3])); + Piece[QStringLiteral("Rotation")] = QJsonArray() << mRotation[0] << mRotation[1] << mRotation[2] << mRotation[3]; else - Piece[QStringLiteral("RotationKeys")] = SaveKeys(mRotationKeys); + Piece[QStringLiteral("RotationKeys")] = SaveKeysJson(mRotationKeys); return Piece; } -void lcPiece::Load(QJsonObject Piece) +bool lcPiece::LoadJson(const QJsonObject& Piece) { + QJsonValue ID = Piece.value(QStringLiteral("ID")); + if (ID.isUndefined()) + return false; + + SetPieceInfo(lcGetPiecesLibrary()->FindPiece(ID.toString().toLatin1(), true)); + + QJsonValue Color = Piece.value(QStringLiteral("Color")); + if (!Color.isUndefined()) + { + mColorCode = Color.toInt(); + mColorIndex = lcGetColorIndex(mColorCode); + } + + QJsonValue Step = Piece.value(QStringLiteral("Step")); + if (!Step.isUndefined()) + mStepShow = Step.toInt(); + + QJsonValue StepHide = Piece.value(QStringLiteral("StepHide")); + if (!StepHide.isUndefined()) + mStepHide = StepHide.toInt(); + + QJsonValue Name = Piece.value(QStringLiteral("Name")); + if (!Name.isUndefined()) + { + QByteArray NameUtf = Name.toString().toUtf8(); // todo: replace with qstring + strncpy(m_strName, NameUtf.constData(), sizeof(m_strName)); + m_strName[sizeof(m_strName) - 1] = 0; + } + + QJsonValue Hidden = Piece.value(QStringLiteral("Hidden")); + if (!Hidden.isUndefined()) + SetHidden(Hidden.toBool()); + + QJsonValue PositionKeys = Piece.value(QStringLiteral("PositionKeys")); + mPositionKeys.SetSize(0); + + LoadKeysJson(mPositionKeys, Piece.value(QStringLiteral("PositionKeys")), mPosition, Piece.value(QStringLiteral("Position"))); + LoadKeysJson(mRotationKeys, Piece.value(QStringLiteral("RotationKeys")), mRotation, Piece.value(QStringLiteral("Rotation"))); + + return true; } ///////////////////////////////////////////////////////////////////////////// @@ -366,19 +491,38 @@ void lcPiece::Initialize(const lcVector3& Position, const lcVector4& AxisAngle, void lcPiece::CreateName(const lcArray& Pieces) { + if (m_strName[0]) + { + bool Found = false; + + for (int PieceIdx = 0; PieceIdx < Pieces.GetSize(); PieceIdx++) + { + if (!strcmp(Pieces[PieceIdx]->m_strName, m_strName)) + { + Found = true; + break; + } + } + + if (!Found) + return; + } + + const char* Prefix = mPieceInfo->m_strDescription; + int Length = strlen(Prefix); int i, max = 0; for (int PieceIdx = 0; PieceIdx < Pieces.GetSize(); PieceIdx++) { lcPiece* Piece = Pieces[PieceIdx]; - if (strncmp(Piece->m_strName, mPieceInfo->m_strDescription, strlen(mPieceInfo->m_strDescription)) == 0) - if (sscanf(Piece->m_strName + strlen(mPieceInfo->m_strDescription), " #%d", &i) == 1) + if (strncmp(Piece->m_strName, Prefix, Length) == 0) + if (sscanf(Piece->m_strName + Length, " #%d", &i) == 1) if (i > max) max = i; } - snprintf(m_strName, sizeof(m_strName), "%s #%.2d", mPieceInfo->m_strDescription, max+1); + snprintf(m_strName, sizeof(m_strName), "%s #%.2d", Prefix, max + 1); m_strName[sizeof(m_strName) - 1] = 0; } diff --git a/common/piece.h b/common/piece.h index 9c6d7fc1..bbd1e4d3 100644 --- a/common/piece.h +++ b/common/piece.h @@ -88,8 +88,11 @@ public: return lcVector3(0.0f, 0.0f, 0.0f); } - QJsonObject Save(); - void Load(QJsonObject Piece); + void SaveLDraw(lcFile& File) const; + bool ParseLDrawLine(QString& Line, lcModel* Model); + + QJsonObject SaveJson() const; + bool LoadJson(const QJsonObject& Piece); virtual void RayTest(lcObjectRayTest& ObjectRayTest) const; virtual void BoxTest(lcObjectBoxTest& ObjectBoxTest) const; @@ -97,7 +100,7 @@ public: void InsertTime(lcStep Start, lcStep Time); void RemoveTime(lcStep Start, lcStep Time); - bool IsHidden() + bool IsHidden() const { return (mState & LC_PIECE_HIDDEN) != 0; } diff --git a/common/project.cpp b/common/project.cpp index 6c780bf9..d591a300 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -953,49 +953,8 @@ bool Project::DoSave(const char* FileName) if ((strcmp(ext, "dat") == 0) || (strcmp(ext, "ldr") == 0)) { - char buf[256]; - - ptr = strrchr(m_strPathName, '\\'); - if (ptr == NULL) - ptr = strrchr(m_strPathName, '/'); - if (ptr == NULL) - ptr = m_strPathName; - else - ptr++; - - sprintf(buf, "0 Model exported from LeoCAD\r\n0 Original name: %s\r\n", ptr); - if (!mProperties.mAuthor.IsEmpty()) - { - strcat(buf, "0 Author: "); - strcat(buf, mProperties.mAuthor.Buffer()); - strcat(buf, "\r\n"); - } - strcat(buf, "\r\n"); - file.WriteBuffer(buf, strlen(buf)); - const char* OldLocale = setlocale(LC_NUMERIC, "C"); - - lcStep LastStep = GetLastStep(); - for (lcStep Step = 1; Step <= LastStep; Step++) - { - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx]; - - if ((Piece->IsVisible(Step)) && (Piece->GetStepShow() == Step)) - { - const float* f = Piece->mModelWorld; - sprintf (buf, "1 %d %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %s.DAT\r\n", - Piece->mColorCode, f[12], -f[14], f[13], f[0], -f[8], f[4], -f[2], f[10], -f[6], f[1], -f[9], f[5], Piece->mPieceInfo->m_strName); - file.WriteBuffer(buf, strlen(buf)); - } - } - - if (Step != LastStep) - file.WriteBuffer("0 STEP\r\n", 8); - } - file.WriteBuffer("0\r\n", 3); - + SaveLDraw(file); setlocale(LC_NUMERIC, OldLocale); } else @@ -1149,7 +1108,17 @@ bool Project::OnOpenDocument(const char* lpszPathName) if (mpdfile) FileReadLDraw(&FileArray[0]->File, mat, &ok, 16, &step, FileArray); else - FileReadLDraw(&file, mat, &ok, 16, &step, FileArray); +// FileReadLDraw(&file, mat, &ok, 16, &step, FileArray); + { + QStringList Lines; + QFile File(lpszPathName); + if (!File.open(QIODevice::ReadOnly)) + { + } + while (!File.atEnd()) + Lines.append(File.readLine()); + LoadLDraw(Lines, mat, 16, step); + } mCurrentStep = step; gMainWindow->UpdateCurrentStep(); @@ -1211,7 +1180,7 @@ void Project::CheckPoint(const char* Description) lcModelHistoryEntry* ModelHistoryEntry = new lcModelHistoryEntry(); strcpy(ModelHistoryEntry->Description, Description); - FileSave(&ModelHistoryEntry->File, true); + ModelHistoryEntry->File = QJsonDocument(SaveJson()).toBinaryData(); mUndoHistory.InsertAt(0, ModelHistoryEntry); mRedoHistory.DeleteAll(); @@ -1604,29 +1573,6 @@ bool Project::GetPiecesBoundingBox(View* view, float BoundingBox[6]) ///////////////////////////////////////////////////////////////////////////// // Project functions -void Project::CalculateStep() -{ - for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++) - { - lcPiece* Piece = mPieces[PieceIdx]; - Piece->UpdatePosition(mCurrentStep); - - if (Piece->IsSelected()) - { - if (!Piece->IsVisible(mCurrentStep)) - Piece->SetSelected(false); - else - SelectGroup(Piece->GetTopGroup(), true); - } - } - - for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++) - mCameras[CameraIdx]->UpdatePosition(mCurrentStep); - - for (int LightIdx = 0; LightIdx < mLights.GetSize(); LightIdx++) - mLights[LightIdx]->UpdatePosition(mCurrentStep); -} - bool Project::RemoveSelectedObjects() { bool RemovedPiece = false; @@ -3526,7 +3472,7 @@ void Project::HandleCommand(LC_COMMANDS id) mRedoHistory.InsertAt(0, Undo); DeleteContents(true); - FileLoad(&mUndoHistory[0]->File, true, false); + LoadJson(QJsonDocument::fromBinaryData(mUndoHistory[0]->File).object()); gMainWindow->UpdateModified(IsModified()); gMainWindow->UpdateUndoRedo(mUndoHistory.GetSize() > 1 ? mUndoHistory[0]->Description : NULL, !mRedoHistory.IsEmpty() ? mRedoHistory[0]->Description : NULL); @@ -3543,7 +3489,7 @@ void Project::HandleCommand(LC_COMMANDS id) mUndoHistory.InsertAt(0, Redo); DeleteContents(true); - FileLoad(&Redo->File, true, false); + LoadJson(QJsonDocument::fromBinaryData(Redo->File).object()); gMainWindow->UpdateModified(IsModified()); gMainWindow->UpdateUndoRedo(mUndoHistory.GetSize() > 1 ? mUndoHistory[0]->Description : NULL, !mRedoHistory.IsEmpty() ? mRedoHistory[0]->Description : NULL); @@ -6067,7 +6013,7 @@ void Project::EndMouseTool(lcTool Tool, bool Accept) if (!Accept) { DeleteContents(true); - FileLoad(&mUndoHistory[0]->File, true, false); + LoadJson(QJsonDocument::fromBinaryData(mUndoHistory[0]->File).object()); return; } diff --git a/common/project.h b/common/project.h index 47fc21c6..6b7e4c7e 100644 --- a/common/project.h +++ b/common/project.h @@ -190,7 +190,6 @@ protected: bool RemoveSelectedObjects(); void GetPieceInsertPosition(lcPiece* OffsetPiece, lcVector3& Position, lcVector4& Rotation); - void CalculateStep(); static int InstanceOfName(const String& existingString, const String& candidateString, String& baseNameOut ); void FindPiece(bool FindFirst, bool SearchForward);