Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preview post-processing stage changes in appleseed.studio #2885

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
1 change: 1 addition & 0 deletions src/appleseed.python/bindpostprocessingstage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void bind_post_processing_stage()
.def("__init__", bpy::make_constructor(create_post_processing_stage))
.def("get_model", &PostProcessingStage::get_model)
.def("get_order", &PostProcessingStage::get_order);
// @Note: this might need to be updated if a "real_time_preview" flag is added.

bind_typed_entity_vector<PostProcessingStage>("PostProcessingStageContainer");

Expand Down
55 changes: 46 additions & 9 deletions src/appleseed.studio/mainwindow/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,10 @@ void MainWindow::update_project_explorer()
m_project_explorer, SIGNAL(signal_project_modified()),
SLOT(slot_project_modified()));

connect(
m_project_explorer, SIGNAL(signal_post_processing_stage_modified(const std::uint64_t)),
SLOT(slot_post_processing_stage_modified(const std::uint64_t)));

connect(
m_project_explorer, SIGNAL(signal_frame_modified()),
SLOT(slot_frame_modified()));
Expand Down Expand Up @@ -1264,6 +1268,25 @@ void MainWindow::start_rendering(const RenderingMode rendering_mode)
m_render_tabs["RGB"]);
}

namespace
{
auto_release_ptr<Frame> make_temporary_frame_copy(const Frame& frame)
{
// todo: creating a frame with denoising enabled is very expensive, see benchmark_frame.cpp.
ParamArray params_copy(frame.get_parameters());
params_copy.remove_path("denoiser");

// Make a temporary copy of the frame.
// Render info, AOVs and other data are not copied.
auto_release_ptr<Frame> working_frame =
FrameFactory::create((std::string(frame.get_name()) + "_copy").c_str(), params_copy);

working_frame->image().copy_from(frame.image());

return working_frame;
}
}

void MainWindow::apply_false_colors_settings()
{
Project* project = m_project_manager.get_project();
Expand All @@ -1277,15 +1300,7 @@ void MainWindow::apply_false_colors_settings()

if (false_colors_enabled)
{
// Make a temporary copy of the frame.
// Render info, AOVs and other data are not copied.
// todo: creating a frame with denoising enabled is very expensive, see benchmark_frame.cpp.
auto_release_ptr<Frame> working_frame =
FrameFactory::create(
(std::string(frame->get_name()) + "_copy").c_str(),
frame->get_parameters()
.remove_path("denoiser"));
working_frame->image().copy_from(frame->image());
auto_release_ptr<Frame> working_frame = make_temporary_frame_copy(*frame);

// Create post-processing stage.
auto_release_ptr<PostProcessingStage> stage(
Expand Down Expand Up @@ -1597,6 +1612,28 @@ void MainWindow::slot_project_modified()
update_window_title();
}

void MainWindow::slot_post_processing_stage_modified(const std::uint64_t stage_uid)
{
Project* project = m_project_manager.get_project();
assert(project != nullptr);

Frame* frame = project->get_frame();
assert(frame != nullptr);

auto_release_ptr<Frame> working_frame = make_temporary_frame_copy(*frame);

// Preview the post-processing stage that was modified.
for (PostProcessingStage& stage : frame->post_processing_stages())
{
if (stage.get_uid() == stage_uid) {
apply_post_processing_stage(stage, working_frame.ref());
return;
}
}

assert(false);
}

void MainWindow::slot_toggle_project_file_monitoring(const bool checked)
{
if (checked)
Expand Down
1 change: 1 addition & 0 deletions src/appleseed.studio/mainwindow/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ class MainWindow
void slot_pack_project_as();
void slot_close_project();
void slot_project_modified();
void slot_post_processing_stage_modified(const std::uint64_t stage_uid);

// Project file monitoring.
void slot_toggle_project_file_monitoring(const bool checked);
Expand Down
55 changes: 55 additions & 0 deletions src/appleseed.studio/mainwindow/project/projectbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "renderer/api/environment.h"
#include "renderer/api/environmentedf.h"
#include "renderer/api/light.h"
#include "renderer/api/postprocessing.h"
#include "renderer/api/project.h"
#include "renderer/api/scene.h"
#include "renderer/api/shadergroup.h"
Expand Down Expand Up @@ -96,12 +97,20 @@ class ProjectBuilder
ParentEntity& parent,
const foundation::Dictionary& values) const;

// Simulate partial specialization of edit_entity() for Entity = renderer::PostProcessingStage.
template <typename ParentEntity>
renderer::PostProcessingStage* edit_entity(
renderer::PostProcessingStage* old_entity,
ParentEntity& parent,
const foundation::Dictionary& values) const;

renderer::Frame* edit_frame(
const foundation::Dictionary& values) const;

signals:
void signal_project_modified() const;
void signal_frame_modified() const;
void signal_post_processing_stage_modified(const std::uint64_t stage_uid) const;

public slots:
void slot_notify_project_modification() const;
Expand Down Expand Up @@ -300,6 +309,52 @@ inline renderer::Light* ProjectBuilder::edit_entity(
return new_entity_ptr;
}

template <typename ParentEntity>
inline renderer::PostProcessingStage* ProjectBuilder::edit_entity(
renderer::PostProcessingStage* old_entity,
ParentEntity& parent,
const foundation::Dictionary& values) const
{
foundation::auto_release_ptr<renderer::PostProcessingStage> new_entity(
create_entity<renderer::PostProcessingStage>(values));
renderer::PostProcessingStage* new_entity_ptr = new_entity.get();

renderer::EntityTraits<renderer::PostProcessingStage>::remove_entity(old_entity, parent);
renderer::EntityTraits<renderer::PostProcessingStage>::insert_entity(new_entity, parent);

slot_notify_project_modification();

// @Note: we need to know whether or not to emit the signal. For this,
// we can either:
// * change the `PostProcessingStage` class to have a `bool` flag (not good)
// * pass this flag in its `params`, so that we can retrieve it here (maybe?)
// * pass the flag through `values` instead (not sure if it'd be better or not)
//
// @Fixme: if the flag was true and is now false, the effect needs to be "unapplied"!

#if 0
// @Note: using this to be able to inspect Dictionary values in Visual Studio.. :(
bool preview_enabled = false;
for (const auto& str : values.strings())
{
const auto key = std::string(str.key());
const auto value = std::string(str.value());
if (key == "real_time_preview")
preview_enabled = true;
if (value == "real_time_preview")
preview_enabled = true;
}
#else
const bool preview_enabled = new_entity_ptr->get_parameters().get_required<bool>("real_time_preview");
#endif

// Signal the modified stage, so that it can be previewed.
if (preview_enabled)
emit signal_post_processing_stage_modified(new_entity_ptr->get_uid());

return new_entity_ptr;
}

template <typename Entity>
foundation::auto_release_ptr<Entity> ProjectBuilder::create_entity(
const foundation::Dictionary& values) const
Expand Down
4 changes: 4 additions & 0 deletions src/appleseed.studio/mainwindow/project/projectexplorer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ ProjectExplorer::ProjectExplorer(
connect(
&m_project_builder, SIGNAL(signal_frame_modified()),
SIGNAL(signal_frame_modified()));

connect(
&m_project_builder, SIGNAL(signal_post_processing_stage_modified(const std::uint64_t)),
SIGNAL(signal_post_processing_stage_modified(const std::uint64_t)));
}

ProjectExplorer::~ProjectExplorer()
Expand Down
1 change: 1 addition & 0 deletions src/appleseed.studio/mainwindow/project/projectexplorer.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class ProjectExplorer
signals:
void signal_project_modified() const;
void signal_frame_modified() const;
void signal_post_processing_stage_modified(const std::uint64_t stage_uid) const;

private:
QTreeWidget* m_tree_widget;
Expand Down
2 changes: 1 addition & 1 deletion src/appleseed.studio/mainwindow/project/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class LineEditSliderAdaptor


//
// Binds QLineEdit and qtcommon::DoubleSlider controls together such that updading
// Binds QLineEdit and qtcommon::DoubleSlider controls together such that updating
// the value in one control updates the value in the other.
//

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ void IPostProcessingStageFactory::add_common_input_metadata(DictionaryArray& met
.insert("type", "soft"))
.insert("use", "required")
.insert("default", "0"));

metadata.push_back(
Dictionary()
.insert("name", "real_time_preview")
.insert("label", "Real-time Preview")
.insert("type", "boolean")
.insert("use", "required")
.insert("default", "false"));
}

} // namespace renderer