mirror of
https://github.com/leozide/leocad
synced 2025-01-17 18:11:42 +01:00
Changed the LDraw exporter to include more features in extensions.
This commit is contained in:
parent
4c0c815682
commit
661fa68011
13 changed files with 975 additions and 142 deletions
|
@ -78,6 +78,22 @@ void lcCamera::Initialize()
|
||||||
|
|
||||||
void lcCamera::CreateName(const lcArray<lcCamera*>& Cameras)
|
void lcCamera::CreateName(const lcArray<lcCamera*>& 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;
|
int i, max = 0;
|
||||||
const char* Prefix = "Camera ";
|
const char* Prefix = "Camera ";
|
||||||
|
|
||||||
|
@ -90,40 +106,168 @@ void lcCamera::CreateName(const lcArray<lcCamera*>& Cameras)
|
||||||
sprintf(m_strName, "%s %d", Prefix, max+1);
|
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;
|
QJsonObject Camera;
|
||||||
|
|
||||||
Camera[QStringLiteral("FOV")] = QString::number(m_fovy);
|
Camera[QStringLiteral("FOV")] = m_fovy;
|
||||||
Camera[QStringLiteral("ZNear")] = QString::number(m_zNear);
|
Camera[QStringLiteral("ZNear")] = m_zNear;
|
||||||
Camera[QStringLiteral("ZFar")] = QString::number(m_zFar);
|
Camera[QStringLiteral("ZFar")] = m_zFar;
|
||||||
Camera[QStringLiteral("Name")] = QString::fromLatin1(m_strName); // todo: replace with qstring
|
Camera[QStringLiteral("Name")] = QString::fromUtf8(m_strName); // todo: replace with qstring
|
||||||
if (IsHidden())
|
if (IsHidden())
|
||||||
Camera[QStringLiteral("Hidden")] = QStringLiteral("true");
|
Camera[QStringLiteral("Hidden")] = QStringLiteral("true");
|
||||||
if (IsOrtho())
|
if (IsOrtho())
|
||||||
Camera[QStringLiteral("Orthographic")] = QStringLiteral("true");
|
Camera[QStringLiteral("Orthographic")] = QStringLiteral("true");
|
||||||
|
|
||||||
if (mPositionKeys.GetSize() < 2)
|
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
|
else
|
||||||
Camera[QStringLiteral("PositionKeys")] = SaveKeys(mPositionKeys);
|
Camera[QStringLiteral("PositionKeys")] = SaveKeysJson(mPositionKeys);
|
||||||
|
|
||||||
if (mTargetPositionKeys.GetSize() < 2)
|
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
|
else
|
||||||
Camera[QStringLiteral("TargetPositionKeys")] = SaveKeys(mTargetPositionKeys);
|
Camera[QStringLiteral("TargetPositionKeys")] = SaveKeysJson(mTargetPositionKeys);
|
||||||
|
|
||||||
if (mUpVectorKeys.GetSize() < 2)
|
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
|
else
|
||||||
Camera[QStringLiteral("UpVectorKeys")] = SaveKeys(mUpVectorKeys);
|
Camera[QStringLiteral("UpVectorKeys")] = SaveKeysJson(mUpVectorKeys);
|
||||||
|
|
||||||
return Camera;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -220,8 +220,11 @@ public:
|
||||||
return lcVector3(0.0f, 0.0f, 0.0f);
|
return lcVector3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject Save();
|
void SaveLDraw(lcFile& File) const;
|
||||||
void Load(QJsonObject Camera);
|
bool ParseLDrawLine(QString& Line);
|
||||||
|
|
||||||
|
QJsonObject SaveJson() const;
|
||||||
|
bool LoadJson(const QJsonObject& Camera);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,8 +240,19 @@ public:
|
||||||
{ return m_nType < LC_CAMERA_MAIN; }
|
{ return m_nType < LC_CAMERA_MAIN; }
|
||||||
bool IsVisible() const
|
bool IsVisible() const
|
||||||
{ return (mState & LC_CAMERA_HIDDEN) == 0; }
|
{ return (mState & LC_CAMERA_HIDDEN) == 0; }
|
||||||
|
|
||||||
bool IsHidden() const
|
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)
|
void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#define LC_VERSION_TEXT "0.80.4"
|
#define LC_VERSION_TEXT "0.80.4"
|
||||||
|
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
|
class lcModel;
|
||||||
class lcObject;
|
class lcObject;
|
||||||
class lcPiece;
|
class lcPiece;
|
||||||
class lcCamera;
|
class lcCamera;
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
#include "piece.h"
|
#include "piece.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
|
#include "group.h"
|
||||||
#include "lc_mainwindow.h"
|
#include "lc_mainwindow.h"
|
||||||
#include "lc_profile.h"
|
#include "lc_profile.h"
|
||||||
|
#include "lc_library.h"
|
||||||
|
|
||||||
void lcModelProperties::LoadDefaults()
|
void lcModelProperties::LoadDefaults()
|
||||||
{
|
{
|
||||||
|
@ -38,18 +40,177 @@ void lcModelProperties::SaveDefaults()
|
||||||
lcSetProfileInt(LC_PROFILE_DEFAULT_AMBIENT_COLOR, lcColorFromVector3(mAmbientColor));
|
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;
|
QJsonObject Properties;
|
||||||
|
|
||||||
if (!mName.IsEmpty())
|
if (!mName.IsEmpty())
|
||||||
Properties[QStringLiteral("Name")] = QString::fromLatin1(mName.Buffer());
|
Properties[QStringLiteral("Name")] = QString::fromLatin1(mName); // todo: qstring
|
||||||
if (!mAuthor.IsEmpty())
|
if (!mAuthor.IsEmpty())
|
||||||
Properties[QStringLiteral("Author")] = QString::fromLatin1(mAuthor.Buffer());
|
Properties[QStringLiteral("Author")] = QString::fromLatin1(mAuthor);
|
||||||
if (!mDescription.IsEmpty())
|
if (!mDescription.IsEmpty())
|
||||||
Properties[QStringLiteral("Description")] = QString::fromLatin1(mDescription.Buffer());
|
Properties[QStringLiteral("Description")] = QString::fromLatin1(mDescription);
|
||||||
if (!mComments.IsEmpty())
|
if (!mComments.IsEmpty())
|
||||||
Properties[QStringLiteral("Comments")] = QString::fromLatin1(mComments.Buffer());
|
Properties[QStringLiteral("Comments")] = QString::fromLatin1(mComments);
|
||||||
|
|
||||||
switch (mBackgroundType)
|
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("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]));
|
Properties[QStringLiteral("BackgroundGradientColor2")] = QStringLiteral("%1 %2 %3").arg(QString::number(mBackgroundGradientColor2[0]), QString::number(mBackgroundGradientColor2[1]), QString::number(mBackgroundGradientColor2[2]));
|
||||||
if (!mBackgroundImage.IsEmpty())
|
if (!mBackgroundImage.IsEmpty())
|
||||||
Properties[QStringLiteral("BackgroundImage")] = QString::fromLatin1(mBackgroundImage.Buffer());
|
Properties[QStringLiteral("BackgroundImage")] = QString::fromLatin1(mBackgroundImage); // todo: qstring
|
||||||
if (mBackgroundImageTile)
|
if (mBackgroundImageTile)
|
||||||
Properties[QStringLiteral("BackgroundImageTile")] = QStringLiteral("true");
|
Properties[QStringLiteral("BackgroundImageTile")] = QStringLiteral("true");
|
||||||
|
|
||||||
|
@ -81,8 +242,9 @@ QJsonObject lcModelProperties::Save()
|
||||||
return Properties;
|
return Properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcModelProperties::Load(QJsonObject Properties)
|
bool lcModelProperties::Load(const QJsonObject& Properties)
|
||||||
{
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcModel::lcModel()
|
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<lcGroup*> 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;
|
QJsonObject Model;
|
||||||
|
|
||||||
Model["Properties"] = mProperties.Save();
|
Model["Properties"] = mProperties.Save();
|
||||||
Model["CurrentStep"] = QString::number(mCurrentStep);
|
Model["CurrentStep"] = (int)mCurrentStep;
|
||||||
|
|
||||||
QJsonArray Pieces;
|
QJsonArray Pieces;
|
||||||
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
|
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
|
||||||
Pieces.append(mPieces[PieceIdx]->Save());
|
Pieces.append(mPieces[PieceIdx]->SaveJson());
|
||||||
Model["Pieces"] = Pieces;
|
Model["Pieces"] = Pieces;
|
||||||
|
|
||||||
QJsonArray Cameras;
|
QJsonArray Cameras;
|
||||||
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
|
||||||
Cameras.append(mCameras[CameraIdx]->Save());
|
Cameras.append(mCameras[CameraIdx]->SaveJson());
|
||||||
Model["Cameras"] = Cameras;
|
Model["Cameras"] = Cameras;
|
||||||
|
|
||||||
QJsonArray Lights;
|
QJsonArray Lights;
|
||||||
|
@ -121,9 +470,114 @@ QJsonObject lcModel::Save()
|
||||||
return Model;
|
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
|
lcStep lcModel::GetLastStep() const
|
||||||
|
@ -136,6 +590,30 @@ lcStep lcModel::GetLastStep() const
|
||||||
return Step;
|
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
|
lcObject* lcModel::GetFocusObject() const
|
||||||
{
|
{
|
||||||
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
|
for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
|
||||||
|
|
|
@ -54,8 +54,11 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject Save();
|
void SaveLDraw(lcFile& File) const;
|
||||||
void Load(QJsonObject Properties);
|
void ParseLDrawLine(char** Tokens);
|
||||||
|
|
||||||
|
QJsonObject Save() const;
|
||||||
|
bool Load(const QJsonObject& Properties);
|
||||||
|
|
||||||
String mName;
|
String mName;
|
||||||
String mAuthor;
|
String mAuthor;
|
||||||
|
@ -95,7 +98,7 @@ enum lcTool
|
||||||
|
|
||||||
struct lcModelHistoryEntry
|
struct lcModelHistoryEntry
|
||||||
{
|
{
|
||||||
lcMemFile File;
|
QByteArray File;
|
||||||
char Description[64];
|
char Description[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,8 +140,13 @@ public:
|
||||||
return mCurrentStep;
|
return mCurrentStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject Save();
|
lcGroup* GetGroup(const char* Name, bool CreateIfMissing);
|
||||||
void Load(QJsonObject Model);
|
|
||||||
|
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;
|
lcObject* GetFocusObject() const;
|
||||||
void FocusOrDeselectObject(const lcObjectSection& ObjectSection);
|
void FocusOrDeselectObject(const lcObjectSection& ObjectSection);
|
||||||
|
@ -148,6 +156,7 @@ public:
|
||||||
void AddToSelection(const lcArray<lcObjectSection>& ObjectSections);
|
void AddToSelection(const lcArray<lcObjectSection>& ObjectSections);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void CalculateStep();
|
||||||
void UpdateSelection() const;
|
void UpdateSelection() const;
|
||||||
void SelectGroup(lcGroup* TopGroup, bool Select);
|
void SelectGroup(lcGroup* TopGroup, bool Select);
|
||||||
void ClearSelection(bool UpdateInterface);
|
void ClearSelection(bool UpdateInterface);
|
||||||
|
|
|
@ -46,6 +46,10 @@ lcLight::~lcLight()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lcLight::SaveLDraw(lcFile& File) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject lcLight::Save()
|
QJsonObject lcLight::Save()
|
||||||
{
|
{
|
||||||
return QJsonObject();
|
return QJsonObject();
|
||||||
|
|
|
@ -170,6 +170,7 @@ public:
|
||||||
return lcVector3(0.0f, 0.0f, 0.0f);
|
return lcVector3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SaveLDraw(lcFile& File) const;
|
||||||
QJsonObject Save();
|
QJsonObject Save();
|
||||||
void Load(QJsonObject Light);
|
void Load(QJsonObject Light);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "lc_global.h"
|
#include "lc_global.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "lc_file.h"
|
||||||
|
|
||||||
lcObject::lcObject(lcObjectType ObjectType)
|
lcObject::lcObject(lcObjectType ObjectType)
|
||||||
: mObjectType(ObjectType)
|
: mObjectType(ObjectType)
|
||||||
|
@ -10,36 +11,26 @@ lcObject::~lcObject()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray lcObject::SaveKeys(const lcArray<lcObjectKey<lcVector3>>& Keys)
|
void lcObject::SaveKeysLDraw(const lcArray<lcObjectKey<lcVector3>>& Keys, const char* KeyName, lcFile& File) const
|
||||||
{
|
{
|
||||||
QJsonArray KeyArray;
|
char Line[1024];
|
||||||
|
|
||||||
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
||||||
{
|
{
|
||||||
lcObjectKey<lcVector3>& Key = Keys[KeyIdx];
|
lcObjectKey<lcVector3>& Key = Keys[KeyIdx];
|
||||||
QJsonObject 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));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray lcObject::SaveKeys(const lcArray<lcObjectKey<lcVector4>>& Keys)
|
void lcObject::SaveKeysLDraw(const lcArray<lcObjectKey<lcVector4>>& Keys, const char* KeyName, lcFile& File) const
|
||||||
{
|
{
|
||||||
QJsonArray KeyArray;
|
char Line[1024];
|
||||||
|
|
||||||
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
for (int KeyIdx = 0; KeyIdx < Keys.GetSize(); KeyIdx++)
|
||||||
{
|
{
|
||||||
lcObjectKey<lcVector4>& Key = Keys[KeyIdx];
|
lcObjectKey<lcVector4>& Key = Keys[KeyIdx];
|
||||||
QJsonObject 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));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return KeyArray;
|
|
||||||
}
|
}
|
||||||
|
|
103
common/object.h
103
common/object.h
|
@ -87,8 +87,107 @@ public:
|
||||||
virtual const char* GetName() const = 0;
|
virtual const char* GetName() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QJsonArray SaveKeys(const lcArray<lcObjectKey<lcVector3>>& Keys);
|
void SaveKeysLDraw(const lcArray<lcObjectKey<lcVector3>>& Keys, const char* KeyName, lcFile& File) const;
|
||||||
QJsonArray SaveKeys(const lcArray<lcObjectKey<lcVector4>>& Keys);
|
void SaveKeysLDraw(const lcArray<lcObjectKey<lcVector4>>& Keys, const char* KeyName, lcFile& File) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void LoadKeyLDraw(lcArray<lcObjectKey<T>>& 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<T>& Key = Keys.Add();
|
||||||
|
Key.Step = Step;
|
||||||
|
Key.Value = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
QJsonArray SaveKeysJson(const lcArray<lcObjectKey<T>>& 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<T>& 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<typename T>
|
||||||
|
void LoadKeysJson(lcArray<lcObjectKey<T>>& 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<T>& 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<typename T>
|
template<typename T>
|
||||||
const T& CalculateKey(const lcArray<lcObjectKey<T>>& Keys, lcStep Step)
|
const T& CalculateKey(const lcArray<lcObjectKey<T>>& Keys, lcStep Step)
|
||||||
|
|
176
common/piece.cpp
176
common/piece.cpp
|
@ -23,8 +23,8 @@ lcPiece::lcPiece(PieceInfo* pPieceInfo)
|
||||||
{
|
{
|
||||||
mPieceInfo = pPieceInfo;
|
mPieceInfo = pPieceInfo;
|
||||||
mState = 0;
|
mState = 0;
|
||||||
mColorIndex = 0;
|
mColorIndex = gDefaultColor;
|
||||||
mColorCode = 0;
|
mColorCode = 16;
|
||||||
mStepShow = 1;
|
mStepShow = 1;
|
||||||
mStepHide = LC_STEP_MAX;
|
mStepHide = LC_STEP_MAX;
|
||||||
memset(m_strName, 0, sizeof(m_strName));
|
memset(m_strName, 0, sizeof(m_strName));
|
||||||
|
@ -43,35 +43,160 @@ lcPiece::~lcPiece()
|
||||||
mPieceInfo->Release();
|
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;
|
QJsonObject Piece;
|
||||||
|
|
||||||
Piece[QStringLiteral("ID")] = QString::fromLatin1(mPieceInfo->m_strName);
|
Piece[QStringLiteral("ID")] = QString::fromLatin1(mPieceInfo->m_strName);
|
||||||
Piece[QStringLiteral("Color")] = QString::number(mColorCode);
|
Piece[QStringLiteral("Color")] = (int)mColorCode;
|
||||||
Piece[QStringLiteral("Step")] = QString::number(mStepShow);
|
Piece[QStringLiteral("Step")] = (int)mStepShow;
|
||||||
if (mStepHide != LC_STEP_MAX)
|
if (mStepHide != LC_STEP_MAX)
|
||||||
Piece[QStringLiteral("StepHide")] = QString::number(mStepHide);
|
Piece[QStringLiteral("StepHide")] = (int)mStepHide;
|
||||||
Piece[QStringLiteral("Name")] = QString::fromLatin1(m_strName); // todo: replace with qstring
|
Piece[QStringLiteral("Name")] = QString::fromUtf8(m_strName); // todo: replace with qstring
|
||||||
if (IsHidden())
|
if (IsHidden())
|
||||||
Piece[QStringLiteral("Hidden")] = QStringLiteral("true");
|
Piece[QStringLiteral("Hidden")] = true;
|
||||||
|
|
||||||
if (mPositionKeys.GetSize() < 2)
|
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
|
else
|
||||||
Piece[QStringLiteral("PositionKeys")] = SaveKeys(mPositionKeys);
|
Piece[QStringLiteral("PositionKeys")] = SaveKeysJson(mPositionKeys);
|
||||||
|
|
||||||
if (mRotationKeys.GetSize() < 2)
|
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
|
else
|
||||||
Piece[QStringLiteral("RotationKeys")] = SaveKeys(mRotationKeys);
|
Piece[QStringLiteral("RotationKeys")] = SaveKeysJson(mRotationKeys);
|
||||||
|
|
||||||
return Piece;
|
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<lcPiece*>& Pieces)
|
void lcPiece::CreateName(const lcArray<lcPiece*>& 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;
|
int i, max = 0;
|
||||||
|
|
||||||
for (int PieceIdx = 0; PieceIdx < Pieces.GetSize(); PieceIdx++)
|
for (int PieceIdx = 0; PieceIdx < Pieces.GetSize(); PieceIdx++)
|
||||||
{
|
{
|
||||||
lcPiece* Piece = Pieces[PieceIdx];
|
lcPiece* Piece = Pieces[PieceIdx];
|
||||||
|
|
||||||
if (strncmp(Piece->m_strName, mPieceInfo->m_strDescription, strlen(mPieceInfo->m_strDescription)) == 0)
|
if (strncmp(Piece->m_strName, Prefix, Length) == 0)
|
||||||
if (sscanf(Piece->m_strName + strlen(mPieceInfo->m_strDescription), " #%d", &i) == 1)
|
if (sscanf(Piece->m_strName + Length, " #%d", &i) == 1)
|
||||||
if (i > max)
|
if (i > max)
|
||||||
max = i;
|
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;
|
m_strName[sizeof(m_strName) - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,11 @@ public:
|
||||||
return lcVector3(0.0f, 0.0f, 0.0f);
|
return lcVector3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject Save();
|
void SaveLDraw(lcFile& File) const;
|
||||||
void Load(QJsonObject Piece);
|
bool ParseLDrawLine(QString& Line, lcModel* Model);
|
||||||
|
|
||||||
|
QJsonObject SaveJson() const;
|
||||||
|
bool LoadJson(const QJsonObject& Piece);
|
||||||
|
|
||||||
virtual void RayTest(lcObjectRayTest& ObjectRayTest) const;
|
virtual void RayTest(lcObjectRayTest& ObjectRayTest) const;
|
||||||
virtual void BoxTest(lcObjectBoxTest& ObjectBoxTest) const;
|
virtual void BoxTest(lcObjectBoxTest& ObjectBoxTest) const;
|
||||||
|
@ -97,7 +100,7 @@ public:
|
||||||
void InsertTime(lcStep Start, lcStep Time);
|
void InsertTime(lcStep Start, lcStep Time);
|
||||||
void RemoveTime(lcStep Start, lcStep Time);
|
void RemoveTime(lcStep Start, lcStep Time);
|
||||||
|
|
||||||
bool IsHidden()
|
bool IsHidden() const
|
||||||
{
|
{
|
||||||
return (mState & LC_PIECE_HIDDEN) != 0;
|
return (mState & LC_PIECE_HIDDEN) != 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -953,49 +953,8 @@ bool Project::DoSave(const char* FileName)
|
||||||
|
|
||||||
if ((strcmp(ext, "dat") == 0) || (strcmp(ext, "ldr") == 0))
|
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");
|
const char* OldLocale = setlocale(LC_NUMERIC, "C");
|
||||||
|
SaveLDraw(file);
|
||||||
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);
|
|
||||||
|
|
||||||
setlocale(LC_NUMERIC, OldLocale);
|
setlocale(LC_NUMERIC, OldLocale);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1149,7 +1108,17 @@ bool Project::OnOpenDocument(const char* lpszPathName)
|
||||||
if (mpdfile)
|
if (mpdfile)
|
||||||
FileReadLDraw(&FileArray[0]->File, mat, &ok, 16, &step, FileArray);
|
FileReadLDraw(&FileArray[0]->File, mat, &ok, 16, &step, FileArray);
|
||||||
else
|
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;
|
mCurrentStep = step;
|
||||||
gMainWindow->UpdateCurrentStep();
|
gMainWindow->UpdateCurrentStep();
|
||||||
|
@ -1211,7 +1180,7 @@ void Project::CheckPoint(const char* Description)
|
||||||
lcModelHistoryEntry* ModelHistoryEntry = new lcModelHistoryEntry();
|
lcModelHistoryEntry* ModelHistoryEntry = new lcModelHistoryEntry();
|
||||||
|
|
||||||
strcpy(ModelHistoryEntry->Description, Description);
|
strcpy(ModelHistoryEntry->Description, Description);
|
||||||
FileSave(&ModelHistoryEntry->File, true);
|
ModelHistoryEntry->File = QJsonDocument(SaveJson()).toBinaryData();
|
||||||
|
|
||||||
mUndoHistory.InsertAt(0, ModelHistoryEntry);
|
mUndoHistory.InsertAt(0, ModelHistoryEntry);
|
||||||
mRedoHistory.DeleteAll();
|
mRedoHistory.DeleteAll();
|
||||||
|
@ -1604,29 +1573,6 @@ bool Project::GetPiecesBoundingBox(View* view, float BoundingBox[6])
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Project functions
|
// 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 Project::RemoveSelectedObjects()
|
||||||
{
|
{
|
||||||
bool RemovedPiece = false;
|
bool RemovedPiece = false;
|
||||||
|
@ -3526,7 +3472,7 @@ void Project::HandleCommand(LC_COMMANDS id)
|
||||||
mRedoHistory.InsertAt(0, Undo);
|
mRedoHistory.InsertAt(0, Undo);
|
||||||
|
|
||||||
DeleteContents(true);
|
DeleteContents(true);
|
||||||
FileLoad(&mUndoHistory[0]->File, true, false);
|
LoadJson(QJsonDocument::fromBinaryData(mUndoHistory[0]->File).object());
|
||||||
|
|
||||||
gMainWindow->UpdateModified(IsModified());
|
gMainWindow->UpdateModified(IsModified());
|
||||||
gMainWindow->UpdateUndoRedo(mUndoHistory.GetSize() > 1 ? mUndoHistory[0]->Description : NULL, !mRedoHistory.IsEmpty() ? mRedoHistory[0]->Description : NULL);
|
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);
|
mUndoHistory.InsertAt(0, Redo);
|
||||||
|
|
||||||
DeleteContents(true);
|
DeleteContents(true);
|
||||||
FileLoad(&Redo->File, true, false);
|
LoadJson(QJsonDocument::fromBinaryData(Redo->File).object());
|
||||||
|
|
||||||
gMainWindow->UpdateModified(IsModified());
|
gMainWindow->UpdateModified(IsModified());
|
||||||
gMainWindow->UpdateUndoRedo(mUndoHistory.GetSize() > 1 ? mUndoHistory[0]->Description : NULL, !mRedoHistory.IsEmpty() ? mRedoHistory[0]->Description : NULL);
|
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)
|
if (!Accept)
|
||||||
{
|
{
|
||||||
DeleteContents(true);
|
DeleteContents(true);
|
||||||
FileLoad(&mUndoHistory[0]->File, true, false);
|
LoadJson(QJsonDocument::fromBinaryData(mUndoHistory[0]->File).object());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,6 @@ protected:
|
||||||
bool RemoveSelectedObjects();
|
bool RemoveSelectedObjects();
|
||||||
void GetPieceInsertPosition(lcPiece* OffsetPiece, lcVector3& Position, lcVector4& Rotation);
|
void GetPieceInsertPosition(lcPiece* OffsetPiece, lcVector3& Position, lcVector4& Rotation);
|
||||||
|
|
||||||
void CalculateStep();
|
|
||||||
static int InstanceOfName(const String& existingString, const String& candidateString, String& baseNameOut );
|
static int InstanceOfName(const String& existingString, const String& candidateString, String& baseNameOut );
|
||||||
|
|
||||||
void FindPiece(bool FindFirst, bool SearchForward);
|
void FindPiece(bool FindFirst, bool SearchForward);
|
||||||
|
|
Loading…
Reference in a new issue