From e1145b344f1e85015da25883dcf55845966f0213 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Thu, 30 Oct 2025 14:46:11 +0100 Subject: [PATCH 1/7] Add stud logo dialogue to Windows preferences UI --- ContextHelp.h | 10 ++++++---- LDView.rc | 10 +++++++--- LDViewPreferences.cpp | 20 ++++++++++++++++++++ LDViewPreferences.h | 1 + Resource.h | 4 +++- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/ContextHelp.h b/ContextHelp.h index d6249343e..aa515b828 100644 --- a/ContextHelp.h +++ b/ContextHelp.h @@ -157,13 +157,15 @@ #define HIDC_STEREO_SPACING 0x808a0431 // IDD_EFFECTS_PREFS #define HIDC_STEREO_SPACING_LABEL 0x808a0432 // IDD_EFFECTS_PREFS #define HIDC_STIPPLE 0x808a03f0 // IDD_EFFECTS_PREFS -#define HIDC_STUD_QUALITY 0x860b0512 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_LOGO_USE 0x860b0512 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_LOGO_COMBO 0x860b0513 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_QUALITY 0x860b0514 // IDD_PRIMITIVES_PREFS #define HIDC_TEXMAPS 0x860b0509 // IDD_PRIMITIVES_PREFS -#define HIDC_TEXTURE_ANISO 0x860b0513 // IDD_PRIMITIVES_PREFS -#define HIDC_TEXTURE_OFFSET 0x860b0516 // IDD_PRIMITIVES_PREFS +#define HIDC_TEXTURE_ANISO 0x860b0515 // IDD_PRIMITIVES_PREFS #define HIDC_TEXTURE_BILINEAR 0x860b0456 // IDD_PRIMITIVES_PREFS #define HIDC_TEXTURE_NEAREST 0x860b0455 // IDD_PRIMITIVES_PREFS -#define HIDC_TEXTURE_STUDS 0x860b0514 // IDD_PRIMITIVES_PREFS +#define HIDC_TEXTURE_OFFSET 0x860b0517 // IDD_PRIMITIVES_PREFS +#define HIDC_TEXTURE_STUDS 0x860b0516 // IDD_PRIMITIVES_PREFS #define HIDC_TEXTURE_TRILINEAR 0x860b0457 // IDD_PRIMITIVES_PREFS #define HIDC_TRANSPARENCY_BOX 0x808a043c // IDD_EFFECTS_PREFS #define HIDC_TRANS_DEFAULT_COLOR 0x808b03ec // IDD_GENERAL_PREFS diff --git a/LDView.rc b/LDView.rc index 81a3f2c2f..a66a01a73 100644 --- a/LDView.rc +++ b/LDView.rc @@ -498,9 +498,11 @@ BEGIN CONTROL "Anisotropic filtering:",IDC_TEXTURE_ANISO,"Button",BS_AUTORADIOBUTTON,23,132,75,10,0,HIDC_TEXTURE_ANISO CONTROL "Slider1",IDC_ANISO_LEVEL,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,100,130,80,18,0,HIDC_ANISO_LEVEL LTEXT "nx",IDC_ANISO_LEVEL_LABEL,185,134,26,8,0,0,HIDC_ANISO_LEVEL_LABEL - GROUPBOX "&Misc",IDC_PRIMITIVES_MISC_BOX,7,157,296,40,WS_GROUP,WS_EX_TRANSPARENT,HIDC_PRIMITIVES_MISC_BOX - CONTROL "Low quality studs (faster)",IDC_STUD_QUALITY,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,170,93,10,0,HIDC_STUD_QUALITY - CONTROL "Use hi-res primitives when available",IDC_HI_RES,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,181,127,10,0,HIDC_HI_RES + GROUPBOX "&Misc",IDC_PRIMITIVES_MISC_BOX,7,157,296,52,WS_GROUP,WS_EX_TRANSPARENT,HIDC_PRIMITIVES_MISC_BOX + CONTROL "Use stud logo geometry",IDC_STUD_LOGO_USE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,168,94,10,0,HIDC_STUD_LOGO_USE + COMBOBOX IDC_STUD_LOGO_COMBO,115,166,82,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP,0,HIDC_STUD_LOGO_COMBO + CONTROL "Low quality studs (faster)",IDC_STUD_QUALITY,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,181,93,10,0,HIDC_STUD_QUALITY + CONTROL "Use hi-res primitives when available",IDC_HI_RES,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,194,127,10,0,HIDC_HI_RES PUSHBUTTON "&Reset",IDC_PRIMITIVES_RESET,253,231,50,14,WS_GROUP,0,HIDC_PRIMITIVES_RESET END @@ -1812,6 +1814,8 @@ BEGIN HIDC_STEREO_SPACING "This option is only available if stereo is enabled. The slider controls the stereo spacing. A small value will result in a very subtle stereoscopic effect, as if you were looking at a very large object from a very long distance. (The minimum value results in no stereoscopic effect at all.) A large value will result in a pronounced stereoscopic effect, as if you were looking at a small object from a very short distance." HIDC_STEREO_SPACING_LABEL "This option is only available if stereo is enabled. The slider controls the stereo spacing. A small value will result in a very subtle stereoscopic effect, as if you were looking at a very large object from a very long distance. (The minimum value results in no stereoscopic effect at all.) A large value will result in a pronounced stereoscopic effect, as if you were looking at a small object from a very short distance." HIDC_STIPPLE "Enabling this option causes transparent shapes to be drawn using a stipple (checkerboard) pattern. This may be significantly faster on some video hardware, but with potentially reduced quality. Using the stipple pattern totally eliminates the errors that may occur where far transparent objects are drawn in front of closer ones. This option is mutually exclusive with the sort option." + HIDC_STUD_LOGO_USE "Enabling this option gives the user the ability to select the displayed stud logo geometry. When unchecked, Texture studs settings will be respected." + HIDC_STUD_LOGO_COMBO "This allows you to select the stud logo display when Use stud logo geometry preference is checked." HIDC_STUD_QUALITY "Enabling this option switches to using the low-resolution stud files instead of the normal-resolution stud files. This can produce significantly faster rendering." HIDC_TEXMAPS "Enabling this option turns on support for the LDraw TEXMAP extension. Disabling it will cause LDView to use any fallback geometry included in the LDraw file." HIDC_TEXTURE_ANISO "This option is only available if primitive substitution and texture studs are both enabled, and your video card supports it. Selecting it causes anisotropic texture filtering to be used. When anisotropic filtering is selected, you can pick the filtering level on the slider to the right of the radio button. This is the highest quality texture filtering." diff --git a/LDViewPreferences.cpp b/LDViewPreferences.cpp index 99e786ba2..d7f0d3ef5 100644 --- a/LDViewPreferences.cpp +++ b/LDViewPreferences.cpp @@ -2084,6 +2084,9 @@ void LDViewPreferences::applyPrimitivesChanges(void) ldPrefs->setTextureOffsetFactor(textureOffsetFromSliderValue( trackBarGetPos(hTextureOffsetSlider))); } + ldPrefs->setUseStudLogo(getCheck(hPrimitivesPage, IDC_STUD_LOGO_USE)); + ldPrefs->setStudLogo(CUIDialog::comboGetCurSel(hPrimitivesPage, + IDC_STUD_LOGO_COMBO)); ldPrefs->setQualityStuds(!getCheck(hPrimitivesPage, IDC_STUD_QUALITY)); ldPrefs->setHiResPrimitives(getCheck(hPrimitivesPage, IDC_HI_RES)); ldPrefs->applyPrimitivesSettings(); @@ -2859,6 +2862,9 @@ DWORD LDViewPreferences::doComboSelChange(HWND hPage, int controlId, enableApply(hPage); break; case IDC_MEMORY_COMBO: + enableApply(hPage); + break; + case IDC_STUD_LOGO_COMBO: enableApply(hPage); break; case IDC_SNAPSHOTS_DIR_COMBO: @@ -3261,6 +3267,18 @@ void LDViewPreferences::setupMemoryUsage(void) CUIDialog::comboSetCurSel(hGeneralPage, IDC_MEMORY_COMBO, ldPrefs->getMemoryUsage()); } +void LDViewPreferences::setupStudLogo(void) +{ + CUIDialog::comboResetContent(hPrimitivesPage, IDC_STUD_LOGO_COMBO); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("Plain"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("SingleWire"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("DoubleWire"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("RaisedFlat"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("RaisedRounded"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("SubtleRounded"))); + CUIDialog::comboSetCurSel(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ldPrefs->getStudLogo()); +} + void LDViewPreferences::updateSaveDir( HWND hTextField, HWND hBrowseButton, @@ -4372,6 +4390,8 @@ void LDViewPreferences::setupPrimitivesPage(void) hPrimitivesPage = hwndArray->pointerAtIndex(primitivesPageNumber); setupTextures(); setupSubstitution(); + setupStudLogo(); + setCheck(hPrimitivesPage, IDC_STUD_LOGO_USE, ldPrefs->getUseStudLogo()); setCheck(hPrimitivesPage, IDC_STUD_QUALITY, !ldPrefs->getQualityStuds()); setCheck(hPrimitivesPage, IDC_HI_RES, ldPrefs->getHiResPrimitives()); } diff --git a/LDViewPreferences.h b/LDViewPreferences.h index 18f895134..8876440c4 100644 --- a/LDViewPreferences.h +++ b/LDViewPreferences.h @@ -149,6 +149,7 @@ class LDViewPreferences: public CUIPropertySheet virtual void setupColorButton(HWND hPage, HWND &hColorButton, int controlID, HBITMAP &hButtonBitmap, COLORREF color); virtual void setupMemoryUsage(void); + virtual void setupStudLogo(void); virtual void setupFov(bool warn = false); virtual void setupBackgroundColorButton(void); virtual void setupDefaultColorButton(void); diff --git a/Resource.h b/Resource.h index dfab1d546..59100b47c 100644 --- a/Resource.h +++ b/Resource.h @@ -400,6 +400,8 @@ #define IDC_CUSTOM_CONFIG_BOX 1322 #define IDC_CUSTOM_CONFIG 1323 #define IDC_BROWSE_CUSTOM_CONFIG 1324 +#define IDC_STUD_LOGO_USE 1325 +#define IDC_STUD_LOGO_COMBO 1326 #define PRINTDLGORD 1538 #define PAGESETUPDLGORD 1546 #define IDD_PRIMITIVES_PREFS 1547 @@ -508,7 +510,7 @@ #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 548 #define _APS_NEXT_COMMAND_VALUE 40122 -#define _APS_NEXT_CONTROL_VALUE 1325 +#define _APS_NEXT_CONTROL_VALUE 1327 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif From ef321d83cd6aa2272efc6ebacae8fa45d44ff27d Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Thu, 30 Oct 2025 14:46:39 +0100 Subject: [PATCH 2/7] Add stud logo preference including command line option --- LDLib/LDPreferences.cpp | 27 ++++++++ LDLib/LDPreferences.h | 6 ++ LDLib/LDUserDefaultsKeys.h | 2 + LDLib/LDrawModelViewer.cpp | 22 +++++++ LDLib/LDrawModelViewer.h | 6 ++ LDLoader/LDLModel.cpp | 117 ++++++++++++++++++++++++++++++++- LDLoader/LDLModel.h | 4 ++ LDLoader/LDLPrimitiveCheck.cpp | 4 ++ LDViewMessages.ini | 7 ++ 9 files changed, 193 insertions(+), 2 deletions(-) diff --git a/LDLib/LDPreferences.cpp b/LDLib/LDPreferences.cpp index 4b905fd46..9d90be427 100644 --- a/LDLib/LDPreferences.cpp +++ b/LDLib/LDPreferences.cpp @@ -78,6 +78,8 @@ LDPreferences::LDPreferences(LDrawModelViewer* modelViewer) , m_texmaps(false) , m_textureOffsetFactor(0.0) , m_useStrips(false) + , m_useStudLogo(false) + , m_studLogo(0) , m_proxyType(0) , m_proxyPort(0) , m_checkPartTracker(false) @@ -407,6 +409,8 @@ void LDPreferences::applyPrimitivesSettings(void) m_modelViewer->setTexturesAfterTransparent(true); m_modelViewer->setTextureOffsetFactor(m_textureOffsetFactor); m_modelViewer->setUseStrips(m_useStrips); + m_modelViewer->setUseStudLogo(m_useStudLogo); + m_modelViewer->setStudLogo(m_studLogo); } } @@ -606,6 +610,8 @@ void LDPreferences::loadDefaultPrimitivesSettings(bool initializing /*= true*/) setTextureOffsetFactor(5.0); setUseStrips(true); m_initializing = false; + setUseStudLogo(false); + setStudLogo(-1/*LDView Default*/); } void LDPreferences::loadDefaultUpdatesSettings(bool initializing /*= true*/) @@ -810,6 +816,8 @@ void LDPreferences::loadPrimitivesSettings(void) m_textureOffsetFactor = getFloatSetting(TEXTURE_OFFSET_FACTOR_KEY, m_textureOffsetFactor); m_useStrips = getBoolSetting(STRIPS_KEY, m_useStrips); + m_useStudLogo = getBoolSetting(STUD_LOGO_USE_KEY, m_useStudLogo); + m_studLogo = getIntSetting(STUD_LOGO_KEY, m_studLogo); } void LDPreferences::loadUpdatesSettings(void) @@ -989,6 +997,11 @@ void LDPreferences::commitPrimitivesSettings(bool flush /*= true*/) setTexmaps(m_texmaps, true); setTextureOffsetFactor(m_textureOffsetFactor, true); setUseStrips(m_useStrips, true); + setUseStudLogo(m_useStudLogo, true); + if (m_useStudLogo) + { + setStudLogo(m_studLogo, true); + } if (flush) { TCUserDefaults::flush(); @@ -2013,6 +2026,20 @@ void LDPreferences::setCurveQuality(int value, bool commit) setSetting(m_curveQuality, value, CURVE_QUALITY_KEY, commit); } +void LDPreferences::setUseStudLogo(bool value, bool commit, bool apply) +{ + setSetting(m_useStudLogo, value, STUD_LOGO_USE_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setUseStudLogo(m_useStudLogo); + } +} + +void LDPreferences::setStudLogo(int value, bool commit) +{ + setSetting(m_studLogo, value, STUD_LOGO_KEY, commit); +} + void LDPreferences::setQualityStuds(bool value, bool commit, bool apply) { setSetting(m_qualityStuds, value, QUALITY_STUDS_KEY, commit); diff --git a/LDLib/LDPreferences.h b/LDLib/LDPreferences.h index c26268ba3..fa8f1134e 100644 --- a/LDLib/LDPreferences.h +++ b/LDLib/LDPreferences.h @@ -198,6 +198,8 @@ class LDPreferences : public TCAlertSender bool getTexmaps(void) { return m_texmaps; } bool getTexturesAfterTransparent(void) { return true; } TCFloat getTextureOffsetFactor(void) { return m_textureOffsetFactor; } + bool getUseStudLogo(void) { return m_useStudLogo; } + int getStudLogo(void) { return m_studLogo; } // Update settings int getProxyType(void) { return m_proxyType; } @@ -337,6 +339,8 @@ class LDPreferences : public TCAlertSender void setTexturesAfterTransparent(bool value, bool commit = false, bool apply = false); void setTextureOffsetFactor(TCFloat value, bool commit = false, bool apply = false); void setUseStrips(bool value, bool commit = false, bool apply = false); + void setUseStudLogo(bool value, bool commit = false, bool apply = false); + void setStudLogo(int value, bool commit = false); // Update settings void setProxyType(int value, bool commit = false); @@ -503,6 +507,8 @@ class LDPreferences : public TCAlertSender bool m_texmaps; TCFloat m_textureOffsetFactor; bool m_useStrips; + bool m_useStudLogo; + int m_studLogo; // Update settings int m_proxyType; diff --git a/LDLib/LDUserDefaultsKeys.h b/LDLib/LDUserDefaultsKeys.h index 74329cd50..63a772fd1 100644 --- a/LDLib/LDUserDefaultsKeys.h +++ b/LDLib/LDUserDefaultsKeys.h @@ -157,6 +157,8 @@ #define WIREFRAME_FOG_KEY "WireframeFog" #define WIREFRAME_THICKNESS_KEY "WireframeThickness" #define ZOOM_MAX_KEY "ZoomMax" // NO UI +#define STUD_LOGO_USE_KEY "UseStudLogo" +#define STUD_LOGO_KEY "StudLogo" // The following are undocumented, and should stay that way. #define DEBUG_LEVEL_KEY "DebugLevel" diff --git a/LDLib/LDrawModelViewer.cpp b/LDLib/LDrawModelViewer.cpp index a85cd363e..e2df540d6 100644 --- a/LDLib/LDrawModelViewer.cpp +++ b/LDLib/LDrawModelViewer.cpp @@ -234,6 +234,7 @@ LDrawModelViewer::LDrawModelViewer(TCFloat width, TCFloat height) flags.keepRightSideUp = false; flags.texmaps = true; flags.useStrips = true; + flags.useStudLogo = false; TCAlertManager::registerHandler(LDLFindFileAlert::alertClass(), this, (TCAlertCallback)&LDrawModelViewer::findFileAlertCallback); // Set 4:4:4 as the default sub-sample pattern for JPEG images. @@ -2335,6 +2336,18 @@ void LDrawModelViewer::setCurveQuality(int value) } } +void LDrawModelViewer::setStudLogo(int value) +{ + if (value != studLogo) + { + studLogo = value; + if (flags.useStudLogo) + { + flags.needsReload = true; + } + } +} + void LDrawModelViewer::setRandomColors(bool value) { if (value != flags.randomColors) @@ -2593,6 +2606,15 @@ void LDrawModelViewer::setTextureOffsetFactor(TCFloat value) } } +void LDrawModelViewer::setUseStudLogo(bool value) +{ + if (value != flags.useStudLogo) + { + flags.useStudLogo = value; + flags.needsReload = true; + } +} + void LDrawModelViewer::setUseStrips(bool value) { if (value != flags.useStrips) diff --git a/LDLib/LDrawModelViewer.h b/LDLib/LDrawModelViewer.h index 0a0207213..fd6ad8150 100644 --- a/LDLib/LDrawModelViewer.h +++ b/LDLib/LDrawModelViewer.h @@ -543,6 +543,8 @@ class LDrawModelViewer: public TCAlertSender void setTextureOffsetFactor(TCFloat value); bool getUseStrips(void) const { return flags.useStrips ? true : false; } void setUseStrips(bool value); + bool getUseStudLogo(void) const { return flags.useStudLogo ? true : false; } + void setUseStudLogo(bool value); bool getRandomColors(void) const { return flags.randomColors ? true : false; @@ -635,6 +637,8 @@ class LDrawModelViewer: public TCAlertSender static void resetUnofficialDownloadTimes(void); static std::string libraryUrl(const std::string& path); // static bool doCommandLineExport(void); + void setStudLogo(int value); + int getStudLogo(void) const { return studLogo; } protected: ~LDrawModelViewer(void); void dealloc(void); @@ -831,6 +835,7 @@ class LDrawModelViewer: public TCAlertSender int highlightR; int highlightG; int highlightB; + int studLogo; #ifdef USE_STD_CHRONO std::chrono::time_point frameTime; #else @@ -927,6 +932,7 @@ class LDrawModelViewer: public TCAlertSender bool texmaps:1; bool texturesAfterTransparent:1; bool useStrips:1; + bool useStudLogo:1; } flags; struct CameraData { diff --git a/LDLoader/LDLModel.cpp b/LDLoader/LDLModel.cpp index fb698c8ba..6014a2634 100644 --- a/LDLoader/LDLModel.cpp +++ b/LDLoader/LDLModel.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #ifdef WIN32 @@ -34,6 +35,43 @@ typedef std::pair SearchDirPair; typedef std::vector SearchDirVector; +#define TC_STUD_LOGO_MAX_DATA_LEN 1024 +#define TC_STUD_LOGO_ARRAY_COUNT(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +struct TCStudLogoPrimitive +{ + char Name[64]; + char Data[TC_STUD_LOGO_MAX_DATA_LEN]; +}; + +static struct TCStudLogoPrimitive StudLogoPrimitives[] = +{ + { /* 00 */ + "stud.dat", + "0 Stud\n0 Name: stud.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2012-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 0 0 6 0 0 0 -4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4disc.dat\n" + }, + { /* 01 */ + "8/stud.dat", + "0 Stud (Fast-Draw)\n0 Name: 8\\stud.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 0 0 6 0 0 0 -4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4disc.dat\n" + }, + { /* 02 */ + "stud2.dat", + "0 Stud Open\n0 Name: stud2.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring2.dat\n0\n" + }, + { /* 03 */ + "8/stud2.dat", + "0 Stud Open (Fast-Draw)\n0 Name: 8\\stud2.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 8\4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring2.dat\n" + }, + { /* 04 */ + "stud2a.dat", + "0 Stud Open without Base Edges\n0 Name: stud2a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring2.dat\n0\n" + }, + { /* 05 */ + "8/stud2a.dat", + "0 Stud Open without Base Edges (Fast-Draw)\n0 Name: 8\\stud2a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 8\4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring2.dat\n" + } +}; + char *LDLModel::sm_systemLDrawDir = NULL; #ifdef WIN32 std::string LDLModel::sm_systemLDrawDirSlashes; @@ -261,7 +299,8 @@ LDLModel *LDLModel::subModelNamed(const char *subModelName, bool lowRes, { ancestorCheck = true; } - if (strcasecmp(subModelName, "stud.dat") == 0) + if (strcasecmp(subModelName, "stud.dat") == 0 || + strcasecmp(subModelName, "stud2.dat") == 0) { m_flags.hasStuds = true; } @@ -841,6 +880,67 @@ bool LDLModel::openSubModelNamed( return false; } +int LDLModel::getStudLogoFile(LDLModel* subModel, const char* dictName, int studLogo, bool openStud) +{ + char data[TC_STUD_LOGO_MAX_DATA_LEN]; + char tempPath[256]; +#ifdef WIN32 + sprintf(tempPath, "%s\\ldview_stud_logo%d_%s", getenv("TEMP"), studLogo, dictName); +#else + sprintf(tempPath, "/tmp/ldview_stud_logo%d_%s", studLogo, dictName); +#endif + + std::ifstream existingSubModelStream(tempPath, std::ios::binary); + if (existingSubModelStream.is_open()) + return (subModel->load(existingSubModelStream)); + + if (studLogo > 0) + { + char style[10] = ""; + if (studLogo > 1) + sprintf(style, "%d", studLogo); + sprintf(data, "0 Stud %s\n0 Name: %s\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive\n0 BFC CERTIFY CCW\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 stud%s-logo%s.dat\n", (openStud ? "open" : style), dictName, (openStud ? "2" : ""), style); + } + else + { + for (unsigned int i = 0; i < TC_STUD_LOGO_ARRAY_COUNT(StudLogoPrimitives); i++) + { + if (strcasecmp(dictName, StudLogoPrimitives[i].Name) == 0) + { + strcpy(data, StudLogoPrimitives[i].Data); + break; + } + } + } + + std::ofstream outputStream; + outputStream.open(tempPath, std::ios_base::trunc | std::ios_base::out); + outputStream << data; + outputStream.close(); + + std::ifstream newSubModelStream(tempPath, std::ios::binary); + return (newSubModelStream.is_open() && subModel->load(newSubModelStream)); +} + +int LDLModel::isStudLogoPrimitive(const char* FileName, int studLogo) +{ + // return if file has '-logo' suffix + if (strstr(FileName, "-logo") != NULL) + return 0; + + for (unsigned int i = 0; i < TC_STUD_LOGO_ARRAY_COUNT(StudLogoPrimitives); i++) + { + if (strcasecmp(FileName, StudLogoPrimitives[i].Name) == 0) + { + if (strcasecmp(FileName, "stud2.dat") == 0 || strcasecmp(FileName, "stud2a.dat") == 0) + return 2; // open stud + else + return 1; + } + } + return 0; +} + bool LDLModel::initializeNewSubModel(LDLModel *subModel, const char *dictName) { std::ifstream closedStream; @@ -878,7 +978,20 @@ bool LDLModel::initializeNewSubModel( subModel->m_flags.unofficial = true; } bool zipValid = zipStream != NULL && zipStream->is_valid(); - if ((subModelStream.is_open() || zipValid) && + bool useStudLogo = TCUserDefaults::boolForKey(STUD_LOGO_USE_KEY, false, true); + unsigned int studLogoPrimitive = 0; + if (useStudLogo && m_flags.loadingPrimitive && m_flags.hasStuds) + { + unsigned int studLogo = TCUserDefaults::longForKey(STUD_LOGO_KEY, 0, true); + unsigned int studLogoType = isStudLogoPrimitive(dictName); + if (studLogoType > 0) + { + bool openStud = studLogoType == 2; + studLogoPrimitive = getStudLogoFile(subModel, dictName, + studLogo, openStud); + } + } + if (!studLogoPrimitive && (subModelStream.is_open() || zipValid) && !subModel->load(subModelStream, zipStream)) { subModelDict->removeObjectForKey(dictName); diff --git a/LDLoader/LDLModel.h b/LDLoader/LDLModel.h index 603b99f06..c3341a845 100644 --- a/LDLoader/LDLModel.h +++ b/LDLoader/LDLModel.h @@ -205,6 +205,10 @@ class LDLModel : public TCAlertSender static void initCheckDirs(); + static int isStudLogoPrimitive(const char* FileName, int studLogo = 0); + static int getStudLogoFile(LDLModel* subModel, const char* dictName, + int studLogo, bool openStud); + char *m_filename; char *m_name; char *m_author; diff --git a/LDLoader/LDLPrimitiveCheck.cpp b/LDLoader/LDLPrimitiveCheck.cpp index a4fae6757..48a772423 100644 --- a/LDLoader/LDLPrimitiveCheck.cpp +++ b/LDLoader/LDLPrimitiveCheck.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #ifdef WIN32 @@ -635,6 +637,8 @@ bool LDLPrimitiveCheck::performPrimitiveSubstitution( } else if (strcasecmp(m_modelName, "stud.dat") == 0) { + if (TCUserDefaults::boolForKey(STUD_LOGO_USE_KEY, false)) + return false; return substituteStud(); } else if (strcasecmp(m_modelName, "1-8sphe.dat") == 0) diff --git a/LDViewMessages.ini b/LDViewMessages.ini index 130e3b89c..d835474f1 100644 --- a/LDViewMessages.ini +++ b/LDViewMessages.ini @@ -98,6 +98,13 @@ BrowseForSnapshotDir =Please select the directory to save snapshots into. BrowseForPartsListDir =Please select the directory to save parts lists into. BrowseForExportDir =Please select the directory to save exports into. +; Stud logo geometry +Plain =0 Plain +SingleWire =1 Single Wire +DoubleWire =2 Double Wire +RaisedFlat =3 Raised Flat +RaisedRounded =4 Raised Rounded +SubtleRounded =5 Subtle Rounded ; ** LDViewWindow ** From f8dcb5128e982d4821132408334d9a19fe26f2fd Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sat, 1 Nov 2025 09:19:12 +0100 Subject: [PATCH 3/7] Rename stud logo to stud style --- ContextHelp.h | 4 +-- LDLib/LDPreferences.cpp | 32 +++++++++---------- LDLib/LDPreferences.h | 12 ++++---- LDLib/LDUserDefaultsKeys.h | 4 +-- LDLib/LDrawModelViewer.cpp | 16 +++++----- LDLib/LDrawModelViewer.h | 12 ++++---- LDLoader/LDLModel.cpp | 56 +++++++++++++++++----------------- LDLoader/LDLModel.h | 6 ++-- LDLoader/LDLPrimitiveCheck.cpp | 2 +- LDView.rc | 8 ++--- LDViewMessages.ini | 2 +- LDViewPreferences.cpp | 30 +++++++++--------- LDViewPreferences.h | 2 +- Resource.h | 4 +-- 14 files changed, 95 insertions(+), 95 deletions(-) diff --git a/ContextHelp.h b/ContextHelp.h index aa515b828..7633d1798 100644 --- a/ContextHelp.h +++ b/ContextHelp.h @@ -157,8 +157,8 @@ #define HIDC_STEREO_SPACING 0x808a0431 // IDD_EFFECTS_PREFS #define HIDC_STEREO_SPACING_LABEL 0x808a0432 // IDD_EFFECTS_PREFS #define HIDC_STIPPLE 0x808a03f0 // IDD_EFFECTS_PREFS -#define HIDC_STUD_LOGO_USE 0x860b0512 // IDD_PRIMITIVES_PREFS -#define HIDC_STUD_LOGO_COMBO 0x860b0513 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_STYLE_USE 0x860b0512 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_STYLE_COMBO 0x860b0513 // IDD_PRIMITIVES_PREFS #define HIDC_STUD_QUALITY 0x860b0514 // IDD_PRIMITIVES_PREFS #define HIDC_TEXMAPS 0x860b0509 // IDD_PRIMITIVES_PREFS #define HIDC_TEXTURE_ANISO 0x860b0515 // IDD_PRIMITIVES_PREFS diff --git a/LDLib/LDPreferences.cpp b/LDLib/LDPreferences.cpp index 9d90be427..c0c12fe25 100644 --- a/LDLib/LDPreferences.cpp +++ b/LDLib/LDPreferences.cpp @@ -78,8 +78,8 @@ LDPreferences::LDPreferences(LDrawModelViewer* modelViewer) , m_texmaps(false) , m_textureOffsetFactor(0.0) , m_useStrips(false) - , m_useStudLogo(false) - , m_studLogo(0) + , m_useStudStyle(false) + , m_studStyle(0) , m_proxyType(0) , m_proxyPort(0) , m_checkPartTracker(false) @@ -409,8 +409,8 @@ void LDPreferences::applyPrimitivesSettings(void) m_modelViewer->setTexturesAfterTransparent(true); m_modelViewer->setTextureOffsetFactor(m_textureOffsetFactor); m_modelViewer->setUseStrips(m_useStrips); - m_modelViewer->setUseStudLogo(m_useStudLogo); - m_modelViewer->setStudLogo(m_studLogo); + m_modelViewer->setUseStudStyle(m_useStudStyle); + m_modelViewer->setStudStyle(m_studStyle); } } @@ -610,8 +610,8 @@ void LDPreferences::loadDefaultPrimitivesSettings(bool initializing /*= true*/) setTextureOffsetFactor(5.0); setUseStrips(true); m_initializing = false; - setUseStudLogo(false); - setStudLogo(-1/*LDView Default*/); + setUseStudStyle(false); + setStudStyle(-1/*LDView Default*/); } void LDPreferences::loadDefaultUpdatesSettings(bool initializing /*= true*/) @@ -816,8 +816,8 @@ void LDPreferences::loadPrimitivesSettings(void) m_textureOffsetFactor = getFloatSetting(TEXTURE_OFFSET_FACTOR_KEY, m_textureOffsetFactor); m_useStrips = getBoolSetting(STRIPS_KEY, m_useStrips); - m_useStudLogo = getBoolSetting(STUD_LOGO_USE_KEY, m_useStudLogo); - m_studLogo = getIntSetting(STUD_LOGO_KEY, m_studLogo); + m_useStudStyle = getBoolSetting(STUD_STYLE_USE_KEY, m_useStudStyle); + m_studStyle = getIntSetting(STUD_STYLE_KEY, m_studStyle); } void LDPreferences::loadUpdatesSettings(void) @@ -997,10 +997,10 @@ void LDPreferences::commitPrimitivesSettings(bool flush /*= true*/) setTexmaps(m_texmaps, true); setTextureOffsetFactor(m_textureOffsetFactor, true); setUseStrips(m_useStrips, true); - setUseStudLogo(m_useStudLogo, true); - if (m_useStudLogo) + setUseStudStyle(m_useStudStyle, true); + if (m_useStudStyle) { - setStudLogo(m_studLogo, true); + setStudStyle(m_studStyle, true); } if (flush) { @@ -2026,18 +2026,18 @@ void LDPreferences::setCurveQuality(int value, bool commit) setSetting(m_curveQuality, value, CURVE_QUALITY_KEY, commit); } -void LDPreferences::setUseStudLogo(bool value, bool commit, bool apply) +void LDPreferences::setUseStudStyle(bool value, bool commit, bool apply) { - setSetting(m_useStudLogo, value, STUD_LOGO_USE_KEY, commit); + setSetting(m_useStudStyle, value, STUD_STYLE_USE_KEY, commit); if (apply && m_modelViewer != NULL) { - m_modelViewer->setUseStudLogo(m_useStudLogo); + m_modelViewer->setUseStudStyle(m_useStudStyle); } } -void LDPreferences::setStudLogo(int value, bool commit) +void LDPreferences::setStudStyle(int value, bool commit) { - setSetting(m_studLogo, value, STUD_LOGO_KEY, commit); + setSetting(m_studStyle, value, STUD_STYLE_KEY, commit); } void LDPreferences::setQualityStuds(bool value, bool commit, bool apply) diff --git a/LDLib/LDPreferences.h b/LDLib/LDPreferences.h index fa8f1134e..9381110c1 100644 --- a/LDLib/LDPreferences.h +++ b/LDLib/LDPreferences.h @@ -198,8 +198,8 @@ class LDPreferences : public TCAlertSender bool getTexmaps(void) { return m_texmaps; } bool getTexturesAfterTransparent(void) { return true; } TCFloat getTextureOffsetFactor(void) { return m_textureOffsetFactor; } - bool getUseStudLogo(void) { return m_useStudLogo; } - int getStudLogo(void) { return m_studLogo; } + bool getUseStudStyle(void) { return m_useStudStyle; } + int getStudStyle(void) { return m_studStyle; } // Update settings int getProxyType(void) { return m_proxyType; } @@ -339,8 +339,8 @@ class LDPreferences : public TCAlertSender void setTexturesAfterTransparent(bool value, bool commit = false, bool apply = false); void setTextureOffsetFactor(TCFloat value, bool commit = false, bool apply = false); void setUseStrips(bool value, bool commit = false, bool apply = false); - void setUseStudLogo(bool value, bool commit = false, bool apply = false); - void setStudLogo(int value, bool commit = false); + void setUseStudStyle(bool value, bool commit = false, bool apply = false); + void setStudStyle(int value, bool commit = false); // Update settings void setProxyType(int value, bool commit = false); @@ -507,8 +507,8 @@ class LDPreferences : public TCAlertSender bool m_texmaps; TCFloat m_textureOffsetFactor; bool m_useStrips; - bool m_useStudLogo; - int m_studLogo; + bool m_useStudStyle; + int m_studStyle; // Update settings int m_proxyType; diff --git a/LDLib/LDUserDefaultsKeys.h b/LDLib/LDUserDefaultsKeys.h index 63a772fd1..7044b2733 100644 --- a/LDLib/LDUserDefaultsKeys.h +++ b/LDLib/LDUserDefaultsKeys.h @@ -157,8 +157,8 @@ #define WIREFRAME_FOG_KEY "WireframeFog" #define WIREFRAME_THICKNESS_KEY "WireframeThickness" #define ZOOM_MAX_KEY "ZoomMax" // NO UI -#define STUD_LOGO_USE_KEY "UseStudLogo" -#define STUD_LOGO_KEY "StudLogo" +#define STUD_STYLE_USE_KEY "UseStudStyle" +#define STUD_STYLE_KEY "StudStyle" // The following are undocumented, and should stay that way. #define DEBUG_LEVEL_KEY "DebugLevel" diff --git a/LDLib/LDrawModelViewer.cpp b/LDLib/LDrawModelViewer.cpp index e2df540d6..db8814e07 100644 --- a/LDLib/LDrawModelViewer.cpp +++ b/LDLib/LDrawModelViewer.cpp @@ -234,7 +234,7 @@ LDrawModelViewer::LDrawModelViewer(TCFloat width, TCFloat height) flags.keepRightSideUp = false; flags.texmaps = true; flags.useStrips = true; - flags.useStudLogo = false; + flags.useStudStyle = false; TCAlertManager::registerHandler(LDLFindFileAlert::alertClass(), this, (TCAlertCallback)&LDrawModelViewer::findFileAlertCallback); // Set 4:4:4 as the default sub-sample pattern for JPEG images. @@ -2336,12 +2336,12 @@ void LDrawModelViewer::setCurveQuality(int value) } } -void LDrawModelViewer::setStudLogo(int value) +void LDrawModelViewer::setStudStyle(int value) { - if (value != studLogo) + if (value != studStyle) { - studLogo = value; - if (flags.useStudLogo) + studStyle = value; + if (flags.useStudStyle) { flags.needsReload = true; } @@ -2606,11 +2606,11 @@ void LDrawModelViewer::setTextureOffsetFactor(TCFloat value) } } -void LDrawModelViewer::setUseStudLogo(bool value) +void LDrawModelViewer::setUseStudStyle(bool value) { - if (value != flags.useStudLogo) + if (value != flags.useStudStyle) { - flags.useStudLogo = value; + flags.useStudStyle = value; flags.needsReload = true; } } diff --git a/LDLib/LDrawModelViewer.h b/LDLib/LDrawModelViewer.h index fd6ad8150..bae2add65 100644 --- a/LDLib/LDrawModelViewer.h +++ b/LDLib/LDrawModelViewer.h @@ -543,8 +543,8 @@ class LDrawModelViewer: public TCAlertSender void setTextureOffsetFactor(TCFloat value); bool getUseStrips(void) const { return flags.useStrips ? true : false; } void setUseStrips(bool value); - bool getUseStudLogo(void) const { return flags.useStudLogo ? true : false; } - void setUseStudLogo(bool value); + bool getUseStudStyle(void) const { return flags.useStudStyle ? true : false; } + void setUseStudStyle(bool value); bool getRandomColors(void) const { return flags.randomColors ? true : false; @@ -637,8 +637,8 @@ class LDrawModelViewer: public TCAlertSender static void resetUnofficialDownloadTimes(void); static std::string libraryUrl(const std::string& path); // static bool doCommandLineExport(void); - void setStudLogo(int value); - int getStudLogo(void) const { return studLogo; } + void setStudStyle(int value); + int getStudStyle(void) const { return studStyle; } protected: ~LDrawModelViewer(void); void dealloc(void); @@ -835,7 +835,7 @@ class LDrawModelViewer: public TCAlertSender int highlightR; int highlightG; int highlightB; - int studLogo; + int studStyle; #ifdef USE_STD_CHRONO std::chrono::time_point frameTime; #else @@ -932,7 +932,7 @@ class LDrawModelViewer: public TCAlertSender bool texmaps:1; bool texturesAfterTransparent:1; bool useStrips:1; - bool useStudLogo:1; + bool useStudStyle:1; } flags; struct CameraData { diff --git a/LDLoader/LDLModel.cpp b/LDLoader/LDLModel.cpp index 6014a2634..10bb66a96 100644 --- a/LDLoader/LDLModel.cpp +++ b/LDLoader/LDLModel.cpp @@ -35,16 +35,16 @@ typedef std::pair SearchDirPair; typedef std::vector SearchDirVector; -#define TC_STUD_LOGO_MAX_DATA_LEN 1024 -#define TC_STUD_LOGO_ARRAY_COUNT(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) +#define TC_STUD_STYLE_MAX_DATA_LEN 1024 +#define TC_STUD_STYLE_ARRAY_COUNT(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) -struct TCStudLogoPrimitive +struct TCStudStylePrimitive { char Name[64]; - char Data[TC_STUD_LOGO_MAX_DATA_LEN]; + char Data[TC_STUD_STYLE_MAX_DATA_LEN]; }; -static struct TCStudLogoPrimitive StudLogoPrimitives[] = +static struct TCStudStylePrimitive StudStylePrimitives[] = { { /* 00 */ "stud.dat", @@ -880,34 +880,34 @@ bool LDLModel::openSubModelNamed( return false; } -int LDLModel::getStudLogoFile(LDLModel* subModel, const char* dictName, int studLogo, bool openStud) +int LDLModel::getStudStyleFile(LDLModel* subModel, const char* dictName, int studStyle, bool openStud) { - char data[TC_STUD_LOGO_MAX_DATA_LEN]; + char data[TC_STUD_STYLE_MAX_DATA_LEN]; char tempPath[256]; #ifdef WIN32 - sprintf(tempPath, "%s\\ldview_stud_logo%d_%s", getenv("TEMP"), studLogo, dictName); + sprintf(tempPath, "%s\\ldview_stud_style%d_%s", getenv("TEMP"), studStyle, dictName); #else - sprintf(tempPath, "/tmp/ldview_stud_logo%d_%s", studLogo, dictName); + sprintf(tempPath, "/tmp/ldview_stud_style%d_%s", studStyle, dictName); #endif std::ifstream existingSubModelStream(tempPath, std::ios::binary); if (existingSubModelStream.is_open()) return (subModel->load(existingSubModelStream)); - if (studLogo > 0) + if (studStyle > 0) { char style[10] = ""; - if (studLogo > 1) - sprintf(style, "%d", studLogo); + if (studStyle > 1) + sprintf(style, "%d", studStyle); sprintf(data, "0 Stud %s\n0 Name: %s\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive\n0 BFC CERTIFY CCW\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 stud%s-logo%s.dat\n", (openStud ? "open" : style), dictName, (openStud ? "2" : ""), style); } else { - for (unsigned int i = 0; i < TC_STUD_LOGO_ARRAY_COUNT(StudLogoPrimitives); i++) + for (unsigned int i = 0; i < TC_STUD_STYLE_ARRAY_COUNT(StudStylePrimitives); i++) { - if (strcasecmp(dictName, StudLogoPrimitives[i].Name) == 0) + if (strcasecmp(dictName, StudStylePrimitives[i].Name) == 0) { - strcpy(data, StudLogoPrimitives[i].Data); + strcpy(data, StudStylePrimitives[i].Data); break; } } @@ -922,15 +922,15 @@ int LDLModel::getStudLogoFile(LDLModel* subModel, const char* dictName, int stud return (newSubModelStream.is_open() && subModel->load(newSubModelStream)); } -int LDLModel::isStudLogoPrimitive(const char* FileName, int studLogo) +int LDLModel::isStudStylePrimitive(const char* FileName, int studStyle) { // return if file has '-logo' suffix if (strstr(FileName, "-logo") != NULL) return 0; - for (unsigned int i = 0; i < TC_STUD_LOGO_ARRAY_COUNT(StudLogoPrimitives); i++) + for (unsigned int i = 0; i < TC_STUD_STYLE_ARRAY_COUNT(StudStylePrimitives); i++) { - if (strcasecmp(FileName, StudLogoPrimitives[i].Name) == 0) + if (strcasecmp(FileName, StudStylePrimitives[i].Name) == 0) { if (strcasecmp(FileName, "stud2.dat") == 0 || strcasecmp(FileName, "stud2a.dat") == 0) return 2; // open stud @@ -978,20 +978,20 @@ bool LDLModel::initializeNewSubModel( subModel->m_flags.unofficial = true; } bool zipValid = zipStream != NULL && zipStream->is_valid(); - bool useStudLogo = TCUserDefaults::boolForKey(STUD_LOGO_USE_KEY, false, true); - unsigned int studLogoPrimitive = 0; - if (useStudLogo && m_flags.loadingPrimitive && m_flags.hasStuds) + bool useStudStyle = TCUserDefaults::boolForKey(STUD_STYLE_USE_KEY, false, true); + unsigned int studStylePrimitive = 0; + if (useStudStyle && m_flags.loadingPrimitive && m_flags.hasStuds) { - unsigned int studLogo = TCUserDefaults::longForKey(STUD_LOGO_KEY, 0, true); - unsigned int studLogoType = isStudLogoPrimitive(dictName); - if (studLogoType > 0) + unsigned int studStyle = TCUserDefaults::longForKey(STUD_STYLE_KEY, 0, true); + unsigned int studStyleType = isStudStylePrimitive(dictName); + if (studStyleType > 0) { - bool openStud = studLogoType == 2; - studLogoPrimitive = getStudLogoFile(subModel, dictName, - studLogo, openStud); + bool openStud = studStyleType == 2; + studStylePrimitive = getStudStyleFile(subModel, dictName, + studStyle, openStud); } } - if (!studLogoPrimitive && (subModelStream.is_open() || zipValid) && + if (!studStylePrimitive && (subModelStream.is_open() || zipValid) && !subModel->load(subModelStream, zipStream)) { subModelDict->removeObjectForKey(dictName); diff --git a/LDLoader/LDLModel.h b/LDLoader/LDLModel.h index c3341a845..32aa42289 100644 --- a/LDLoader/LDLModel.h +++ b/LDLoader/LDLModel.h @@ -205,9 +205,9 @@ class LDLModel : public TCAlertSender static void initCheckDirs(); - static int isStudLogoPrimitive(const char* FileName, int studLogo = 0); - static int getStudLogoFile(LDLModel* subModel, const char* dictName, - int studLogo, bool openStud); + static int isStudStylePrimitive(const char* FileName, int studStyle = 0); + static int getStudStyleFile(LDLModel* subModel, const char* dictName, + int studStyle, bool openStud); char *m_filename; char *m_name; diff --git a/LDLoader/LDLPrimitiveCheck.cpp b/LDLoader/LDLPrimitiveCheck.cpp index 48a772423..ec9479274 100644 --- a/LDLoader/LDLPrimitiveCheck.cpp +++ b/LDLoader/LDLPrimitiveCheck.cpp @@ -637,7 +637,7 @@ bool LDLPrimitiveCheck::performPrimitiveSubstitution( } else if (strcasecmp(m_modelName, "stud.dat") == 0) { - if (TCUserDefaults::boolForKey(STUD_LOGO_USE_KEY, false)) + if (TCUserDefaults::boolForKey(STUD_STYLE_USE_KEY, false)) return false; return substituteStud(); } diff --git a/LDView.rc b/LDView.rc index a66a01a73..3a9570f28 100644 --- a/LDView.rc +++ b/LDView.rc @@ -499,8 +499,8 @@ BEGIN CONTROL "Slider1",IDC_ANISO_LEVEL,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,100,130,80,18,0,HIDC_ANISO_LEVEL LTEXT "nx",IDC_ANISO_LEVEL_LABEL,185,134,26,8,0,0,HIDC_ANISO_LEVEL_LABEL GROUPBOX "&Misc",IDC_PRIMITIVES_MISC_BOX,7,157,296,52,WS_GROUP,WS_EX_TRANSPARENT,HIDC_PRIMITIVES_MISC_BOX - CONTROL "Use stud logo geometry",IDC_STUD_LOGO_USE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,168,94,10,0,HIDC_STUD_LOGO_USE - COMBOBOX IDC_STUD_LOGO_COMBO,115,166,82,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP,0,HIDC_STUD_LOGO_COMBO + CONTROL "Use stud style geometry",IDC_STUD_STYLE_USE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,168,94,10,0,HIDC_STUD_STYLE_USE + COMBOBOX IDC_STUD_STYLE_COMBO,115,166,82,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP,0,HIDC_STUD_STYLE_COMBO CONTROL "Low quality studs (faster)",IDC_STUD_QUALITY,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,181,93,10,0,HIDC_STUD_QUALITY CONTROL "Use hi-res primitives when available",IDC_HI_RES,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,194,127,10,0,HIDC_HI_RES PUSHBUTTON "&Reset",IDC_PRIMITIVES_RESET,253,231,50,14,WS_GROUP,0,HIDC_PRIMITIVES_RESET @@ -1814,8 +1814,8 @@ BEGIN HIDC_STEREO_SPACING "This option is only available if stereo is enabled. The slider controls the stereo spacing. A small value will result in a very subtle stereoscopic effect, as if you were looking at a very large object from a very long distance. (The minimum value results in no stereoscopic effect at all.) A large value will result in a pronounced stereoscopic effect, as if you were looking at a small object from a very short distance." HIDC_STEREO_SPACING_LABEL "This option is only available if stereo is enabled. The slider controls the stereo spacing. A small value will result in a very subtle stereoscopic effect, as if you were looking at a very large object from a very long distance. (The minimum value results in no stereoscopic effect at all.) A large value will result in a pronounced stereoscopic effect, as if you were looking at a small object from a very short distance." HIDC_STIPPLE "Enabling this option causes transparent shapes to be drawn using a stipple (checkerboard) pattern. This may be significantly faster on some video hardware, but with potentially reduced quality. Using the stipple pattern totally eliminates the errors that may occur where far transparent objects are drawn in front of closer ones. This option is mutually exclusive with the sort option." - HIDC_STUD_LOGO_USE "Enabling this option gives the user the ability to select the displayed stud logo geometry. When unchecked, Texture studs settings will be respected." - HIDC_STUD_LOGO_COMBO "This allows you to select the stud logo display when Use stud logo geometry preference is checked." + HIDC_STUD_STYLE_USE "Enabling this option gives the user the ability to select the displayed stud style geometry. When unchecked, Texture studs settings will be respected." + HIDC_STUD_STYLE_COMBO "This allows you to select the stud style display when Use stud style geometry preference is checked." HIDC_STUD_QUALITY "Enabling this option switches to using the low-resolution stud files instead of the normal-resolution stud files. This can produce significantly faster rendering." HIDC_TEXMAPS "Enabling this option turns on support for the LDraw TEXMAP extension. Disabling it will cause LDView to use any fallback geometry included in the LDraw file." HIDC_TEXTURE_ANISO "This option is only available if primitive substitution and texture studs are both enabled, and your video card supports it. Selecting it causes anisotropic texture filtering to be used. When anisotropic filtering is selected, you can pick the filtering level on the slider to the right of the radio button. This is the highest quality texture filtering." diff --git a/LDViewMessages.ini b/LDViewMessages.ini index d835474f1..2c8edc3c0 100644 --- a/LDViewMessages.ini +++ b/LDViewMessages.ini @@ -98,7 +98,7 @@ BrowseForSnapshotDir =Please select the directory to save snapshots into. BrowseForPartsListDir =Please select the directory to save parts lists into. BrowseForExportDir =Please select the directory to save exports into. -; Stud logo geometry +; Stud style geometry Plain =0 Plain SingleWire =1 Single Wire DoubleWire =2 Double Wire diff --git a/LDViewPreferences.cpp b/LDViewPreferences.cpp index d7f0d3ef5..3316f6521 100644 --- a/LDViewPreferences.cpp +++ b/LDViewPreferences.cpp @@ -2084,9 +2084,9 @@ void LDViewPreferences::applyPrimitivesChanges(void) ldPrefs->setTextureOffsetFactor(textureOffsetFromSliderValue( trackBarGetPos(hTextureOffsetSlider))); } - ldPrefs->setUseStudLogo(getCheck(hPrimitivesPage, IDC_STUD_LOGO_USE)); - ldPrefs->setStudLogo(CUIDialog::comboGetCurSel(hPrimitivesPage, - IDC_STUD_LOGO_COMBO)); + ldPrefs->setUseStudStyle(getCheck(hPrimitivesPage, IDC_STUD_STYLE_USE)); + ldPrefs->setStudStyle(CUIDialog::comboGetCurSel(hPrimitivesPage, + IDC_STUD_STYLE_COMBO)); ldPrefs->setQualityStuds(!getCheck(hPrimitivesPage, IDC_STUD_QUALITY)); ldPrefs->setHiResPrimitives(getCheck(hPrimitivesPage, IDC_HI_RES)); ldPrefs->applyPrimitivesSettings(); @@ -2864,7 +2864,7 @@ DWORD LDViewPreferences::doComboSelChange(HWND hPage, int controlId, case IDC_MEMORY_COMBO: enableApply(hPage); break; - case IDC_STUD_LOGO_COMBO: + case IDC_STUD_STYLE_COMBO: enableApply(hPage); break; case IDC_SNAPSHOTS_DIR_COMBO: @@ -3267,16 +3267,16 @@ void LDViewPreferences::setupMemoryUsage(void) CUIDialog::comboSetCurSel(hGeneralPage, IDC_MEMORY_COMBO, ldPrefs->getMemoryUsage()); } -void LDViewPreferences::setupStudLogo(void) +void LDViewPreferences::setupStudStyle(void) { - CUIDialog::comboResetContent(hPrimitivesPage, IDC_STUD_LOGO_COMBO); - CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("Plain"))); - CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("SingleWire"))); - CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("DoubleWire"))); - CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("RaisedFlat"))); - CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("RaisedRounded"))); - CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ls(_UC("SubtleRounded"))); - CUIDialog::comboSetCurSel(hPrimitivesPage, IDC_STUD_LOGO_COMBO, ldPrefs->getStudLogo()); + CUIDialog::comboResetContent(hPrimitivesPage, IDC_STUD_STYLE_COMBO); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("Plain"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("SingleWire"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("DoubleWire"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("RaisedFlat"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("RaisedRounded"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("SubtleRounded"))); + CUIDialog::comboSetCurSel(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ldPrefs->getStudStyle()); } void LDViewPreferences::updateSaveDir( @@ -4390,8 +4390,8 @@ void LDViewPreferences::setupPrimitivesPage(void) hPrimitivesPage = hwndArray->pointerAtIndex(primitivesPageNumber); setupTextures(); setupSubstitution(); - setupStudLogo(); - setCheck(hPrimitivesPage, IDC_STUD_LOGO_USE, ldPrefs->getUseStudLogo()); + setupStudStyle(); + setCheck(hPrimitivesPage, IDC_STUD_STYLE_USE, ldPrefs->getUseStudStyle()); setCheck(hPrimitivesPage, IDC_STUD_QUALITY, !ldPrefs->getQualityStuds()); setCheck(hPrimitivesPage, IDC_HI_RES, ldPrefs->getHiResPrimitives()); } diff --git a/LDViewPreferences.h b/LDViewPreferences.h index 8876440c4..f9696034b 100644 --- a/LDViewPreferences.h +++ b/LDViewPreferences.h @@ -149,7 +149,7 @@ class LDViewPreferences: public CUIPropertySheet virtual void setupColorButton(HWND hPage, HWND &hColorButton, int controlID, HBITMAP &hButtonBitmap, COLORREF color); virtual void setupMemoryUsage(void); - virtual void setupStudLogo(void); + virtual void setupStudStyle(void); virtual void setupFov(bool warn = false); virtual void setupBackgroundColorButton(void); virtual void setupDefaultColorButton(void); diff --git a/Resource.h b/Resource.h index 59100b47c..abea27530 100644 --- a/Resource.h +++ b/Resource.h @@ -400,8 +400,8 @@ #define IDC_CUSTOM_CONFIG_BOX 1322 #define IDC_CUSTOM_CONFIG 1323 #define IDC_BROWSE_CUSTOM_CONFIG 1324 -#define IDC_STUD_LOGO_USE 1325 -#define IDC_STUD_LOGO_COMBO 1326 +#define IDC_STUD_STYLE_USE 1325 +#define IDC_STUD_STYLE_COMBO 1326 #define PRINTDLGORD 1538 #define PAGESETUPDLGORD 1546 #define IDD_PRIMITIVES_PREFS 1547 From 7e3ed83a03c79cc4585798ff8b527f8d323b78f4 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sat, 1 Nov 2025 11:35:46 +0100 Subject: [PATCH 4/7] Setup stud style and automate edge line color --- LDLib/LDPreferences.cpp | 252 +++++++++++++++++++++++++++++++++- LDLib/LDPreferences.h | 56 +++++++- LDLib/LDUserDefaultsKeys.h | 12 ++ LDLib/LDrawModelViewer.cpp | 160 ++++++++++++++++++++-- LDLib/LDrawModelViewer.h | 47 ++++++- LDLoader/LDLModel.cpp | 127 ++++++++++++++--- LDLoader/LDLModel.h | 4 +- LDLoader/LDLPalette.cpp | 274 ++++++++++++++++++++++++++++++++++++- LDLoader/LDLPalette.h | 20 +++ LDViewMessages.ini | 2 + 10 files changed, 911 insertions(+), 43 deletions(-) diff --git a/LDLib/LDPreferences.cpp b/LDLib/LDPreferences.cpp index c0c12fe25..8f7d329ab 100644 --- a/LDLib/LDPreferences.cpp +++ b/LDLib/LDPreferences.cpp @@ -198,6 +198,28 @@ void LDPreferences::getRGB(int color, int &r, int &g, int &b) b = color & 0xFF; } +TCULong LDPreferences::getRGBAColor(int r, int g, int b, int a) +{ + return ((a >> 24) & 0xFF) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF); +} + +void LDPreferences::getRGBA(int color, int& r, int& g, int& b, int& a) +{ + // Colors are stored in ARGB format. + a = (color >> 24) & 0xFF; + r = (color >> 16) & 0xFF; + g = (color >> 8) & 0xFF; + b = color & 0xFF; +} + +void LDPreferences::getRGBAColorSetting(const char* key, int& r, int& g, int& b, + int& a, TCULong defaultColor) +{ + long value = (TCULong)getRGBAFromStringSetting(key, defaultColor); + + getRGBA(value, r, g, b, a); +} + void LDPreferences::getColorSetting(const char *key, int &r, int &g, int &b, TCULong defaultColor) { @@ -364,6 +386,9 @@ void LDPreferences::applyGeometrySettings(void) m_modelViewer->setUsePolygonOffset(m_usePolygonOffset); m_modelViewer->setBlackHighlights(m_blackHighlights); m_modelViewer->setHighlightLineWidth((GLfloat)m_edgeThickness); + m_modelViewer->setAutomateEdgeColor(m_automateEdgeColor); + m_modelViewer->setPartEdgeContrast(m_partEdgeContrast); + m_modelViewer->setPartEdgeSaturation(m_partEdgeSaturation); } } @@ -411,6 +436,15 @@ void LDPreferences::applyPrimitivesSettings(void) m_modelViewer->setUseStrips(m_useStrips); m_modelViewer->setUseStudStyle(m_useStudStyle); m_modelViewer->setStudStyle(m_studStyle); + m_modelViewer->setStudCylinderColorEnabled(m_studCylinderColorEnabled); + m_modelViewer->setPartEdgeColorEnabled(m_partEdgeColorEnabled); + m_modelViewer->setBlackEdgeColorEnabled(m_blackEdgeColorEnabled); + m_modelViewer->setDarkEdgeColorEnabled(m_darkEdgeColorEnabled); + m_modelViewer->setStudCylinderColor(m_studCylinderColor); + m_modelViewer->setPartEdgeColor(m_partEdgeColor); + m_modelViewer->setBlackEdgeColor(m_blackEdgeColor); + m_modelViewer->setDarkEdgeColor(m_darkEdgeColor); + m_modelViewer->setPartColorLDIndex(m_partColorLDIndex); } } @@ -562,7 +596,11 @@ void LDPreferences::loadDefaultGeometrySettings(bool initializing /*= true*/) setUsePolygonOffset(true); setBlackHighlights(false); setEdgeThickness(1); + setAutomateEdgeColor(false); + setPartEdgeContrast(0.5f); + setPartEdgeSaturation(0.5f); m_initializing = false; + } void LDPreferences::loadDefaultEffectsSettings(bool initializing /*= true*/) @@ -609,9 +647,18 @@ void LDPreferences::loadDefaultPrimitivesSettings(bool initializing /*= true*/) setTexmaps(true); setTextureOffsetFactor(5.0); setUseStrips(true); - m_initializing = false; setUseStudStyle(false); - setStudStyle(-1/*LDView Default*/); + setStudStyle(0/*Plain*/); + setStudCylinderColorEnabled(true); + setPartEdgeColorEnabled(true); + setBlackEdgeColorEnabled(true); + setDarkEdgeColorEnabled(true); + setStudCylinderColor(27, 42, 52, 255); + setPartEdgeColor(0, 0, 0, 255); + setBlackEdgeColor(255, 255, 255, 255); + setDarkEdgeColor(27, 42, 52, 255); + setPartColorLDIndex(0.5f); + m_initializing = false; } void LDPreferences::loadDefaultUpdatesSettings(bool initializing /*= true*/) @@ -768,6 +815,10 @@ void LDPreferences::loadGeometrySettings(void) m_usePolygonOffset = getBoolSetting(POLYGON_OFFSET_KEY, m_usePolygonOffset); m_blackHighlights = getBoolSetting(BLACK_HIGHLIGHTS_KEY, m_blackHighlights); m_edgeThickness = getIntSetting(EDGE_THICKNESS_KEY, m_edgeThickness); + + m_automateEdgeColor = getBoolSetting(AUTOMATE_EDGE_COLOR_KEY, m_automateEdgeColor); + m_partEdgeContrast = getFloatSetting(PART_EDGE_CONTRAST_KEY, m_partEdgeContrast); + m_partEdgeSaturation = getFloatSetting(PART_EDGE_SATURATION_KEY, m_partEdgeSaturation); } void LDPreferences::loadEffectsSettings(void) @@ -816,8 +867,21 @@ void LDPreferences::loadPrimitivesSettings(void) m_textureOffsetFactor = getFloatSetting(TEXTURE_OFFSET_FACTOR_KEY, m_textureOffsetFactor); m_useStrips = getBoolSetting(STRIPS_KEY, m_useStrips); + m_useStudStyle = getBoolSetting(STUD_STYLE_USE_KEY, m_useStudStyle); m_studStyle = getIntSetting(STUD_STYLE_KEY, m_studStyle); + + m_studCylinderColorEnabled = getBoolSetting(STUD_CYLINDER_COLOR_ENABLED_KEY, m_studCylinderColorEnabled); + m_partEdgeColorEnabled = getBoolSetting(PART_EDGE_COLOR_ENABLED_KEY, m_partEdgeColorEnabled); + m_blackEdgeColorEnabled = getBoolSetting(BLACK_EDGE_COLOR_ENABLED_KEY, m_blackEdgeColorEnabled); + m_darkEdgeColorEnabled = getBoolSetting(DARK_EDGE_COLOR_ENABLED_KEY, m_darkEdgeColorEnabled); + + m_studCylinderColor = (TCULong)getRGBAFromStringSetting(STUD_CYLINDER_COLOR_KEY, m_studCylinderColor); + m_partEdgeColor = (TCULong)getRGBAFromStringSetting(PART_EDGE_COLOR_KEY, m_partEdgeColor); + m_blackEdgeColor = (TCULong)getRGBAFromStringSetting(BLACK_EDGE_COLOR_KEY, m_blackEdgeColor); + m_darkEdgeColor = (TCULong)getRGBAFromStringSetting(DARK_EDGE_COLOR_KEY, m_darkEdgeColor); + + m_partColorLDIndex = getFloatSetting(PART_COLOR_LD_INDEX_KEY, m_partColorLDIndex); } void LDPreferences::loadUpdatesSettings(void) @@ -945,6 +1009,9 @@ void LDPreferences::commitGeometrySettings(bool flush /*= true*/) setBlackHighlights(m_blackHighlights, true); } setEdgeThickness(m_edgeThickness, true); + setAutomateEdgeColor(m_automateEdgeColor, true); + setPartEdgeContrast(m_partEdgeContrast, true); + setPartEdgeSaturation(m_partEdgeSaturation, true); if (flush) { TCUserDefaults::flush(); @@ -997,11 +1064,32 @@ void LDPreferences::commitPrimitivesSettings(bool flush /*= true*/) setTexmaps(m_texmaps, true); setTextureOffsetFactor(m_textureOffsetFactor, true); setUseStrips(m_useStrips, true); + setUseStudStyle(m_useStudStyle, true); if (m_useStudStyle) { setStudStyle(m_studStyle, true); } + int r, g, b, a; + getRGBA(m_studCylinderColor, r, g, b, a); + setStudCylinderColor(r, g, b, a, true); + + getRGBA(m_partEdgeColor, r, g, b, a); + setPartEdgeColor(r, g, b, a, true); + + getRGBA(m_blackEdgeColor, r, g, b, a); + setBlackEdgeColor(r, g, b, a, true); + + getRGBA(m_darkEdgeColor, r, g, b, a); + setDarkEdgeColor(r, g, b, a, true); + + setStudCylinderColorEnabled(m_studCylinderColorEnabled, true); + setPartEdgeColorEnabled(m_partEdgeColorEnabled, true); + setBlackEdgeColorEnabled(m_blackEdgeColorEnabled, true); + setDarkEdgeColorEnabled(m_darkEdgeColorEnabled, true); + + setPartColorLDIndex(m_partColorLDIndex, true); + if (flush) { TCUserDefaults::flush(); @@ -1155,6 +1243,29 @@ void LDPreferences::setupModelSize(void) } } +void LDPreferences::setRGBAColorSetting(TCULong& setting, int r, int g, int b, int a, + const char* key, bool commit) +{ + TCULong value = getRGBAColor(r, g, b, a); + if (setting != value || (m_changedSettings[key] && commit)) + { + setting = value; + if (commit) + { + char stringValue[128]; + + sprintf(stringValue, "%d,%d,%d,%d", r, g, b, a); + TCUserDefaults::setStringForKey(stringValue, key, + !m_globalSettings[key]); + m_changedSettings.erase(key); + } + else + { + m_changedSettings[key] = true; + } + } +} + void LDPreferences::setColorSetting(TCULong &setting, int r, int g, int b, const char *key, bool commit) { @@ -1408,6 +1519,25 @@ float LDPreferences::getFloatSetting(const char *key, float defaultValue) return TCUserDefaults::floatForKey(key, defaultValue, !m_globalSettings[key]); } +long LDPreferences::getRGBAFromStringSetting(const char* key, + TCULong defaultValue) +{ + std::string rgbaString; + + rgbaString = getStringSetting(key); + if (rgbaString.length()) + { + int n, r, g, b, a; + + n = sscanf(rgbaString.c_str(), "%d,%d,%d,%d", &r, &g, &b, &a); + if (n == 3 || n == 4) + { + return getRGBAColor(r, g, b, (n == 3 ? 255 : a)); + } + } + return defaultValue; +} + std::string LDPreferences::getStringSetting( const char *key, const char *defaultValue /*= NULL*/, @@ -2026,6 +2156,15 @@ void LDPreferences::setCurveQuality(int value, bool commit) setSetting(m_curveQuality, value, CURVE_QUALITY_KEY, commit); } +void LDPreferences::setAutomateEdgeColor(bool value, bool commit, bool apply) +{ + setSetting(m_automateEdgeColor, value, AUTOMATE_EDGE_COLOR_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setAutomateEdgeColor(m_automateEdgeColor); + } +} + void LDPreferences::setUseStudStyle(bool value, bool commit, bool apply) { setSetting(m_useStudStyle, value, STUD_STYLE_USE_KEY, commit); @@ -2035,9 +2174,96 @@ void LDPreferences::setUseStudStyle(bool value, bool commit, bool apply) } } -void LDPreferences::setStudStyle(int value, bool commit) +void LDPreferences::setStudStyle(int value, bool commit, bool apply) { setSetting(m_studStyle, value, STUD_STYLE_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setStudStyle(m_studStyle); + } +} + +void LDPreferences::setStudCylinderColorEnabled(bool value, bool commit, bool apply) +{ + setSetting(m_studCylinderColorEnabled, value, STUD_CYLINDER_COLOR_ENABLED_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setStudCylinderColorEnabled(m_studCylinderColorEnabled); + } +} + +void LDPreferences::setPartEdgeColorEnabled(bool value, bool commit, bool apply) +{ + setSetting(m_partEdgeColorEnabled, value, PART_EDGE_COLOR_ENABLED_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setPartEdgeColorEnabled(m_partEdgeColorEnabled); + } +} + +void LDPreferences::setBlackEdgeColorEnabled(bool value, bool commit, bool apply) +{ + setSetting(m_blackEdgeColorEnabled, value, BLACK_EDGE_COLOR_ENABLED_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setBlackEdgeColorEnabled(m_blackEdgeColorEnabled); + } +} + +void LDPreferences::setDarkEdgeColorEnabled(bool value, bool commit, bool apply) +{ + setSetting(m_darkEdgeColorEnabled, value, DARK_EDGE_COLOR_ENABLED_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setDarkEdgeColorEnabled(m_darkEdgeColorEnabled); + } +} + +void LDPreferences::setStudCylinderColor(int r, int g, int b, int a, bool commit) +{ + setRGBAColorSetting(m_studCylinderColor, r, g, b, a, STUD_CYLINDER_COLOR_KEY, commit); +} + +void LDPreferences::setPartEdgeColor(int r, int g, int b, int a, bool commit) +{ + setRGBAColorSetting(m_partEdgeColor, r, g, b, a, PART_EDGE_COLOR_KEY, commit); +} + +void LDPreferences::setBlackEdgeColor(int r, int g, int b, int a, bool commit) +{ + setRGBAColorSetting(m_blackEdgeColor, r, g, b, a, BLACK_EDGE_COLOR_KEY, commit); +} + +void LDPreferences::setDarkEdgeColor(int r, int g, int b, int a, bool commit) +{ + setRGBAColorSetting(m_darkEdgeColor, r, g, b, a, DARK_EDGE_COLOR_KEY, commit); +} + +void LDPreferences::setPartColorLDIndex(TCFloat value, bool commit, bool apply) +{ + setSetting(m_partColorLDIndex, value, PART_COLOR_LD_INDEX_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setPartColorLDIndex(m_partColorLDIndex); + } +} + +void LDPreferences::setPartEdgeContrast(TCFloat value, bool commit, bool apply) +{ + setSetting(m_partEdgeContrast, value, PART_EDGE_CONTRAST_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setPartEdgeContrast(m_partEdgeContrast); + } +} + +void LDPreferences::setPartEdgeSaturation(TCFloat value, bool commit, bool apply) +{ + setSetting(m_partEdgeSaturation, value, PART_EDGE_SATURATION_KEY, commit); + if (apply && m_modelViewer != NULL) + { + m_modelViewer->setPartEdgeSaturation(m_partEdgeSaturation); + } } void LDPreferences::setQualityStuds(bool value, bool commit, bool apply) @@ -2218,6 +2444,26 @@ void LDPreferences::getCustomColor(int index, int &r, int &g, int &b) getRGB(m_customColors[index], r, g, b); } +void LDPreferences::getStudCylinderColor(int& r, int& g, int& b, int& a) +{ + getRGBA(m_studCylinderColor, r, g, b, a); +} + +void LDPreferences::getPartEdgeColor(int& r, int& g, int& b, int& a) +{ + getRGBA(m_partEdgeColor, r, g, b, a); +} + +void LDPreferences::getBlackEdgeColor(int& r, int& g, int& b, int& a) +{ + getRGBA(m_blackEdgeColor, r, g, b, a); +} + +void LDPreferences::getDarkEdgeColor(int& r, int& g, int& b, int& a) +{ + getRGBA(m_darkEdgeColor, r, g, b, a); +} + LDPreferences::LightDirection LDPreferences::getLightDirection(void) { if (m_lightVector == TCVector(-1.0f, 1.0f, 1.0f)) diff --git a/LDLib/LDPreferences.h b/LDLib/LDPreferences.h index 9381110c1..034abf949 100644 --- a/LDLib/LDPreferences.h +++ b/LDLib/LDPreferences.h @@ -198,9 +198,25 @@ class LDPreferences : public TCAlertSender bool getTexmaps(void) { return m_texmaps; } bool getTexturesAfterTransparent(void) { return true; } TCFloat getTextureOffsetFactor(void) { return m_textureOffsetFactor; } + + bool getAutomateEdgeColor(void) { return m_automateEdgeColor; }; bool getUseStudStyle(void) { return m_useStudStyle; } int getStudStyle(void) { return m_studStyle; } + bool getStudCylinderColorEnabled(void) { return m_studCylinderColorEnabled; } + bool getPartEdgeColorEnabled(void) { return m_partEdgeColorEnabled; } + bool getBlackEdgeColorEnabled(void) { return m_blackEdgeColorEnabled; } + bool getDarkEdgeColorEnabled(void) { return m_darkEdgeColorEnabled; } + + void getStudCylinderColor(int& r, int& g, int& b, int& a); + void getPartEdgeColor(int& r, int& g, int& b, int& a); + void getBlackEdgeColor(int& r, int& g, int& b, int& a); + void getDarkEdgeColor(int& r, int& g, int& b, int& a); + + TCFloat getPartColorLDIndex(void) { return m_partColorLDIndex; }; + TCFloat getPartEdgeContrast(void) { return m_partEdgeContrast; }; + TCFloat getPartEdgeSaturation(void) { return m_partEdgeContrast; }; + // Update settings int getProxyType(void) { return m_proxyType; } const char *getProxyServer(void) { return m_proxyServer.c_str(); } @@ -339,8 +355,24 @@ class LDPreferences : public TCAlertSender void setTexturesAfterTransparent(bool value, bool commit = false, bool apply = false); void setTextureOffsetFactor(TCFloat value, bool commit = false, bool apply = false); void setUseStrips(bool value, bool commit = false, bool apply = false); + + void setAutomateEdgeColor(bool value, bool commit = false, bool apply = false); void setUseStudStyle(bool value, bool commit = false, bool apply = false); - void setStudStyle(int value, bool commit = false); + void setStudStyle(int value, bool commit = false, bool apply = false); + + void setStudCylinderColorEnabled(bool value, bool commit = false, bool apply = false); + void setPartEdgeColorEnabled(bool value, bool commit = false, bool apply = false); + void setBlackEdgeColorEnabled(bool value, bool commit = false, bool apply = false); + void setDarkEdgeColorEnabled(bool value, bool commit = false, bool apply = false); + + void setPartColorLDIndex(TCFloat value, bool commit = false, bool apply = false); + void setStudCylinderColor(int r, int g, int b, int a, bool commit = false); + void setPartEdgeColor(int r, int g, int b, int a, bool commit = false); + void setBlackEdgeColor(int r, int g, int b, int a, bool commit = false); + void setDarkEdgeColor(int r, int g, int b, int a, bool commit = false); + + void setPartEdgeContrast(TCFloat value, bool commit = false, bool apply = false); + void setPartEdgeSaturation(TCFloat value, bool commit = false, bool apply = false); // Update settings void setProxyType(int value, bool commit = false); @@ -385,6 +417,8 @@ class LDPreferences : public TCAlertSender const char *key, bool commit); void setColorSetting(TCULong &setting, int r, int g, int b, const char *key, bool commit); + void setRGBAColorSetting(TCULong& setting, int r, int g, int b, int a, + const char* key, bool commit); bool getBoolSetting(const char *key, bool defaultValue = false); LongVector getLongVectorSetting(const char *key, const LongVector &defaultValue = LongVector()); @@ -400,6 +434,11 @@ class LDPreferences : public TCAlertSender const char *defaultValue = NULL, bool isPath = false); void getColorSetting(const char *key, int &r, int &g, int &b, TCULong defaultColor = 0); + void getRGBAColorSetting(const char* key, int& r, int& g, int& b, + int& a, TCULong defaultColor); + long getRGBAFromStringSetting(const char* key, TCULong defaultValue = 0); + virtual void getRGBA(int color, int& r, int& g, int& b, int& a); + virtual TCULong getRGBAColor(int r, int g, int b, int a); virtual void getRGB(int color, int &r, int &g, int &b); virtual int getColor(int r, int g, int b); @@ -507,9 +546,22 @@ class LDPreferences : public TCAlertSender bool m_texmaps; TCFloat m_textureOffsetFactor; bool m_useStrips; + + bool m_automateEdgeColor; bool m_useStudStyle; int m_studStyle; - + bool m_studCylinderColorEnabled; + bool m_partEdgeColorEnabled; + bool m_blackEdgeColorEnabled; + bool m_darkEdgeColorEnabled; + TCFloat m_partColorLDIndex; + TCULong m_studCylinderColor; + TCULong m_partEdgeColor; + TCULong m_blackEdgeColor; + TCULong m_darkEdgeColor; + TCFloat m_partEdgeContrast; + TCFloat m_partEdgeSaturation; + // Update settings int m_proxyType; std::string m_proxyServer; diff --git a/LDLib/LDUserDefaultsKeys.h b/LDLib/LDUserDefaultsKeys.h index 7044b2733..467a3e856 100644 --- a/LDLib/LDUserDefaultsKeys.h +++ b/LDLib/LDUserDefaultsKeys.h @@ -157,8 +157,20 @@ #define WIREFRAME_FOG_KEY "WireframeFog" #define WIREFRAME_THICKNESS_KEY "WireframeThickness" #define ZOOM_MAX_KEY "ZoomMax" // NO UI +#define AUTOMATE_EDGE_COLOR_KEY "AutomateEdgeColor" #define STUD_STYLE_USE_KEY "UseStudStyle" #define STUD_STYLE_KEY "StudStyle" +#define STUD_CYLINDER_COLOR_ENABLED_KEY "StudCylinderColorEnabled" +#define PART_EDGE_COLOR_ENABLED_KEY "PartEdgeColorEnabled" +#define BLACK_EDGE_COLOR_ENABLED_KEY "BlackEdgeColorEnabled" +#define DARK_EDGE_COLOR_ENABLED_KEY "DarkEdgeColorEnabled" +#define STUD_CYLINDER_COLOR_KEY "StudCylinderColor" +#define PART_EDGE_COLOR_KEY "PartEdgeColor" +#define BLACK_EDGE_COLOR_KEY "BlackEdgeColor" +#define DARK_EDGE_COLOR_KEY "DarkEdgeColor" +#define PART_COLOR_LD_INDEX_KEY "PartColorLDIndex" +#define PART_EDGE_CONTRAST_KEY "PartEdgeContrast" +#define PART_EDGE_SATURATION_KEY "PartEdgeSaturation" // The following are undocumented, and should stay that way. #define DEBUG_LEVEL_KEY "DebugLevel" diff --git a/LDLib/LDrawModelViewer.cpp b/LDLib/LDrawModelViewer.cpp index db8814e07..95fd72e99 100644 --- a/LDLib/LDrawModelViewer.cpp +++ b/LDLib/LDrawModelViewer.cpp @@ -155,7 +155,19 @@ LDrawModelViewer::LDrawModelViewer(TCFloat width, TCFloat height) highlightR(160), highlightG(224), highlightB(255), - cameraData(NULL) + cameraData(NULL), + studStyle(0), + partColorLDIndex(0.5f), + partEdgeContrast(0.5f), + partEdgeSaturation(0.5f), + studCylinderColorEnabled(true), + partEdgeColorEnabled(true), + blackEdgeColorEnabled(true), + darkEdgeColorEnabled(true), + studCylinderColor(1780276), // 27,42,52,255 + partEdgeColor(0), // 0,0,0,255 + blackEdgeColor(16777215), // 255,255,255,255 + darkEdgeColor(1780276) // 27,42,52,255 { #ifdef _LEAK_DEBUG strcpy(className, "LDrawModelViewer"); @@ -235,6 +247,7 @@ LDrawModelViewer::LDrawModelViewer(TCFloat width, TCFloat height) flags.texmaps = true; flags.useStrips = true; flags.useStudStyle = false; + flags.automateEdgeColor = false; TCAlertManager::registerHandler(LDLFindFileAlert::alertClass(), this, (TCAlertCallback)&LDrawModelViewer::findFileAlertCallback); // Set 4:4:4 as the default sub-sample pattern for JPEG images. @@ -2336,6 +2349,25 @@ void LDrawModelViewer::setCurveQuality(int value) } } +void LDrawModelViewer::setAutomateEdgeColor(bool value) +{ + if (value != flags.automateEdgeColor) + { + flags.automateEdgeColor = value; + flags.needsReparse = true; + } + +} + +void LDrawModelViewer::setUseStudStyle(bool value) +{ + if (value != flags.useStudStyle) + { + flags.useStudStyle = value; + flags.needsReload = true; + } +} + void LDrawModelViewer::setStudStyle(int value) { if (value != studStyle) @@ -2348,6 +2380,123 @@ void LDrawModelViewer::setStudStyle(int value) } } +void LDrawModelViewer::setStudCylinderColorEnabled(bool value) +{ + if (value != studCylinderColorEnabled) + { + studCylinderColorEnabled = value; + if (flags.useStudStyle) + { + flags.needsReload = true; + } + } +} + +void LDrawModelViewer::setPartEdgeColorEnabled(bool value) +{ + if (value != partEdgeColorEnabled) + { + partEdgeColorEnabled = value; + if (flags.useStudStyle) + { + flags.needsReload = true; + } + } +} + +void LDrawModelViewer::setBlackEdgeColorEnabled(bool value) +{ + if (value != blackEdgeColorEnabled) + { + blackEdgeColorEnabled = value; + if (flags.useStudStyle) + { + flags.needsReload = true; + } + } +} + +void LDrawModelViewer::setDarkEdgeColorEnabled(bool value) +{ + if (value != darkEdgeColorEnabled) + { + darkEdgeColorEnabled = value; + if (flags.useStudStyle) + { + flags.needsReload = true; + } + } +} + +void LDrawModelViewer::setStudCylinderColor(TCULong value) +{ + if (value != studCylinderColor) + { + studCylinderColor = value; + flags.needsReload = true; + } +} + +void LDrawModelViewer::setPartEdgeColor(TCULong value) +{ + if (value != partEdgeColor) + { + partEdgeColor = value; + flags.needsReload = true; + } +} + +void LDrawModelViewer::setBlackEdgeColor(TCULong value) +{ + if (value != blackEdgeColor) + { + blackEdgeColor = value; + flags.needsReload = true; + } +} + +void LDrawModelViewer::setDarkEdgeColor(TCULong value) +{ + if (value != darkEdgeColor) + { + darkEdgeColor = value; + flags.needsReload = true; + } +} + +void LDrawModelViewer::setPartColorLDIndex(TCFloat value) +{ + if (value != partColorLDIndex) + { + partColorLDIndex = value; + flags.needsReload = true; + } +} + +void LDrawModelViewer::setPartEdgeContrast(TCFloat value) +{ + if (value != partEdgeContrast) + { + partEdgeContrast = value; + if (flags.automateEdgeColor) + { + flags.needsReload = true; + } + } +} + +void LDrawModelViewer::setPartEdgeSaturation(TCFloat value) +{ + if (value != partEdgeSaturation) + { + partEdgeSaturation = value; + if (flags.automateEdgeColor) + { + flags.needsReload = true; + } + } +} + void LDrawModelViewer::setRandomColors(bool value) { if (value != flags.randomColors) @@ -2606,15 +2755,6 @@ void LDrawModelViewer::setTextureOffsetFactor(TCFloat value) } } -void LDrawModelViewer::setUseStudStyle(bool value) -{ - if (value != flags.useStudStyle) - { - flags.useStudStyle = value; - flags.needsReload = true; - } -} - void LDrawModelViewer::setUseStrips(bool value) { if (value != flags.useStrips) diff --git a/LDLib/LDrawModelViewer.h b/LDLib/LDrawModelViewer.h index bae2add65..0c6493b19 100644 --- a/LDLib/LDrawModelViewer.h +++ b/LDLib/LDrawModelViewer.h @@ -543,8 +543,6 @@ class LDrawModelViewer: public TCAlertSender void setTextureOffsetFactor(TCFloat value); bool getUseStrips(void) const { return flags.useStrips ? true : false; } void setUseStrips(bool value); - bool getUseStudStyle(void) const { return flags.useStudStyle ? true : false; } - void setUseStudStyle(bool value); bool getRandomColors(void) const { return flags.randomColors ? true : false; @@ -637,8 +635,41 @@ class LDrawModelViewer: public TCAlertSender static void resetUnofficialDownloadTimes(void); static std::string libraryUrl(const std::string& path); // static bool doCommandLineExport(void); + void setAutomateEdgeColor(bool value); + void setUseStudStyle(bool value); void setStudStyle(int value); + + void setStudCylinderColorEnabled(bool value); + void setPartEdgeColorEnabled(bool value); + void setBlackEdgeColorEnabled(bool value); + void setDarkEdgeColorEnabled(bool value); + + void setStudCylinderColor(TCULong value); + void setPartEdgeColor(TCULong value); + void setBlackEdgeColor(TCULong value); + void setDarkEdgeColor(TCULong value); + + void setPartColorLDIndex(TCFloat value); + void setPartEdgeContrast(TCFloat value); + void setPartEdgeSaturation(TCFloat value); + + bool getAutomateEdgeColor(void) { return flags.automateEdgeColor ? true : false; }; + bool getUseStudStyle(void) const { return flags.useStudStyle ? true : false; } int getStudStyle(void) const { return studStyle; } + + bool getStudCylinderColorEnabled(void) { return studCylinderColorEnabled != false; } + bool getPartEdgeColorEnabled(void) { return partEdgeColorEnabled != false; } + bool getBlackEdgeColorEnabled(void) { return blackEdgeColorEnabled != false; } + bool getDarkEdgeColorEnabled(void) { return darkEdgeColorEnabled != false; } + + TCULong getStudCylinderColor(void) const { return studCylinderColor; }; + TCULong getPartEdgeColor(void) const { return partEdgeColor; }; + TCULong getBlackEdgeColor(void) const { return blackEdgeColor; }; + TCULong getDarkEdgeColor(void) const { return darkEdgeColor; }; + + TCFloat getPartColorLDIndex(void) { return partColorLDIndex; }; + TCFloat getPartEdgeContrast(void) { return partEdgeContrast; }; + TCFloat getPartEdgeSaturation(void) { return partEdgeSaturation; }; protected: ~LDrawModelViewer(void); void dealloc(void); @@ -836,6 +867,17 @@ class LDrawModelViewer: public TCAlertSender int highlightG; int highlightB; int studStyle; + bool studCylinderColorEnabled; + bool partEdgeColorEnabled; + bool blackEdgeColorEnabled; + bool darkEdgeColorEnabled; + TCULong studCylinderColor; + TCULong partEdgeColor; + TCULong blackEdgeColor; + TCULong darkEdgeColor; + TCFloat partColorLDIndex; + TCFloat partEdgeContrast; + TCFloat partEdgeSaturation; #ifdef USE_STD_CHRONO std::chrono::time_point frameTime; #else @@ -933,6 +975,7 @@ class LDrawModelViewer: public TCAlertSender bool texturesAfterTransparent:1; bool useStrips:1; bool useStudStyle:1; + bool automateEdgeColor:1; } flags; struct CameraData { diff --git a/LDLoader/LDLModel.cpp b/LDLoader/LDLModel.cpp index 10bb66a96..3a27bf843 100644 --- a/LDLoader/LDLModel.cpp +++ b/LDLoader/LDLModel.cpp @@ -48,27 +48,79 @@ static struct TCStudStylePrimitive StudStylePrimitives[] = { { /* 00 */ "stud.dat", - "0 Stud\n0 Name: stud.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2012-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 0 0 6 0 0 0 -4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4disc.dat\n" + "0 Stud\n0 Name: stud.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2012-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 4242 0 0 0 6 0 0 0 -4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4disc.dat\n" }, { /* 01 */ "8/stud.dat", - "0 Stud (Fast-Draw)\n0 Name: 8\\stud.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 0 0 6 0 0 0 -4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4disc.dat\n" + "0 Stud (Fast-Draw)\n0 Name: 8\\stud.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 4242 0 0 0 6 0 0 0 -4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4disc.dat\n" }, { /* 02 */ "stud2.dat", - "0 Stud Open\n0 Name: stud2.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring2.dat\n0\n" + "0 Stud Open\n0 Name: stud2.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring2.dat\n0\n" }, { /* 03 */ "8/stud2.dat", - "0 Stud Open (Fast-Draw)\n0 Name: 8\\stud2.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 8\4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring2.dat\n" + "0 Stud Open (Fast-Draw)\n0 Name: 8\\stud2.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 4 0 0 0 4 0 0 0 4 8\4-4cyli.dat\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring2.dat\n" }, { /* 04 */ "stud2a.dat", - "0 Stud Open without Base Edges\n0 Name: stud2a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring2.dat\n0\n" + "0 Stud Open without Base Edges\n0 Name: stud2a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring2.dat\n0\n" }, { /* 05 */ "8/stud2a.dat", - "0 Stud Open without Base Edges (Fast-Draw)\n0 Name: 8\\stud2a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 16 0 -4 0 4 0 0 0 4 0 0 0 4 8\4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring2.dat\n" + "0 Stud Open without Base Edges (Fast-Draw)\n0 Name: 8\\stud2a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 4 0 0 0 4 0 0 0 4 8\4-4cyli.dat\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring2.dat\n" + }, + { /* 06 */ + "stud3.dat", + "0 Stud Tube Solid\n0 Name: stud3.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2012-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4disc.dat\n1 4242 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n" + }, + { /* 07 */ + "8/stud3.dat", + "0 Stud Tube Solid (Fast-Draw)\n0 Name: 8\\stud3.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 8\4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 8\4-4disc.dat\n1 4242 0 -4 0 4 0 0 0 4 0 0 0 4 8\4-4cyli.dat\n" + }, + { /* 08 */ + "stud4.dat", + "0 Stud Tube Open\n0 Name: stud4.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 8 0 0 0 1 0 0 0 8 4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 0 0 8 0 0 0 1 0 0 0 8 4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 8 0 0 0 4 0 0 0 8 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring3.dat\n0\n" + }, + { /* 09 */ + "8/stud4.dat", + "0 Stud Tube Open (Fast-Draw)\n0 Name: 8\\stud4.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 8 0 0 0 1 0 0 0 8 8\4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 0 0 8 0 0 0 1 0 0 0 8 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 8 0 0 0 4 0 0 0 8 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring3.dat\n" + }, + { /* 10 */ + "stud4a.dat", + "0 Stud Tube Open without Base Edges\n0 Name: stud4a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive UPDATE 2009-02\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 8 0 0 0 1 0 0 0 8 4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 8 0 0 0 4 0 0 0 8 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring3.dat\n0\n" + }, + { /* 11 */ + "8/stud4a.dat", + "0 Stud Tube Open without Base Edges (Fast-Draw)\n0 Name: 8\\stud4a.dat\n0 Author: James Jessiman\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 8 0 0 0 1 0 0 0 8 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 8 0 0 0 4 0 0 0 8 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring3.dat\n" + }, + { /* 12 */ + "stud4h.dat", + "0 Stud Tube Open with Extended Hole\n0 Name: stud4h.dat\n0 Author: Tim Gould [timgould]\n0 !LDRAW_ORG Primitive UPDATE 2012-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 8 0 0 0 1 0 0 0 8 4-4edge.dat\n1 16 0 4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 0 0 8 0 0 0 1 0 0 0 8 4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 6 0 0 0 8 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 8 0 0 0 4 0 0 0 8 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring3.dat\n0\n" + }, + { /* 13 */ + "8/stud4h.dat", + "0 Stud Tube Open with Extended Hole (Fast-Draw)\n0 Name: 8\\stud4h.dat\n0 Author: Tim Gould [timgould]\n0 !LDRAW_ORG 8_Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 -4 0 8 0 0 0 1 0 0 0 8 8\4-4edge.dat\n1 16 0 4 0 6 0 0 0 1 0 0 0 6 8\4-4edge.dat\n1 16 0 0 0 8 0 0 0 1 0 0 0 8 8\4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 6 0 0 0 8 0 0 0 6 8\4-4cyli.dat\n1 16 0 -4 0 8 0 0 0 4 0 0 0 8 8\4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 8\4-4ring3.dat\n" + }, + { /* 14 */ + "2-4stud4.dat", + "0 Stud Tube Open 0.5\n0 Name: 2-4stud4.dat\n0 Author: Joerg Sommerer [Brickaneer]\n0 !LDRAW_ORG Primitive UPDATE 2016-01\n\n0 BFC CERTIFY CCW\n\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 2-4edge.dat\n1 16 0 -4 0 8 0 0 0 1 0 0 0 8 2-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 2-4edge.dat\n1 16 0 0 0 8 0 0 0 1 0 0 0 8 2-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 2-4cyli.dat\n1 16 0 -4 0 8 0 0 0 4 0 0 0 8 2-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 2-4ring3.dat\n" + }, + { /* 15 */ + "stud-logo.dat", + "0 Stud with LEGO Logo - Non-3D Thin Lines\n0 Name: stud-logo.dat\n0 Author: Paul Easter [pneaster]\n0 !LDRAW_ORG Unofficial_Primitive\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 4242 0 0 0 6 0 0 0 -4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4disc.dat\n\n1 16 0 -4 0 1 0 0 0 1 0 0 0 1 logo.dat\n" + }, + { /* 16 */ + "8/stud-logo.dat", + "0 Stud with LEGO Logo - Non-3D Thin Lines (Fast-Draw)\n0 Name: 8\\stud-logo.dat\n0 Author: Steffen [Steffen]\n0 !LDRAW_ORG Unofficial_8_Primitive\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 8\\stud.dat\n" + }, + { /* 17 */ + "stud2-logo.dat", + "0 Stud Open with LEGO Logo - Non-3D Thin Lines\n0 Name: stud2-logo.dat\n0 Author: Paul Easter [pneaster]\n0 !LDRAW_ORG Unofficial_Primitive\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 0 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n1 16 0 -4 0 4 0 0 0 1 0 0 0 4 4-4edge.dat\n1 16 0 -4 0 6 0 0 0 1 0 0 0 6 4-4edge.dat\n0 BFC INVERTNEXT\n1 4242 0 -4 0 4 0 0 0 4 0 0 0 4 4-4cyli.dat\n1 4242 0 -4 0 6 0 0 0 4 0 0 0 6 4-4cyli.dat\n1 16 0 -4 0 2 0 0 0 1 0 0 0 2 4-4ring2.dat\n\n1 16 0 0 0 0.6 0 0 0 1 0 0 0 0.6 logo.dat\n" + }, + { /* 18 */ + "8/stud2-logo.dat", + "0 Stud Open with LEGO Logo - Non-3D Thin Lines (Fast-Draw)\n0 Name: 8\\stud2-logo.dat\n0 Author: Steffen [Steffen]\n0 !LDRAW_ORG Unofficial_8_Primitive\n\n0 BFC CERTIFY CCW\n\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 8\\stud2.dat\n" } }; @@ -79,6 +131,7 @@ std::string LDLModel::sm_systemLDrawDirSlashes; char *LDLModel::sm_defaultLDrawDir = NULL; LDrawIniS *LDLModel::sm_lDrawIni = NULL; int LDLModel::sm_modelCount = 0; +bool LDLModel::sm_studCylinderColorEnabled = true; LDLFileCaseCallback LDLModel::fileCaseCallback = NULL; LDLModel::LDLModelCleanup LDLModel::sm_cleanup; StringList LDLModel::sm_checkDirs; @@ -299,8 +352,7 @@ LDLModel *LDLModel::subModelNamed(const char *subModelName, bool lowRes, { ancestorCheck = true; } - if (strcasecmp(subModelName, "stud.dat") == 0 || - strcasecmp(subModelName, "stud2.dat") == 0) + if (isStudStylePrimitive(subModelName, TCUserDefaults::longForKey(STUD_STYLE_KEY, 0))) { m_flags.hasStuds = true; } @@ -880,26 +932,55 @@ bool LDLModel::openSubModelNamed( return false; } +char* LDLModel::setStudCylinderColor(char* input) +{ + if (sm_studCylinderColorEnabled) + return input; + + const std::string studColor = "4242"; + const std::string mainColor = "16"; + + std::string result(input); // Copy input safely into std::string + + size_t pos = 0; + while ((pos = result.find(studColor, pos)) != std::string::npos) + { + result.replace(pos, studColor.length(), mainColor); + pos += mainColor.length(); // Move past replacement + } + + // Allocate C-style buffer for return + char* buffer = static_cast(malloc(result.size() + 1)); + if (!buffer) + return nullptr; + + std::memcpy(buffer, result.c_str(), result.size() + 1); // includes '\0' + + return buffer; +} + int LDLModel::getStudStyleFile(LDLModel* subModel, const char* dictName, int studStyle, bool openStud) { + sm_studCylinderColorEnabled = TCUserDefaults::boolForKey(STUD_CYLINDER_COLOR_ENABLED_KEY, true); + int studCylinder = sm_studCylinderColorEnabled ? 1 : 0; char data[TC_STUD_STYLE_MAX_DATA_LEN]; char tempPath[256]; #ifdef WIN32 - sprintf(tempPath, "%s\\ldview_stud_style%d_%s", getenv("TEMP"), studStyle, dictName); + sprintf(tempPath, "%s\\ldview_stud_style%d_%d_%s", getenv("TEMP"), studStyle, studCylinder, dictName); #else - sprintf(tempPath, "/tmp/ldview_stud_style%d_%s", studStyle, dictName); + sprintf(tempPath, "/tmp/ldview_stud_style%d_%d_%s", studStyle, studCylinder, dictName); #endif std::ifstream existingSubModelStream(tempPath, std::ios::binary); if (existingSubModelStream.is_open()) return (subModel->load(existingSubModelStream)); - if (studStyle > 0) + if (studStyle > 0 && studStyle < 6) { char style[10] = ""; if (studStyle > 1) sprintf(style, "%d", studStyle); - sprintf(data, "0 Stud %s\n0 Name: %s\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive\n0 BFC CERTIFY CCW\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 stud%s-logo%s.dat\n", (openStud ? "open" : style), dictName, (openStud ? "2" : ""), style); + sprintf(data, "0 Stud %s\n0 Name: %s\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive\n0 BFC CERTIFY CCW\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 stud%s-logo%s.dat\n", (openStud ? "Open" : style), dictName, (openStud ? "2" : ""), style); } else { @@ -907,7 +988,11 @@ int LDLModel::getStudStyleFile(LDLModel* subModel, const char* dictName, int stu { if (strcasecmp(dictName, StudStylePrimitives[i].Name) == 0) { - strcpy(data, StudStylePrimitives[i].Data); + bool isOpen = isStudStylePrimitive(dictName, studStyle) == 2; + if (studStyle == 7 && (strcasecmp(dictName, "stud.dat") == 0 || isOpen)) + sprintf(data, "0 Stud %s\n0 Name: %s\n0 Author: James Jessiman\n0 !LDRAW_ORG Primitive\n0 BFC CERTIFY CCW\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 stud%s-logo.dat\n", (isOpen ? "Open" : ""), dictName, (isOpen ? "2" : "")); + else + strcpy(data, setStudCylinderColor(StudStylePrimitives[i].Data)); break; } } @@ -924,16 +1009,20 @@ int LDLModel::getStudStyleFile(LDLModel* subModel, const char* dictName, int stu int LDLModel::isStudStylePrimitive(const char* FileName, int studStyle) { - // return if file has '-logo' suffix - if (strstr(FileName, "-logo") != NULL) + // for styles 0-5, return if file has '-logo' suffix + if (studStyle < 6 && strstr(FileName, "-logo") != NULL) return 0; for (unsigned int i = 0; i < TC_STUD_STYLE_ARRAY_COUNT(StudStylePrimitives); i++) { if (strcasecmp(FileName, StudStylePrimitives[i].Name) == 0) { + // for styles 0-5, only check for stud, stud2 and stud2a + if (studStyle < 6 && i > 5) + return 0; + if (strcasecmp(FileName, "stud2.dat") == 0 || strcasecmp(FileName, "stud2a.dat") == 0) - return 2; // open stud + return 2; // open stud else return 1; } @@ -978,12 +1067,12 @@ bool LDLModel::initializeNewSubModel( subModel->m_flags.unofficial = true; } bool zipValid = zipStream != NULL && zipStream->is_valid(); - bool useStudStyle = TCUserDefaults::boolForKey(STUD_STYLE_USE_KEY, false, true); + bool useStudStyle = TCUserDefaults::boolForKey(STUD_STYLE_USE_KEY, false); unsigned int studStylePrimitive = 0; if (useStudStyle && m_flags.loadingPrimitive && m_flags.hasStuds) { - unsigned int studStyle = TCUserDefaults::longForKey(STUD_STYLE_KEY, 0, true); - unsigned int studStyleType = isStudStylePrimitive(dictName); + unsigned int studStyle = TCUserDefaults::longForKey(STUD_STYLE_KEY, 0); + unsigned int studStyleType = isStudStylePrimitive(dictName, studStyle); if (studStyleType > 0) { bool openStud = studStyleType == 2; diff --git a/LDLoader/LDLModel.h b/LDLoader/LDLModel.h index 32aa42289..07ce94ace 100644 --- a/LDLoader/LDLModel.h +++ b/LDLoader/LDLModel.h @@ -205,7 +205,8 @@ class LDLModel : public TCAlertSender static void initCheckDirs(); - static int isStudStylePrimitive(const char* FileName, int studStyle = 0); + static int isStudStylePrimitive(const char* FileName, int studStyle); + static char* setStudCylinderColor(char* input); static int getStudStyleFile(LDLModel* subModel, const char* dictName, int studStyle, bool openStud); @@ -282,6 +283,7 @@ class LDLModel : public TCAlertSender static char *sm_defaultLDrawDir; static LDrawIniS *sm_lDrawIni; static int sm_modelCount; + static bool sm_studCylinderColorEnabled; static LDLFileCaseCallback fileCaseCallback; static std::string sm_ldrawZipPath; static std::string sm_unoffZipPath; diff --git a/LDLoader/LDLPalette.cpp b/LDLoader/LDLPalette.cpp index f3dafafcd..3ebf2f5bf 100644 --- a/LDLoader/LDLPalette.cpp +++ b/LDLoader/LDLPalette.cpp @@ -1,6 +1,10 @@ #include "LDLPalette.h" #include #include +#include +#include +#include +#include #include #ifdef WIN32 @@ -13,6 +17,147 @@ static const TCByte transA = 110; +#define TC_SRGB_TO_LINEAR(v) (powf(v, 2.2f)) +#define TC_LINEAR_TO_SRGB(v) (powf(v, 1.0f / 2.2f)) +#define TC_LUM_FROM_SRGB(r,g,b) ((0.2126f * TC_SRGB_TO_LINEAR(r)) + (0.7152f * TC_SRGB_TO_LINEAR(g)) + (0.0722f * TC_SRGB_TO_LINEAR(b))) +#define TC_LUM_FROM_RGB(r,g,b) ((0.2126f * r) + (0.7152f * g) + (0.0722f * b)) +#define TC_RGB_EPSILON (0.5f / 255.0f) +#define TC_RGB_TO_DEC(v) (v / 255.0f) + +bool LDLPalette::sm_automateEdgeColor = false; +bool LDLPalette::sm_useStudStyle = false; +int LDLPalette::sm_studStyle = 0; +//bool LDLPalette::sm_studCylinderColorEnabled = true; +bool LDLPalette::sm_partEdgeColorEnabled = true; +bool LDLPalette::sm_blackEdgeColorEnabled = true; +bool LDLPalette::sm_darkEdgeColorEnabled = true; +LDLColor LDLPalette::sm_studCylinderColor{ 27,42,52,255 }; +LDLColor LDLPalette::sm_partEdgeColor{ 0,0,0,255 }; +LDLColor LDLPalette::sm_blackEdgeColor{ 255,255,255,255 }; +LDLColor LDLPalette::sm_darkEdgeColor{ 27,42,52,255 }; +TCFloat LDLPalette::sm_partColorLDIndex = 0.5f; +TCFloat LDLPalette::sm_partEdgeContrast = 0.5f; +TCFloat LDLPalette::sm_partEdgeSaturation = 0.5f; + +static TCVector TC_RGB2HSL(TCVector rgb) +{ + int Mi; + TCFloat M, m, C, h, S, L; // h is H/60 + + Mi = (rgb[0] >= rgb[1]) ? 0 : 1; + Mi = (rgb[Mi] >= rgb[2]) ? Mi : 2; + M = rgb[Mi]; + + m = (rgb[0] < rgb[1]) ? rgb[0] : rgb[1]; + m = (m < rgb[2]) ? m : rgb[2]; + + C = M - m; + L = (M + m) / 2.0f; + + if (C < TC_RGB_EPSILON) // C == 0.0 + h = 0.0f; + else if (Mi == 0) // M == R + h = 0.0f + (rgb[1] - rgb[2]) / C; + else if (Mi == 1) // M == G + h = 2.0f + (rgb[2] - rgb[0]) / C; + else // M = B + h = 4.0f + (rgb[0] - rgb[1]) / C; + + h = (h < 0.0) ? h + 6.0f : h; + h = (h >= 6.0) ? h - 6.0f : h; + + S = ((L < (TC_RGB_EPSILON / 2.0f)) || (L > (1.0f - (TC_RGB_EPSILON / 2.0f)))) + ? 0.0f : (2.0f * (M - L)) / (1.0f - fabs((2.0f * L) - 1.0f)); + + return TCVector(h, S, L); +} + +static TCVector TC_HSL2RGB(TCVector hSL) +{ + TCVector rgb; + float h, S, L, C, X, m; + + h = hSL[0]; + S = hSL[1]; + L = hSL[2]; + + C = (1.0f - fabs(2.0f * L - 1.0f)) * S; + X = C * (1.0f - fabs(fmodf(h, 2.0f) - 1.0f)); + + if (h < 1.0f) + rgb = TCVector(C, X, 0.0f); + else if (h < 2.0f) + rgb = TCVector(X, C, 0.0f); + else if (h < 3.0f) + rgb = TCVector(0.0f, C, X); + else if (h < 4.0f) + rgb = TCVector(0.0f, X, C); + else if (h < 5.0f) + rgb = TCVector(X, 0.0f, C); + else + rgb = TCVector(C, 0.0f, X); + + m = L - C / 2.0f; + + rgb[0] += m; + rgb[1] += m; + rgb[2] += m; + + return rgb; +} + +static LDLColor getAlgorithmicEdgeColor(const TCVector& Value, const float ValueLum, + const float EdgeLum, const float Contrast, const float Saturation) +{ + float y1, yt; + float y0 = ValueLum; + float ye = EdgeLum; + float cont = Contrast; + float sat = Saturation; + TCVector hSL, rgb1, rgbf; + + // Determine luma target + if (ye < y0) + { + // Light base color + yt = y0 - cont * y0; + } + else + { + // Dark base color + yt = y0 + cont * (1.0f - y0); + } + + // Get base color in hSL + hSL = TC_RGB2HSL(Value); + + // Desaturate + hSL[1] *= sat; + + // Adjusted color to RGB + rgb1 = TC_HSL2RGB(TCVector(hSL[0], hSL[1], 0.5f)); + + // Fix adjusted color luma to target value + y1 = TC_LUM_FROM_RGB(rgb1[0], rgb1[1], rgb1[2]); + if (yt < y1) + { + // Make darker via scaling + rgbf = (yt / y1) * rgb1; + } + else + { + // Make lighter via scaling anti-color + rgbf = TCVector(1.0f, 1.0f, 1.0f) - rgb1; + rgbf *= (1.0f - yt) / (1.0f - y1); + rgbf = TCVector(1.0f, 1.0f, 1.0f) - rgbf; + } + + TCVector rgb = TCVector(TC_LINEAR_TO_SRGB(rgbf[0]), TC_LINEAR_TO_SRGB(rgbf[1]), + TC_LINEAR_TO_SRGB(rgbf[2])) *= 255; + + return LDLColor{ (TCByte)rgb[0], (TCByte)rgb[1], (TCByte)rgb[2], 255 }; +} + LDLPalette *LDLPalette::sm_defaultPalette = NULL; TCByte LDLPalette::sm_transA = transA; LDLPalette::LDLPaletteCleanup LDLPalette::sm_cleanup; @@ -195,6 +340,7 @@ void LDLPalette::init(void) initStandardColors(); initDitherColors(); initOtherColors(); + initStudStyleSettings(); } void LDLPalette::reset(void) @@ -334,23 +480,137 @@ void LDLPalette::initOtherColors(void) initSpecular(494, 0.9f, 0.9f, 1.5f, 1.0f, 5.0f); } -int LDLPalette::getEdgeColorNumber(int colorNumber) +void LDLPalette::initStudStyleSettings() { - if (colorNumber < 512 && colorNumber >= 0) + //sm_studCylinderColorEnabled = TCUserDefaults::boolForKey(PART_EDGE_COLOR_ENABLED_KEY, sm_studCylinderColorEnabled); + sm_partEdgeColorEnabled = TCUserDefaults::boolForKey(PART_EDGE_COLOR_ENABLED_KEY, sm_partEdgeColorEnabled); + sm_blackEdgeColorEnabled = TCUserDefaults::boolForKey(BLACK_EDGE_COLOR_ENABLED_KEY, sm_blackEdgeColorEnabled); + sm_darkEdgeColorEnabled = TCUserDefaults::boolForKey(DARK_EDGE_COLOR_ENABLED_KEY, sm_darkEdgeColorEnabled); + sm_automateEdgeColor = TCUserDefaults::boolForKey(AUTOMATE_EDGE_COLOR_KEY, sm_automateEdgeColor); + sm_useStudStyle = TCUserDefaults::boolForKey(STUD_STYLE_USE_KEY, sm_useStudStyle); + sm_studStyle = (int)TCUserDefaults::longForKey(STUD_STYLE_KEY, sm_studStyle); + sm_partColorLDIndex = TCUserDefaults::floatForKey(PART_COLOR_LD_INDEX_KEY, sm_partColorLDIndex); + sm_partEdgeContrast = TCUserDefaults::floatForKey(PART_EDGE_CONTRAST_KEY, sm_partEdgeContrast); + sm_partEdgeSaturation = TCUserDefaults::floatForKey(PART_EDGE_SATURATION_KEY, sm_partEdgeSaturation); + + if (!sm_useStudStyle || (sm_studStyle < 6 && !sm_automateEdgeColor)) + return; + + int r, g, b, a; + std::string rgbaString = TCUserDefaults::stringForKey(STUD_CYLINDER_COLOR_KEY, "27,42,52,255"); + if (sscanf(rgbaString.c_str(), "%d,%d,%d,%d", &r, &g, &b, &a) == 4) + sm_studCylinderColor = LDLColor{ (TCByte)r, (TCByte)g, (TCByte)b, (TCByte)a }; + rgbaString = TCUserDefaults::stringForKey(PART_EDGE_COLOR_KEY, "0,0,0,255"); + if (sscanf(rgbaString.c_str(), "%d,%d,%d,%d", &r, &g, &b, &a) == 4) + sm_partEdgeColor = LDLColor{ (TCByte)r, (TCByte)g, (TCByte)b, (TCByte)a }; + rgbaString = TCUserDefaults::stringForKey(BLACK_EDGE_COLOR_KEY, "255,255,255,255"); + if (sscanf(rgbaString.c_str(), "%d,%d,%d,%d", &r, &g, &b, &a) == 4) + sm_blackEdgeColor = LDLColor{ (TCByte)r, (TCByte)g, (TCByte)b, (TCByte)a }; + rgbaString = TCUserDefaults::stringForKey(DARK_EDGE_COLOR_KEY, "27,42,52,255"); + if (sscanf(rgbaString.c_str(), "%d,%d,%d,%d", &r, &g, &b, &a) == 4) + sm_darkEdgeColor = LDLColor{ (TCByte)r, (TCByte)g, (TCByte)b, (TCByte)a }; + + int edgeColorNumber = getEdgeColorNumberFromRGB(sm_partEdgeColor); + LDLColorInfo* colorInfo = updateColor(4242, sm_studCylinderColor, sm_studCylinderColor, + edgeColorNumber, (-25500.0f / 255.0f)); + if (colorInfo) { - return m_colors[colorNumber].edgeColorNumber; + const char* name = "Stud Cylinder Color"; + strncpy(colorInfo->name, name, sizeof(colorInfo->name)); + colorInfo->name[sizeof(colorInfo->name) - 1] = 0; + m_namesMap[name] = 4242; + colorInfo->rubber = false; + colorInfo->chrome = false; } else + debugPrintf("Error creating Stud Cylinder Color (%d)\n", 4242); +} + +int LDLPalette::getEdgeColorNumberFromRGB(const LDLColor& color) +{ + char hexColor[16]; + int edgeColorNumber; + snprintf(hexColor, sizeof hexColor, "%02x%02x%02x", (int)color.r, (int)color.g, (int)color.b); + if (sscanf(hexColor, "%x", &edgeColorNumber) == 1) { - LDLColorInfo colorInfo; + edgeColorNumber &= 0xFFFFFF; + edgeColorNumber |= 0x2000000; // Encode EDGE as extended RGB color. + return edgeColorNumber; + } + debugPrintf("Failed to get extended HEX from RGB %s\n", hexColor); + return 0; +} - if (getCustomColorInfo(colorNumber, colorInfo)) +int LDLPalette::getStudStyleOrAutoEdgeColor(int colorNumber) +{ + LDLColorInfo colorInfo = getAnyColorInfo(colorNumber); + TCVector value(TC_RGB_TO_DEC((int)colorInfo.color.r), TC_RGB_TO_DEC((int)colorInfo.color.g), TC_RGB_TO_DEC((int)colorInfo.color.b)); + const TCFloat valueLuminescence = TC_LUM_FROM_SRGB(value[0], value[1], value[2]); + + if (sm_automateEdgeColor) + { + if (colorInfo.automated) { return colorInfo.edgeColorNumber; } else { - return 0; + int r, g, b, a; + getRGBA(colorInfo.edgeColorNumber, r, g, b, a); + const TCFloat edgeLuminescence = TC_LUM_FROM_SRGB(TC_RGB_TO_DEC(r), TC_RGB_TO_DEC(g), TC_RGB_TO_DEC(b)); + + LDLColor algEdgeColor = getAlgorithmicEdgeColor(value, valueLuminescence, edgeLuminescence, sm_partEdgeContrast, sm_partEdgeSaturation); + int edgeColorNumber = getEdgeColorNumberFromRGB(algEdgeColor); + + LDLColorInfo* adjustColorInfo; + adjustColorInfo = updateColor(colorNumber, colorInfo.color, colorInfo.ditherColor, edgeColorNumber); + adjustColorInfo->automated = true; + return edgeColorNumber; + } + } + else + { + TCFloat lightDarkControl = TC_SRGB_TO_LINEAR(sm_partColorLDIndex); + if (sm_blackEdgeColorEnabled && colorNumber == 0) + return getEdgeColorNumberFromRGB(sm_blackEdgeColor); + else if (sm_darkEdgeColorEnabled && colorNumber != 4242 && + valueLuminescence < lightDarkControl) + return getEdgeColorNumberFromRGB(sm_darkEdgeColor); + else if (sm_partEdgeColorEnabled) + return getEdgeColorNumberFromRGB(sm_partEdgeColor); + } + + debugPrintf("Error creating edge color number for color: %d\n", + colorNumber); + + return 0; +} + +int LDLPalette::getEdgeColorNumber(int colorNumber) +{ + + if (sm_studStyle > 5 || sm_automateEdgeColor) + { + return getStudStyleOrAutoEdgeColor(colorNumber); + } + else + { + if (colorNumber < 512 && colorNumber >= 0) + { + return m_colors[colorNumber].edgeColorNumber; + } + else + { + LDLColorInfo colorInfo; + + if (getCustomColorInfo(colorNumber, colorInfo)) + { + return colorInfo.edgeColorNumber; + } + else + { + return 0; + } } } } @@ -436,6 +696,7 @@ void LDLPalette::initColorInfo(LDLColorInfo &colorInfo, int r, int g, int b, colorInfo.luminance = -100.0f; colorInfo.chrome = false; colorInfo.rubber = false; + colorInfo.automated = false; initSpecularAndShininess(colorInfo); } @@ -783,6 +1044,7 @@ LDLColorInfo *LDLPalette::updateColor(int colorNumber, const LDLColor &color, customColor->colorNumber = colorNumber; colorInfo = &customColor->colorInfo; + colorInfo->automated = false; m_customColors->addObject(customColor); customColor->release(); } diff --git a/LDLoader/LDLPalette.h b/LDLoader/LDLPalette.h index 615dcf849..bdf566ded 100644 --- a/LDLoader/LDLPalette.h +++ b/LDLoader/LDLPalette.h @@ -23,6 +23,7 @@ typedef struct float luminance; bool chrome; bool rubber; + bool automated; } LDLColorInfo; class LDLPalette : public TCObject @@ -94,6 +95,25 @@ class LDLPalette : public TCObject TCTypedObjectArray *m_customColors; CIStringIntMap m_namesMap; + void initStudStyleSettings(void); + int getStudStyleOrAutoEdgeColor(int colorNumber); + int getEdgeColorNumberFromRGB(const LDLColor& color); + + static bool sm_automateEdgeColor; + static bool sm_useStudStyle; + static int sm_studStyle; + //static bool sm_studCylinderColorEnabled; + static bool sm_partEdgeColorEnabled; + static bool sm_blackEdgeColorEnabled; + static bool sm_darkEdgeColorEnabled; + static LDLColor sm_studCylinderColor; + static LDLColor sm_partEdgeColor; + static LDLColor sm_blackEdgeColor; + static LDLColor sm_darkEdgeColor; + static TCFloat sm_partColorLDIndex; + static TCFloat sm_partEdgeContrast; + static TCFloat sm_partEdgeSaturation; + static LDLPalette *sm_defaultPalette; static TCByte sm_transA; static class LDLPaletteCleanup diff --git a/LDViewMessages.ini b/LDViewMessages.ini index 2c8edc3c0..3490a900b 100644 --- a/LDViewMessages.ini +++ b/LDViewMessages.ini @@ -105,6 +105,8 @@ DoubleWire =2 Double Wire RaisedFlat =3 Raised Flat RaisedRounded =4 Raised Rounded SubtleRounded =5 Subtle Rounded +HighContrast =6 High Contrast Plain +HighContrastSingleWire =7 High Contrast Single Wire ; ** LDViewWindow ** From 2879a1abfa3c2b2ca31b699e40e82a0bf6917758 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Fri, 7 Nov 2025 20:28:21 +0100 Subject: [PATCH 5/7] Setup Windows preferences UI --- ContextHelp.h | 31 ++- LDView.rc | 98 ++++++++- LDViewPreferences.cpp | 487 +++++++++++++++++++++++++++++++++++++++++- LDViewPreferences.h | 60 ++++++ Resource.h | 38 +++- 5 files changed, 702 insertions(+), 12 deletions(-) diff --git a/ContextHelp.h b/ContextHelp.h index 7633d1798..0be41e5b5 100644 --- a/ContextHelp.h +++ b/ContextHelp.h @@ -8,11 +8,16 @@ #define HIDC_ALWAYS_BLACK 0x808903f5 // IDD_GEOMETRY_PREFS #define HIDC_ANISO_LEVEL 0x860b03fb // IDD_PRIMITIVES_PREFS #define HIDC_ANISO_LEVEL_LABEL 0x860b04d0 // IDD_PRIMITIVES_PREFS +#define HIDC_AUTOMATE_EDGE_COLOR_CHECK 0x8089053a // IDD_GEOMETRY_PREFS +#define HIDC_AUTOMATE_EDGE_COLOR 0x808903f6 // IDD_GEOMETRY_PREFS #define HIDC_AUTO_CROP 0x808d04bd // IDD_SAVE_OPTIONS #define HIDC_BACKGROUND_COLOR 0x808b03fd // IDD_GENERAL_PREFS #define HIDC_BACKGROUND_COLOR_LABEL 0x808b0439 // IDD_GENERAL_PREFS #define HIDC_BFC 0x80890412 // IDD_GEOMETRY_PREFS #define HIDC_BFC_BOX 0x808904a0 // IDD_GEOMETRY_PREFS +#define HIDC_BLACK_EDGE_COLOR 0x8224053d // IDD_STUD_STYLE_COLORS +#define HIDC_BLACK_EDGE_COLOR_CHECK 0x8224053c // IDD_STUD_STYLE_COLORS +#define HIDC_BLACK_EDGE_COLOR_RESET 0x8224053e // IDD_STUD_STYLE_COLORS #define HIDC_BLUE_NEUTRAL_FACES 0x80890415 // IDD_GEOMETRY_PREFS #define HIDC_BROWSE_CUSTOM_CONFIG 0x808b052c // IDD_GENERAL_PREFS #define HIDC_BROWSE_EXPORT_DIR 0x808b04f6 // IDD_GENERAL_PREFS @@ -27,6 +32,10 @@ #define HIDC_LDRAW_RESET 0x808e0467 // IDD_LDRAW_PREFS #define HIDC_CONDITIONAL_CONTROLS 0x80890410 // IDD_GEOMETRY_PREFS #define HIDC_CONDITIONAL_HIGHLIGHTS 0x8089050a // IDD_GEOMETRY_PREFS +#define HIDC_CONTRAST_NAME 0x82240544 // IDD_STUD_STYLE_COLORS +#define HIDC_CONTRAST_RESET 0x82240546 // IDD_STUD_STYLE_COLORS +#define HIDC_CONTRAST_SLIDER 0x82240543 // IDD_STUD_STYLE_COLORS +#define HIDC_CONTRAST_VALUE 0x82240545 // IDD_STUD_STYLE_COLORS #define HIDC_CROSS_EYED_STEREO 0x808a03f6 // IDD_EFFECTS_PREFS #define HIDC_CURVE_QUALITY 0x860b03fa // IDD_PRIMITIVES_PREFS #define HIDC_CURVE_QUALITY_LABEL 0x860b03fc // IDD_PRIMITIVES_PREFS @@ -40,6 +49,9 @@ #define HIDC_CUTAWAY_OPACITY_LABEL 0x808a0464 // IDD_EFFECTS_PREFS #define HIDC_CUTAWAY_THICKNESS 0x808a0466 // IDD_EFFECTS_PREFS #define HIDC_CUTAWAY_THICKNESS_LABEL 0x808a0465 // IDD_EFFECTS_PREFS +#define HIDC_DARK_EDGE_COLOR 0x82240540 // IDD_STUD_STYLE_COLORS +#define HIDC_DARK_EDGE_COLOR_CHECK 0x8224053f // IDD_STUD_STYLE_COLORS +#define HIDC_DARK_EDGE_COLOR_RESET 0x82240541 // IDD_STUD_STYLE_COLORS #define HIDC_DEFAULT_COLOR 0x808b03ff // IDD_GENERAL_PREFS #define HIDC_DEFAULT_COLOR_LABEL 0x808b043a // IDD_GENERAL_PREFS #define HIDC_DELETE_PREF_SET 0x860c0477 // IDD_PREFSETS_PREFS @@ -67,6 +79,7 @@ #define HIDC_GREEN_FRONT_FACES 0x80890414 // IDD_GEOMETRY_PREFS #define HIDC_HIDE_LIGHT_DAT 0x808a03f3 // IDD_EFFECTS_PREFS #define HIDC_HIGHLIGHTS 0x808903eb // IDD_GEOMETRY_PREFS +#define HIDC_HIGH_CONTRAST_COLOR 0x860b052f // IDD_PRIMITIVES_PREFS #define HIDC_HI_RES 0x860b050b // IDD_PRIMITIVES_PREFS #define HIDC_IGNORE_FBO 0x808d04ab // IDD_SAVE_OPTIONS #define HIDC_IGNORE_PBUFFER 0x808d04a6 // IDD_SAVE_OPTIONS @@ -75,6 +88,10 @@ #define HIDC_LIGHTING_BOX 0x808a045d // IDD_EFFECTS_PREFS #define HIDC_LIGHTING_QUALITY 0x808a03e9 // IDD_EFFECTS_PREFS #define HIDC_LIGHTING_SUBDUED 0x808a040d // IDD_EFFECTS_PREFS +#define HIDC_LIGHT_DARK_NAME 0x82240532 // IDD_STUD_STYLE_COLORS +#define HIDC_LIGHT_DARK_RESET 0x82240534 // IDD_STUD_STYLE_COLORS +#define HIDC_LIGHT_DARK_SLIDER 0x82240531 // IDD_STUD_STYLE_COLORS +#define HIDC_LIGHT_DARK_VALUE 0x82240533 // IDD_STUD_STYLE_COLORS #define HIDC_LIGHT_DIR 0x808a04ca // IDD_EFFECTS_PREFS #define HIDC_LINE_AA 0x808b0471 // IDD_GENERAL_PREFS #define HIDC_MEMORY_COMBO 0x808b04aa // IDD_GENERAL_PREFS @@ -90,6 +107,9 @@ #define HIDC_PARTS_LIST_DIR 0x808b04f1 // IDD_GENERAL_PREFS #define HIDC_PARTS_LIST_DIR_COMBO 0x808b04ee // IDD_GENERAL_PREFS #define HIDC_PART_BOUNDING_BOXES 0x808904f9 // IDD_GEOMETRY_PREFS +#define HIDC_PART_EDGE_COLOR 0x8224053a // IDD_STUD_STYLE_COLORS +#define HIDC_PART_EDGE_COLOR_CHECK 0x82240539 // IDD_STUD_STYLE_COLORS +#define HIDC_PART_EDGE_COLOR_RESET 0x8224053b // IDD_STUD_STYLE_COLORS #define HIDC_PREFSETS_LABEL 0x860c047d // IDD_PREFSETS_PREFS #define HIDC_PREFSETS_LIST 0x860c0478 // IDD_PREFSETS_PREFS #define HIDC_PREF_SET_HOT_KEY 0x860c0479 // IDD_PREFSETS_PREFS @@ -112,6 +132,10 @@ #define HIDC_REMOVE_HIDDEN_LINES 0x80890411 // IDD_GEOMETRY_PREFS #define HIDC_RESET_TIMES 0x80a70518 // IDD_UPDATES_PREFS #define HIDC_SAME_SCALE 0x808d04c2 // IDD_SAVE_OPTIONS +#define HIDC_SATURATION_NAME 0x82240548 // IDD_STUD_STYLE_COLORS +#define HIDC_SATURATION_RESET 0x8224054a // IDD_STUD_STYLE_COLORS +#define HIDC_SATURATION_SLIDER 0x82240547 // IDD_STUD_STYLE_COLORS +#define HIDC_SATURATION_VALUE 0x82240549 // IDD_STUD_STYLE_COLORS #define HIDC_SAVE_ACTUAL_SIZE 0x808d043e // IDD_SAVE_OPTIONS #define HIDC_SAVE_ACTUAL_SIZE_BOX 0x808d04a9 // IDD_SAVE_OPTIONS #define HIDC_SAVE_DIGITS 0x808d0443 // IDD_SAVE_OPTIONS @@ -157,9 +181,12 @@ #define HIDC_STEREO_SPACING 0x808a0431 // IDD_EFFECTS_PREFS #define HIDC_STEREO_SPACING_LABEL 0x808a0432 // IDD_EFFECTS_PREFS #define HIDC_STIPPLE 0x808a03f0 // IDD_EFFECTS_PREFS -#define HIDC_STUD_STYLE_USE 0x860b0512 // IDD_PRIMITIVES_PREFS -#define HIDC_STUD_STYLE_COMBO 0x860b0513 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_CYLINDER_COLOR 0x82240537 // IDD_STUD_STYLE_COLORS +#define HIDC_STUD_CYLINDER_COLOR_CHECK 0x82240536 // IDD_STUD_STYLE_COLORS +#define HIDC_STUD_CYLINDER_COLOR_RESET 0x82240538 // IDD_STUD_STYLE_COLORS #define HIDC_STUD_QUALITY 0x860b0514 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_STYLE_COMBO 0x860b0513 // IDD_PRIMITIVES_PREFS +#define HIDC_STUD_STYLE_USE 0x860b0512 // IDD_PRIMITIVES_PREFS #define HIDC_TEXMAPS 0x860b0509 // IDD_PRIMITIVES_PREFS #define HIDC_TEXTURE_ANISO 0x860b0515 // IDD_PRIMITIVES_PREFS #define HIDC_TEXTURE_BILINEAR 0x860b0456 // IDD_PRIMITIVES_PREFS diff --git a/LDView.rc b/LDView.rc index 3a9570f28..3eb76a08e 100644 --- a/LDView.rc +++ b/LDView.rc @@ -282,8 +282,11 @@ BEGIN CONTROL "Show control points",IDC_CONDITIONAL_CONTROLS,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,178,87,74,10,0,HIDC_CONDITIONAL_CONTROLS CONTROL "High quality",IDC_QUALITY_LINES,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,169,98,51,10,0,HIDC_QUALITY_LINES CONTROL "Always black",IDC_ALWAYS_BLACK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,169,109,61,10,0,HIDC_ALWAYS_BLACK - LTEXT "Thickness:",IDC_EDGE_THICKNESS_LABEL,166,125,36,8,0,WS_EX_TRANSPARENT,HIDC_EDGE_THICKNESS_LABEL - CONTROL "Slider1",IDC_EDGE_THICKNESS,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,204,120,68,18,0,HIDC_EDGE_THICKNESS + CONTROL "Automate edge line color",IDC_AUTOMATE_EDGE_COLOR_CHECK, + "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,169,120,97,10,0,HIDC_AUTOMATE_EDGE_COLOR_CHECK + PUSHBUTTON "...",IDC_AUTOMATE_EDGE_COLOR,270,118,13,14,0,0,HIDC_AUTOMATE_EDGE_COLOR + LTEXT "Thickness:",IDC_EDGE_THICKNESS_LABEL,166,136,36,8,0,WS_EX_TRANSPARENT,HIDC_EDGE_THICKNESS_LABEL + CONTROL "Slider1",IDC_EDGE_THICKNESS,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,204,131,68,18,0,HIDC_EDGE_THICKNESS PUSHBUTTON "&Reset",IDC_GEOMETRY_RESET,253,231,50,14,WS_GROUP,0,HIDC_GEOMETRY_RESET END @@ -500,7 +503,8 @@ BEGIN LTEXT "nx",IDC_ANISO_LEVEL_LABEL,185,134,26,8,0,0,HIDC_ANISO_LEVEL_LABEL GROUPBOX "&Misc",IDC_PRIMITIVES_MISC_BOX,7,157,296,52,WS_GROUP,WS_EX_TRANSPARENT,HIDC_PRIMITIVES_MISC_BOX CONTROL "Use stud style geometry",IDC_STUD_STYLE_USE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,168,94,10,0,HIDC_STUD_STYLE_USE - COMBOBOX IDC_STUD_STYLE_COMBO,115,166,82,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP,0,HIDC_STUD_STYLE_COMBO + COMBOBOX IDC_STUD_STYLE_COMBO,115,166,106,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP,0,HIDC_STUD_STYLE_COMBO + PUSHBUTTON "...",IDC_HIGH_CONTRAST_COLOR,227,165,13,14,0,0,HIDC_HIGH_CONTRAST_COLOR CONTROL "Low quality studs (faster)",IDC_STUD_QUALITY,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,181,93,10,0,HIDC_STUD_QUALITY CONTROL "Use hi-res primitives when available",IDC_HI_RES,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_GROUP | WS_TABSTOP,15,194,127,10,0,HIDC_HI_RES PUSHBUTTON "&Reset",IDC_PRIMITIVES_RESET,253,231,50,14,WS_GROUP,0,HIDC_PRIMITIVES_RESET @@ -820,6 +824,53 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,98,24,50,14 END +IDD_HIGH_CONTRAST_STUD_COLOR DIALOGEX 0, 0, 247, 167 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "High Contrast Studs" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Edge Line Color",IDC_EDGE_LINE_COLOR_GROUP,13,9,216,32 + CONTROL "",IDC_LIGHT_DARK_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,75,19,64,15,0,HIDC_LIGHT_DARK_SLIDER + LTEXT "Light/Dark Value",IDC_LIGHT_DARK_NAME,17,22,53,8,0,0,HIDC_LIGHT_DARK_NAME + LTEXT "0.00",IDC_LIGHT_DARK_VALUE,145,22,16,8,0,0,HIDC_LIGHT_DARK_VALUE + PUSHBUTTON "Reset",IDC_LIGHT_DARK_RESET,172,19,49,14,WS_GROUP,0,HIDC_LIGHT_DARK_RESET + GROUPBOX "High Contrast",IDC_HIGH_CONTRAST_COLOR_GROUP,13,43,216,92 + CONTROL "Stud cylinder color",IDC_STUD_CYLINDER_COLOR_CHECK, + "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,17,55,75,10,0,HIDC_STUD_CYLINDER_COLOR_CHECK + CONTROL "",IDC_STUD_CYLINDER_COLOR,"Button",BS_OWNERDRAW | BS_BITMAP | BS_NOTIFY | WS_GROUP | WS_TABSTOP,134,52,29,16,0,HIDC_STUD_CYLINDER_COLOR + PUSHBUTTON "Reset",IDC_STUD_CYLINDER_COLOR_RESET,172,53,49,14,WS_GROUP,0,HIDC_STUD_CYLINDER_COLOR_RESET + CONTROL "Parts edge color",IDC_PART_EDGE_COLOR_CHECK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,17,75,68,10,0,HIDC_PART_EDGE_COLOR_CHECK + CONTROL "",IDC_PART_EDGE_COLOR,"Button",BS_OWNERDRAW | BS_BITMAP | BS_NOTIFY | WS_GROUP | WS_TABSTOP,134,72,29,16,0,HIDC_PART_EDGE_COLOR + PUSHBUTTON "Reset",IDC_PART_EDGE_COLOR_RESET,172,73,49,14,WS_GROUP,0,HIDC_PART_EDGE_COLOR_RESET + CONTROL "Black parts edge color",IDC_BLACK_EDGE_COLOR_CHECK, + "Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,18,96,86,10,0,HIDC_BLACK_EDGE_COLOR_CHECK + CONTROL "",IDC_BLACK_EDGE_COLOR,"Button",BS_OWNERDRAW | BS_BITMAP | BS_NOTIFY | WS_GROUP | WS_TABSTOP,134,92,29,16,0,HIDC_BLACK_EDGE_COLOR + PUSHBUTTON "Reset",IDC_BLACK_EDGE_COLOR_RESET,172,93,50,14,WS_GROUP,0,HIDC_BLACK_EDGE_COLOR_RESET + CONTROL "Dark parts edge color",IDC_DARK_EDGE_COLOR_CHECK,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,17,116,85,10,0,HIDC_DARK_EDGE_COLOR_CHECK + CONTROL "",IDC_DARK_EDGE_COLOR,"Button",BS_OWNERDRAW | BS_BITMAP | BS_NOTIFY | WS_GROUP | WS_TABSTOP,134,113,29,16,0,HIDC_DARK_EDGE_COLOR + PUSHBUTTON "Reset",IDC_DARK_EDGE_COLOR_RESET,172,114,50,14,WS_GROUP,0,HIDC_DARK_EDGE_COLOR_RESET + DEFPUSHBUTTON "OK",IDC_HIGH_CONTRAST_STUD_COLOR_OK,116,140,50,14 + PUSHBUTTON "Cancel",IDCANCEL,172,140,50,14 +END + +IDD_AUTOMATE_EDGE_LINE_COLOR DIALOGEX 0, 0, 245, 92 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Automate Edge Line Color" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Edge Line Color",IDC_AUTO_EDGE_LINE_COLOR_GROUP,13,10,219,51 + CONTROL "",IDC_CONTRAST_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,79,20,64,15,0,HIDC_CONTRAST_SLIDER + LTEXT "Contrast",IDC_CONTRAST_NAME,23,23,29,8,0,0,HIDC_CONTRAST_NAME + LTEXT "0.00",IDC_CONTRAST_VALUE,150,23,16,8,0,0,HIDC_CONTRAST_VALUE + PUSHBUTTON "Reset",IDC_CONTRAST_RESET,176,20,49,14,WS_GROUP,0,HIDC_CONTRAST_RESET + CONTROL "",IDC_SATURATION_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,79,40,64,15,0,HIDC_SATURATION_SLIDER + LTEXT "Saturation",IDC_SATURATION_NAME,23,43,34,8,0,0,HIDC_SATURATION_NAME + LTEXT "0.00",IDC_SATURATION_VALUE,150,43,16,8,0,0,HIDC_SATURATION_VALUE + PUSHBUTTON "Reset",IDC_SATURATION_RESET,176,41,49,14,WS_GROUP,0,HIDC_SATURATION_RESET + DEFPUSHBUTTON "OK",IDC_AUTOMATE_EDGE_LINE_COLOR_OK,122,66,50,14 + PUSHBUTTON "Cancel",IDCANCEL,176,66,50,14 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -1080,6 +1131,22 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 39 END + + IDD_HIGH_CONTRAST_STUD_COLOR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 239 + TOPMARGIN, 7 + BOTTOMMARGIN, 160 + END + + IDD_AUTOMATE_EDGE_LINE_COLOR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 238 + TOPMARGIN, 7 + BOTTOMMARGIN, 86 + END END #endif // APSTUDIO_INVOKED @@ -1671,6 +1738,9 @@ BEGIN HIDC_BACKGROUND_COLOR_LABEL "This allows you to set the color used to draw the background behind the model." HIDC_BFC "Enabling this option turns on back-face culling (BFC). BFC is a technique that can improve rendering performance by not drawing the back faces of polygons. (Only BFC-certified parts have their back faces removed.)\r\n\r\nNote that while this can improve rendering performance, it can also slow things down, so don't assume that enabling this will always result in the best performance." HIDC_BFC_BOX "BFC-related settings." + HIDC_BLACK_EDGE_COLOR "Set the edge color for black parts. For example, a common edge color for black parts is white." + HIDC_BLACK_EDGE_COLOR_CHECK "Use this to enable the black parts edge color preference." + HIDC_BLACK_EDGE_COLOR_RESET "This resets the black parts edge color to its default value. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." HIDC_BLUE_NEUTRAL_FACES "This option is only available while BFC is enabled. Enabling it causes the faces of non-BFC-certified polygons to be drawn in blue. This is mainly useful for part authors to allow them to correctly specify which direction faces should face in order to BFC certify their part files." HIDC_BROWSE_CUSTOM_CONFIG "Set the path of the file used for custom config." HIDC_BROWSE_EXPORT_DIR "Set the default directory to use for Exports.\r\n\r\nModel: The default directory is the same directory as the currently loaded model.\r\n\r\nLast Saved Export: The default directory is whatever directory was used last. (The first time you save an export, the default directory is the model's directory.)\r\n\r\nSpecified: The default directory is specified in the field to the right of the drop-down box. Use the Browse... button to browse for a directory, or enter it in the field directly." @@ -1682,6 +1752,10 @@ BEGIN HIDC_COLORS_BOX "Color-related settings." HIDC_CONDITIONAL_CONTROLS "This option is only available if edge lines and conditional lines are enabled. Enabling it causes lines to be drawn from the first point of each conditional line to each of its two control points. This option is primarily designed for part authors, so they can verify that the control points are in the correct location." HIDC_CONDITIONAL_HIGHLIGHTS "This option is only available if edge lines are enabled. Enabling it causes conditional edge lines to be computed and drawn. Conditional edge lines show up as a silhouette of curved surfaces; they are only drawn when they are visually at the edge of the surface from the current viewing angle." + HIDC_CONTRAST_NAME "Set the contrast preference for automated part edge color calculation." + HIDC_CONTRAST_RESET "This resets the contrast preference to its default value. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." + HIDC_CONTRAST_SLIDER "Set the contrast preference for automated part edge color calculation." + HIDC_CONTRAST_VALUE "Diaplay the contrast value." HIDC_CROSS_EYED_STEREO "This option is only available if stereo is enabled. Selecting this sets the stereo mode to cross-eyed stereo. The two images are drawn side by side, with the image for the right eye on the left and the image for the left eye on the right. By crossing your eyes and then focusing, you can see a stereoscopic image. Many people find it difficult or even impossible to focus with their eyes crossed." HIDC_CURVE_QUALITY "This option is only available if primitive substitution is enabled. It adjusts the quality of substituted primitives by changing the number of facets used to draw curved primitives. Changing this from its default value can lead to holes in the model between the substitute primitives and other geometry. Be very careful with this setting. Setting it too high can lead to huge slow-downs. The default setting of 2 (9%) is fine for most models." HIDC_CURVE_QUALITY_LABEL "This option is only available if primitive substitution is enabled. It adjusts the quality of substituted primitives by changing the number of facets used to draw curved primitives. Changing this from its default value can lead to holes in the model between the substitute primitives and other geometry. Be very careful with this setting. Setting it too high can lead to huge slow-downs. The default setting of 2 (9%) is fine for most models." @@ -1695,6 +1769,9 @@ BEGIN HIDC_CUTAWAY_OPACITY_LABEL "This option is only available if wireframe cutaway is enabled. The slider controls the opacity of the wireframe cutaway. When Color is selected as the type of wireframe cutaway to draw this may be fixed at 100% on some graphics cards. Also, when color is selected and sort is not selected in the transparency box, transparent pieces will ignore the opacity setting and be drawn with the standard opacity setting for transparent pieces." HIDC_CUTAWAY_THICKNESS "This option is only available if wireframe cutaway is enabled. The slider controls the thickness of the lines in the wireframe cutaway." HIDC_CUTAWAY_THICKNESS_LABEL "This option is only available if wireframe cutaway is enabled. The slider controls the thickness of the lines in the wireframe cutaway." + HIDC_DARK_EDGE_COLOR "Set the edge color for dark parts. For example, a common edge color for dark parts is light grey." + HIDC_DARK_EDGE_COLOR_CHECK "Use this to enable the dark edge color preference." + HIDC_DARK_EDGE_COLOR_RESET "This resets the dark edge color to its default value. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." HIDC_DEFAULT_COLOR "This allows you to set the default color. Normally this is only visible when you load a part directly. Most models don't ever use this color.\r\n\r\nNote that edge lines on default-colored objects will be black unless you choose the exact RGB value used by one of the standard LDraw colors. The default custom colors in the color panel correspond to the first 16 standard LDraw colors. Resetting the General preferences also resets these colors." HIDC_DEFAULT_COLOR_LABEL "This allows you to set the default color. Normally this is only visible when you load a part directly. Most models don't ever use this color.\r\n\r\nNote that edge lines on default-colored objects will be black unless you choose the exact RGB value used by one of the standard LDraw colors. The default custom colors in the color panel correspond to the first 16 standard LDraw colors. Resetting the General preferences also resets these colors." HIDC_DELETE_PREF_SET "This deletes the currently selected preference set." @@ -1721,6 +1798,7 @@ BEGIN HIDC_GEOMETRY_RESET "This resets all the Geometry preferences to their default values. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." HIDC_GREEN_FRONT_FACES "This option is only available while BFC is enabled. Enabling it causes the front faces of polygons to be drawn in green. This is mainly useful for part authors to allow them to correctly specify which direction faces should face in order to BFC certify their part files." HIDC_HIDE_LIGHT_DAT "Selecting this causes LDView to not display the geometry from LIGHT.DAT parts. Since the geometry is a small set of 3D coordinate axes, you often don't want to see it." + HIDC_HIGH_CONTRAST_COLOR "Display the High Contrast Stud Color settings dialog." HIDC_HIGHLIGHTS "Enabling this option causes the edge lines that outline all the pieces to be drawn. It is recommended that you disable the seam width option if you enable this option." HIDC_HI_RES "Enabling this option causes LDView to attempt to load hi-res versions of primitives before loading the standard ones. The hi-res primitives are otherwise known as 48-sided primitives, because they approximate circular features with 48-sided features." HIDC_IGNORE_FBO "Enabling this option disables the use of a framebuffer object for snapshot rendering. Use of a framebuffer object can result in a corrupt image on certain video cards with certain video drivers. If your snapshots are corrupted, enable this. Otherwise, leave it disabled." @@ -1729,6 +1807,10 @@ BEGIN HIDC_LDRAW_DIR "This contains the full path to the LDraw directory.\r\n\r\nNote: Even if the LDraw Zip is set, this still must be set, and will be used to download unofficial parts from ldraw.org." HIDC_LDRAW_RESET "This resets all the LDraw preferences to their default values. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." HIDC_LDRAW_ZIP "This contains the full path to the LDraw Parts Library Zip.\r\n\r\nNote: If a file named ldrawunf.zip exists in the same directory as this file, it will automatically be searched for unofficial parts." + HIDC_LIGHT_DARK_NAME "Set the light dark factor preference for high contrast part color calculation." + HIDC_LIGHT_DARK_RESET "This resets the light dark factor to its default value. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." + HIDC_LIGHT_DARK_SLIDER "Set the light dark factor preference for high contrast part color calculation." + HIDC_LIGHT_DARK_VALUE "Diaplay the light dark factor value." HIDC_LIGHTING "Enabling this option enables lighting. If you disable lighting, it is strongly recommended that you enable edge lines, unless you are in wireframe mode. (Both edge lines and wireframe mode are on the Geometry tab.)" HIDC_LIGHTING_BOX "Lighting-related settings." HIDC_LIGHTING_QUALITY "This option is only available if lighting is enabled. Selecting this enables high quality lighting. The easiest way to see the difference between having this option on and off is with a baseplate. If you angle a baseplate until the specular highlight becomes visible (it gets shiny), and then switch back and forth, you will see that the highlight is located in a specific location when high quality lighting is enabled, and covers the entire surface when it is disabled. Enabling this can significantly decrease performance, especially with large models." @@ -1748,6 +1830,9 @@ BEGIN HIDC_PARTS_LIST_DIR "Set the default directory to use for Parts Lists.\r\n\r\nModel: The default directory is the same directory as the currently loaded model.\r\n\r\nLast Saved Parts List: The default directory is whatever directory was used last. (The first time you save a parts list, the default directory is the model's directory.)\r\n\r\nSpecified: The default directory is specified in the field to the right of the drop-down box. Use the Browse... button to browse for a directory, or enter it in the field directly." HIDC_PARTS_LIST_DIR_COMBO "Set the default directory to use for Parts Lists.\r\n\r\nModel: The default directory is the same directory as the currently loaded model.\r\n\r\nLast Saved Parts List: The default directory is whatever directory was used last. (The first time you save a parts list, the default directory is the model's directory.)\r\n\r\nSpecified: The default directory is specified in the field to the right of the drop-down box. Use the Browse... button to browse for a directory, or enter it in the field directly." HIDC_PART_BOUNDING_BOXES "Enabling this option makes it so that all parts in the model are drawn as just bounding boxes. A bounding box is the minimum axis-aligned box that can completely contain the part. Geometry that isn't detected as being inside a part is drawn normally." + HIDC_PART_EDGE_COLOR "Set the part edge color. For example, a common edge color is dark grey." + HIDC_PART_EDGE_COLOR_CHECK "Use this to enable the part edge color preference." + HIDC_PART_EDGE_COLOR_RESET "This resets the part edge color to its default value. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." HIDC_PREFSETS_LABEL "This list shows all of the available preference sets. Until you create new ones, there is only one item in this list, named . Selecting an item from this list will cause LDView to use the preferences stored in that set after you hit Apply. If you have made any changes to preferences on other tabs and select a new preference set, it will prompt you whether you want to apply those changes, abandon them, or cancel your selection." HIDC_PREFSETS_LIST "This list shows all of the available preference sets. Until you create new ones, there is only one item in this list, named . Selecting an item from this list will cause LDView to use the preferences stored in that set after you hit Apply. If you have made any changes to preferences on other tabs and select a new preference set, it will prompt you whether you want to apply those changes, abandon them, or cancel your selection." HIDC_PREF_SET_HOT_KEY "This allows you to assign a hot key to the currently selected preference set." @@ -1770,6 +1855,10 @@ BEGIN HIDC_REMOVE_HIDDEN_LINES "This option is only available if wireframe drawing is enabled. Enabling it causes the solid (non-transparent) portions of the model to hide lines that are behind them, even though these portions themselves aren't actually drawn." HIDC_RESET_TIMES "Clears the recorded time for last download of unofficial parts. This forces LDView to check the LDraw parts tracker for all unofficial parts, instead of waiting the specified number of days.\r\n\r\nPlease note: Unlike other settings, hitting this happens immediately; you do not have to hit Apply or OK." HIDC_SAME_SCALE "This option is only available if all steps are enabled. Enabling it causes all step snapshots to be generated using the same scale." + HIDC_SATURATION_NAME "Set the saturation preference for automated part edge color calculation." + HIDC_SATURATION_RESET "This resets the saturation preference to its default value. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." + HIDC_SATURATION_SLIDER "Set the saturation preference for automated part edge color calculation." + HIDC_SATURATION_VALUE "Diaplay the saturation value." HIDC_SAVE_ACTUAL_SIZE "Enabling this option allows you to specify a width and height for the snapshot image. Otherwise, the snapshot created will have the same dimensions as the LDView window." HIDC_SAVE_ACTUAL_SIZE_BOX "Settings related to the image size." HIDC_SAVE_DIGITS "This option is only available when save snapshot series is enabled. It controls the number of digits in the number that is appended to the filename. Zeroes are added before the number to make up the number of digits you select here. For example, if you select 3 here, and the number is 5, then 005 will be used in the filename instead of just 5." @@ -1816,6 +1905,9 @@ BEGIN HIDC_STIPPLE "Enabling this option causes transparent shapes to be drawn using a stipple (checkerboard) pattern. This may be significantly faster on some video hardware, but with potentially reduced quality. Using the stipple pattern totally eliminates the errors that may occur where far transparent objects are drawn in front of closer ones. This option is mutually exclusive with the sort option." HIDC_STUD_STYLE_USE "Enabling this option gives the user the ability to select the displayed stud style geometry. When unchecked, Texture studs settings will be respected." HIDC_STUD_STYLE_COMBO "This allows you to select the stud style display when Use stud style geometry preference is checked." + HIDC_STUD_CYLINDER_COLOR "Set the stud cylinder high contrast color. For example, a common high contrast stud cylinder color is black." + HIDC_STUD_CYLINDER_COLOR_CHECK "Use this to enable the stud cylinder color preference." + HIDC_STUD_CYLINDER_COLOR_RESET "This resets the stud cylinder color to its default value. As with all other preference changes, you must hit OK or Apply for the reset values to go into effect." HIDC_STUD_QUALITY "Enabling this option switches to using the low-resolution stud files instead of the normal-resolution stud files. This can produce significantly faster rendering." HIDC_TEXMAPS "Enabling this option turns on support for the LDraw TEXMAP extension. Disabling it will cause LDView to use any fallback geometry included in the LDraw file." HIDC_TEXTURE_ANISO "This option is only available if primitive substitution and texture studs are both enabled, and your video card supports it. Selecting it causes anisotropic texture filtering to be used. When anisotropic filtering is selected, you can pick the filtering level on the slider to the right of the radio button. This is the highest quality texture filtering." diff --git a/LDViewPreferences.cpp b/LDViewPreferences.cpp index 3316f6521..a0ad6ed59 100644 --- a/LDViewPreferences.cpp +++ b/LDViewPreferences.cpp @@ -64,7 +64,7 @@ ucstring LDViewPreferences::ldviewPath; LDViewPreferences::LDViewPreferences( HINSTANCE hInstance, - LDViewWindow *ldviewWindow, + LDViewWindow* ldviewWindow, LDrawModelViewer* modelViewer) : CUIPropertySheet(ls(_UC("LDViewPreferences")), hInstance) , modelViewer(modelViewer != NULL ? ((LDrawModelViewer*)modelViewer->retain()) : NULL) @@ -82,6 +82,18 @@ LDViewPreferences::LDViewPreferences( , hBackgroundColorButton(NULL) , hDefaultColorBitmap(NULL) , hDefaultColorButton(NULL) + , hStudCylinderColorBitmap(NULL) + , hStudCylinderColorButton(NULL) + , hStudCylinderColorReset(NULL) + , hPartEdgeColorBitmap(NULL) + , hPartEdgeColorButton(NULL) + , hPartEdgeColorReset(NULL) + , hBlackEdgeColorBitmap(NULL) + , hBlackEdgeColorButton(NULL) + , hBlackEdgeColorReset(NULL) + , hDarkEdgeColorBitmap(NULL) + , hDarkEdgeColorButton(NULL) + , hDarkEdgeColorReset(NULL) , hMouseOverButton(NULL) , origButtonWindowProc(NULL) , hButtonColorDC(NULL) @@ -96,6 +108,17 @@ LDViewPreferences::LDViewPreferences( , setActiveWarned(false) , checkAbandon(true) , hButtonTheme(NULL) + , hAutomateEdgeColorButton(NULL) + , hHighContrastColorButton(NULL) + , hHighContrastStudColor(NULL) + , hAutomateEdgeLineColor(NULL) + , partEdgeLightDarkValue(0.0f) + , partEdgeContrastValue(0.0f) + , partEdgeSaturationValue(0.0f) + , studCylinderColorEnabled(false) + , partEdgeColorEnabled(false) + , blackEdgeColorEnabled(false) + , darkEdgeColorEnabled(false) // hTabTheme(NULL) { WillyMessage("\n\n\n"); @@ -487,6 +510,42 @@ COLORREF LDViewPreferences::getDefaultColor(void) return RGB((BYTE)r, (BYTE)g, (BYTE)b); } +void LDViewPreferences::getStudCylinderColor(void) +{ + int r, g, b, a; + + ldPrefs->getStudCylinderColor(r, g, b, a); + crStudCylinderColor = RGB((BYTE)r, (BYTE)g, (BYTE)b); + studCylinderColorEnabled = ldPrefs->getStudCylinderColorEnabled(); +} + +void LDViewPreferences::getPartEdgeColor(void) +{ + int r, g, b, a; + + ldPrefs->getPartEdgeColor(r, g, b, a); + crPartEdgeColor = RGB((BYTE)r, (BYTE)g, (BYTE)b); + partEdgeColorEnabled = ldPrefs->getPartEdgeColorEnabled(); +} + +void LDViewPreferences::getBlackEdgeColor(void) +{ + int r, g, b, a; + + ldPrefs->getBlackEdgeColor(r, g, b, a); + crBlackEdgeColor = RGB((BYTE)r, (BYTE)g, (BYTE)b); + blackEdgeColorEnabled = ldPrefs->getBlackEdgeColorEnabled(); +} + +void LDViewPreferences::getDarkEdgeColor(void) +{ + int r, g, b, a; + + ldPrefs->getDarkEdgeColor(r, g, b, a); + crDarkEdgeColor = RGB((BYTE)r, (BYTE)g, (BYTE)b); + darkEdgeColorEnabled = ldPrefs->getDarkEdgeColorEnabled(); +} + void LDViewPreferences::setDrawConditionalHighlights(bool value) { if (value != ldPrefs->getDrawConditionalHighlights()) @@ -1020,6 +1079,23 @@ BOOL LDViewPreferences::doDialogNotify(HWND hDlg, int controlId, return FALSE; } } + else if (hDlg == hHighContrastStudColor) + { + if (controlId == IDC_LIGHT_DARK_SLIDER) + { + enableApply(hPrimitivesPage); + setStudStyleSliderValue(hDlg, controlId); + } + } + else if (hDlg == hAutomateEdgeLineColor) + { + if (controlId == IDC_CONTRAST_SLIDER || + controlId == IDC_SATURATION_SLIDER) + { + enableApply(hGeometryPage); + setStudStyleSliderValue(hDlg, controlId); + } + } } else if (notification->code == CBN_SELCHANGE) { @@ -1339,6 +1415,37 @@ void LDViewPreferences::setupDefaultColorButton(void) getDefaultColor()); } +BOOL LDViewPreferences::highContrastStudColorInit(HWND hDlg) +{ + UCCHAR label[16]; + hHighContrastStudColor = hDlg; + + CUIDialog::trackBarSetup(hDlg, IDC_LIGHT_DARK_SLIDER, 0, 10, 1, + sliderPosFromStudStyleVal(partEdgeLightDarkValue)); + setStudStyleSliderValue(hDlg, IDC_LIGHT_DARK_SLIDER); + + setupStudStyleColorButton(hDlg, IDC_STUD_CYLINDER_COLOR); + setupStudStyleColorButton(hDlg, IDC_PART_EDGE_COLOR); + setupStudStyleColorButton(hDlg, IDC_BLACK_EDGE_COLOR); + setupStudStyleColorButton(hDlg, IDC_DARK_EDGE_COLOR); + return TRUE; +} + +BOOL LDViewPreferences::automateEdgeLineColorInit(HWND hDlg) +{ + UCCHAR label[16]; + hAutomateEdgeLineColor = hDlg; + + CUIDialog::trackBarSetup(hDlg, IDC_CONTRAST_SLIDER, 0, 10, 1, + sliderPosFromStudStyleVal(partEdgeContrastValue)); + setStudStyleSliderValue(hDlg, IDC_CONTRAST_SLIDER); + + CUIDialog::trackBarSetup(hDlg, IDC_SATURATION_SLIDER, 0, 10, 1, + sliderPosFromStudStyleVal(partEdgeSaturationValue)); + setStudStyleSliderValue(hDlg, IDC_SATURATION_SLIDER); + return TRUE; +} + LRESULT CALLBACK LDViewPreferences::staticIconButtonProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -1992,6 +2099,10 @@ void LDViewPreferences::applyGeometryChanges(void) IDC_QUALITY_LINES)); ldPrefs->setBlackHighlights(getCheck(hGeometryPage, IDC_ALWAYS_BLACK)); + ldPrefs->setAutomateEdgeColor(getCheck(hGeometryPage, + IDC_AUTOMATE_EDGE_COLOR_CHECK)); + ldPrefs->setPartEdgeContrast(partEdgeContrastValue); + ldPrefs->setPartEdgeSaturation(partEdgeSaturationValue); } ldPrefs->setEdgeThickness(CUIDialog::trackBarGetPos(hGeometryPage, IDC_EDGE_THICKNESS)); @@ -2087,6 +2198,40 @@ void LDViewPreferences::applyPrimitivesChanges(void) ldPrefs->setUseStudStyle(getCheck(hPrimitivesPage, IDC_STUD_STYLE_USE)); ldPrefs->setStudStyle(CUIDialog::comboGetCurSel(hPrimitivesPage, IDC_STUD_STYLE_COMBO)); + ldPrefs->setPartColorLDIndex(partEdgeLightDarkValue); + ldPrefs->setStudCylinderColorEnabled(studCylinderColorEnabled); + ldPrefs->setPartEdgeColorEnabled(partEdgeColorEnabled); + ldPrefs->setBlackEdgeColorEnabled(blackEdgeColorEnabled); + ldPrefs->setDarkEdgeColorEnabled(darkEdgeColorEnabled); + int r, g, b; + if (studCylinderColorEnabled) + { + r = GetRValue(crStudCylinderColor); + g = GetGValue(crStudCylinderColor); + b = GetBValue(crStudCylinderColor); + ldPrefs->setStudCylinderColor(r, g, b, 255); + } + if (partEdgeColorEnabled) + { + r = GetRValue(crPartEdgeColor); + g = GetGValue(crPartEdgeColor); + b = GetBValue(crPartEdgeColor); + ldPrefs->setPartEdgeColor(r, g, b, 255); + } + if (blackEdgeColorEnabled) + { + r = GetRValue(crBlackEdgeColor); + g = GetGValue(crBlackEdgeColor); + b = GetBValue(crBlackEdgeColor); + ldPrefs->setBlackEdgeColor(r, g, b, 255); + } + if (darkEdgeColorEnabled) + { + r = GetRValue(crDarkEdgeColor); + g = GetGValue(crDarkEdgeColor); + b = GetBValue(crDarkEdgeColor); + ldPrefs->setDarkEdgeColor(r, g, b, 255); + } ldPrefs->setQualityStuds(!getCheck(hPrimitivesPage, IDC_STUD_QUALITY)); ldPrefs->setHiResPrimitives(getCheck(hPrimitivesPage, IDC_HI_RES)); ldPrefs->applyPrimitivesSettings(); @@ -2200,6 +2345,26 @@ void LDViewPreferences::chooseDefaultColor(void) ldPrefs->setDefaultColor(r, g, b); } +void LDViewPreferences::chooseStudCylinderColor(void) +{ + chooseColor(hStudCylinderColorButton, hStudCylinderColorBitmap, crStudCylinderColor); +} + +void LDViewPreferences::choosePartEdgeColor(void) +{ + chooseColor(hPartEdgeColorButton, hPartEdgeColorBitmap, crPartEdgeColor); +} + +void LDViewPreferences::chooseBlackEdgeColor(void) +{ + chooseColor(hBlackEdgeColorButton, hBlackEdgeColorBitmap, crBlackEdgeColor); +} + +void LDViewPreferences::chooseDarkEdgeColor(void) +{ + chooseColor(hDarkEdgeColorButton, hDarkEdgeColorBitmap, crDarkEdgeColor); +} + void LDViewPreferences::chooseColor(HWND hColorButton, HBITMAP hColorBitmap, COLORREF &color) { @@ -2362,6 +2527,15 @@ void LDViewPreferences::doGeometryClick(int controlId, HWND /*controlHWnd*/) case IDC_SEAMS: doSeams(); break; + case IDC_ALWAYS_BLACK: + doAlwaysBlack(); + break; + case IDC_AUTOMATE_EDGE_COLOR_CHECK: + doAutomateEdgeColorCheck(); + break; + case IDC_AUTOMATE_EDGE_COLOR: + doAutomateEdgeColor(); + break; case IDC_GEOMETRY_RESET: ldPrefs->loadDefaultGeometrySettings(false); setupGeometryPage(); @@ -2487,6 +2661,22 @@ void LDViewPreferences::doNewPrefSet(void) } } +void LDViewPreferences::doHighContrastColor(void) +{ + if (DialogBoxParam(getLanguageModule(), MAKEINTRESOURCE(IDD_HIGH_CONTRAST_STUD_COLOR), + hPropSheet, staticDialogProc, (LPARAM)this) == IDOK) + { + } +} + +void LDViewPreferences::doAutomateEdgeColor(void) +{ + if (DialogBoxParam(getLanguageModule(), MAKEINTRESOURCE(IDD_AUTOMATE_EDGE_LINE_COLOR), + hPropSheet, staticDialogProc, (LPARAM)this) == IDOK) + { + } +} + ucstring LDViewPreferences::getHotKey(int index) { char key[128]; @@ -2706,6 +2896,180 @@ void LDViewPreferences::doOtherClick(HWND hDlg, int controlId, { EndDialog(hDlg, controlId); } + else if (hDlg == hHighContrastStudColor) + { + if (controlId == IDC_HIGH_CONTRAST_STUD_COLOR_OK) + { + EndDialog(hDlg, IDOK); + } + else if (controlId == IDC_STUD_CYLINDER_COLOR_CHECK) + { + enableApply(hPrimitivesPage); + studCylinderColorEnabled = getCheck(hDlg, controlId); + EnableWindow(hStudCylinderColorButton, studCylinderColorEnabled); + EnableWindow(hStudCylinderColorReset, studCylinderColorEnabled); + } + else if (controlId == IDC_STUD_CYLINDER_COLOR) + { + chooseStudCylinderColor(); + } + else if (controlId == IDC_PART_EDGE_COLOR_CHECK) + { + enableApply(hPrimitivesPage); + partEdgeColorEnabled = getCheck(hDlg, controlId); + EnableWindow(hPartEdgeColorButton, partEdgeColorEnabled); + EnableWindow(hPartEdgeColorReset, partEdgeColorEnabled); + } + else if (controlId == IDC_PART_EDGE_COLOR) + { + choosePartEdgeColor(); + } + else if (controlId == IDC_BLACK_EDGE_COLOR_CHECK) + { + enableApply(hPrimitivesPage); + blackEdgeColorEnabled = getCheck(hDlg, controlId); + EnableWindow(hBlackEdgeColorButton, blackEdgeColorEnabled); + EnableWindow(hBlackEdgeColorReset, blackEdgeColorEnabled); + } + else if (controlId == IDC_BLACK_EDGE_COLOR) + { + chooseBlackEdgeColor(); + } + else if (controlId == IDC_DARK_EDGE_COLOR_CHECK) + { + enableApply(hPrimitivesPage); + darkEdgeColorEnabled = getCheck(hDlg, controlId); + EnableWindow(hDarkEdgeColorButton, darkEdgeColorEnabled); + EnableWindow(hDarkEdgeColorReset, darkEdgeColorEnabled); + } + else if (controlId == IDC_DARK_EDGE_COLOR) + { + chooseDarkEdgeColor(); + } + else if (controlId == IDC_LIGHT_DARK_RESET) + { + CUIDialog::trackBarSetup(hDlg, IDC_LIGHT_DARK_SLIDER, 0, 10, 1, + sliderPosFromStudStyleVal(ldPrefs->getPartColorLDIndex())); + setStudStyleSliderValue(hDlg, IDC_LIGHT_DARK_SLIDER); + } + else if (controlId == IDC_STUD_CYLINDER_COLOR_RESET) + { + setupStudStyleColorButton(hDlg, IDC_STUD_CYLINDER_COLOR); + } + else if (controlId == IDC_PART_EDGE_COLOR_RESET) + { + setupStudStyleColorButton(hDlg, IDC_PART_EDGE_COLOR); + } + else if (controlId == IDC_BLACK_EDGE_COLOR_RESET) + { + setupStudStyleColorButton(hDlg, IDC_BLACK_EDGE_COLOR); + } + else if (controlId == IDC_DARK_EDGE_COLOR_RESET) + { + setupStudStyleColorButton(hDlg, IDC_DARK_EDGE_COLOR); + } + } + else if (hDlg == hAutomateEdgeLineColor) + { + if (controlId == IDC_AUTOMATE_EDGE_LINE_COLOR_OK) + { + EndDialog(hDlg, IDOK); + } + else if (controlId == IDC_CONTRAST_RESET) + { + CUIDialog::trackBarSetup(hDlg, IDC_CONTRAST_SLIDER, 0, 10, 1, + sliderPosFromStudStyleVal(ldPrefs->getPartEdgeContrast())); + setStudStyleSliderValue(hDlg, IDC_CONTRAST_SLIDER); + } + else if (controlId == IDC_SATURATION_RESET) + { + CUIDialog::trackBarSetup(hDlg, IDC_SATURATION_SLIDER, 0, 10, 1, + sliderPosFromStudStyleVal(ldPrefs->getPartEdgeSaturation())); + setStudStyleSliderValue(hDlg, IDC_SATURATION_SLIDER); + } + } +} + +void LDViewPreferences::setStudStyleSliderValue(HWND hDlg, int controlId) +{ + UCCHAR label[16]; + HWND hSliderValue = NULL; + HWND hSliderControl = GetDlgItem(hDlg, controlId); + float value = studStyleValFromSliderPos(trackBarGetPos(hSliderControl)); + if (controlId == IDC_LIGHT_DARK_SLIDER) + { + partEdgeLightDarkValue = value; + hSliderValue = GetDlgItem(hDlg, IDC_LIGHT_DARK_VALUE); + } + else if (controlId == IDC_CONTRAST_SLIDER) + { + partEdgeContrastValue = value; + hSliderValue = GetDlgItem(hDlg, IDC_CONTRAST_VALUE); + } + else if (controlId == IDC_SATURATION_SLIDER) + { + partEdgeSaturationValue = value; + hSliderValue = GetDlgItem(hDlg, IDC_SATURATION_VALUE); + } + if (hSliderValue) + { + if (value > 0) + { + sucprintf(label, COUNT_OF(label), _UC("%.2f"), value); + } + else + { + label[0] = 0; + } + CUIDialog::windowSetText(hSliderValue, label); + } +} + +void LDViewPreferences::setupStudStyleColorButton(HWND hDlg, int controlId) +{ + switch (controlId) + { + case IDC_STUD_CYLINDER_COLOR: + setupColorButton(hDlg, hStudCylinderColorButton, controlId, hStudCylinderColorBitmap, + crStudCylinderColor); + hStudCylinderColorReset = GetDlgItem(hDlg, IDC_STUD_CYLINDER_COLOR_RESET); + studCylinderColorEnabled = ldPrefs->getStudCylinderColorEnabled(); + if (getCheck(hDlg, IDC_STUD_CYLINDER_COLOR_CHECK) != studCylinderColorEnabled) + setCheck(hDlg, IDC_STUD_CYLINDER_COLOR_CHECK, studCylinderColorEnabled); + EnableWindow(hStudCylinderColorButton, studCylinderColorEnabled); + EnableWindow(hStudCylinderColorReset, studCylinderColorEnabled); + break; + case IDC_PART_EDGE_COLOR: + setupColorButton(hDlg, hPartEdgeColorButton, controlId, hPartEdgeColorBitmap, + crPartEdgeColor); + hPartEdgeColorReset = GetDlgItem(hDlg, IDC_PART_EDGE_COLOR_RESET); + partEdgeColorEnabled = ldPrefs->getPartEdgeColorEnabled(); + if (getCheck(hDlg, IDC_PART_EDGE_COLOR_CHECK) != partEdgeColorEnabled) + setCheck(hDlg, IDC_PART_EDGE_COLOR_CHECK, partEdgeColorEnabled); + EnableWindow(hPartEdgeColorButton, partEdgeColorEnabled); + EnableWindow(hPartEdgeColorReset, partEdgeColorEnabled); + break; + case IDC_BLACK_EDGE_COLOR: + setupColorButton(hDlg, hBlackEdgeColorButton, controlId, hBlackEdgeColorBitmap, + crBlackEdgeColor); + hBlackEdgeColorReset = GetDlgItem(hDlg, IDC_BLACK_EDGE_COLOR_RESET); + blackEdgeColorEnabled = ldPrefs->getBlackEdgeColorEnabled(); + if (getCheck(hDlg, IDC_BLACK_EDGE_COLOR_CHECK) != blackEdgeColorEnabled) + setCheck(hDlg, IDC_BLACK_EDGE_COLOR_CHECK, blackEdgeColorEnabled); + EnableWindow(hBlackEdgeColorButton, blackEdgeColorEnabled); + EnableWindow(hBlackEdgeColorReset, blackEdgeColorEnabled); + break; + case IDC_DARK_EDGE_COLOR: + setupColorButton(hDlg, hDarkEdgeColorButton, controlId, hDarkEdgeColorBitmap, + crDarkEdgeColor); + hDarkEdgeColorReset = GetDlgItem(hDlg, IDC_DARK_EDGE_COLOR_RESET); + darkEdgeColorEnabled = ldPrefs->getDarkEdgeColorEnabled(); + if (getCheck(hDlg, IDC_DARK_EDGE_COLOR_CHECK) != darkEdgeColorEnabled) + setCheck(hDlg, IDC_DARK_EDGE_COLOR_CHECK, darkEdgeColorEnabled); + EnableWindow(hDarkEdgeColorButton, darkEdgeColorEnabled); + EnableWindow(hDarkEdgeColorReset, darkEdgeColorEnabled); + break; + } } void LDViewPreferences::setAniso(int value) @@ -2760,6 +3124,12 @@ void LDViewPreferences::doPrimitivesClick(int controlId, HWND /*controlHWnd*/) EnableWindow(hAnisoLevelSlider, TRUE); } break; + case IDC_STUD_STYLE_USE: + doStudStyle(); + break; + case IDC_HIGH_CONTRAST_COLOR: + doHighContrastColor(); + break; case IDC_PRIMITIVES_RESET: ldPrefs->loadDefaultPrimitivesSettings(false); setupPrimitivesPage(); @@ -2865,6 +3235,9 @@ DWORD LDViewPreferences::doComboSelChange(HWND hPage, int controlId, enableApply(hPage); break; case IDC_STUD_STYLE_COMBO: + ldPrefs->setStudStyle(CUIDialog::comboGetCurSel(hPrimitivesPage, + IDC_STUD_STYLE_COMBO)); + doStudStyle(); enableApply(hPage); break; case IDC_SNAPSHOTS_DIR_COMBO: @@ -3012,6 +3385,20 @@ void LDViewPreferences::doConditionals(void) } } +void LDViewPreferences::doAlwaysBlack(void) +{ + EnableWindow(hAutomateEdgeColorCheck, !getCheck(hGeometryPage, + IDC_ALWAYS_BLACK)); +} + +void LDViewPreferences::doAutomateEdgeColorCheck(void) +{ + EnableWindow(hAutomateEdgeColorButton, getCheck(hGeometryPage, + IDC_AUTOMATE_EDGE_COLOR_CHECK)); + EnableWindow(hAlwaysBlackButton, !getCheck(hGeometryPage, + IDC_AUTOMATE_EDGE_COLOR_CHECK)); +} + void LDViewPreferences::setCheck(HWND hPage, int buttonId, bool value) { CUIDialog::buttonSetChecked(hPage, buttonId, value); @@ -3171,6 +3558,15 @@ void LDViewPreferences::updateTexmapsEnabled(void) void LDViewPreferences::doTextureStuds(void) { updateTextureFilteringEnabled(); + if (getCheck(hPrimitivesPage, IDC_TEXTURE_STUDS)) + { + setCheck(hPrimitivesPage, IDC_STUD_STYLE_USE, FALSE); + disableStudStyle(); + } + else + { + enableStudStyle(); + } } void LDViewPreferences::doTexmaps(void) @@ -3267,6 +3663,46 @@ void LDViewPreferences::setupMemoryUsage(void) CUIDialog::comboSetCurSel(hGeneralPage, IDC_MEMORY_COMBO, ldPrefs->getMemoryUsage()); } +void LDViewPreferences::enableStudStyle(void) +{ + hHighContrastColorButton = GetDlgItem(hPrimitivesPage, IDC_HIGH_CONTRAST_COLOR); + EnableWindow(GetDlgItem(hPrimitivesPage, IDC_STUD_STYLE_USE), TRUE); + EnableWindow(GetDlgItem(hPrimitivesPage, IDC_STUD_STYLE_COMBO), TRUE); + EnableWindow(hHighContrastColorButton, ldPrefs->getStudStyle() > 5); +} + +void LDViewPreferences::disableStudStyle(void) +{ + EnableWindow(GetDlgItem(hPrimitivesPage, IDC_STUD_STYLE_USE), FALSE); + EnableWindow(GetDlgItem(hPrimitivesPage, IDC_STUD_STYLE_COMBO), FALSE); + EnableWindow(GetDlgItem(hPrimitivesPage, IDC_HIGH_CONTRAST_COLOR), FALSE); +} + +void LDViewPreferences::doStudStyle(void) +{ + if (getCheck(hPrimitivesPage, IDC_STUD_STYLE_USE)) + { + setCheck(hPrimitivesPage, IDC_TEXTURE_STUDS, false); + EnableWindow(hTextureStudsButton, FALSE); + disableTextureFiltering(); + } + else + { + setCheck(hPrimitivesPage, IDC_TEXTURE_STUDS, ldPrefs->getTextureStuds()); + EnableWindow(hTextureStudsButton, TRUE); + updateTextureFilteringEnabled(); + } + if (!getCheck(hPrimitivesPage, IDC_TEXTURE_STUDS)) + { + enableStudStyle(); + } + partEdgeLightDarkValue = ldPrefs->getPartColorLDIndex(); + getStudCylinderColor(); + getPartEdgeColor(); + getBlackEdgeColor(); + getDarkEdgeColor(); +} + void LDViewPreferences::setupStudStyle(void) { CUIDialog::comboResetContent(hPrimitivesPage, IDC_STUD_STYLE_COMBO); @@ -3276,7 +3712,12 @@ void LDViewPreferences::setupStudStyle(void) CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("RaisedFlat"))); CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("RaisedRounded"))); CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("SubtleRounded"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("HighContrast"))); + CUIDialog::comboAddString(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ls(_UC("HighContrastSingleWire"))); CUIDialog::comboSetCurSel(hPrimitivesPage, IDC_STUD_STYLE_COMBO, ldPrefs->getStudStyle()); + + setCheck(hPrimitivesPage, IDC_STUD_STYLE_USE, ldPrefs->getUseStudStyle()); + doStudStyle(); } void LDViewPreferences::updateSaveDir( @@ -3921,9 +4362,11 @@ void LDViewPreferences::enableEdges(void) EnableWindow(hConditionalHighlightsButton, TRUE); EnableWindow(hEdgesOnlyButton, TRUE); EnableWindow(hQualityLinesButton, TRUE); - EnableWindow(hAlwaysBlackButton, TRUE); + EnableWindow(hAlwaysBlackButton, !ldPrefs->getAutomateEdgeColor()); EnableWindow(hEdgeThicknessLabel, TRUE); EnableWindow(hEdgeThicknessSlider, TRUE); + EnableWindow(hAutomateEdgeColorCheck, !ldPrefs->getBlackHighlights()); + EnableWindow(hAutomateEdgeColorButton, ldPrefs->getAutomateEdgeColor()); if (ldPrefs->getDrawConditionalHighlights()) { enableConditionals(); @@ -3932,11 +4375,14 @@ void LDViewPreferences::enableEdges(void) { disableConditionals(); } + setCheck(hGeometryPage, IDC_AUTOMATE_EDGE_COLOR_CHECK, ldPrefs->getAutomateEdgeColor() && + !ldPrefs->getBlackHighlights()); setCheck(hGeometryPage, IDC_EDGES_ONLY, ldPrefs->getEdgesOnly()); setCheck(hGeometryPage, IDC_CONDITIONAL_HIGHLIGHTS, ldPrefs->getDrawConditionalHighlights()); setCheck(hGeometryPage, IDC_QUALITY_LINES, ldPrefs->getUsePolygonOffset()); - setCheck(hGeometryPage, IDC_ALWAYS_BLACK, ldPrefs->getBlackHighlights()); + setCheck(hGeometryPage, IDC_ALWAYS_BLACK, ldPrefs->getBlackHighlights() && + !ldPrefs->getAutomateEdgeColor()); } void LDViewPreferences::disableEdges(void) @@ -3947,6 +4393,8 @@ void LDViewPreferences::disableEdges(void) EnableWindow(hAlwaysBlackButton, FALSE); EnableWindow(hEdgeThicknessLabel, FALSE); EnableWindow(hEdgeThicknessSlider, FALSE); + EnableWindow(hAutomateEdgeColorCheck, FALSE); + EnableWindow(hAutomateEdgeColorButton, FALSE); disableConditionals(); setCheck(hGeometryPage, IDC_EDGES_ONLY, false); setCheck(hGeometryPage, IDC_CONDITIONAL_HIGHLIGHTS, false); @@ -3963,6 +4411,12 @@ void LDViewPreferences::setupEdgeLines(void) hShowAllConditionalButton = GetDlgItem(hGeometryPage, IDC_ALL_CONDITIONAL); hShowConditionalControlsButton = GetDlgItem(hGeometryPage, IDC_CONDITIONAL_CONTROLS); + hAutomateEdgeColorCheck = GetDlgItem(hGeometryPage, + IDC_AUTOMATE_EDGE_COLOR_CHECK); + hAutomateEdgeColorButton = GetDlgItem(hGeometryPage, + IDC_AUTOMATE_EDGE_COLOR); + partEdgeContrastValue = ldPrefs->getPartEdgeContrast(); + partEdgeSaturationValue = ldPrefs->getPartEdgeSaturation(); hEdgesOnlyButton = GetDlgItem(hGeometryPage, IDC_EDGES_ONLY); hQualityLinesButton = GetDlgItem(hGeometryPage, IDC_QUALITY_LINES); hAlwaysBlackButton = GetDlgItem(hGeometryPage, IDC_ALWAYS_BLACK); @@ -4332,6 +4786,16 @@ TCFloat32 LDViewPreferences::anisoFromSliderValue(int value) return (TCFloat32)(1 << value); } +int LDViewPreferences::sliderPosFromStudStyleVal(double value) +{ + return (int)(value * 10); +} + +TCFloat32 LDViewPreferences::studStyleValFromSliderPos(int position) +{ + return (TCFloat32)(position / 10.0f); +} + void LDViewPreferences::setupSubstitution(void) { setupGroupCheckButton(hPrimitivesPage, IDC_PRIMITIVE_SUBSTITUTION, @@ -4391,7 +4855,6 @@ void LDViewPreferences::setupPrimitivesPage(void) setupTextures(); setupSubstitution(); setupStudStyle(); - setCheck(hPrimitivesPage, IDC_STUD_STYLE_USE, ldPrefs->getUseStudStyle()); setCheck(hPrimitivesPage, IDC_STUD_QUALITY, !ldPrefs->getQualityStuds()); setCheck(hPrimitivesPage, IDC_HI_RES, ldPrefs->getHiResPrimitives()); } @@ -4707,7 +5170,19 @@ BOOL LDViewPreferences::doDialogInit( CUIPropertySheet::doDialogInit(hDlg, hFocusWindow, lParam); HWND hNewPrefSetField = NULL; HWND hHotKeyCombo = NULL; + HWND hHighContrastStudControl = NULL; + HWND hAutomateEdgeLineControl = NULL; + hHighContrastStudControl = GetDlgItem(hDlg, IDC_LIGHT_DARK_SLIDER); + if (hHighContrastStudControl) + { + return highContrastStudColorInit(hDlg); + } + hAutomateEdgeLineControl = GetDlgItem(hDlg, IDC_CONTRAST_SLIDER); + if (hAutomateEdgeLineControl) + { + return automateEdgeLineColorInit(hDlg); + } hNewPrefSetField = GetDlgItem(hDlg, IDC_NEW_PREF_SET_FIELD); if (hNewPrefSetField) { @@ -5215,7 +5690,9 @@ BOOL LDViewPreferences::doDrawItem(HWND hDlg, int itemId, { HWND hWnd = GetDlgItem(hDlg, itemId); - if (itemId == IDC_DEFAULT_COLOR || itemId == IDC_BACKGROUND_COLOR) + if (itemId == IDC_DEFAULT_COLOR || itemId == IDC_BACKGROUND_COLOR || + itemId == IDC_STUD_CYLINDER_COLOR || itemId == IDC_PART_EDGE_COLOR || + itemId == IDC_BLACK_EDGE_COLOR || itemId == IDC_DARK_EDGE_COLOR) { return doDrawColorButton(hDlg, hWnd, hButtonTheme, drawItemStruct); } diff --git a/LDViewPreferences.h b/LDViewPreferences.h index f9696034b..e94be28ec 100644 --- a/LDViewPreferences.h +++ b/LDViewPreferences.h @@ -71,6 +71,10 @@ class LDViewPreferences: public CUIPropertySheet void setOptionalStandardLight(bool value); COLORREF getBackgroundColor(void); COLORREF getDefaultColor(void); + void getStudCylinderColor(void); + void getPartEdgeColor(void); + void getBlackEdgeColor(void); + void getDarkEdgeColor(void); bool getUseSeams(void); void setUseSeams(bool value); int getSeamWidth(void); @@ -156,6 +160,8 @@ class LDViewPreferences: public CUIPropertySheet virtual void setupSeamWidth(void); virtual void setupFullScreenRefresh(void); virtual void setupSaveDirs(void); + virtual BOOL highContrastStudColorInit(HWND hDlg); + virtual BOOL automateEdgeLineColorInit(HWND hDlg); virtual void updateSaveDir(HWND hTextField, HWND hBrowseButton, LDPreferences::DefaultDirMode dirMode, const ucstring &filename); virtual void setupSaveDir(HWND hComboBox, HWND hTextField, @@ -171,6 +177,15 @@ class LDViewPreferences: public CUIPropertySheet virtual void browseForDir(CUCSTR prompt, HWND hTextField, ucstring &dir); virtual void chooseDefaultColor(void); + virtual void chooseStudCylinderColor(void); + virtual void choosePartEdgeColor(void); + virtual void chooseBlackEdgeColor(void); + virtual void chooseDarkEdgeColor(void); + virtual void doHighContrastColor(void); + virtual void doAutomateEdgeColorCheck(void); + virtual void doAutomateEdgeColor(void); + virtual void doStudStyle(void); + virtual void doAlwaysBlack(void); virtual void doFSRefresh(void); virtual void doStipple(void); virtual void doSort(void); @@ -276,7 +291,11 @@ class LDViewPreferences: public CUIPropertySheet virtual void disableTextureFiltering(void); virtual void enableTexmaps(void); virtual void disableTexmaps(void); + virtual void enableStudStyle(void); + virtual void disableStudStyle(void); virtual void setupOpacitySlider(void); + virtual void setupStudStyleColorButton(HWND hDlg, int controlId); + virtual void setStudStyleSliderValue(HWND hDlg, int controlId); virtual ucstring getPrefSet(int index); virtual ucstring getSelectedPrefSet(void); virtual void selectPrefSet(const ucstring& prefSet = ucstring(), bool force = false); @@ -343,6 +362,8 @@ class LDViewPreferences: public CUIPropertySheet static TCFloat32 textureOffsetFromSliderValue(int value); static int sliderValueFromAniso(double value); static TCFloat32 anisoFromSliderValue(int value); + static int sliderPosFromStudStyleVal(double value); + static TCFloat32 studStyleValFromSliderPos(int position); LDrawModelViewer* modelViewer; LDViewWindow* ldviewWindow; @@ -366,6 +387,25 @@ class LDViewPreferences: public CUIPropertySheet HWND hBackgroundColorButton; HBITMAP hDefaultColorBitmap; HWND hDefaultColorButton; + + // Stud Style and Edge Lines Color Controls + HBITMAP hStudCylinderColorBitmap; + COLORREF crStudCylinderColor; + HWND hStudCylinderColorButton; + HWND hStudCylinderColorReset; + HBITMAP hPartEdgeColorBitmap; + COLORREF crPartEdgeColor; + HWND hPartEdgeColorButton; + HWND hPartEdgeColorReset; + HBITMAP hBlackEdgeColorBitmap; + COLORREF crBlackEdgeColor; + HWND hBlackEdgeColorButton; + HWND hBlackEdgeColorReset; + HBITMAP hDarkEdgeColorBitmap; + COLORREF crDarkEdgeColor; + HWND hDarkEdgeColorButton; + HWND hDarkEdgeColorReset; + HWND hSnapshotDirCombo; HWND hSnapshotDirField; HWND hSnapshotBrowseButton; @@ -459,6 +499,26 @@ class LDViewPreferences: public CUIPropertySheet HWND hNewPrefSetButton; HWND hPrefSetHotKeyButton; + // Stud Style and Edge Lines Controls + HWND hAutomateEdgeColorCheck; + HWND hAutomateEdgeColorButton; + HWND hHighContrastColorButton; + + // Stud Style and Edge Lines Dialogs + HWND hHighContrastStudColor; + HWND hAutomateEdgeLineColor; + + // Stud Style and Edge Lines Color Values + TCFloat partEdgeLightDarkValue; + TCFloat partEdgeContrastValue; + TCFloat partEdgeSaturationValue; + + // Stud Style Color Enabled Checks + bool studCylinderColorEnabled; + bool partEdgeColorEnabled; + bool blackEdgeColorEnabled; + bool darkEdgeColorEnabled; + bool setActiveWarned; bool checkAbandon; diff --git a/Resource.h b/Resource.h index abea27530..5dbf73c77 100644 --- a/Resource.h +++ b/Resource.h @@ -105,6 +105,8 @@ #define IDR_DOTS 545 #define IDR_EXTRA_DIRS_TOOLBAR 546 #define IDR_TB_WALK 547 +#define IDD_HIGH_CONTRAST_STUD_COLOR 548 +#define IDD_AUTOMATE_EDGE_LINE_COLOR 549 #define IDC_LIGHTING_QUALITY 1001 #define IDC_FRAME_RATE 1002 #define IDC_HIGHLIGHTS 1003 @@ -201,6 +203,8 @@ #define IDC_SAVE_SERIES 1092 #define IDC_SAVE_DIGITS_SPIN 1093 #define IDC_SAVE_DIGITS_LABEL 1094 +#define IDC_AUTOMATE_EDGE_COLOR_CHECK 1095 +#define IDC_AUTOMATE_EDGE_COLOR 1096 #define IDC_PRINT_DPI 1103 #define IDC_TEXTURE_NEAREST 1109 #define IDC_TEXTURE_BILINEAR 1110 @@ -402,6 +406,36 @@ #define IDC_BROWSE_CUSTOM_CONFIG 1324 #define IDC_STUD_STYLE_USE 1325 #define IDC_STUD_STYLE_COMBO 1326 +#define IDC_HIGH_CONTRAST_COLOR 1327 +#define IDC_EDGE_LINE_COLOR_GROUP 1328 +#define IDC_LIGHT_DARK_SLIDER 1329 +#define IDC_LIGHT_DARK_NAME 1330 +#define IDC_LIGHT_DARK_VALUE 1331 +#define IDC_LIGHT_DARK_RESET 1332 +#define IDC_HIGH_CONTRAST_COLOR_GROUP 1333 +#define IDC_STUD_CYLINDER_COLOR_CHECK 1334 +#define IDC_STUD_CYLINDER_COLOR 1335 +#define IDC_STUD_CYLINDER_COLOR_RESET 1336 +#define IDC_PART_EDGE_COLOR_CHECK 1337 +#define IDC_PART_EDGE_COLOR 1338 +#define IDC_PART_EDGE_COLOR_RESET 1339 +#define IDC_BLACK_EDGE_COLOR_CHECK 1340 +#define IDC_BLACK_EDGE_COLOR 1341 +#define IDC_BLACK_EDGE_COLOR_RESET 1342 +#define IDC_DARK_EDGE_COLOR_CHECK 1343 +#define IDC_DARK_EDGE_COLOR 1344 +#define IDC_DARK_EDGE_COLOR_RESET 1345 +#define IDC_AUTO_EDGE_LINE_COLOR_GROUP 1346 +#define IDC_CONTRAST_SLIDER 1347 +#define IDC_CONTRAST_NAME 1348 +#define IDC_CONTRAST_VALUE 1349 +#define IDC_CONTRAST_RESET 1350 +#define IDC_SATURATION_SLIDER 1351 +#define IDC_SATURATION_NAME 1352 +#define IDC_SATURATION_VALUE 1353 +#define IDC_SATURATION_RESET 1354 +#define IDC_HIGH_CONTRAST_STUD_COLOR_OK 1355 +#define IDC_AUTOMATE_EDGE_LINE_COLOR_OK 1356 #define PRINTDLGORD 1538 #define PAGESETUPDLGORD 1546 #define IDD_PRIMITIVES_PREFS 1547 @@ -508,9 +542,9 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NO_MFC 1 #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 548 +#define _APS_NEXT_RESOURCE_VALUE 550 #define _APS_NEXT_COMMAND_VALUE 40122 -#define _APS_NEXT_CONTROL_VALUE 1327 +#define _APS_NEXT_CONTROL_VALUE 1357 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif From fdc4da5bcfccaff620017c49e81a3d5b6b781ed9 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sun, 9 Nov 2025 00:09:06 +0100 Subject: [PATCH 6/7] Fix 'memcpy is not a member of std' error on Qt 5.15 build --- LDLoader/LDLModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LDLoader/LDLModel.cpp b/LDLoader/LDLModel.cpp index 3a27bf843..8cdc8238b 100644 --- a/LDLoader/LDLModel.cpp +++ b/LDLoader/LDLModel.cpp @@ -954,7 +954,7 @@ char* LDLModel::setStudCylinderColor(char* input) if (!buffer) return nullptr; - std::memcpy(buffer, result.c_str(), result.size() + 1); // includes '\0' + memcpy(buffer, result.c_str(), result.size() + 1); // includes '\0' return buffer; } From 93cb299cc27b82349178826ab8fb6f4dfedb2c94 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Sun, 9 Nov 2025 00:09:46 +0100 Subject: [PATCH 7/7] Fix GCC reorder warning --- LDLib/LDrawModelViewer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LDLib/LDrawModelViewer.cpp b/LDLib/LDrawModelViewer.cpp index 95fd72e99..95ce8c0c6 100644 --- a/LDLib/LDrawModelViewer.cpp +++ b/LDLib/LDrawModelViewer.cpp @@ -155,11 +155,7 @@ LDrawModelViewer::LDrawModelViewer(TCFloat width, TCFloat height) highlightR(160), highlightG(224), highlightB(255), - cameraData(NULL), studStyle(0), - partColorLDIndex(0.5f), - partEdgeContrast(0.5f), - partEdgeSaturation(0.5f), studCylinderColorEnabled(true), partEdgeColorEnabled(true), blackEdgeColorEnabled(true), @@ -167,7 +163,11 @@ LDrawModelViewer::LDrawModelViewer(TCFloat width, TCFloat height) studCylinderColor(1780276), // 27,42,52,255 partEdgeColor(0), // 0,0,0,255 blackEdgeColor(16777215), // 255,255,255,255 - darkEdgeColor(1780276) // 27,42,52,255 + darkEdgeColor(1780276), // 27,42,52,255 + partColorLDIndex(0.5f), + partEdgeContrast(0.5f), + partEdgeSaturation(0.5f), + cameraData(NULL) { #ifdef _LEAK_DEBUG strcpy(className, "LDrawModelViewer");