mirror of
https://github.com/leozide/leocad.git
synced 2026-10-27 06:20:55 +00:00
Replace manual piece-data retain/release bookkeeping with shared copyable asset-reference handles. Pieces, models, selection, minifigs, thumbnails, and stored insertion previews retain their dependencies explicitly, while transient queries continue to borrow pointers. Separate registered lookup and acquisition from asynchronous load requests and explicit readiness waits. Keep loader-held references through work and notification delivery, resetting shared request handles on the UI thread and guarding callback-triggered library teardown. Validated with the Qt 6.10 debug build and 26 offscreen lifecycle checks, including cancellation, stale requests, copy/move operations, model/preview teardown, undo, project merge/export, and loader shutdown.
517 lines
15 KiB
C++
517 lines
15 KiB
C++
#include "lc_global.h"
|
|
#include "minifig.h"
|
|
#include "lc_colors.h"
|
|
#include "lc_piecedata.h"
|
|
#include "lc_model.h"
|
|
#include "lc_library.h"
|
|
#include "lc_application.h"
|
|
#include "lc_file.h"
|
|
#include "lc_profile.h"
|
|
|
|
const char* MinifigWizard::mSectionNames[LC_MFW_NUMITEMS] =
|
|
{
|
|
"HATS", // LC_MFW_HATS
|
|
"HATS2", // LC_MFW_HATS2
|
|
"HEAD", // LC_MFW_HEAD
|
|
"NECK", // LC_MFW_NECK
|
|
"BODY", // LC_MFW_BODY
|
|
"BODY2", // LC_MFW_BODY2
|
|
"BODY3", // LC_MFW_BODY3
|
|
"RARM", // LC_MFW_RARM
|
|
"LARM", // LC_MFW_LARM
|
|
"RHAND", // LC_MFW_RHAND
|
|
"LHAND", // LC_MFW_LHAND
|
|
"RHANDA", // LC_MFW_RHANDA
|
|
"LHANDA", // LC_MFW_LHANDA
|
|
"RLEG", // LC_MFW_RLEG
|
|
"LLEG", // LC_MFW_LLEG
|
|
"RLEGA", // LC_MFW_RLEGA
|
|
"LLEGA", // LC_MFW_LLEGA
|
|
};
|
|
|
|
MinifigWizard::MinifigWizard()
|
|
: mModel(new lcModel(QString(), nullptr, false))
|
|
{
|
|
LoadSettings();
|
|
LoadTemplates();
|
|
|
|
lcMinifigTemplate& Template = mTemplates[GetDefaultTemplateName()];
|
|
const int ColorCodes[LC_MFW_NUMITEMS] = { 4, 7, 14, 7, 1, 0, 7, 4, 4, 14, 14, 7, 7, 0, 0, 7, 7 };
|
|
const char* const Pieces[LC_MFW_NUMITEMS] = { "3624.dat", "", "3626bp01.dat", "", "973.dat", "3815.dat", "", "3819.dat", "3818.dat", "3820.dat", "3820.dat", "", "", "3817.dat", "3816.dat", "", "" };
|
|
|
|
for (int PartIndex = 0; PartIndex < LC_MFW_NUMITEMS; PartIndex++)
|
|
{
|
|
Template.Parts[PartIndex] = Pieces[PartIndex];
|
|
Template.ColorCodes[PartIndex] = ColorCodes[PartIndex];
|
|
Template.Angles[PartIndex] = 0.0f;
|
|
}
|
|
|
|
for (int PartIndex = 0; PartIndex < LC_MFW_NUMITEMS; PartIndex++)
|
|
{
|
|
mMinifig.ColorIndices[PartIndex] = gDefaultColor;
|
|
mMinifig.Angles[PartIndex] = 0.0f;
|
|
mMinifig.Matrices[PartIndex] = lcMatrix44Identity();
|
|
}
|
|
}
|
|
|
|
MinifigWizard::~MinifigWizard()
|
|
{
|
|
SaveTemplates();
|
|
}
|
|
|
|
QString MinifigWizard::GetDefaultTemplateName()
|
|
{
|
|
return QCoreApplication::translate("MinifigWizard", "Default");
|
|
}
|
|
|
|
void MinifigWizard::LoadSettings()
|
|
{
|
|
QString CustomSettingsPath = lcGetProfileString(LC_PROFILE_MINIFIG_SETTINGS);
|
|
|
|
if (!CustomSettingsPath.isEmpty())
|
|
{
|
|
lcDiskFile DiskSettings(CustomSettingsPath);
|
|
|
|
if (DiskSettings.Open(QIODevice::ReadOnly))
|
|
{
|
|
ParseSettings(DiskSettings);
|
|
return;
|
|
}
|
|
}
|
|
|
|
lcDiskFile MinifigFile(":/resources/minifig.ini");
|
|
|
|
if (MinifigFile.Open(QIODevice::ReadOnly))
|
|
ParseSettings(MinifigFile);
|
|
}
|
|
|
|
void MinifigWizard::ParseSettings(lcFile& Settings)
|
|
{
|
|
for (int SectionIndex = 0; SectionIndex < LC_MFW_NUMITEMS; SectionIndex++)
|
|
{
|
|
std::vector<lcMinifigPieceInfo>& InfoArray = mSettings[SectionIndex];
|
|
|
|
InfoArray.clear();
|
|
Settings.Seek(0, SEEK_SET);
|
|
|
|
char Line[1024];
|
|
bool FoundSection = false;
|
|
const char* SectionName = mSectionNames[SectionIndex];
|
|
const size_t SectionNameLength = strlen(SectionName);
|
|
|
|
while (Settings.ReadLine(Line, sizeof(Line)))
|
|
{
|
|
if (Line[0] == '[' && !strncmp(Line + 1, SectionName, SectionNameLength) && Line[SectionNameLength + 1] == ']')
|
|
{
|
|
FoundSection = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!FoundSection)
|
|
{
|
|
lcMinifigPieceInfo MinifigInfo;
|
|
strncpy(MinifigInfo.Description, "None", sizeof(MinifigInfo.Description));
|
|
MinifigInfo.Description[sizeof(MinifigInfo.Description)-1] = 0;
|
|
MinifigInfo.Offset = lcMatrix44Identity();
|
|
MinifigInfo.PieceData = nullptr;
|
|
|
|
InfoArray.emplace_back(std::move(MinifigInfo));
|
|
continue;
|
|
}
|
|
|
|
while (Settings.ReadLine(Line, sizeof(Line)))
|
|
{
|
|
if (Line[0] == '[')
|
|
break;
|
|
|
|
char* DescriptionStart = strchr(Line, '"');
|
|
if (!DescriptionStart)
|
|
continue;
|
|
DescriptionStart++;
|
|
char* DescriptionEnd = strchr(DescriptionStart, '"');
|
|
if (!DescriptionEnd)
|
|
continue;
|
|
*DescriptionEnd = 0;
|
|
DescriptionEnd++;
|
|
|
|
char* NameStart = strchr(DescriptionEnd, '"');
|
|
if (!NameStart)
|
|
continue;
|
|
NameStart++;
|
|
char* NameEnd = strchr(NameStart, '"');
|
|
if (!NameEnd)
|
|
continue;
|
|
*NameEnd = 0;
|
|
NameEnd++;
|
|
|
|
lcPieceData* PieceData = lcGetPiecesLibrary()->FindPieceData(NameStart, nullptr);
|
|
if (!PieceData && *NameStart)
|
|
continue;
|
|
|
|
float Mat[12];
|
|
int Flags;
|
|
|
|
if (sscanf(NameEnd, "%d %g %g %g %g %g %g %g %g %g %g %g %g",
|
|
&Flags, &Mat[0], &Mat[1], &Mat[2], &Mat[3], &Mat[4], &Mat[5], &Mat[6],
|
|
&Mat[7], &Mat[8], &Mat[9], &Mat[10], &Mat[11]) != 13)
|
|
continue;
|
|
|
|
lcMatrix44 Offset = lcMatrix44Identity();
|
|
float* OffsetMatrix = &Offset[0][0];
|
|
|
|
OffsetMatrix[0] = Mat[0];
|
|
OffsetMatrix[8] = -Mat[1];
|
|
OffsetMatrix[4] = Mat[2];
|
|
OffsetMatrix[2] = -Mat[3];
|
|
OffsetMatrix[10] = Mat[4];
|
|
OffsetMatrix[6] = -Mat[5];
|
|
OffsetMatrix[1] = Mat[6];
|
|
OffsetMatrix[9] = -Mat[7];
|
|
OffsetMatrix[5] = Mat[8];
|
|
OffsetMatrix[12] = Mat[9];
|
|
OffsetMatrix[14] = -Mat[10];
|
|
OffsetMatrix[13] = Mat[11];
|
|
|
|
lcMinifigPieceInfo MinifigInfo;
|
|
strncpy(MinifigInfo.Description, DescriptionStart, sizeof(MinifigInfo.Description));
|
|
MinifigInfo.Description[sizeof(MinifigInfo.Description)-1] = 0;
|
|
MinifigInfo.Offset = Offset;
|
|
MinifigInfo.PieceData = PieceData;
|
|
|
|
InfoArray.emplace_back(std::move(MinifigInfo));
|
|
}
|
|
}
|
|
}
|
|
|
|
void MinifigWizard::LoadTemplate(const QString& TemplateName)
|
|
{
|
|
const std::map<QString, lcMinifigTemplate>::iterator& TemplateIt = mTemplates.find(TemplateName);
|
|
|
|
if (TemplateIt == mTemplates.end())
|
|
return;
|
|
|
|
const lcMinifigTemplate& Template = TemplateIt->second;
|
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
|
|
for (int PartIndex = 0; PartIndex < LC_MFW_NUMITEMS; PartIndex++)
|
|
{
|
|
mMinifig.ColorIndices[PartIndex] = lcGetColorIndex(Template.ColorCodes[PartIndex]);
|
|
mMinifig.Angles[PartIndex] = Template.Angles[PartIndex];
|
|
mMinifig.Matrices[PartIndex] = lcMatrix44Identity();
|
|
|
|
mMinifig.PieceData[PartIndex] = Library->AcquirePieceData(Template.Parts[PartIndex].toLatin1(), nullptr, false, false);
|
|
|
|
if (mMinifig.PieceData[PartIndex])
|
|
Library->RequestPieceDataLoad(mMinifig.PieceData[PartIndex].Get(), lcLoadPriority::Normal);
|
|
}
|
|
|
|
std::vector<lcPieceDataRef> RequiredPieceData;
|
|
|
|
for (const lcPieceDataRef& PieceData : mMinifig.PieceData)
|
|
if (PieceData)
|
|
RequiredPieceData.push_back(PieceData);
|
|
|
|
Library->WaitForPieceData(RequiredPieceData);
|
|
|
|
Calculate();
|
|
}
|
|
|
|
void MinifigWizard::SaveTemplate(const QString& TemplateName, const lcMinifigTemplate& Template)
|
|
{
|
|
mTemplates[TemplateName] = Template;
|
|
}
|
|
|
|
void MinifigWizard::DeleteTemplate(const QString& TemplateName)
|
|
{
|
|
mTemplates.erase(TemplateName);
|
|
}
|
|
|
|
void MinifigWizard::AddTemplatesJson(const QByteArray& TemplateData)
|
|
{
|
|
QJsonDocument Document = QJsonDocument::fromJson(TemplateData);
|
|
QJsonObject RootObject = Document.object();
|
|
|
|
int Version = RootObject["Version"].toInt(0);
|
|
QJsonObject TemplatesObject;
|
|
|
|
if (Version > 0)
|
|
TemplatesObject = RootObject["Templates"].toObject();
|
|
else
|
|
TemplatesObject = RootObject;
|
|
|
|
for (QJsonObject::const_iterator ElementIt = TemplatesObject.constBegin(); ElementIt != TemplatesObject.constEnd(); ElementIt++)
|
|
{
|
|
if (!ElementIt.value().isObject())
|
|
continue;
|
|
|
|
QJsonObject TemplateObject = ElementIt.value().toObject();
|
|
lcMinifigTemplate Template;
|
|
|
|
for (int PartIdx = 0; PartIdx < LC_MFW_NUMITEMS; PartIdx++)
|
|
{
|
|
QJsonObject PartObject = TemplateObject.value(QLatin1String(mSectionNames[PartIdx])).toObject();
|
|
|
|
Template.Parts[PartIdx] = PartObject["Id"].toString();
|
|
Template.ColorCodes[PartIdx] = PartObject["Color"].toInt();
|
|
Template.Angles[PartIdx] = PartObject["Angle"].toDouble();
|
|
}
|
|
|
|
mTemplates.emplace(ElementIt.key(), std::move(Template));
|
|
}
|
|
}
|
|
|
|
QByteArray MinifigWizard::GetTemplatesJson() const
|
|
{
|
|
QJsonObject TemplatesObject;
|
|
|
|
for (const auto& TemplateEntry : mTemplates)
|
|
{
|
|
const lcMinifigTemplate& Template = TemplateEntry.second;
|
|
QJsonObject TemplateObject;
|
|
|
|
for (int PartIdx = 0; PartIdx < LC_MFW_NUMITEMS; PartIdx++)
|
|
{
|
|
QJsonObject PartObject;
|
|
|
|
PartObject["Id"] = Template.Parts[PartIdx];
|
|
PartObject["Color"] = Template.ColorCodes[PartIdx];
|
|
PartObject["Angle"] = Template.Angles[PartIdx];
|
|
|
|
TemplateObject[QLatin1String(mSectionNames[PartIdx])] = PartObject;
|
|
}
|
|
|
|
TemplatesObject[TemplateEntry.first] = TemplateObject;
|
|
}
|
|
|
|
QJsonObject RootObject;
|
|
RootObject["Templates"] = TemplatesObject;
|
|
RootObject["Version"] = 1;
|
|
|
|
return QJsonDocument(RootObject).toJson();
|
|
}
|
|
|
|
void MinifigWizard::LoadTemplates()
|
|
{
|
|
mTemplates.clear();
|
|
|
|
QSettings Settings;
|
|
Settings.beginGroup("Minifig");
|
|
QByteArray TemplateData = Settings.value("Templates").toByteArray();
|
|
|
|
AddTemplatesJson(TemplateData);
|
|
}
|
|
|
|
void MinifigWizard::SaveTemplates()
|
|
{
|
|
QSettings Settings;
|
|
Settings.beginGroup("Minifig");
|
|
Settings.setValue("Templates", GetTemplatesJson());
|
|
}
|
|
|
|
void MinifigWizard::Calculate()
|
|
{
|
|
float HeadOffset = 0.0f;
|
|
lcMatrix44 Root, Mat, Mat2;
|
|
|
|
const lcPieceDataRef* PieceData = mMinifig.PieceData;
|
|
const float* Angles = mMinifig.Angles;
|
|
lcMatrix44* Matrices = mMinifig.Matrices;
|
|
|
|
const bool DroidTorso = PieceData[LC_MFW_BODY] && !qstricmp(PieceData[LC_MFW_BODY]->mFileName, "30375.dat");
|
|
const bool SkeletonTorso = PieceData[LC_MFW_BODY] && !qstricmp(PieceData[LC_MFW_BODY]->mFileName, "6260.dat");
|
|
|
|
if (PieceData[LC_MFW_BODY3])
|
|
Root = lcMatrix44Translation(lcVector3(0, 0, 74.0f));
|
|
else
|
|
Root = lcMatrix44Translation(lcVector3(0, 0, 72.0f));
|
|
Matrices[LC_MFW_BODY] = lcMul(mSettings[LC_MFW_BODY][GetSelectionIndex(LC_MFW_BODY)].Offset, Root);
|
|
|
|
if (PieceData[LC_MFW_NECK])
|
|
{
|
|
Matrices[LC_MFW_NECK] = lcMul(mSettings[LC_MFW_NECK][GetSelectionIndex(LC_MFW_NECK)].Offset, Root);
|
|
HeadOffset = 0.08f;
|
|
}
|
|
|
|
if (PieceData[LC_MFW_HEAD])
|
|
{
|
|
Mat = lcMatrix44RotationZ(-LC_DTOR * Angles[LC_MFW_HEAD]);
|
|
Mat.SetTranslation(lcVector3(0.0f, 0.0f, 24.0f + HeadOffset));
|
|
Mat = lcMul(mSettings[LC_MFW_HEAD][GetSelectionIndex(LC_MFW_HEAD)].Offset, Mat);
|
|
Matrices[LC_MFW_HEAD] = lcMul(Mat, Root);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_HATS])
|
|
{
|
|
Mat = lcMatrix44RotationZ(-LC_DTOR * Angles[LC_MFW_HATS]);
|
|
Mat = lcMul(mSettings[LC_MFW_HATS][GetSelectionIndex(LC_MFW_HATS)].Offset, Mat);
|
|
Matrices[LC_MFW_HATS] = lcMul(Mat, Matrices[LC_MFW_HEAD]);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_HATS2])
|
|
{
|
|
Mat = lcMatrix44RotationX(-LC_DTOR * Angles[LC_MFW_HATS2]);
|
|
Mat = lcMul(mSettings[LC_MFW_HATS2][GetSelectionIndex(LC_MFW_HATS2)].Offset, Mat);
|
|
Matrices[LC_MFW_HATS2] = lcMul(Mat, Matrices[LC_MFW_HATS]);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_RARM])
|
|
{
|
|
Mat = lcMatrix44RotationX(-LC_DTOR * Angles[LC_MFW_RARM]);
|
|
|
|
if (DroidTorso || SkeletonTorso)
|
|
Mat2 = lcMatrix44Identity();
|
|
else
|
|
Mat2 = lcMatrix44RotationY(-LC_DTOR * 9.791f);
|
|
Mat2.SetTranslation(lcVector3(15.552f, 0, -8.88f));
|
|
|
|
Mat = lcMul(mSettings[LC_MFW_RARM][GetSelectionIndex(LC_MFW_RARM)].Offset, Mat);
|
|
Mat = lcMul(Mat, Mat2);
|
|
Matrices[LC_MFW_RARM] = lcMul(Mat, Root);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_RHAND])
|
|
{
|
|
Mat = lcMatrix44RotationY(-LC_DTOR * Angles[LC_MFW_RHAND]);
|
|
Mat2 = lcMatrix44RotationX(LC_DTOR * 45);
|
|
Mat = lcMul(mSettings[LC_MFW_RHAND][GetSelectionIndex(LC_MFW_RHAND)].Offset, Mat);
|
|
Mat = lcMul(Mat, Mat2);
|
|
Mat.SetTranslation(lcVector3(5.0f, -10.0f, -19.0f));
|
|
Matrices[LC_MFW_RHAND] = lcMul(Mat, Matrices[LC_MFW_RARM]);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_RHANDA])
|
|
{
|
|
Mat = lcMatrix44RotationZ(LC_DTOR * Angles[LC_MFW_RHANDA]);
|
|
Mat.SetTranslation(lcVector3(0, -9.25f, 0));
|
|
Mat = lcMul(mSettings[LC_MFW_RHANDA][GetSelectionIndex(LC_MFW_RHANDA)].Offset, Mat);
|
|
Mat = lcMul(Mat, lcMatrix44RotationX(LC_DTOR * 15.0f));
|
|
Matrices[LC_MFW_RHANDA] = lcMul(Mat, Matrices[LC_MFW_RHAND]);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_LARM])
|
|
{
|
|
Mat = lcMatrix44RotationX(-LC_DTOR * Angles[LC_MFW_LARM]);
|
|
|
|
if (DroidTorso || SkeletonTorso)
|
|
Mat2 = lcMatrix44Identity();
|
|
else
|
|
Mat2 = lcMatrix44RotationY(LC_DTOR * 9.791f);
|
|
Mat2.SetTranslation(lcVector3(-15.552f, 0.0f, -8.88f));
|
|
|
|
Mat = lcMul(mSettings[LC_MFW_LARM][GetSelectionIndex(LC_MFW_LARM)].Offset, Mat);
|
|
Mat = lcMul(Mat, Mat2);
|
|
Matrices[LC_MFW_LARM] = lcMul(Mat, Root);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_LHAND])
|
|
{
|
|
Mat = lcMatrix44RotationY(-LC_DTOR * Angles[LC_MFW_LHAND]);
|
|
Mat2 = lcMatrix44RotationX(LC_DTOR * 45);
|
|
Mat = lcMul(mSettings[LC_MFW_LHAND][GetSelectionIndex(LC_MFW_LHAND)].Offset, Mat);
|
|
Mat = lcMul(Mat, Mat2);
|
|
Mat.SetTranslation(lcVector3(-5.0f, -10.0f, -19.0f));
|
|
Matrices[LC_MFW_LHAND] = lcMul(Mat, Matrices[LC_MFW_LARM]);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_LHANDA])
|
|
{
|
|
Mat = lcMatrix44RotationZ(LC_DTOR * Angles[LC_MFW_LHANDA]);
|
|
Mat.SetTranslation(lcVector3(0, -9.25f, 0));
|
|
Mat = lcMul(mSettings[LC_MFW_LHANDA][GetSelectionIndex(LC_MFW_LHANDA)].Offset, Mat);
|
|
Mat = lcMul(Mat, lcMatrix44RotationX(LC_DTOR * 15.0f));
|
|
Matrices[LC_MFW_LHANDA] = lcMul(Mat, Matrices[LC_MFW_LHAND]);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_BODY2])
|
|
{
|
|
Mat = lcMatrix44Identity();
|
|
Mat.SetTranslation(lcVector3(0, 0, -32.0f));
|
|
Mat = lcMul(mSettings[LC_MFW_BODY2][GetSelectionIndex(LC_MFW_BODY2)].Offset, Mat);
|
|
Matrices[LC_MFW_BODY2] = lcMul(Mat, Root);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_BODY3])
|
|
{
|
|
Mat = lcMatrix44Identity();
|
|
Mat.SetTranslation(lcVector3(0, 0, -32.0f));
|
|
Mat = lcMul(mSettings[LC_MFW_BODY3][GetSelectionIndex(LC_MFW_BODY3)].Offset, Mat);
|
|
Matrices[LC_MFW_BODY3] = lcMul(Mat, Root);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_RLEG])
|
|
{
|
|
Mat = lcMatrix44RotationX(-LC_DTOR * Angles[LC_MFW_RLEG]);
|
|
Mat.SetTranslation(lcVector3(0, 0, -44.0f));
|
|
Mat = lcMul(mSettings[LC_MFW_RLEG][GetSelectionIndex(LC_MFW_RLEG)].Offset, Mat);
|
|
Matrices[LC_MFW_RLEG] = lcMul(Mat, Root);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_RLEGA])
|
|
{
|
|
const lcVector3 Center(-10.0f, -1.0f, -28.0f);
|
|
Mat = lcMatrix44RotationZ(LC_DTOR * Angles[LC_MFW_RLEGA]);
|
|
Mat2 = mSettings[LC_MFW_RLEGA][GetSelectionIndex(LC_MFW_RLEGA)].Offset;
|
|
Mat2.SetTranslation(lcMul31(-Center, Mat2));
|
|
Mat = lcMul(Mat2, Mat);
|
|
Mat.SetTranslation(lcMul31(Center, Mat2));
|
|
Matrices[LC_MFW_RLEGA] = lcMul(Mat, Matrices[LC_MFW_RLEG]);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_LLEG])
|
|
{
|
|
Mat = lcMatrix44RotationX(-LC_DTOR * Angles[LC_MFW_LLEG]);
|
|
Mat.SetTranslation(lcVector3(0, 0, -44.0f));
|
|
Mat = lcMul(mSettings[LC_MFW_LLEG][GetSelectionIndex(LC_MFW_LLEG)].Offset, Mat);
|
|
Matrices[LC_MFW_LLEG] = lcMul(Mat, Root);
|
|
}
|
|
|
|
if (PieceData[LC_MFW_LLEGA])
|
|
{
|
|
const lcVector3 Center(10.0f, -1.0f, -28.0f);
|
|
Mat = lcMatrix44RotationZ(LC_DTOR * Angles[LC_MFW_LLEGA]);
|
|
Mat2 = mSettings[LC_MFW_LLEGA][GetSelectionIndex(LC_MFW_LLEGA)].Offset;
|
|
Mat2.SetTranslation(lcMul31(-Center, Mat2));
|
|
Mat = lcMul(Mat2, Mat);
|
|
Mat.SetTranslation(lcMul31(Center, Mat2));
|
|
Matrices[LC_MFW_LLEGA] = lcMul(Mat, Matrices[LC_MFW_LLEG]);
|
|
}
|
|
|
|
mModel->SetMinifig(mMinifig);
|
|
}
|
|
|
|
int MinifigWizard::GetSelectionIndex(int Type) const
|
|
{
|
|
const std::vector<lcMinifigPieceInfo>& InfoArray = mSettings[Type];
|
|
|
|
for (size_t Index = 0; Index < InfoArray.size(); Index++)
|
|
if (InfoArray[Index].PieceData == mMinifig.PieceData[Type])
|
|
return (int)Index;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void MinifigWizard::SetPieceData(int Type, lcPieceData* PieceData)
|
|
{
|
|
mMinifig.PieceData[Type] = lcPieceDataRef(PieceData);
|
|
|
|
if (mMinifig.PieceData[Type])
|
|
lcGetPiecesLibrary()->WaitForPieceData(mMinifig.PieceData[Type]);
|
|
|
|
Calculate();
|
|
}
|
|
|
|
void MinifigWizard::SetColorIndex(int Type, int ColorIndex)
|
|
{
|
|
mMinifig.ColorIndices[Type] = ColorIndex;
|
|
|
|
Calculate();
|
|
}
|
|
|
|
void MinifigWizard::SetAngle(int Type, float Angle)
|
|
{
|
|
mMinifig.Angles[Type] = Angle;
|
|
|
|
Calculate();
|
|
}
|