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:
@@ -192,21 +192,21 @@ void ColorDialog::ColorSpaceChanged(const QString &input,
|
||||
ColorProcessorPtr ref_to_input = ColorProcessor::Create(
|
||||
color_manager_, color_manager_->GetReferenceColorSpace(), input);
|
||||
|
||||
// FIXME: For some reason, using OCIO::TRANSFORM_DIR_INVERSE (wrapped by ColorProcessor::kInverse) causes OCIO to
|
||||
// crash. We've disabled that functionality for now (also disabling display_tab_ in ColorValuesWidget)
|
||||
|
||||
/*ColorProcessorPtr display_to_ref = ColorProcessor::Create(color_manager_->GetConfig(),
|
||||
color_manager_->GetReferenceColorSpace(),
|
||||
display,
|
||||
view,
|
||||
look,
|
||||
ColorProcessor::kInverse);*/
|
||||
// Display -> reference is the inverse of the display transform. Older OCIO
|
||||
// versions crashed on TRANSFORM_DIR_INVERSE; guard by requiring a valid
|
||||
// processor and fall back to disabling the display tab if creation fails.
|
||||
ColorProcessorPtr display_to_ref = ColorProcessor::Create(
|
||||
color_manager_, color_manager_->GetReferenceColorSpace(), output,
|
||||
ColorProcessor::kInverse);
|
||||
if (display_to_ref && !display_to_ref->GetProcessor()) {
|
||||
display_to_ref = nullptr;
|
||||
}
|
||||
|
||||
color_wheel_->SetColorProcessor(input_to_ref_processor_, ref_to_display);
|
||||
hsv_value_gradient_->SetColorProcessor(input_to_ref_processor_,
|
||||
ref_to_display);
|
||||
color_values_widget_->SetColorProcessor(
|
||||
input_to_ref_processor_, ref_to_display, nullptr, ref_to_input);
|
||||
input_to_ref_processor_, ref_to_display, display_to_ref, ref_to_input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "tabs/preferencesdisktab.h"
|
||||
#include "tabs/preferencesaudiotab.h"
|
||||
#include "tabs/preferenceskeyboardtab.h"
|
||||
#include "tabs/preferencesluttab.h"
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
|
||||
namespace olive
|
||||
@@ -60,6 +61,7 @@ PreferencesDialog::PreferencesDialog(MainWindow *main_window, int start_tab)
|
||||
new PreferencesBehaviorTab(PreferencesBehaviorTab::kCategoryRendering),
|
||||
tr("Rendering"));
|
||||
AddTab(new PreferencesDiskTab(), tr("Disk"));
|
||||
AddTab(new PreferencesLutTab(), tr("LUT"));
|
||||
AddTab(new PreferencesKeyboardTab(main_window), tr("Keyboard"));
|
||||
|
||||
SetCurrentTab(start_tab);
|
||||
|
||||
@@ -22,6 +22,8 @@ set(OLIVE_SOURCES
|
||||
dialog/preferences/tabs/preferencesbehaviortab.cpp
|
||||
dialog/preferences/tabs/preferencesdisktab.h
|
||||
dialog/preferences/tabs/preferencesdisktab.cpp
|
||||
dialog/preferences/tabs/preferencesluttab.h
|
||||
dialog/preferences/tabs/preferencesluttab.cpp
|
||||
dialog/preferences/tabs/preferencesappearancetab.h
|
||||
dialog/preferences/tabs/preferencesappearancetab.cpp
|
||||
dialog/preferences/tabs/preferencesaudiotab.h
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/***
|
||||
|
||||
Oak - Non-Linear Video Editor
|
||||
Copyright (C) 2026 Oak Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "preferencesluttab.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "render/lutlibrary.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
PreferencesLutTab::PreferencesLutTab()
|
||||
{
|
||||
QVBoxLayout *outer_layout = new QVBoxLayout(this);
|
||||
|
||||
QGroupBox *library_group = new QGroupBox(tr("LUT Library"));
|
||||
outer_layout->addWidget(library_group);
|
||||
|
||||
QVBoxLayout *library_layout = new QVBoxLayout(library_group);
|
||||
|
||||
library_layout->addWidget(new QLabel(
|
||||
tr("Directories scanned for .cube and .3dl LUT files. LUT nodes offer "
|
||||
"these locations when picking a LUT file.")));
|
||||
|
||||
library_dirs_list_ = new QListWidget();
|
||||
library_dirs_list_->addItems(LUTLibrary::GetDirectories());
|
||||
library_layout->addWidget(library_dirs_list_);
|
||||
|
||||
QHBoxLayout *button_layout = new QHBoxLayout();
|
||||
button_layout->addStretch();
|
||||
|
||||
QPushButton *add_btn = new QPushButton(tr("Add..."));
|
||||
connect(add_btn, &QPushButton::clicked, this, [this]() {
|
||||
const QString dir = QFileDialog::getExistingDirectory(
|
||||
this, tr("Add LUT Library Directory"));
|
||||
if (!dir.isEmpty() &&
|
||||
library_dirs_list_->findItems(dir, Qt::MatchExactly).isEmpty()) {
|
||||
library_dirs_list_->addItem(dir);
|
||||
}
|
||||
});
|
||||
button_layout->addWidget(add_btn);
|
||||
|
||||
QPushButton *remove_btn = new QPushButton(tr("Remove"));
|
||||
connect(remove_btn, &QPushButton::clicked, this, [this]() {
|
||||
qDeleteAll(library_dirs_list_->selectedItems());
|
||||
});
|
||||
button_layout->addWidget(remove_btn);
|
||||
|
||||
library_layout->addLayout(button_layout);
|
||||
|
||||
outer_layout->addStretch();
|
||||
}
|
||||
|
||||
void PreferencesLutTab::Accept(MultiUndoCommand *command)
|
||||
{
|
||||
Q_UNUSED(command)
|
||||
|
||||
QStringList dirs;
|
||||
for (int i = 0; i < library_dirs_list_->count(); i++) {
|
||||
dirs.append(library_dirs_list_->item(i)->text());
|
||||
}
|
||||
|
||||
LUTLibrary::SetDirectories(dirs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/***
|
||||
|
||||
Oak - Non-Linear Video Editor
|
||||
Copyright (C) 2026 Oak Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef PREFERENCESLUTTAB_H
|
||||
#define PREFERENCESLUTTAB_H
|
||||
|
||||
#include <QListWidget>
|
||||
|
||||
#include "dialog/configbase/configdialogbase.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class PreferencesLutTab : public ConfigDialogBaseTab {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PreferencesLutTab();
|
||||
|
||||
virtual void Accept(MultiUndoCommand *command) override;
|
||||
|
||||
private:
|
||||
QListWidget *library_dirs_list_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PREFERENCESLUTTAB_H
|
||||
Reference in New Issue
Block a user