From 0a749f6f3afc5b82e3fab870b57e60955f248895 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Wed, 20 Jan 2021 11:56:30 +0100 Subject: [PATCH] Stud style --- common/lc_application.cpp | 2 +- common/lc_colors.cpp | 172 +++++++++++++++++++++++++++------- common/lc_colors.h | 4 +- common/lc_library.cpp | 103 +++++++++++++------- common/lc_library.h | 1 + leocad.qrc | 2 + qt/lc_qpreferencesdialog.h | 2 +- qt/lc_qpreferencesdialog.ui | 20 +++- resources/studslegostyle1.zip | Bin 0 -> 8375 bytes resources/studslegostyle2.zip | Bin 0 -> 9315 bytes 10 files changed, 229 insertions(+), 77 deletions(-) create mode 100644 resources/studslegostyle1.zip create mode 100644 resources/studslegostyle2.zip diff --git a/common/lc_application.cpp b/common/lc_application.cpp index c8d1d546..e6365724 100644 --- a/common/lc_application.cpp +++ b/common/lc_application.cpp @@ -656,7 +656,7 @@ lcCommandLineOptions lcApplication::ParseCommandLineOptions() } else if (Option == QLatin1String("-sl") || Option == QLatin1String("--stud-logo")) { - ParseInteger(Options.StudLogo, 0, 5); + ParseInteger(Options.StudLogo, 0, 7); if (Options.StudLogo != lcGetProfileInt(LC_PROFILE_STUD_LOGO)) lcGetPiecesLibrary()->SetStudLogo(Options.StudLogo, false); diff --git a/common/lc_colors.cpp b/common/lc_colors.cpp index 3915e8e4..16e81bb5 100644 --- a/common/lc_colors.cpp +++ b/common/lc_colors.cpp @@ -209,46 +209,76 @@ int lcGetBrickLinkColor(int ColorIndex) return 0; } -bool lcLoadColorFile(lcFile& File) +bool lcLoadColorFile(lcFile& File, bool Update) { char Line[1024], Token[1024]; std::vector& Colors = gColorList; lcColor Color, MainColor, EdgeColor; - Colors.clear(); + if (Update) + { + EdgeColor = Colors[lcGetColorIndex(24)]; + for (auto EdgeColorIt = Colors.begin(); EdgeColorIt != Colors.end() ; EdgeColorIt++) + { + if (EdgeColorIt->Code == 24) + { + Colors.erase(EdgeColorIt); + break; + } + } - for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++) - gColorGroups[GroupIdx].Colors.clear(); + MainColor = Colors[lcGetColorIndex(16)]; + for (auto MainColorIt = Colors.begin(); MainColorIt != Colors.end() ; MainColorIt++) + { + if (MainColorIt->Code == 16) + { + Colors.erase(MainColorIt); + break; + } + } - gColorGroups[0].Name = QApplication::tr("Solid", "Colors"); - gColorGroups[1].Name = QApplication::tr("Translucent", "Colors"); - gColorGroups[2].Name = QApplication::tr("Special", "Colors"); + std::vector& SolidColors = gColorGroups[LC_COLORGROUP_SOLID].Colors; + const auto& DefaultColorIt = std::find(SolidColors.begin(), SolidColors.end(), gDefaultColor); + if (DefaultColorIt != SolidColors.end()) + SolidColors.erase(DefaultColorIt); + } + else + { + Colors.clear(); - MainColor.Code = 16; - MainColor.Translucent = false; - MainColor.Value[0] = 1.0f; - MainColor.Value[1] = 1.0f; - MainColor.Value[2] = 0.5f; - MainColor.Value[3] = 1.0f; - MainColor.Edge[0] = 0.2f; - MainColor.Edge[1] = 0.2f; - MainColor.Edge[2] = 0.2f; - MainColor.Edge[3] = 1.0f; - strcpy(MainColor.Name, "Main Color"); - strcpy(MainColor.SafeName, "Main_Color"); + for (int GroupIdx = 0; GroupIdx < LC_NUM_COLORGROUPS; GroupIdx++) + gColorGroups[GroupIdx].Colors.clear(); - EdgeColor.Code = 24; - EdgeColor.Translucent = false; - EdgeColor.Value[0] = 0.5f; - EdgeColor.Value[1] = 0.5f; - EdgeColor.Value[2] = 0.5f; - EdgeColor.Value[3] = 1.0f; - EdgeColor.Edge[0] = 0.2f; - EdgeColor.Edge[1] = 0.2f; - EdgeColor.Edge[2] = 0.2f; - EdgeColor.Edge[3] = 1.0f; - strcpy(EdgeColor.Name, "Edge Color"); - strcpy(EdgeColor.SafeName, "Edge_Color"); + gColorGroups[0].Name = QApplication::tr("Solid", "Colors"); + gColorGroups[1].Name = QApplication::tr("Translucent", "Colors"); + gColorGroups[2].Name = QApplication::tr("Special", "Colors"); + + MainColor.Code = 16; + MainColor.Translucent = false; + MainColor.Value[0] = 1.0f; + MainColor.Value[1] = 1.0f; + MainColor.Value[2] = 0.5f; + MainColor.Value[3] = 1.0f; + MainColor.Edge[0] = 0.2f; + MainColor.Edge[1] = 0.2f; + MainColor.Edge[2] = 0.2f; + MainColor.Edge[3] = 1.0f; + strcpy(MainColor.Name, "Main Color"); + strcpy(MainColor.SafeName, "Main_Color"); + + EdgeColor.Code = 24; + EdgeColor.Translucent = false; + EdgeColor.Value[0] = 0.5f; + EdgeColor.Value[1] = 0.5f; + EdgeColor.Value[2] = 0.5f; + EdgeColor.Value[3] = 1.0f; + EdgeColor.Edge[0] = 0.2f; + EdgeColor.Edge[1] = 0.2f; + EdgeColor.Edge[2] = 0.2f; + EdgeColor.Edge[3] = 1.0f; + strcpy(EdgeColor.Name, "Edge Color"); + strcpy(EdgeColor.SafeName, "Edge_Color"); + } while (File.ReadLine(Line, sizeof(Line))) { @@ -340,7 +370,7 @@ bool lcLoadColorFile(lcFile& File) GroupSpecial = true; } else if (!strcmp(Token, "CHROME") || !strcmp(Token, "PEARLESCENT") || !strcmp(Token, "RUBBER") || - !strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE")) + !strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE")) { GroupSpecial = true; } @@ -361,19 +391,19 @@ bool lcLoadColorFile(lcFile& File) Color.Edge[2] = 33.0f / 255.0f; } - bool Duplicate = false; + bool ExistingColorUpdate = false; for (lcColor& ExistingColor : Colors) { if (ExistingColor.Code == Color.Code) { ExistingColor = Color; - Duplicate = true; + ExistingColorUpdate = true; break; } } - if (Duplicate) + if (ExistingColorUpdate) continue; if (Color.Code == 16) @@ -399,6 +429,7 @@ bool lcLoadColorFile(lcFile& File) } gDefaultColor = (int)Colors.size(); + Colors.push_back(MainColor); gColorGroups[LC_COLORGROUP_SOLID].Colors.push_back(gDefaultColor); @@ -415,7 +446,7 @@ void lcLoadDefaultColors() lcDiskFile ConfigFile(":/resources/ldconfig.ldr"); if (ConfigFile.Open(QIODevice::ReadOnly)) - lcLoadColorFile(ConfigFile); + lcLoadColorFile(ConfigFile, false); } int lcGetColorIndex(quint32 ColorCode) @@ -455,3 +486,72 @@ int lcGetColorIndex(quint32 ColorCode) gColorList.push_back(Color); return (int)gColorList.size() - 1; } + +void lcLoadLegoStyleDisplayColors() +{ + QByteArray ColorData; + const char *ColorEntry = "0 !COLOUR Stud_Style_Black CODE 4242 VALUE #1B2A34 EDGE #000000\r\n"; + ColorData.append(ColorEntry); + lcMemFile ColorMemFile; + ColorMemFile.WriteBuffer(ColorData.constData(), ColorData.size()); + ColorMemFile.Seek(0, SEEK_SET); + + lcLoadColorFile(ColorMemFile, true); + + lcColor* DarkGrey = &gColorList[lcGetColorIndexByName("Stud Style Dark Gray Edge")]; + lcColor* Black = &gColorList[lcGetColorIndexByName("Stud Style Black Edge")]; + + for (size_t ColorIdx = 0; ColorIdx < gColorList.size(); ColorIdx++) + { + lcColor* Color = &gColorList[ColorIdx]; + if (Color->Code == 4242) + continue; + + float r = 0.0f, g = 0.0f, b = 0.0f; + float rr = Color->Value[0] * 255.0f, + gg = Color->Value[1] * 255.0f, + bb = Color->Value[2] * 255.0f; + if (30 * rr + 59 * gg + 11 * bb <= 3600) + { + if (DarkGrey) + { + r = DarkGrey->Edge[0]; + g = DarkGrey->Edge[1]; + b = DarkGrey->Edge[2]; + } + else + { + r = 27.0f; + g = 42.0f; + b = 52.0f; + } + } + else + { + if (Color->Code == 0) + { + r = 255.0f; + g = 255.0f; + b = 255.0f; + } + else if (Black) + { + r = Black->Edge[0]; + g = Black->Edge[1]; + b = Black->Edge[2]; + } + } + + Color->Edge[0] = r / 255.0f; + Color->Edge[1] = g / 255.0f; + Color->Edge[2] = b / 255.0f; + } +} + +int lcGetColorIndexByName(const char * ColorName) +{ + for (size_t ColorIdx = 0; ColorIdx < gColorList.size(); ColorIdx++) + if (gColorList[ColorIdx].Name == ColorName) + return (int)ColorIdx; + return 0x0; +} diff --git a/common/lc_colors.h b/common/lc_colors.h index 50dad8eb..bb102d96 100644 --- a/common/lc_colors.h +++ b/common/lc_colors.h @@ -49,8 +49,10 @@ extern int gEdgeColor; extern int gDefaultColor; void lcLoadDefaultColors(); -bool lcLoadColorFile(lcFile& File); +void lcLoadLegoStyleDisplayColors(); +bool lcLoadColorFile(lcFile& File, bool Update); int lcGetColorIndex(quint32 ColorCode); +int lcGetColorIndexByName(const char * ColorName); int lcGetBrickLinkColor(int ColorIndex); inline quint32 lcGetColorCodeFromExtendedColor(int Color) diff --git a/common/lc_library.cpp b/common/lc_library.cpp index eefadbee..3491fda5 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -238,24 +238,9 @@ bool lcPiecesLibrary::Load(const QString& LibraryPath, bool ShowProgress) { Unload(); - auto LoadCustomColors = []() - { - QString CustomColorsPath = lcGetProfileString(LC_PROFILE_COLOR_CONFIG); - - if (CustomColorsPath.isEmpty()) - return false; - - lcDiskFile ColorFile(CustomColorsPath); - return ColorFile.Open(QIODevice::ReadOnly) && lcLoadColorFile(ColorFile); - }; - if (OpenArchive(LibraryPath, lcZipFileType::Official)) { - lcMemFile ColorFile; - - if (!LoadCustomColors()) - if (!mZipFiles[static_cast(lcZipFileType::Official)]->ExtractFile("ldraw/ldconfig.ldr", ColorFile) || !lcLoadColorFile(ColorFile)) - lcLoadDefaultColors(); + LoadColors(false); mLibraryDir = QFileInfo(LibraryPath).absoluteDir(); QString UnofficialFileName = mLibraryDir.absoluteFilePath(QLatin1String("ldrawunf.zip")); @@ -270,20 +255,7 @@ bool lcPiecesLibrary::Load(const QString& LibraryPath, bool ShowProgress) mLibraryDir.setPath(LibraryPath); if (OpenDirectory(mLibraryDir, ShowProgress)) - { - if (!LoadCustomColors()) - { - lcDiskFile ColorFile(mLibraryDir.absoluteFilePath(QLatin1String("ldconfig.ldr"))); - - if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile)) - { - ColorFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String("LDConfig.ldr"))); - - if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile)) - lcLoadDefaultColors(); - } - } - } + LoadColors(false); else return false; } @@ -295,6 +267,44 @@ bool lcPiecesLibrary::Load(const QString& LibraryPath, bool ShowProgress) return true; } +void lcPiecesLibrary::LoadColors(bool Update) +{ + auto LoadCustomColors = [&Update]() + { + QString CustomColorsPath = lcGetProfileString(LC_PROFILE_COLOR_CONFIG); + + if (CustomColorsPath.isEmpty()) + return false; + + lcDiskFile ColorFile(CustomColorsPath); + return ColorFile.Open(QIODevice::ReadOnly) && lcLoadColorFile(ColorFile, Update); + }; + + if (mZipFiles[static_cast(lcZipFileType::Official)]) + { + lcMemFile ColorFile; + + if (!LoadCustomColors()) + if (!mZipFiles[static_cast(lcZipFileType::Official)]->ExtractFile("ldraw/ldconfig.ldr", ColorFile) || !lcLoadColorFile(ColorFile, Update)) + lcLoadDefaultColors(); + } + else + { + if (!LoadCustomColors()) + { + lcDiskFile ColorFile(mLibraryDir.absoluteFilePath(QLatin1String("ldconfig.ldr"))); + + if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile, Update)) + { + ColorFile.SetFileName(mLibraryDir.absoluteFilePath(QLatin1String("LDConfig.ldr"))); + + if (!ColorFile.Open(QIODevice::ReadOnly) || !lcLoadColorFile(ColorFile, Update)) + lcLoadDefaultColors(); + } + } + } +} + void lcPiecesLibrary::UpdateStudLogoSource() { if (!mSources.empty() && mSources.front()->Type == lcLibrarySourceType::StudLogo) @@ -305,7 +315,16 @@ void lcPiecesLibrary::UpdateStudLogoSource() if (!mStudLogo) return; - std::unique_ptr StudLogoFile(new lcDiskFile(QString(":/resources/studlogo%1.zip").arg(QString::number(mStudLogo)))); + if (mStudLogo > 5) + lcLoadLegoStyleDisplayColors(); + + std::unique_ptr StudLogoFile; + if (mStudLogo < 6) + StudLogoFile = std::unique_ptr(new lcDiskFile(QString(":/resources/studlogo%1.zip").arg(QString::number(mStudLogo)))); + else if (mStudLogo == 6) + StudLogoFile = std::unique_ptr(new lcDiskFile(QString(":/resources/studslegostyle1.zip"))); + else + StudLogoFile = std::unique_ptr(new lcDiskFile(QString(":/resources/studslegostyle2.zip"))); if (StudLogoFile->Open(QIODevice::ReadOnly)) OpenArchive(std::move(StudLogoFile), lcZipFileType::StudLogo); @@ -1520,6 +1539,9 @@ bool lcPiecesLibrary::SupportsStudLogo() const void lcPiecesLibrary::SetStudLogo(int StudLogo, bool Reload) { + if (mStudLogo > 5 && StudLogo < 6 && Reload) + LoadColors(Reload); + mStudLogo = StudLogo; UpdateStudLogoSource(); @@ -1602,6 +1624,21 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive) lcMeshLoader MeshLoader(Primitive->mMeshData, true, nullptr, false); + auto StudLogoPrimitive = [this, &Primitive] () + { + if (!mSources.empty() && mSources.front()->Type == lcLibrarySourceType::StudLogo) + { + char Name[LC_PIECE_NAME_LEN]; + strcpy(Name, Primitive->mName); + strupr(Name); + const std::unique_ptr& Source = mSources.front(); + const auto& PrimitiveIt = Source->Primitives.find(Name); + if (PrimitiveIt != Source->Primitives.end()) + return true; + } + return false; + }; + if (mZipFiles[static_cast(lcZipFileType::Official)]) { lcLibraryPrimitive* LowPrimitive = nullptr; @@ -1610,7 +1647,7 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive) if (Primitive->mStud) { - if (!strcmp(Primitive->mName, "stud.dat") || !strcmp(Primitive->mName, "stud2.dat")) + if (StudLogoPrimitive()) Primitive->mMeshData.mHasLogoStud = true; else if (strncmp(Primitive->mName, "8/", 2)) // todo: this is currently the only place that uses mName so use mFileName instead. this should also be done for the loose file libraries. { @@ -1647,7 +1684,7 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive) { if (Primitive->mStud) { - if (!strcmp(Primitive->mName,"stud.dat") || !strcmp(Primitive->mName, "stud2.dat")) + if (StudLogoPrimitive()) Primitive->mMeshData.mHasLogoStud = true; } diff --git a/common/lc_library.h b/common/lc_library.h index d7c70bd9..1592f859 100644 --- a/common/lc_library.h +++ b/common/lc_library.h @@ -102,6 +102,7 @@ public: lcPiecesLibrary& operator=(lcPiecesLibrary&&) = delete; bool Load(const QString& LibraryPath, bool ShowProgress); + void LoadColors(bool Update); void Unload(); void RemoveTemporaryPieces(); void RemovePiece(PieceInfo* Info); diff --git a/leocad.qrc b/leocad.qrc index f9a05af1..a5e03d3c 100644 --- a/leocad.qrc +++ b/leocad.qrc @@ -101,6 +101,8 @@ resources/studlogo3.zip resources/studlogo4.zip resources/studlogo5.zip + resources/studslegostyle1.zip + resources/studslegostyle2.zip resources/ldconfig.ldr resources/minifig.ini resources/ldraw.xml diff --git a/qt/lc_qpreferencesdialog.h b/qt/lc_qpreferencesdialog.h index fa448dd8..c2ca24b4 100644 --- a/qt/lc_qpreferencesdialog.h +++ b/qt/lc_qpreferencesdialog.h @@ -41,7 +41,7 @@ class lcQPreferencesDialog; class lcQPreferencesDialog : public QDialog { Q_OBJECT - + public: lcQPreferencesDialog(QWidget* Parent, lcPreferencesDialogOptions* Options); ~lcQPreferencesDialog(); diff --git a/qt/lc_qpreferencesdialog.ui b/qt/lc_qpreferencesdialog.ui index 5a92909b..3aed1786 100644 --- a/qt/lc_qpreferencesdialog.ui +++ b/qt/lc_qpreferencesdialog.ui @@ -390,27 +390,37 @@ - Logo1 + 1 LDraw Single Wire - Logo2 + 2 LDraw Double Wire - Logo3 + 3 LDraw Raised Floating - Logo4 + 4 LDraw Raised Rounded - Logo5 + 5 LDraw Subtle Rounded + + + + + 6 LEGO Without Logo + + + + + 7 LEGO Single Wire diff --git a/resources/studslegostyle1.zip b/resources/studslegostyle1.zip new file mode 100644 index 0000000000000000000000000000000000000000..245efb6f4dff84911a079a546df33c18b1684bc6 GIT binary patch literal 8375 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 literal 0 HcmV?d00001 diff --git a/resources/studslegostyle2.zip b/resources/studslegostyle2.zip new file mode 100644 index 0000000000000000000000000000000000000000..c4426e116349e75f28c8967378370aa95755e221 GIT binary patch literal 9315 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