Add Chromium-only Blender WebEngine parity work
This commit is contained in:
73
blender-5.2.0/source/blender/editors/render/CMakeLists.txt
Normal file
73
blender-5.2.0/source/blender/editors/render/CMakeLists.txt
Normal file
@@ -0,0 +1,73 @@
|
||||
# SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
../include
|
||||
../../makesrna
|
||||
# RNA_prototypes.hh
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
render_internal.cc
|
||||
render_opengl.cc
|
||||
render_ops.cc
|
||||
render_preview.cc
|
||||
render_shading.cc
|
||||
render_texture_cache.cc
|
||||
render_update.cc
|
||||
render_view.cc
|
||||
|
||||
render_intern.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
PRIVATE bf::blenkernel
|
||||
PRIVATE bf::blenlib
|
||||
PRIVATE bf::blenloader
|
||||
PRIVATE bf::blentranslation
|
||||
PRIVATE bf::bmesh
|
||||
PRIVATE bf::depsgraph
|
||||
PRIVATE bf::dna
|
||||
PRIVATE bf::draw
|
||||
PRIVATE bf::gpu
|
||||
PRIVATE bf::imbuf
|
||||
PRIVATE bf::imbuf::movie
|
||||
PRIVATE bf::intern::clog
|
||||
PRIVATE bf::intern::guardedalloc
|
||||
PRIVATE bf::animrig
|
||||
PRIVATE bf::nodes
|
||||
PRIVATE bf::render
|
||||
PRIVATE bf::sequencer
|
||||
PRIVATE bf::windowmanager
|
||||
)
|
||||
|
||||
if(WITH_HEADLESS)
|
||||
add_definitions(-DWITH_HEADLESS)
|
||||
else()
|
||||
list(APPEND LIB
|
||||
bf_editor_datafiles
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
if(WITH_FREESTYLE)
|
||||
list(APPEND INC
|
||||
../../freestyle
|
||||
)
|
||||
add_definitions(-DWITH_FREESTYLE)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES)
|
||||
add_definitions(-DWITH_CYCLES)
|
||||
list(APPEND INC ../../../../intern/cycles/blender)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_editor_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.hh
|
||||
add_dependencies(bf_editor_render bf_rna)
|
||||
110
blender-5.2.0/source/blender/editors/render/render_intern.hh
Normal file
110
blender-5.2.0/source/blender/editors/render/render_intern.hh
Normal file
@@ -0,0 +1,110 @@
|
||||
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edrend
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct ReportList;
|
||||
struct Scene;
|
||||
struct ScrArea;
|
||||
struct bContext;
|
||||
struct wmOperatorType;
|
||||
|
||||
/* `render_shading.cc` */
|
||||
|
||||
void OBJECT_OT_material_slot_add(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_remove(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_assign(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_select(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_deselect(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_copy(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_move(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_remove_unused(wmOperatorType *ot);
|
||||
void OBJECT_OT_material_slot_remove_all(wmOperatorType *ot);
|
||||
|
||||
void MATERIAL_OT_new(wmOperatorType *ot);
|
||||
void TEXTURE_OT_new(wmOperatorType *ot);
|
||||
void WORLD_OT_new(wmOperatorType *ot);
|
||||
|
||||
void MATERIAL_OT_copy(wmOperatorType *ot);
|
||||
void MATERIAL_OT_paste(wmOperatorType *ot);
|
||||
|
||||
void SCENE_OT_view_layer_add(wmOperatorType *ot);
|
||||
void SCENE_OT_view_layer_remove(wmOperatorType *ot);
|
||||
void SCENE_OT_view_layer_add_aov(wmOperatorType *ot);
|
||||
void SCENE_OT_view_layer_remove_aov(wmOperatorType *ot);
|
||||
void SCENE_OT_view_layer_add_lightgroup(wmOperatorType *ot);
|
||||
void SCENE_OT_view_layer_remove_lightgroup(wmOperatorType *ot);
|
||||
void SCENE_OT_view_layer_add_used_lightgroups(wmOperatorType *ot);
|
||||
void SCENE_OT_view_layer_remove_unused_lightgroups(wmOperatorType *ot);
|
||||
|
||||
void OBJECT_OT_lightprobe_cache_bake(wmOperatorType *ot);
|
||||
void OBJECT_OT_lightprobe_cache_free(wmOperatorType *ot);
|
||||
|
||||
void SCENE_OT_render_view_add(wmOperatorType *ot);
|
||||
void SCENE_OT_render_view_remove(wmOperatorType *ot);
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
void SCENE_OT_freestyle_module_add(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_module_remove(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_module_move(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_lineset_add(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_lineset_copy(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_lineset_paste(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_lineset_remove(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_lineset_move(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_linestyle_new(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_color_modifier_add(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_alpha_modifier_add(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_thickness_modifier_add(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_geometry_modifier_add(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_modifier_remove(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_modifier_move(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_modifier_copy(wmOperatorType *ot);
|
||||
void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot);
|
||||
#endif
|
||||
|
||||
void TEXTURE_OT_slot_copy(wmOperatorType *ot);
|
||||
void TEXTURE_OT_slot_paste(wmOperatorType *ot);
|
||||
void TEXTURE_OT_slot_move(wmOperatorType *ot);
|
||||
|
||||
/* `render_texture_cache.cc` */
|
||||
|
||||
void RENDER_OT_generate_texture_cache(wmOperatorType *ot);
|
||||
void RENDER_OT_clear_texture_cache(wmOperatorType *ot);
|
||||
|
||||
/* `render_internal.cc` */
|
||||
|
||||
/* Base class for all WM_JOB_TYPE_RENDER jobs. */
|
||||
struct RenderJobBase {
|
||||
Scene *scene = nullptr;
|
||||
Scene *current_scene = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Contextual render, using current scene, view3d?
|
||||
*/
|
||||
void RENDER_OT_render(wmOperatorType *ot);
|
||||
void RENDER_OT_shutter_curve_preset(wmOperatorType *ot);
|
||||
|
||||
/* `render_view.cc` */
|
||||
|
||||
/**
|
||||
* New window uses x,y to set position.
|
||||
*/
|
||||
ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports);
|
||||
|
||||
void RENDER_OT_view_show(wmOperatorType *ot);
|
||||
void RENDER_OT_view_cancel(wmOperatorType *ot);
|
||||
|
||||
/* `render_opengl.cc` */
|
||||
|
||||
void RENDER_OT_opengl(wmOperatorType *ot);
|
||||
|
||||
} // namespace blender
|
||||
1302
blender-5.2.0/source/blender/editors/render/render_internal.cc
Normal file
1302
blender-5.2.0/source/blender/editors/render/render_internal.cc
Normal file
File diff suppressed because it is too large
Load Diff
1475
blender-5.2.0/source/blender/editors/render/render_opengl.cc
Normal file
1475
blender-5.2.0/source/blender/editors/render/render_opengl.cc
Normal file
File diff suppressed because it is too large
Load Diff
94
blender-5.2.0/source/blender/editors/render/render_ops.cc
Normal file
94
blender-5.2.0/source/blender/editors/render/render_ops.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
/* SPDX-FileCopyrightText: 2009 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edrend
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "ED_render.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "render_intern.hh" /* own include */
|
||||
|
||||
namespace blender {
|
||||
|
||||
/***************************** render ***********************************/
|
||||
|
||||
void ED_operatortypes_render()
|
||||
{
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_add);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_remove);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_assign);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_select);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_deselect);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_copy);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_move);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_remove_unused);
|
||||
WM_operatortype_append(OBJECT_OT_material_slot_remove_all);
|
||||
|
||||
WM_operatortype_append(OBJECT_OT_lightprobe_cache_bake);
|
||||
WM_operatortype_append(OBJECT_OT_lightprobe_cache_free);
|
||||
|
||||
WM_operatortype_append(MATERIAL_OT_new);
|
||||
WM_operatortype_append(TEXTURE_OT_new);
|
||||
WM_operatortype_append(WORLD_OT_new);
|
||||
|
||||
WM_operatortype_append(MATERIAL_OT_copy);
|
||||
WM_operatortype_append(MATERIAL_OT_paste);
|
||||
|
||||
WM_operatortype_append(SCENE_OT_view_layer_add);
|
||||
WM_operatortype_append(SCENE_OT_view_layer_remove);
|
||||
WM_operatortype_append(SCENE_OT_view_layer_add_aov);
|
||||
WM_operatortype_append(SCENE_OT_view_layer_remove_aov);
|
||||
WM_operatortype_append(SCENE_OT_view_layer_add_lightgroup);
|
||||
WM_operatortype_append(SCENE_OT_view_layer_remove_lightgroup);
|
||||
WM_operatortype_append(SCENE_OT_view_layer_add_used_lightgroups);
|
||||
WM_operatortype_append(SCENE_OT_view_layer_remove_unused_lightgroups);
|
||||
|
||||
WM_operatortype_append(SCENE_OT_render_view_add);
|
||||
WM_operatortype_append(SCENE_OT_render_view_remove);
|
||||
|
||||
#ifdef WITH_FREESTYLE
|
||||
WM_operatortype_append(SCENE_OT_freestyle_module_add);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_module_remove);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_module_move);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_lineset_add);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_lineset_copy);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_lineset_paste);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_lineset_remove);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_lineset_move);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_linestyle_new);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_color_modifier_add);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_alpha_modifier_add);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_thickness_modifier_add);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_geometry_modifier_add);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_modifier_remove);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_modifier_move);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_modifier_copy);
|
||||
WM_operatortype_append(SCENE_OT_freestyle_stroke_material_create);
|
||||
#endif
|
||||
|
||||
WM_operatortype_append(TEXTURE_OT_slot_copy);
|
||||
WM_operatortype_append(TEXTURE_OT_slot_paste);
|
||||
WM_operatortype_append(TEXTURE_OT_slot_move);
|
||||
|
||||
#ifdef WITH_CYCLES
|
||||
WM_operatortype_append(RENDER_OT_generate_texture_cache);
|
||||
WM_operatortype_append(RENDER_OT_clear_texture_cache);
|
||||
#endif
|
||||
|
||||
/* `render_internal.cc` */
|
||||
WM_operatortype_append(RENDER_OT_view_show);
|
||||
WM_operatortype_append(RENDER_OT_render);
|
||||
WM_operatortype_append(RENDER_OT_view_cancel);
|
||||
WM_operatortype_append(RENDER_OT_shutter_curve_preset);
|
||||
|
||||
/* `render_opengl.cc` */
|
||||
WM_operatortype_append(RENDER_OT_opengl);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
2468
blender-5.2.0/source/blender/editors/render/render_preview.cc
Normal file
2468
blender-5.2.0/source/blender/editors/render/render_preview.cc
Normal file
File diff suppressed because it is too large
Load Diff
3213
blender-5.2.0/source/blender/editors/render/render_shading.cc
Normal file
3213
blender-5.2.0/source/blender/editors/render/render_shading.cc
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,490 @@
|
||||
/* SPDX-FileCopyrightText: 2026 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edrend
|
||||
*/
|
||||
|
||||
#ifdef WITH_CYCLES
|
||||
|
||||
# include "render_intern.hh" /* own include */
|
||||
|
||||
# include <fmt/format.h>
|
||||
# include <mutex>
|
||||
# include <string>
|
||||
# include <utility>
|
||||
|
||||
# include "MEM_guardedalloc.h"
|
||||
|
||||
# include "DNA_image_types.h"
|
||||
# include "DNA_userdef_types.h"
|
||||
# include "DNA_windowmanager_enums.h"
|
||||
|
||||
# include "BLI_fileops.h"
|
||||
# include "BLI_listbase.h"
|
||||
# include "BLI_path_utils.hh"
|
||||
# include "BLI_set.hh"
|
||||
# include "BLI_string.h"
|
||||
# include "BLI_task.hh"
|
||||
# include "BLI_utildefines.h"
|
||||
# include "BLI_vector.hh"
|
||||
|
||||
# include "BKE_bpath.hh"
|
||||
# include "BKE_context.hh"
|
||||
# include "BKE_global.hh"
|
||||
# include "BKE_image.hh"
|
||||
# include "BKE_lib_query.hh"
|
||||
# include "BKE_main.hh"
|
||||
# include "BKE_node.hh"
|
||||
# include "BKE_report.hh"
|
||||
|
||||
# include "BLT_translation.hh"
|
||||
|
||||
# include "RNA_access.hh"
|
||||
# include "RNA_define.hh"
|
||||
|
||||
# include "UI_interface_icons.hh"
|
||||
# include "UI_interface_layout.hh"
|
||||
# include "UI_resources.hh"
|
||||
|
||||
# include "WM_api.hh"
|
||||
|
||||
# include "CCL_api.h"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Texture Cache Image Gathering
|
||||
* \{ */
|
||||
|
||||
/* Gather all images referenced by shader node trees. */
|
||||
static Set<const Image *> gather_cache_images(Main *bmain)
|
||||
{
|
||||
Set<const Image *> images;
|
||||
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type != NTREE_SHADER) {
|
||||
continue;
|
||||
}
|
||||
BKE_library_foreach_ID_link(
|
||||
bmain,
|
||||
&ntree->id,
|
||||
[&](LibraryIDLinkCallbackData *cb_data) {
|
||||
ID *image_id = *cb_data->id_pointer;
|
||||
if (image_id && GS(image_id->name) == ID_IM) {
|
||||
Image *image = blender::id_cast<Image *>(image_id);
|
||||
images.add(image);
|
||||
}
|
||||
return IDWALK_RET_NOP;
|
||||
},
|
||||
nullptr,
|
||||
IDWALK_READONLY);
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
/* Gather all source image files to the texture cache, expanding UDIM tiles and
|
||||
* optionally image sequences. */
|
||||
static Vector<std::pair<const Image *, std::string>> gather_cache_filepaths(
|
||||
Main *bmain, const bool include_sequences)
|
||||
{
|
||||
Vector<std::pair<const Image *, std::string>> filepaths;
|
||||
|
||||
for (const Image *image : gather_cache_images(bmain)) {
|
||||
if (ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_GENERATED, IMA_SRC_VIEWER)) {
|
||||
continue;
|
||||
}
|
||||
if (BKE_image_has_packedfile(image)) {
|
||||
continue;
|
||||
}
|
||||
if (image->filepath[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get regular absolute path. */
|
||||
char filepath[FILE_MAX];
|
||||
STRNCPY(filepath, image->filepath);
|
||||
BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&image->id));
|
||||
BLI_path_normalize(filepath);
|
||||
|
||||
/* Handle each UDIM tile. */
|
||||
if (image->source == IMA_SRC_TILED) {
|
||||
eUDIM_TILE_FORMAT tile_format = UDIM_TILE_FORMAT_NONE;
|
||||
char *udim_pattern = BKE_image_get_tile_strformat(filepath, &tile_format);
|
||||
|
||||
if (tile_format != UDIM_TILE_FORMAT_NONE) {
|
||||
for (const ImageTile &tile : image->tiles) {
|
||||
char tile_filepath[FILE_MAX];
|
||||
BKE_image_set_filepath_from_tile_number(
|
||||
tile_filepath, udim_pattern, tile_format, tile.tile_number);
|
||||
if (BLI_is_file(tile_filepath)) {
|
||||
filepaths.append({image, tile_filepath});
|
||||
}
|
||||
}
|
||||
MEM_delete(udim_pattern);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle each image sequence frame. */
|
||||
if (image->source == IMA_SRC_SEQUENCE) {
|
||||
if (include_sequences) {
|
||||
BKE_bpath_sequence_filepaths_foreach(filepath, [&](StringRef frame_filepath) {
|
||||
filepaths.append({image, frame_filepath});
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle regular image. */
|
||||
if (BLI_is_file(filepath)) {
|
||||
filepaths.append({image, filepath});
|
||||
}
|
||||
}
|
||||
|
||||
return filepaths;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generate Texture Cache Operator
|
||||
* \{ */
|
||||
|
||||
struct GenerateTextureCacheJob {
|
||||
Main *bmain;
|
||||
bool include_sequences;
|
||||
};
|
||||
|
||||
struct GenerateTextureCacheUI {
|
||||
int sequence_generate_num = 0;
|
||||
};
|
||||
|
||||
static void generate_texture_cache(Main *bmain,
|
||||
ReportList *reports,
|
||||
const bool include_sequences,
|
||||
wmJobWorkerStatus *worker_status = nullptr)
|
||||
{
|
||||
const Vector<std::pair<const Image *, std::string>> filepaths = gather_cache_filepaths(
|
||||
bmain, include_sequences);
|
||||
|
||||
/* Determine which texture cache files need to be generated. */
|
||||
Set<std::string> found_tx;
|
||||
int uptodate_num = 0;
|
||||
Vector<std::pair<const Image *, std::string>> outdated;
|
||||
for (const auto &item : filepaths) {
|
||||
std::string tx_filepath;
|
||||
const bool up_to_date = CCL_resolve_texture_cache(
|
||||
item.first, item.second.c_str(), U.texture_cachedir, tx_filepath);
|
||||
if (tx_filepath.empty() || !found_tx.add(tx_filepath)) {
|
||||
continue;
|
||||
}
|
||||
if (up_to_date) {
|
||||
uptodate_num++;
|
||||
}
|
||||
else {
|
||||
outdated.append(item);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate texture cache. */
|
||||
std::atomic<int> completed_num = 0;
|
||||
std::atomic<int> failed_num = 0;
|
||||
std::mutex reports_mutex;
|
||||
|
||||
blender::threading::parallel_for_each(outdated, [&](const auto &item) {
|
||||
if (worker_status) {
|
||||
if (G.is_break || worker_status->stop) {
|
||||
return;
|
||||
}
|
||||
worker_status->progress = (completed_num + failed_num) / float(outdated.size());
|
||||
worker_status->do_update = true;
|
||||
}
|
||||
|
||||
if (CCL_generate_texture_cache(item.first, item.second.c_str(), U.texture_cachedir)) {
|
||||
completed_num++;
|
||||
}
|
||||
else {
|
||||
std::scoped_lock lock(reports_mutex);
|
||||
BKE_reportf(
|
||||
reports, RPT_ERROR, "Failed to generate texture cache for: %s", item.second.c_str());
|
||||
failed_num++;
|
||||
}
|
||||
});
|
||||
|
||||
/* Report stats. */
|
||||
if (found_tx.is_empty()) {
|
||||
BKE_report(reports, RPT_INFO, "No image files found to generate tx files");
|
||||
}
|
||||
else {
|
||||
BKE_reportf(reports,
|
||||
(failed_num) ? RPT_WARNING : RPT_INFO,
|
||||
"Generated %d tx files, %d failed, %d up to date",
|
||||
completed_num.load(),
|
||||
failed_num.load(),
|
||||
uptodate_num);
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_texture_cache_startjob(void *customdata, wmJobWorkerStatus *worker_status)
|
||||
{
|
||||
GenerateTextureCacheJob *job = static_cast<GenerateTextureCacheJob *>(customdata);
|
||||
generate_texture_cache(
|
||||
job->bmain, worker_status->reports, job->include_sequences, worker_status);
|
||||
}
|
||||
|
||||
static wmOperatorStatus generate_texture_cache_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
const bool include_sequences = RNA_boolean_get(op->ptr, "generate_sequences");
|
||||
|
||||
/* No dialog, execute immediately without job. */
|
||||
if (op->customdata == nullptr) {
|
||||
generate_texture_cache(bmain, op->reports, include_sequences);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
MEM_delete(static_cast<GenerateTextureCacheUI *>(op->customdata));
|
||||
op->customdata = nullptr;
|
||||
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmJob *wm_job = WM_jobs_get(wm,
|
||||
CTX_wm_window(C),
|
||||
bmain,
|
||||
RPT_("Generating texture cache..."),
|
||||
WM_JOB_PRIORITY | WM_JOB_PROGRESS,
|
||||
WM_JOB_TYPE_GENERATE_TEXTURE_CACHE);
|
||||
|
||||
GenerateTextureCacheJob *job = MEM_new<GenerateTextureCacheJob>(__func__);
|
||||
job->bmain = bmain;
|
||||
job->include_sequences = include_sequences;
|
||||
WM_jobs_customdata_set(wm_job, job, [](void *customdata) {
|
||||
MEM_delete(static_cast<GenerateTextureCacheJob *>(customdata));
|
||||
});
|
||||
|
||||
WM_jobs_timer(wm_job, 0.2, NC_WM | ND_JOB, 0);
|
||||
WM_jobs_callbacks(wm_job, generate_texture_cache_startjob, nullptr, nullptr, nullptr);
|
||||
|
||||
G.is_break = false;
|
||||
WM_jobs_start(wm, wm_job);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static wmOperatorStatus generate_texture_cache_invoke(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent * /*event*/)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
/* Count files. */
|
||||
Set<std::string> found_tx;
|
||||
int regular_generate_num = 0;
|
||||
int sequence_generate_num = 0;
|
||||
int uptodate_num = 0;
|
||||
|
||||
const bool include_sequences = true;
|
||||
const Vector<std::pair<const Image *, std::string>> filepaths = gather_cache_filepaths(
|
||||
bmain, include_sequences);
|
||||
for (const auto &item : filepaths) {
|
||||
const bool is_sequence = item.first->source == IMA_SRC_SEQUENCE;
|
||||
std::string tx_filepath;
|
||||
const bool up_to_date = CCL_resolve_texture_cache(
|
||||
item.first, item.second.c_str(), U.texture_cachedir, tx_filepath);
|
||||
if (tx_filepath.empty() || !found_tx.add(tx_filepath)) {
|
||||
continue;
|
||||
}
|
||||
if (up_to_date) {
|
||||
uptodate_num++;
|
||||
}
|
||||
else if (is_sequence) {
|
||||
sequence_generate_num++;
|
||||
}
|
||||
else {
|
||||
regular_generate_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing to generate, just execute to show the message. */
|
||||
if (regular_generate_num == 0 && sequence_generate_num == 0) {
|
||||
return generate_texture_cache_exec(C, op);
|
||||
}
|
||||
|
||||
/* Show confirmation dialog. */
|
||||
std::string message;
|
||||
if (uptodate_num > 0) {
|
||||
message += fmt::format(fmt::runtime(IFACE_("{} tx files up to date")), uptodate_num);
|
||||
}
|
||||
if (regular_generate_num > 0) {
|
||||
if (!message.empty()) {
|
||||
message += '\n';
|
||||
}
|
||||
message += fmt::format(fmt::runtime(IFACE_("{} tx files to be generated")),
|
||||
regular_generate_num);
|
||||
}
|
||||
|
||||
GenerateTextureCacheUI *data = MEM_new<GenerateTextureCacheUI>(__func__);
|
||||
data->sequence_generate_num = sequence_generate_num;
|
||||
op->customdata = data;
|
||||
|
||||
return WM_operator_props_dialog_popup(C,
|
||||
op,
|
||||
300,
|
||||
IFACE_("Generate Texture Cache?"),
|
||||
IFACE_("Generate"),
|
||||
false,
|
||||
std::move(message),
|
||||
true);
|
||||
}
|
||||
|
||||
static void generate_texture_cache_ui(bContext * /*C*/, wmOperator *op)
|
||||
{
|
||||
ui::Layout &layout = *op->layout;
|
||||
const GenerateTextureCacheUI *data = static_cast<GenerateTextureCacheUI *>(op->customdata);
|
||||
|
||||
if (data) {
|
||||
if (data->sequence_generate_num > 0) {
|
||||
const std::string label = fmt::format(
|
||||
fmt::runtime(IFACE_("Include {} image sequence tx files")), data->sequence_generate_num);
|
||||
layout.prop(op->ptr, "generate_sequences", UI_ITEM_NONE, label, ICON_NONE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Show unconditionally outside the confirmation dialog, like a redo panel. */
|
||||
layout.prop(op->ptr, "generate_sequences", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_texture_cache_cancel(bContext * /*C*/, wmOperator *op)
|
||||
{
|
||||
if (op->customdata) {
|
||||
MEM_delete(static_cast<GenerateTextureCacheUI *>(op->customdata));
|
||||
op->customdata = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void RENDER_OT_generate_texture_cache(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Generate Texture Cache";
|
||||
ot->idname = "RENDER_OT_generate_texture_cache";
|
||||
ot->description = "Generate Cycles texture cache files for all images used in shader nodes";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->exec = generate_texture_cache_exec;
|
||||
ot->invoke = generate_texture_cache_invoke;
|
||||
ot->ui = generate_texture_cache_ui;
|
||||
ot->cancel = generate_texture_cache_cancel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna,
|
||||
"generate_sequences",
|
||||
true,
|
||||
"Image Sequences",
|
||||
"Generate texture cache files for all frames of image sequences");
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Clear Texture Cache Operator
|
||||
* \{ */
|
||||
|
||||
static Set<std::string> gather_clear_tx_files(Main *bmain)
|
||||
{
|
||||
Set<std::string> tx_files;
|
||||
|
||||
const bool include_sequences = true;
|
||||
const Vector<std::pair<const Image *, std::string>> filepaths = gather_cache_filepaths(
|
||||
bmain, include_sequences);
|
||||
|
||||
Set<std::string> source_filepaths;
|
||||
for (const auto &item : filepaths) {
|
||||
source_filepaths.add(item.second);
|
||||
}
|
||||
|
||||
for (const auto &item : filepaths) {
|
||||
BKE_image_texture_cache_filepaths_foreach(
|
||||
item.second.c_str(), U.texture_cachedir, [&](StringRef cache_filepath) {
|
||||
/* Defensive check just in case a tx file was referenced directly even
|
||||
* though this should not be done. */
|
||||
if (source_filepaths.contains(cache_filepath)) {
|
||||
return;
|
||||
}
|
||||
tx_files.add(cache_filepath);
|
||||
});
|
||||
}
|
||||
|
||||
return tx_files;
|
||||
}
|
||||
|
||||
static wmOperatorStatus clear_texture_cache_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
const Set<std::string> tx_files = gather_clear_tx_files(bmain);
|
||||
|
||||
int deleted_num = 0;
|
||||
for (const std::string &tx_filepath : tx_files) {
|
||||
if (BLI_delete(tx_filepath.c_str(), false, false) == 0) {
|
||||
deleted_num++;
|
||||
}
|
||||
else {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Failed to delete tx file: %s", tx_filepath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
BKE_reportf(op->reports, RPT_INFO, "Deleted %d tx files", deleted_num);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static wmOperatorStatus clear_texture_cache_invoke(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent * /*event*/)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
const int used_num = gather_clear_tx_files(bmain).size();
|
||||
|
||||
if (used_num == 0) {
|
||||
BKE_report(op->reports, RPT_INFO, "No tx files to delete");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const std::string message = fmt::format(fmt::runtime(IFACE_("{} tx files to be deleted")),
|
||||
used_num);
|
||||
|
||||
return WM_operator_confirm_ex(C,
|
||||
op,
|
||||
IFACE_("Clear Texture Cache?"),
|
||||
message.c_str(),
|
||||
IFACE_("Clear Cache"),
|
||||
ui::AlertIcon::Info,
|
||||
false);
|
||||
}
|
||||
|
||||
void RENDER_OT_clear_texture_cache(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Clear Texture Cache";
|
||||
ot->idname = "RENDER_OT_clear_texture_cache";
|
||||
ot->description = "Delete Cycles texture cache files from disk";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->exec = clear_texture_cache_exec;
|
||||
ot->invoke = clear_texture_cache_invoke;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
|
||||
#endif
|
||||
396
blender-5.2.0/source/blender/editors/render/render_update.cc
Normal file
396
blender-5.2.0/source/blender/editors/render/render_update.cc
Normal file
@@ -0,0 +1,396 @@
|
||||
/* SPDX-FileCopyrightText: 2009 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edrend
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_cachefile_types.h"
|
||||
#include "DNA_light_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "DRW_engine.hh"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#include "BKE_brush.hh"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_icons.hh"
|
||||
#include "BKE_main.hh"
|
||||
#include "BKE_main_invariants.hh"
|
||||
#include "BKE_material.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_node_tree_update.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_scene.hh"
|
||||
|
||||
#include "RE_engine.h"
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "SEQ_animation.hh"
|
||||
#include "SEQ_prefetch.hh"
|
||||
#include "SEQ_relations.hh"
|
||||
#include "SEQ_sequencer.hh"
|
||||
|
||||
#include "ED_node.hh"
|
||||
#include "ED_node_preview.hh"
|
||||
#include "ED_paint.hh"
|
||||
#include "ED_render.hh"
|
||||
#include "ED_view3d.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Render Engines
|
||||
* \{ */
|
||||
|
||||
void ED_render_view3d_update(Depsgraph *depsgraph,
|
||||
wmWindow *window,
|
||||
ScrArea *area,
|
||||
const bool updated)
|
||||
{
|
||||
Main *bmain = DEG_get_bmain(depsgraph);
|
||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
|
||||
for (ARegion ®ion : area->regionbase) {
|
||||
if (region.regiontype != RGN_TYPE_WINDOW) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region.regiondata);
|
||||
RenderEngine *engine = rv3d->view_render ? RE_view_engine_get(rv3d->view_render) : nullptr;
|
||||
|
||||
/* call update if the scene changed, or if the render engine
|
||||
* tagged itself for update (e.g. because it was busy at the
|
||||
* time of the last update) */
|
||||
if (engine && (updated || (engine->flag & RE_ENGINE_DO_UPDATE))) {
|
||||
/* Create temporary context to execute callback in. */
|
||||
bContext *C = CTX_create();
|
||||
CTX_data_main_set(C, bmain);
|
||||
CTX_data_scene_set(C, scene);
|
||||
CTX_wm_manager_set(C, static_cast<wmWindowManager *>(bmain->wm.first));
|
||||
CTX_wm_window_set(C, window);
|
||||
CTX_wm_screen_set(C, WM_window_get_active_screen(window));
|
||||
CTX_wm_area_set(C, area);
|
||||
CTX_wm_region_set(C, ®ion);
|
||||
|
||||
engine->flag &= ~RE_ENGINE_DO_UPDATE;
|
||||
/* NOTE: Important to pass non-updated depsgraph, This is because this function is called
|
||||
* from inside dependency graph evaluation. Additionally, if we pass fully evaluated one
|
||||
* we will lose updates stored in the graph. */
|
||||
engine->type->view_update(engine, C, CTX_data_depsgraph_pointer(C));
|
||||
|
||||
CTX_free(C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_compositor(const DEGEditorUpdateContext *update_context)
|
||||
{
|
||||
const Scene *scene = DEG_get_evaluated(update_context->depsgraph, update_context->scene);
|
||||
const bNodeTree *node_tree = scene->compositing_node_group;
|
||||
if (!node_tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (node_tree->id.recalc & ID_RECALC_NTREE_OUTPUT) {
|
||||
ED_node_compositor_job(
|
||||
update_context->bmain, update_context->scene, update_context->view_layer);
|
||||
}
|
||||
}
|
||||
|
||||
void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, const bool updated)
|
||||
{
|
||||
Main *bmain = update_ctx->bmain;
|
||||
static bool recursive_check = false;
|
||||
|
||||
/* don't do this render engine update if we're updating the scene from
|
||||
* other threads doing e.g. rendering or baking jobs */
|
||||
if (!BLI_thread_is_main()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't call this recursively for frame updates */
|
||||
if (recursive_check) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do not call if no WM available, see #42688. */
|
||||
if (bmain->wm.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
recursive_check = true;
|
||||
|
||||
wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
|
||||
for (wmWindow &window : wm->windows) {
|
||||
bScreen *screen = WM_window_get_active_screen(&window);
|
||||
|
||||
for (ScrArea &area : screen->areabase) {
|
||||
if (area.spacetype == SPACE_VIEW3D) {
|
||||
ED_render_view3d_update(update_ctx->depsgraph, &window, &area, updated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_compositor(update_ctx);
|
||||
|
||||
recursive_check = false;
|
||||
}
|
||||
|
||||
void ED_render_engine_area_exit(Main *bmain, ScrArea *area)
|
||||
{
|
||||
/* clear all render engines in this area */
|
||||
wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
|
||||
|
||||
if (area->spacetype != SPACE_VIEW3D) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ARegion ®ion : area->regionbase) {
|
||||
if (region.regiontype != RGN_TYPE_WINDOW || !(region.regiondata)) {
|
||||
continue;
|
||||
}
|
||||
ED_view3d_stop_render_preview(wm, ®ion);
|
||||
}
|
||||
}
|
||||
|
||||
void ED_render_engine_changed(Main *bmain, const bool update_scene_data)
|
||||
{
|
||||
/* on changing the render engine type, clear all running render engines */
|
||||
for (bScreen *screen = static_cast<bScreen *>(bmain->screens.first); screen;
|
||||
screen = static_cast<bScreen *>(screen->id.next))
|
||||
{
|
||||
for (ScrArea &area : screen->areabase) {
|
||||
ED_render_engine_area_exit(bmain, &area);
|
||||
}
|
||||
}
|
||||
/* Stop and invalidate all shader previews. */
|
||||
ED_preview_kill_jobs(static_cast<wmWindowManager *>(bmain->wm.first), bmain);
|
||||
for (Material &ma : bmain->materials) {
|
||||
BKE_material_make_node_previews_dirty(&ma);
|
||||
}
|
||||
RE_FreePersistentData(nullptr);
|
||||
/* Inform all render engines and draw managers. */
|
||||
DEGEditorUpdateContext update_ctx = {nullptr};
|
||||
update_ctx.bmain = bmain;
|
||||
for (Scene *scene = static_cast<Scene *>(bmain->scenes.first); scene;
|
||||
scene = static_cast<Scene *>(scene->id.next))
|
||||
{
|
||||
update_ctx.scene = scene;
|
||||
for (ViewLayer &view_layer : scene->view_layers) {
|
||||
/* TDODO(sergey): Iterate over depsgraphs instead? */
|
||||
update_ctx.depsgraph = BKE_scene_ensure_depsgraph(bmain, scene, &view_layer);
|
||||
update_ctx.view_layer = &view_layer;
|
||||
ED_render_id_flush_update(&update_ctx, &scene->id);
|
||||
}
|
||||
if (update_scene_data) {
|
||||
BKE_ntree_update_tag_id_changed(bmain, &scene->id);
|
||||
BKE_ntree_update(*bmain);
|
||||
}
|
||||
}
|
||||
BKE_main_ensure_invariants(*bmain);
|
||||
}
|
||||
|
||||
void ED_render_view_layer_changed(Main *bmain, bScreen *screen)
|
||||
{
|
||||
for (ScrArea &area : screen->areabase) {
|
||||
ED_render_engine_area_exit(bmain, &area);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Updates
|
||||
*
|
||||
* #ED_render_id_flush_update gets called from #DEG_id_tag_update,
|
||||
* to do editor level updates when the ID changes.
|
||||
* When these ID blocks are in the dependency graph,
|
||||
* we can get rid of the manual dependency checks.
|
||||
* \{ */
|
||||
|
||||
static void material_changed(Main *bmain, Material *ma)
|
||||
{
|
||||
/* icons */
|
||||
BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
|
||||
ED_previews_tag_dirty_by_id(*bmain, ma->id);
|
||||
}
|
||||
|
||||
static void lamp_changed(Main *bmain, Light *la)
|
||||
{
|
||||
/* icons */
|
||||
BKE_icon_changed(BKE_icon_id_ensure(&la->id));
|
||||
ED_previews_tag_dirty_by_id(*bmain, la->id);
|
||||
}
|
||||
|
||||
static void texture_changed(Main *bmain, Tex *tex)
|
||||
{
|
||||
Scene *scene;
|
||||
|
||||
/* icons */
|
||||
BKE_icon_changed(BKE_icon_id_ensure(&tex->id));
|
||||
ED_previews_tag_dirty_by_id(*bmain, tex->id);
|
||||
|
||||
for (scene = static_cast<Scene *>(bmain->scenes.first); scene;
|
||||
scene = static_cast<Scene *>(scene->id.next))
|
||||
{
|
||||
/* paint overlays */
|
||||
for (ViewLayer &view_layer : scene->view_layers) {
|
||||
BKE_paint_invalidate_overlay_tex(*bmain, scene, &view_layer, tex);
|
||||
}
|
||||
}
|
||||
|
||||
for (Brush &brush : bmain->brushes) {
|
||||
if (ELEM(tex, brush.mtex.tex, brush.mask_mtex.tex)) {
|
||||
BKE_brush_tag_unsaved_changes(&brush);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void world_changed(Main *bmain, World *wo)
|
||||
{
|
||||
/* icons */
|
||||
BKE_icon_changed(BKE_icon_id_ensure(&wo->id));
|
||||
ED_previews_tag_dirty_by_id(*bmain, wo->id);
|
||||
}
|
||||
|
||||
static void image_changed(Main *bmain, Image *ima)
|
||||
{
|
||||
Tex *tex;
|
||||
|
||||
/* icons */
|
||||
BKE_icon_changed(BKE_icon_id_ensure(&ima->id));
|
||||
ED_previews_tag_dirty_by_id(*bmain, ima->id);
|
||||
|
||||
/* textures */
|
||||
for (tex = static_cast<Tex *>(bmain->textures.first); tex;
|
||||
tex = static_cast<Tex *>(tex->id.next))
|
||||
{
|
||||
if (tex->type == TEX_IMAGE && tex->ima == ima) {
|
||||
texture_changed(bmain, tex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure downstream editors are made aware of changes to the Image data. */
|
||||
WM_main_add_notifier(NC_IMAGE | NA_EDITED, ima);
|
||||
}
|
||||
|
||||
static void scene_changed(Main *bmain, Scene *scene)
|
||||
{
|
||||
Object *ob;
|
||||
|
||||
/* glsl */
|
||||
for (ob = static_cast<Object *>(bmain->objects.first); ob;
|
||||
ob = static_cast<Object *>(ob->id.next))
|
||||
{
|
||||
if (ob->mode & OB_MODE_TEXTURE_PAINT) {
|
||||
BKE_texpaint_slots_refresh_object(scene, ob);
|
||||
ED_paint_proj_mesh_data_check(*scene, *ob, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_sequencer(const DEGEditorUpdateContext *update_ctx, Main *bmain, ID *id)
|
||||
{
|
||||
if (ELEM(id->recalc,
|
||||
0,
|
||||
ID_RECALC_SELECT,
|
||||
ID_RECALC_FRAME_CHANGE,
|
||||
ID_RECALC_AUDIO_FPS,
|
||||
ID_RECALC_AUDIO_VOLUME,
|
||||
ID_RECALC_AUDIO_MUTE,
|
||||
ID_RECALC_AUDIO_LISTENER,
|
||||
ID_RECALC_AUDIO))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Scene *changed_scene = update_ctx->scene;
|
||||
|
||||
if (GS(id->name) != ID_SCE) {
|
||||
seq::relations_invalidate_scene_strips(bmain, changed_scene);
|
||||
}
|
||||
|
||||
/* Invalidate rendered VSE caches in `changed_scene`, because strip animation may have been
|
||||
* updated. */
|
||||
if (GS(id->name) == ID_AC) {
|
||||
Editing *ed = seq::editing_get(changed_scene);
|
||||
if (ed != nullptr && seq::animation_keyframes_exist(changed_scene) &&
|
||||
&changed_scene->adt->action->id == id)
|
||||
{
|
||||
seq::prefetch_stop(changed_scene);
|
||||
seq::cache_cleanup(changed_scene, seq::CacheCleanup::FinalAndIntra);
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalidate cache for strips that use this compositing tree. */
|
||||
if (GS(id->name) == ID_NT) {
|
||||
const bNodeTree *node_tree = reinterpret_cast<const bNodeTree *>(id);
|
||||
if (node_tree->type == NTREE_COMPOSIT) {
|
||||
seq::relations_invalidate_compositor_users(bmain, node_tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
|
||||
{
|
||||
/* this can be called from render or baking thread when a python script makes
|
||||
* changes, in that case we don't want to do any editor updates, and making
|
||||
* GPU changes is not possible because OpenGL only works in the main thread */
|
||||
if (!BLI_thread_is_main()) {
|
||||
return;
|
||||
}
|
||||
Main *bmain = update_ctx->bmain;
|
||||
/* Internal ID update handlers. */
|
||||
switch (GS(id->name)) {
|
||||
case ID_MA:
|
||||
material_changed(bmain, id_cast<Material *>(id));
|
||||
break;
|
||||
case ID_TE:
|
||||
texture_changed(bmain, id_cast<Tex *>(id));
|
||||
break;
|
||||
case ID_WO:
|
||||
world_changed(bmain, id_cast<World *>(id));
|
||||
break;
|
||||
case ID_LA:
|
||||
lamp_changed(bmain, id_cast<Light *>(id));
|
||||
break;
|
||||
case ID_IM:
|
||||
image_changed(bmain, id_cast<Image *>(id));
|
||||
break;
|
||||
case ID_SCE:
|
||||
scene_changed(bmain, id_cast<Scene *>(id));
|
||||
break;
|
||||
case ID_BR:
|
||||
BKE_brush_tag_unsaved_changes(reinterpret_cast<Brush *>(id));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
update_sequencer(update_ctx, bmain, id);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
411
blender-5.2.0/source/blender/editors/render/render_view.cc
Normal file
411
blender-5.2.0/source/blender/editors/render/render_view.cc
Normal file
@@ -0,0 +1,411 @@
|
||||
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edrend
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_image.hh"
|
||||
#include "BKE_report.hh"
|
||||
#include "BKE_scene.hh"
|
||||
#include "BKE_screen.hh"
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "wm_window.hh"
|
||||
|
||||
#include "render_intern.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utilities for Finding Areas
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Returns biggest area that is not uv/image editor. Note that it uses buttons
|
||||
* window as the last possible alternative.
|
||||
* would use #BKE_screen_find_big_area(...) but this is too specific.
|
||||
*/
|
||||
static ScrArea *biggest_non_image_area(bContext *C)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
ScrArea *big = nullptr;
|
||||
int size, maxsize = 0, bwmaxsize = 0;
|
||||
short foundwin = 0;
|
||||
|
||||
for (ScrArea &area : screen->areabase) {
|
||||
if (area.winx > 30 && area.winy > 30) {
|
||||
size = area.winx * area.winy;
|
||||
if (!area.full && area.spacetype == SPACE_PROPERTIES) {
|
||||
if (foundwin == 0 && size > bwmaxsize) {
|
||||
bwmaxsize = size;
|
||||
big = &area;
|
||||
}
|
||||
}
|
||||
else if (area.spacetype != SPACE_IMAGE && size > maxsize) {
|
||||
maxsize = size;
|
||||
big = &area;
|
||||
foundwin = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return big;
|
||||
}
|
||||
|
||||
static ScrArea *find_area_showing_render_result(bContext *C, Scene *scene, wmWindow **r_win)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
ScrArea *area_render = nullptr;
|
||||
wmWindow *win_render = nullptr;
|
||||
|
||||
/* find an image-window showing render result */
|
||||
for (wmWindow &win : wm->windows) {
|
||||
if (WM_window_get_active_scene(&win) != scene) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bScreen *screen = WM_window_get_active_screen(&win);
|
||||
for (ScrArea &area : screen->areabase) {
|
||||
if (area.spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = static_cast<SpaceImage *>(area.spacedata.first);
|
||||
if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) {
|
||||
area_render = &area;
|
||||
win_render = &win;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (area_render) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*r_win = win_render;
|
||||
return area_render;
|
||||
}
|
||||
|
||||
static ScrArea *find_area_image_empty(bContext *C)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
ScrArea *area;
|
||||
SpaceImage *sima;
|
||||
|
||||
/* find an image-window showing render result */
|
||||
for (area = static_cast<ScrArea *>(screen->areabase.first); area; area = area->next) {
|
||||
if (area->spacetype == SPACE_IMAGE) {
|
||||
sima = static_cast<SpaceImage *>(area->spacedata.first);
|
||||
if ((sima->mode == SI_MODE_VIEW) && !sima->image) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Open Image Editor for Render
|
||||
* \{ */
|
||||
|
||||
ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ScrArea *area = nullptr;
|
||||
SpaceImage *sima;
|
||||
bool area_was_image = false;
|
||||
|
||||
if (U.render_display_type == USER_RENDER_DISPLAY_NONE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (U.render_display_type == USER_RENDER_DISPLAY_WINDOW) {
|
||||
int sizex, sizey;
|
||||
BKE_render_resolution(&scene->r, false, &sizex, &sizey);
|
||||
|
||||
sizex += 30 * UI_SCALE_FAC;
|
||||
sizey += 60 * UI_SCALE_FAC;
|
||||
|
||||
/* arbitrary... miniature image window views don't make much sense */
|
||||
sizex = std::max(sizex, 320);
|
||||
sizey = std::max(sizey, 256);
|
||||
|
||||
WM_window_dpi_set_userdef(CTX_wm_window(C));
|
||||
rctf *stored_bounds = &U.stored_bounds.image;
|
||||
const bool bounds_valid = (stored_bounds && (BLI_rctf_size_x(stored_bounds) > 150.0f) &&
|
||||
(BLI_rctf_size_y(stored_bounds) > 100.0f));
|
||||
const bool mm_placement = WM_capabilities_flag() & WM_CAPABILITY_MULTIMONITOR_PLACEMENT;
|
||||
if (bounds_valid && mm_placement) {
|
||||
mx = int(stored_bounds->xmin * UI_SCALE_FAC);
|
||||
my = int(stored_bounds->ymin * UI_SCALE_FAC);
|
||||
}
|
||||
|
||||
const rcti window_rect = {
|
||||
/*xmin*/ mx,
|
||||
/*xmax*/ mx + sizex,
|
||||
/*ymin*/ my,
|
||||
/*ymax*/ my + sizey,
|
||||
};
|
||||
|
||||
/* changes context! */
|
||||
if (WM_window_open(C,
|
||||
IFACE_("Blender Render"),
|
||||
&window_rect,
|
||||
SPACE_IMAGE,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
WIN_ALIGN_ABSOLUTE,
|
||||
nullptr,
|
||||
nullptr) == nullptr)
|
||||
{
|
||||
BKE_report(reports, RPT_ERROR, "Failed to open window!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
area = CTX_wm_area(C);
|
||||
if (area->spacedata.is_single() == false) {
|
||||
sima = static_cast<SpaceImage *>(area->spacedata.first);
|
||||
sima->flag |= SI_PREVSPACE;
|
||||
}
|
||||
}
|
||||
else if (U.render_display_type == USER_RENDER_DISPLAY_SCREEN) {
|
||||
area = CTX_wm_area(C);
|
||||
|
||||
/* If the active screen is already in full-screen mode, skip this and
|
||||
* unset the area, so that the full-screen area is just changed later. */
|
||||
if (area && area->full) {
|
||||
area = nullptr;
|
||||
}
|
||||
else {
|
||||
if (area && area->spacetype == SPACE_IMAGE) {
|
||||
area_was_image = true;
|
||||
}
|
||||
|
||||
/* this function returns with changed context */
|
||||
area = ED_screen_full_newspace(C, area, SPACE_IMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!area) {
|
||||
wmWindow *win_show = nullptr;
|
||||
area = find_area_showing_render_result(C, scene, &win_show);
|
||||
if (area == nullptr) {
|
||||
/* No need to set `win_show` as the area selected will be from the active window. */
|
||||
area = find_area_image_empty(C);
|
||||
}
|
||||
|
||||
/* if area found in other window, we make that one show in front */
|
||||
if (win_show && win_show != CTX_wm_window(C)) {
|
||||
wm_window_raise(win_show);
|
||||
}
|
||||
|
||||
if (area == nullptr) {
|
||||
/* find largest open non-image area */
|
||||
area = biggest_non_image_area(C);
|
||||
if (area) {
|
||||
ED_area_newspace(C, area, SPACE_IMAGE, true);
|
||||
sima = static_cast<SpaceImage *>(area->spacedata.first);
|
||||
|
||||
/* Makes "Escape" go back to previous space. */
|
||||
sima->flag |= SI_PREVSPACE;
|
||||
|
||||
/* We already had a full-screen here -> mark new space as a stacked full-screen. */
|
||||
if (area->full) {
|
||||
area->flag |= AREA_FLAG_STACKED_FULLSCREEN;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* use any area of decent size */
|
||||
area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TYPE_ANY, 0);
|
||||
if (area->spacetype != SPACE_IMAGE) {
|
||||
// XXX newspace(area, SPACE_IMAGE);
|
||||
sima = static_cast<SpaceImage *>(area->spacedata.first);
|
||||
|
||||
/* Makes "Escape" go back to previous space. */
|
||||
sima->flag |= SI_PREVSPACE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sima = static_cast<SpaceImage *>(area->spacedata.first);
|
||||
sima->link_flag |= SPACE_FLAG_TYPE_TEMPORARY;
|
||||
|
||||
/* get the correct image, and scale it */
|
||||
sima->image = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
|
||||
|
||||
/* If we're rendering to full screen, set appropriate hints on image editor
|
||||
* so it can restore properly on pressing escape. */
|
||||
if (area->full) {
|
||||
sima->flag |= SI_FULLWINDOW;
|
||||
|
||||
/* Tell the image editor to revert to previous space in space list on close
|
||||
* _only_ if it wasn't already an image editor when the render was invoked */
|
||||
if (area_was_image == 0) {
|
||||
sima->flag |= SI_PREVSPACE;
|
||||
}
|
||||
else {
|
||||
/* Leave it alone so the image editor will just go back from
|
||||
* full screen to the original tiled setup */
|
||||
}
|
||||
}
|
||||
|
||||
if ((sima->flag & SI_PREVSPACE) && sima->next) {
|
||||
SpaceLink *old_sl = sima->next;
|
||||
old_sl->link_flag |= SPACE_FLAG_TYPE_WAS_ACTIVE;
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Cancel Render Viewer Operator
|
||||
* \{ */
|
||||
|
||||
static wmOperatorStatus render_view_cancel_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
|
||||
|
||||
/* ensure image editor full-screen and area full-screen states are in sync */
|
||||
if ((sima->flag & SI_FULLWINDOW) && !area->full) {
|
||||
sima->flag &= ~SI_FULLWINDOW;
|
||||
}
|
||||
|
||||
/* determine if render already shows */
|
||||
if (sima->flag & SI_PREVSPACE) {
|
||||
sima->flag &= ~SI_PREVSPACE;
|
||||
|
||||
if (sima->flag & SI_FULLWINDOW) {
|
||||
sima->flag &= ~SI_FULLWINDOW;
|
||||
ED_screen_full_prevspace(C, area);
|
||||
}
|
||||
else {
|
||||
ED_area_prevspace(C, area);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
if (sima->flag & SI_FULLWINDOW) {
|
||||
sima->flag &= ~SI_FULLWINDOW;
|
||||
ED_screen_state_toggle(C, win, area, SCREENMAXIMIZED);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
if (WM_window_is_temp_screen(win)) {
|
||||
wm_window_close_request(C, CTX_wm_manager(C), win);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
void RENDER_OT_view_cancel(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Cancel Render View";
|
||||
ot->description = "Cancel showing the render view";
|
||||
ot->idname = "RENDER_OT_view_cancel";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->exec = render_view_cancel_exec;
|
||||
ot->poll = ED_operator_image_active;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Show Render Viewer Operator
|
||||
* \{ */
|
||||
|
||||
static wmOperatorStatus render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
wmWindow *wincur = CTX_wm_window(C);
|
||||
|
||||
/* test if we have currently a temp screen active */
|
||||
if (WM_window_is_temp_screen(wincur)) {
|
||||
wm_window_lower(wincur);
|
||||
}
|
||||
else {
|
||||
wmWindow *win_show = nullptr;
|
||||
ScrArea *area = find_area_showing_render_result(C, CTX_data_scene(C), &win_show);
|
||||
|
||||
/* is there another window on current scene showing result? */
|
||||
for (wmWindow &win : CTX_wm_manager(C)->windows) {
|
||||
const bScreen *screen = WM_window_get_active_screen(&win);
|
||||
|
||||
if ((WM_window_is_temp_screen(&win) &&
|
||||
(static_cast<ScrArea *>(screen->areabase.first))->spacetype == SPACE_IMAGE) ||
|
||||
(&win == win_show && win_show != wincur))
|
||||
{
|
||||
wm_window_raise(&win);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
/* determine if render already shows */
|
||||
if (area) {
|
||||
/* but don't close it when rendering */
|
||||
if (G.is_rendering == false) {
|
||||
SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
|
||||
|
||||
if (sima->flag & SI_PREVSPACE) {
|
||||
sima->flag &= ~SI_PREVSPACE;
|
||||
|
||||
if (sima->flag & SI_FULLWINDOW) {
|
||||
sima->flag &= ~SI_FULLWINDOW;
|
||||
ED_screen_full_prevspace(C, area);
|
||||
}
|
||||
else {
|
||||
ED_area_prevspace(C, area);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
render_view_open(C, event->xy[0], event->xy[1], op->reports);
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void RENDER_OT_view_show(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Show/Hide Render View";
|
||||
ot->description = "Toggle show render view";
|
||||
ot->idname = "RENDER_OT_view_show";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->invoke = render_view_show_invoke;
|
||||
ot->poll = ED_operator_screenactive;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
Reference in New Issue
Block a user