color: global LUT library, LUT error reporting, clamp + display fixes

- Add a global LUT library: user-configurable directories (new
  Preferences > LUT tab) scanned recursively for .cube/.3dl files; LUT
  node file pickers offer the library dirs as sidebar shortcuts via a
  'lut_library' input property handled by the param view bridge
- OCIOLutNode no longer fails silently: missing files, unsupported
  extensions and OCIO load errors are recorded in last_error() and
  surfaced in the status bar (input still passes through for rendering
  safety)
- ColorDialog: re-enable the display -> reference conversion using
  ColorProcessor::kInverse with a validity guard, and re-enable the
  Display tab in ColorValuesWidget; covered by a round-trip regression
  test proving the old OCIO inverse crash no longer occurs
- OCIOGradingTransformLinearNode: enforce the OCIO clampWhite >
  clampBlack invariant per frame in Value() so keyframed/connected
  values cannot produce invalid grading transforms, and constrain the
  white clamp UI minimum whenever the black clamp is static
- Regression tests for LUT extension checks, direction switching, node
  error reporting, LUT library scanning, display inverse round-trip and
  clamp enforcement
This commit is contained in:
2026-07-16 22:53:33 +08:00
parent ddca6a5e01
commit 547c2480e0
18 changed files with 829 additions and 33 deletions
@@ -91,9 +91,6 @@ ColorValuesWidget::ColorValuesWidget(ColorManager *manager, QWidget *parent)
connect(display_tab_, &ColorValuesTab::ColorChanged, this,
&ColorValuesWidget::UpdateValuesFromDisplay);
// FIXME: Display -> Ref temporarily disabled due to OCIO crash (see ColorDialog::ColorSpaceChanged for more info)
display_tab_->setEnabled(false);
layout->addWidget(tabs);
}
}
+24 -4
View File
@@ -24,6 +24,7 @@
#include <QFileDialog>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QUrl>
#include "ui/icons/icons.h"
@@ -56,11 +57,30 @@ void FileField::BrowseBtnClicked()
{
QString s;
if (directory_mode_) {
s = QFileDialog::getExistingDirectory(this, tr("Open Directory"));
if (sidebar_urls_.isEmpty()) {
if (directory_mode_) {
s = QFileDialog::getExistingDirectory(this, tr("Open Directory"));
} else {
s = QFileDialog::getOpenFileName(this, tr("Open File"), QString(),
name_filter_);
}
} else {
s = QFileDialog::getOpenFileName(this, tr("Open File"), QString(),
name_filter_);
// Sidebar URLs require the non-static dialog API
QFileDialog dialog(this, tr("Open File"));
dialog.setFileMode(directory_mode_ ? QFileDialog::Directory :
QFileDialog::ExistingFile);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
if (!directory_mode_ && !name_filter_.isEmpty()) {
dialog.setNameFilter(name_filter_);
}
dialog.setSidebarUrls(sidebar_urls_);
if (directory_mode_) {
dialog.setOption(QFileDialog::ShowDirsOnly, true);
}
if (dialog.exec() == QDialog::Accepted && !dialog.selectedFiles().isEmpty()) {
s = dialog.selectedFiles().first();
}
}
if (!s.isEmpty()) {
+13
View File
@@ -58,6 +58,17 @@ public:
name_filter_ = filter;
}
/**
* @brief Sets extra sidebar shortcuts (e.g. a library directory) for the
* browse dialog
*
* Note: setting sidebar URLs requires Qt's non-native file dialog.
*/
void SetSidebarUrls(const QList<QUrl> &urls)
{
sidebar_urls_ = urls;
}
signals:
void FilenameChanged(const QString &filename);
@@ -70,6 +81,8 @@ private:
QString name_filter_;
QList<QUrl> sidebar_urls_;
private slots:
void BrowseBtnClicked();
@@ -23,6 +23,7 @@
#include <QCheckBox>
#include <QFontComboBox>
#include <QUrl>
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
@@ -36,6 +37,7 @@
#include "node/project/sequence/sequence.h"
#include "nodeparamviewarraywidget.h"
#include "nodeparamviewtextedit.h"
#include "render/lutlibrary.h"
#include "undo/undostack.h"
#include "widget/bezier/bezierwidget.h"
#include "widget/colorbutton/colorbutton.h"
@@ -938,6 +940,16 @@ void NodeParamViewWidgetBridge::SetProperty(const QString &key,
ff->SetDirectoryMode(value.toBool());
} else if (key == QStringLiteral("filter")) {
ff->SetNameFilter(value.toString());
} else if (key == QStringLiteral("lut_library") && value.toBool()) {
// Offer the global LUT library directories as sidebar shortcuts in
// the browse dialog
QList<QUrl> sidebar_urls;
for (const QString &dir : LUTLibrary::GetDirectories()) {
sidebar_urls.append(QUrl::fromLocalFile(dir));
}
if (!sidebar_urls.isEmpty()) {
ff->SetSidebarUrls(sidebar_urls);
}
}
}