WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 351 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
354 changed files with 3208 additions and 2941 deletions
Showing only changes of commit aec2761e9c - Show all commits

View File

@ -109,12 +109,12 @@ typedef struct CLG_LogRef {
struct CLG_LogRef *next;
} CLG_LogRef;
void CLG_log_str(CLG_LogType *lg,
void CLG_log_str(const CLG_LogType *lg,
enum CLG_Severity severity,
const char *file_line,
const char *fn,
const char *message) _CLOG_ATTR_NONNULL(1, 3, 4, 5);
void CLG_logf(CLG_LogType *lg,
void CLG_logf(const CLG_LogType *lg,
enum CLG_Severity severity,
const char *file_line,
const char *fn,
@ -156,7 +156,7 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
#define CLOG_AT_SEVERITY(clg_ref, severity, verbose_level, ...) \
{ \
CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
const CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || \
(severity >= CLG_SEVERITY_WARN)) \
{ \
@ -167,7 +167,7 @@ int CLG_color_support_get(CLG_LogRef *clg_ref);
#define CLOG_STR_AT_SEVERITY(clg_ref, severity, verbose_level, str) \
{ \
CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
const CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || \
(severity >= CLG_SEVERITY_WARN)) \
{ \

View File

@ -429,7 +429,7 @@ static void write_severity(CLogStringBuf *cstr, enum CLG_Severity severity, bool
}
}
static void write_type(CLogStringBuf *cstr, CLG_LogType *lg)
static void write_type(CLogStringBuf *cstr, const CLG_LogType *lg)
{
clg_str_append(cstr, " (");
clg_str_append(cstr, lg->identifier);
@ -460,7 +460,7 @@ static void write_file_line_fn(CLogStringBuf *cstr,
clg_str_append(cstr, ": ");
}
void CLG_log_str(CLG_LogType *lg,
void CLG_log_str(const CLG_LogType *lg,
enum CLG_Severity severity,
const char *file_line,
const char *fn,
@ -498,7 +498,7 @@ void CLG_log_str(CLG_LogType *lg,
}
}
void CLG_logf(CLG_LogType *lg,
void CLG_logf(const CLG_LogType *lg,
enum CLG_Severity severity,
const char *file_line,
const char *fn,

View File

@ -124,7 +124,8 @@ class DeviceInfo {
/* Multiple Devices with the same ID would be very bad. */
assert(id != info.id ||
(type == info.type && num == info.num && description == info.description));
return id == info.id;
return id == info.id && use_hardware_raytracing == info.use_hardware_raytracing &&
kernel_optimization_level == info.kernel_optimization_level;
}
};

View File

@ -512,8 +512,8 @@ static void updateGPUCurveMapping(OCIO_GPUCurveMappping &curvemap,
curvemap.cache_id = curve_mapping_settings->cache_id;
/* Update texture. */
int offset[3] = {0, 0, 0};
int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
const int offset[3] = {0, 0, 0};
const int extent[3] = {curve_mapping_settings->lut_size, 0, 0};
const float *pixels = curve_mapping_settings->lut;
GPU_texture_update_sub(
curvemap.texture, GPU_DATA_FLOAT, pixels, UNPACK3(offset), UNPACK3(extent));

View File

@ -60,17 +60,17 @@ TEST(MeshTopology, TrivialFaceTopology)
EXPECT_EQ(mesh_topology.getNumFaceVertices(2), 5);
{
int vertex_indices[] = {0, 1, 2, 3};
const int vertex_indices[] = {0, 1, 2, 3};
mesh_topology.setFaceVertexIndices(0, 4, vertex_indices);
}
{
int vertex_indices[] = {4, 5, 6};
const int vertex_indices[] = {4, 5, 6};
mesh_topology.setFaceVertexIndices(1, 3, vertex_indices);
}
{
int vertex_indices[] = {7, 8, 9, 10, 11};
const int vertex_indices[] = {7, 8, 9, 10, 11};
mesh_topology.setFaceVertexIndices(2, 5, vertex_indices);
}

View File

@ -417,7 +417,13 @@ class AnnotationDataPanel:
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
if context.space_data.type not in {'VIEW_3D', 'TOPBAR', 'SEQUENCE_EDITOR'}:
if context.space_data.type not in {
'VIEW_3D',
'TOPBAR',
'SEQUENCE_EDITOR',
'IMAGE_EDITOR',
'NODE_EDITOR',
'PROPERTIES'}:
self.layout.prop(context.space_data, "show_annotation", text="")
def draw(self, context):

View File

@ -171,8 +171,8 @@ class _defs_annotate:
gpl = context.active_annotation_layer
if gpl is not None:
layout.label(text="Annotation:")
if context.space_data.type in {'VIEW_3D', 'SEQUENCE_EDITOR'}:
if context.space_data.type in {'VIEW_3D', 'SEQUENCE_EDITOR', 'IMAGE_EDITOR', 'NODE_EDITOR'}:
layout.label(text="Annotation:")
if region_type == 'TOOL_HEADER':
sub = layout.split(align=True, factor=0.5)
sub.ui_units_x = 6.5
@ -184,7 +184,15 @@ class _defs_annotate:
panel="TOPBAR_PT_annotation_layers",
text=text,
)
elif context.space_data.type == 'PROPERTIES':
row = layout.row(align=True)
row.prop(gpl, "color", text="Annotation")
row.popover(
panel="TOPBAR_PT_annotation_layers",
text=text,
)
else:
layout.label(text="Annotation:")
layout.prop(gpl, "color", text="")
space_type = tool.space_type

View File

@ -6556,8 +6556,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col.prop(shading, "studiolight_intensity")
col.prop(shading, "studiolight_background_alpha")
if engine != 'BLENDER_EEVEE_NEXT':
col.prop(shading, "studiolight_background_blur")
col.prop(shading, "studiolight_background_blur")
col = split.column() # to align properly with above
elif shading.type == 'RENDERED':
@ -6582,8 +6581,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col.prop(shading, "studiolight_intensity")
col.prop(shading, "studiolight_background_alpha")
engine = context.scene.render.engine
if engine != 'BLENDER_EEVEE_NEXT':
col.prop(shading, "studiolight_background_blur")
col.prop(shading, "studiolight_background_blur")
col = split.column() # to align properly with above

View File

@ -223,7 +223,7 @@ bool AssetCatalogDefinitionFile::write_to_disk_unsafe(const CatalogFilePath &des
}
bool AssetCatalogDefinitionFile::ensure_directory_exists(
const CatalogFilePath directory_path) const
const CatalogFilePath &directory_path) const
{
/* TODO(@sybren): design a way to get such errors presented to users (or ensure that they never
* occur). */

View File

@ -81,7 +81,7 @@ class AssetCatalogDefinitionFile {
* Return true when the file was written correctly, false when there was a problem.
*/
bool write_to_disk_unsafe(const CatalogFilePath &dest_file_path) const;
bool ensure_directory_exists(const CatalogFilePath directory_path) const;
bool ensure_directory_exists(const CatalogFilePath &directory_path) const;
};
} // namespace blender::asset_system

View File

@ -20,7 +20,8 @@ namespace blender::asset_system {
AssetIdentifier::AssetIdentifier(std::shared_ptr<std::string> library_root_path,
std::string relative_asset_path)
: library_root_path_(library_root_path), relative_asset_path_(relative_asset_path)
: library_root_path_(std::move(library_root_path)),
relative_asset_path_(std::move(relative_asset_path))
{
}

View File

@ -22,7 +22,7 @@ AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
const int id_type,
std::unique_ptr<AssetMetaData> metadata,
const AssetLibrary &owner_asset_library)
: identifier_(identifier),
: identifier_(std::move(identifier)),
is_local_id_(false),
owner_asset_library_(owner_asset_library),
external_asset_()
@ -35,7 +35,7 @@ AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier,
ID &id,
const AssetLibrary &owner_asset_library)
: identifier_(identifier),
: identifier_(std::move(identifier)),
is_local_id_(true),
owner_asset_library_(owner_asset_library),
local_asset_id_(&id)

View File

@ -144,8 +144,8 @@ void BLF_batch_draw_end();
/**
* Draw the string using the current font.
*/
void BLF_draw_ex(int fontid, const char *str, size_t str_len, ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_draw(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
ATTR_NONNULL(2);
int BLF_draw_mono(int fontid, const char *str, size_t str_len, int cwidth, int tab_columns)
ATTR_NONNULL(2);
@ -205,23 +205,21 @@ size_t BLF_width_to_rstrlen(int fontid,
* This function return the bounding box of the string
* and are not multiplied by the aspect.
*/
void BLF_boundbox_ex(int fontid, const char *str, size_t str_len, rcti *box, ResultBLF *r_info)
ATTR_NONNULL(2);
void BLF_boundbox(int fontid, const char *str, size_t str_len, rcti *box) ATTR_NONNULL();
void BLF_boundbox(int fontid,
const char *str,
size_t str_len,
rcti *box,
ResultBLF *r_info = nullptr) ATTR_NONNULL(2);
/**
* The next both function return the width and height
* of the string, using the current font and both value
* are multiplied by the aspect of the font.
*/
float BLF_width_ex(int fontid, const char *str, size_t str_len, ResultBLF *r_info)
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_width(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
float BLF_height_ex(int fontid, const char *str, size_t str_len, ResultBLF *r_info)
float BLF_height(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_height(int fontid, const char *str, size_t str_len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
/**
* Return dimensions of the font without any sample text.
@ -306,9 +304,8 @@ void BLF_buffer_col(int fontid, const float rgba[4]) ATTR_NONNULL(2);
* Draw the string into the buffer, this function draw in both buffer,
* float and unsigned char _BUT_ it's not necessary set both buffer, NULL is valid here.
*/
void BLF_draw_buffer_ex(int fontid, const char *str, size_t str_len, ResultBLF *r_info)
void BLF_draw_buffer(int fontid, const char *str, size_t str_len, ResultBLF *r_info = nullptr)
ATTR_NONNULL(2);
void BLF_draw_buffer(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2);
/* `blf_thumbs.cc` */

View File

@ -567,13 +567,21 @@ static void blf_draw_gpu__end(const FontBLF *font)
}
}
void BLF_draw_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
void BLF_draw(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
BLF_RESULT_CHECK_INIT(r_info);
if (str_len == 0 || str[0] == '\0') {
return;
}
FontBLF *font = blf_get(fontid);
if (font) {
/* Avoid bgl usage to corrupt BLF drawing. */
GPU_bgl_end();
blf_draw_gpu__start(font);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw__wrap(font, str, str_len, r_info);
@ -584,17 +592,6 @@ void BLF_draw_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r
blf_draw_gpu__end(font);
}
}
void BLF_draw(int fontid, const char *str, const size_t str_len)
{
if (str_len == 0 || str[0] == '\0') {
return;
}
/* Avoid bgl usage to corrupt BLF drawing. */
GPU_bgl_end();
BLF_draw_ex(fontid, str, str_len, nullptr);
}
int BLF_draw_mono(int fontid, const char *str, const size_t str_len, int cwidth, int tab_columns)
{
@ -699,7 +696,7 @@ size_t BLF_width_to_rstrlen(
return 0;
}
void BLF_boundbox_ex(
void BLF_boundbox(
int fontid, const char *str, const size_t str_len, rcti *r_box, ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@ -716,11 +713,6 @@ void BLF_boundbox_ex(
}
}
void BLF_boundbox(int fontid, const char *str, const size_t str_len, rcti *r_box)
{
BLF_boundbox_ex(fontid, str, str_len, r_box, nullptr);
}
void BLF_width_and_height(
int fontid, const char *str, const size_t str_len, float *r_width, float *r_height)
{
@ -734,7 +726,7 @@ void BLF_width_and_height(
}
}
float BLF_width_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
float BLF_width(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@ -747,11 +739,6 @@ float BLF_width_ex(int fontid, const char *str, const size_t str_len, ResultBLF
return 0.0f;
}
float BLF_width(int fontid, const char *str, const size_t str_len)
{
return BLF_width_ex(fontid, str, str_len, nullptr);
}
float BLF_fixed_width(int fontid)
{
FontBLF *font = blf_get(fontid);
@ -763,7 +750,7 @@ float BLF_fixed_width(int fontid)
return 0.0f;
}
float BLF_height_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
float BLF_height(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@ -776,11 +763,6 @@ float BLF_height_ex(int fontid, const char *str, const size_t str_len, ResultBLF
return 0.0f;
}
float BLF_height(int fontid, const char *str, const size_t str_len)
{
return BLF_height_ex(fontid, str, str_len, nullptr);
}
int BLF_height_max(int fontid)
{
FontBLF *font = blf_get(fontid);
@ -915,7 +897,7 @@ void blf_draw_buffer__start(FontBLF *font)
}
void blf_draw_buffer__end() {}
void BLF_draw_buffer_ex(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
void BLF_draw_buffer(int fontid, const char *str, const size_t str_len, ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
@ -930,10 +912,6 @@ void BLF_draw_buffer_ex(int fontid, const char *str, const size_t str_len, Resul
blf_draw_buffer__end();
}
}
void BLF_draw_buffer(int fontid, const char *str, const size_t str_len)
{
BLF_draw_buffer_ex(fontid, str, str_len, nullptr);
}
blender::Vector<blender::StringRef> BLF_string_wrap(int fontid,
blender::StringRef str,

View File

@ -12,14 +12,14 @@
#include "BLI_bounds_types.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_implicit_sharing.hh"
#include "BLI_index_mask.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_offset_indices.hh"
#include "BLI_shared_cache.hh"
#include "BLI_span.hh"
#include "BLI_vector.hh"
#include "BLI_virtual_array.hh"
#include "BLI_virtual_array_fwd.hh"
#include "BKE_attribute_math.hh"
#include "BKE_curves.h"

View File

@ -28,13 +28,13 @@ void cdf_free(CDataFile *cdf);
/* File read/write/remove */
bool cdf_read_open(CDataFile *cdf, const char *filepath);
bool cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay);
bool cdf_read_layer(CDataFile *cdf, const CDataFileLayer *blay);
bool cdf_read_data(CDataFile *cdf, unsigned int size, void *data);
void cdf_read_close(CDataFile *cdf);
bool cdf_write_open(CDataFile *cdf, const char *filepath);
bool cdf_write_layer(CDataFile *cdf, CDataFileLayer *blay);
bool cdf_write_data(CDataFile *cdf, unsigned int size, void *data);
bool cdf_write_data(CDataFile *cdf, unsigned int size, const void *data);
void cdf_write_close(CDataFile *cdf);
void cdf_remove(const char *filepath);

View File

@ -6,7 +6,7 @@
#include "BLI_math_vector_types.hh"
#include "BLI_offset_indices.hh"
#include "BLI_virtual_array.hh"
#include "BLI_virtual_array_fwd.hh"
/** \file
* \ingroup bke

View File

@ -32,9 +32,7 @@ void legacy_gpencil_object(Main &bmain, Object &object);
void legacy_main(Main &bmain, BlendFileReadReport &reports);
void thickness_factor_to_modifier(const bGPdata &src_object_data, Object &dst_object);
void layer_adjustments_to_modifiers(Main &bmain,
const bGPdata &src_object_data,
Object &dst_object);
void layer_adjustments_to_modifiers(Main &bmain, bGPdata &src_object_data, Object &dst_object);
void lineart_wrap_v3(const LineartGpencilModifierData *lmd_legacy,
GreasePencilLineartModifierData *lmd);

View File

@ -140,7 +140,7 @@ Mesh *BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *
bool BKE_mesh_attribute_required(const char *name);
float (*BKE_mesh_orco_verts_get(Object *ob))[3];
float (*BKE_mesh_orco_verts_get(const Object *ob))[3];
void BKE_mesh_orco_verts_transform(Mesh *mesh, float (*orco)[3], int totvert, bool invert);
/**

View File

@ -140,9 +140,6 @@ struct MeshRuntime {
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
BVHCache *bvh_cache = nullptr;
/** Cache of non-manifold boundary data for Shrink-wrap Target Project. */
std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_data;
/** Needed in case we need to lazily initialize the mesh. */
CustomData_MeshMasks cd_mask_extra = {};
@ -204,6 +201,9 @@ struct MeshRuntime {
/** Cache of data about vertices not used by faces. See #Mesh::verts_no_face(). */
SharedCache<LooseVertCache> verts_no_face_cache;
/** Cache of non-manifold boundary data for shrinkwrap target Project. */
SharedCache<ShrinkwrapBoundaryData> shrinkwrap_boundary_cache;
/**
* A bit vector the size of the number of vertices, set to true for the center vertices of
* subdivided faces. The values are set by the subdivision surface modifier and used by

View File

@ -16,7 +16,7 @@
#include "BLI_bounds_types.hh"
#include "BLI_compiler_compat.h"
#include "BLI_function_ref.hh"
#include "BLI_index_mask.hh"
#include "BLI_index_mask_fwd.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_offset_indices.hh"
#include "BLI_span.hh"

View File

@ -283,7 +283,7 @@ void BKE_scene_multiview_view_filepath_get(const RenderData *rd,
const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char *viewname);
const char *BKE_scene_multiview_view_id_suffix_get(const RenderData *rd, int view_id);
void BKE_scene_multiview_view_prefix_get(Scene *scene,
const char *name,
const char *filepath,
char *r_prefix,
const char **r_ext);
void BKE_scene_multiview_videos_dimensions_get(

View File

@ -60,10 +60,11 @@ struct ShrinkwrapBoundaryData {
blender::Array<ShrinkwrapBoundaryVertData> boundary_verts;
};
/**
* Free boundary data for target project.
*/
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh);
namespace blender::bke::shrinkwrap {
const ShrinkwrapBoundaryData &boundary_cache_ensure(const Mesh &mesh);
} // namespace blender::bke::shrinkwrap
/* Information about a mesh and BVH tree. */
struct ShrinkwrapTreeData {
@ -79,7 +80,7 @@ struct ShrinkwrapTreeData {
blender::Span<blender::float3> vert_normals;
blender::Span<blender::float3> corner_normals;
const bool *sharp_faces;
ShrinkwrapBoundaryData *boundary;
const ShrinkwrapBoundaryData *boundary;
};
/**

View File

@ -65,7 +65,7 @@ void txt_clean_text(struct Text *text);
void txt_order_cursors(struct Text *text, bool reverse);
int txt_find_string(struct Text *text, const char *findstr, int wrap, int match_case);
bool txt_has_sel(const struct Text *text);
int txt_get_span(struct TextLine *from, struct TextLine *to);
int txt_get_span(struct TextLine *from, const struct TextLine *to);
void txt_move_up(struct Text *text, bool sel);
void txt_move_down(struct Text *text, bool sel);
void txt_move_left(struct Text *text, bool sel);
@ -116,8 +116,8 @@ int txt_setcurr_tab_spaces(struct Text *text, int space);
bool txt_cursor_is_line_start(const struct Text *text);
bool txt_cursor_is_line_end(const struct Text *text);
int txt_calc_tab_left(struct TextLine *tl, int ch);
int txt_calc_tab_right(struct TextLine *tl, int ch);
int txt_calc_tab_left(const struct TextLine *tl, int ch);
int txt_calc_tab_right(const struct TextLine *tl, int ch);
/**
* Utility functions, could be moved somewhere more generic but are python/text related.

View File

@ -102,7 +102,7 @@ bool BKE_vfont_to_curve_ex(Object *ob,
CharTrans **r_chartransdata);
bool BKE_vfont_to_curve_nubase(Object *ob, eEditFontMode mode, ListBase *r_nubase);
int BKE_vfont_cursor_to_text_index(Object *ob, float cursor_location[2]);
int BKE_vfont_cursor_to_text_index(Object *ob, const float cursor_location[2]);
/**
* \warning Expects to have access to evaluated data (i.e. passed object should be evaluated one).
@ -111,7 +111,7 @@ bool BKE_vfont_to_curve(Object *ob, eEditFontMode mode);
void BKE_vfont_build_char(Curve *cu,
ListBase *nubase,
unsigned int character,
CharInfo *info,
const CharInfo *info,
float ofsx,
float ofsy,
float rot,

View File

@ -318,7 +318,7 @@ void DM_interp_vert_data(const DerivedMesh *source,
&source->vertData, &dest->vertData, src_indices, weights, nullptr, count, dest_index);
}
static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
static float (*get_editbmesh_orco_verts(const BMEditMesh *em))[3]
{
BMIter iter;
BMVert *eve;
@ -338,7 +338,7 @@ static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
}
/* orco custom data layer */
static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free))[3]
static float (*get_orco_coords(const Object *ob, const BMEditMesh *em, int layer, int *free))[3]
{
*free = 0;
@ -355,11 +355,11 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free)
/* apply shape key for cloth, this should really be solved
* by a more flexible customdata system, but not simple */
if (!em) {
ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type(
const ClothModifierData *clmd = (const ClothModifierData *)BKE_modifiers_findby_type(
ob, eModifierType_Cloth);
if (clmd && clmd->sim_parms->shapekey_rest) {
KeyBlock *kb = BKE_keyblock_find_by_index(BKE_key_from_object(ob),
clmd->sim_parms->shapekey_rest);
const KeyBlock *kb = BKE_keyblock_find_by_index(
BKE_key_from_object(const_cast<Object *>(ob)), clmd->sim_parms->shapekey_rest);
if (kb && kb->data) {
return (float(*)[3])kb->data;
@ -373,7 +373,7 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free)
return nullptr;
}
static Mesh *create_orco_mesh(Object *ob, Mesh *mesh, BMEditMesh *em, int layer)
static Mesh *create_orco_mesh(const Object *ob, const Mesh *mesh, const BMEditMesh *em, int layer)
{
Mesh *orco_mesh;
float(*orco)[3];
@ -410,8 +410,11 @@ static MutableSpan<float3> orco_coord_layer_ensure(Mesh *mesh, const eCustomData
return MutableSpan(reinterpret_cast<float3 *>(data), mesh->verts_num);
}
static void add_orco_mesh(
Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orco, const eCustomDataType layer)
static void add_orco_mesh(Object *ob,
const BMEditMesh *em,
Mesh *mesh,
const Mesh *mesh_orco,
const eCustomDataType layer)
{
const int totvert = mesh->verts_num;
@ -1269,12 +1272,14 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
}
}
static void mesh_build_extra_data(Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval)
static void mesh_build_extra_data(const Depsgraph *depsgraph,
const Object *ob,
const Mesh *mesh_eval)
{
uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id);
if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) {
BKE_shrinkwrap_compute_boundary_data(mesh_eval);
blender::bke::shrinkwrap::boundary_cache_ensure(*mesh_eval);
}
}

View File

@ -4799,7 +4799,7 @@ void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, co
/* pass */
}
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
const CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
if (blay) {
if (cdf_read_layer(cdf, blay)) {

View File

@ -295,7 +295,7 @@ bool cdf_read_open(CDataFile *cdf, const char *filepath)
return true;
}
bool cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay)
bool cdf_read_layer(CDataFile *cdf, const CDataFileLayer *blay)
{
size_t offset;
int a;
@ -387,7 +387,7 @@ bool cdf_write_layer(CDataFile * /*cdf*/, CDataFileLayer * /*blay*/)
return true;
}
bool cdf_write_data(CDataFile *cdf, uint size, void *data)
bool cdf_write_data(CDataFile *cdf, uint size, const void *data)
{
/* write data */
if (!fwrite(data, size, 1, cdf->writef)) {

View File

@ -10,6 +10,7 @@
#include <fmt/format.h>
#include "BKE_action.h"
#include "BKE_anim_data.hh"
#include "BKE_attribute.hh"
#include "BKE_colorband.hh"
@ -62,23 +63,51 @@ namespace blender::bke::greasepencil::convert {
* (also includes drivers, and actions linked through the NLA).
* \{ */
static bool legacy_fcurves_process(ListBase &fcurves,
blender::FunctionRef<bool(FCurve *fcurve)> callback)
using FCurveCallback = bool(bAction *owner_action, FCurve &fcurve);
/* Utils to move a list of fcurves from one container (Action or Drivers) to another. */
static void legacy_fcurves_move(ListBase &fcurves_dst,
ListBase &fcurves_src,
const Span<FCurve *> fcurves)
{
for (FCurve *fcurve : fcurves) {
BLI_assert(BLI_findindex(&fcurves_src, fcurve) >= 0);
BLI_remlink(&fcurves_src, fcurve);
BLI_addtail(&fcurves_dst, fcurve);
}
}
/* Basic common check to decide whether a legacy fcurve should be processed or not. */
static bool legacy_fcurves_is_valid_for_root_path(FCurve &fcurve, StringRefNull legacy_root_path)
{
if (!fcurve.rna_path) {
return false;
}
StringRefNull rna_path = fcurve.rna_path;
if (!rna_path.startswith(legacy_root_path)) {
return false;
}
return true;
}
static bool legacy_fcurves_process(bAction *owner_action,
ListBase &fcurves,
blender::FunctionRef<FCurveCallback> callback)
{
bool is_changed = false;
LISTBASE_FOREACH (FCurve *, fcurve, &fcurves) {
const bool local_is_changed = callback(fcurve);
const bool local_is_changed = callback(owner_action, *fcurve);
is_changed = is_changed || local_is_changed;
}
return is_changed;
}
static bool legacy_nla_strip_process(NlaStrip &nla_strip,
blender::FunctionRef<bool(FCurve *fcurve)> callback)
blender::FunctionRef<FCurveCallback> callback)
{
bool is_changed = false;
if (nla_strip.act) {
if (legacy_fcurves_process(nla_strip.act->curves, callback)) {
if (legacy_fcurves_process(nla_strip.act, nla_strip.act->curves, callback)) {
DEG_id_tag_update(&nla_strip.act->id, ID_RECALC_ANIMATION);
is_changed = true;
}
@ -91,24 +120,24 @@ static bool legacy_nla_strip_process(NlaStrip &nla_strip,
}
static bool legacy_animation_process(AnimData &anim_data,
blender::FunctionRef<bool(FCurve *fcurve)> callback)
blender::FunctionRef<FCurveCallback> callback)
{
bool is_changed = false;
if (anim_data.action) {
if (legacy_fcurves_process(anim_data.action->curves, callback)) {
if (legacy_fcurves_process(anim_data.action, anim_data.action->curves, callback)) {
DEG_id_tag_update(&anim_data.action->id, ID_RECALC_ANIMATION);
is_changed = true;
}
}
if (anim_data.tmpact) {
if (legacy_fcurves_process(anim_data.tmpact->curves, callback)) {
if (legacy_fcurves_process(anim_data.tmpact, anim_data.tmpact->curves, callback)) {
DEG_id_tag_update(&anim_data.tmpact->id, ID_RECALC_ANIMATION);
is_changed = true;
}
}
{
const bool local_is_changed = legacy_fcurves_process(anim_data.drivers, callback);
const bool local_is_changed = legacy_fcurves_process(nullptr, anim_data.drivers, callback);
is_changed = is_changed || local_is_changed;
}
@ -623,6 +652,15 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
copy_v3_v3(grease_pencil.onion_skinning_settings.color_after, gpd.gcolor_next);
BKE_id_materials_copy(&bmain, &gpd.id, &grease_pencil.id);
/* Copy animation data from legacy GP data.
*
* Note that currently, Actions IDs are not duplicated. They may be needed ultimately, but for
* the time being, assuming invalid fcurves/drivers are fine here. */
if (AnimData *gpd_animdata = BKE_animdata_from_id(&gpd.id)) {
grease_pencil.adt = BKE_animdata_copy_in_lib(
&bmain, gpd.id.lib, gpd_animdata, LIB_ID_COPY_DEFAULT);
}
}
static bNodeTree *add_offset_radius_node_tree(Main &bmain)
@ -737,18 +775,115 @@ void thickness_factor_to_modifier(const bGPdata &src_object_data, Object &dst_ob
BKE_modifiers_persistent_uid_init(dst_object, *md);
}
void layer_adjustments_to_modifiers(Main &bmain,
const bGPdata &src_object_data,
Object &dst_object)
void layer_adjustments_to_modifiers(Main &bmain, bGPdata &src_object_data, Object &dst_object)
{
bNodeTree *offset_radius_node_tree = nullptr;
/* Handling of animation here is a bit complex, since paths needs to be updated, but also
* FCurves need to be transferred from legacy GPData animation to Object animation.
*
* NOTE: NLA animation in GPData that would control adjustment properties is not converted. This
* would require (partially) re-creating a copy of the potential bGPData NLA into the Object NLA,
* which is too complex for the few potential usecases.
*
* This is achieved in several steps, roughly:
* * For each GP layer, chack if there is animation on the adjutment data.
* * Rename relevant FCurves RNA paths from GP animation data, and store their reference in
* temporary vectors.
* * Once all layers have been processed, move all affected FCurves from GPData animation to
* Object one. */
AnimData *gpd_animdata = BKE_animdata_from_id(&src_object_data.id);
AnimData *dst_object_animdata = BKE_animdata_from_id(&dst_object.id);
/* Old 'adjutment' GPData RNA property path to new matching modifier property RNA path. */
static const std::pair<const char *, const char *> fcurve_tint_valid_prop_paths[] = {
{".tint_color", ".color"}, {".tint_factor", ".factor"}};
static const std::pair<const char *, const char *> fcurve_thickness_valid_prop_paths[] = {
{".line_change", "[\"Socket_1\"]"}};
/* Store all FCurves that need to be moved from GPData animation to Object animation,
* respectively for the main action, the temp action, and the drivers. */
blender::Vector<FCurve *> fcurves_from_gpd_main_action;
blender::Vector<FCurve *> fcurves_from_gpd_tmp_action;
blender::Vector<FCurve *> fcurves_from_gpd_drivers;
/* Common filtering of FCurve RNA path to decide whether they can/need to be processed here or
* not. */
auto adjustment_animation_fcurve_is_valid =
[&](bAction *owner_action, FCurve &fcurve, blender::StringRefNull legacy_root_path) -> bool {
/* Only take into account drivers (nullptr `action_owner`), and Actions directly assigned
* to the animdata, not the NLA ones. */
if (owner_action && !ELEM(owner_action, gpd_animdata->action, gpd_animdata->tmpact)) {
return false;
}
if (!legacy_fcurves_is_valid_for_root_path(fcurve, legacy_root_path)) {
return false;
}
return true;
};
/* Replace layer adjustments with modifiers. */
LISTBASE_FOREACH (bGPDlayer *, gpl, &src_object_data.layers) {
const float3 tint_color = float3(gpl->tintcolor);
const float tint_factor = gpl->tintcolor[3];
const int thickness_px = gpl->line_change;
bool has_tint_adjustment = tint_factor > 0.0f;
bool has_tint_adjustment_animation = false;
bool has_thickness_adjustment = thickness_px != 0;
bool has_thickness_adjustment_animation = false;
char layer_name_esc[sizeof(gpl->info) * 2];
BLI_str_escape(layer_name_esc, gpl->info, sizeof(layer_name_esc));
const std::string legacy_root_path = fmt::format("layers[\"{}\"]", layer_name_esc);
/* If tint or thickness are animated, relevamt modifiers also need to be created. */
if (gpd_animdata) {
auto adjustment_animation_detection = [&](bAction *owner_action, FCurve &fcurve) -> bool {
/* Early out if we already know that both data are animated. */
if (has_tint_adjustment_animation && has_thickness_adjustment_animation) {
return false;
}
if (!adjustment_animation_fcurve_is_valid(owner_action, fcurve, legacy_root_path)) {
return false;
}
StringRefNull rna_path = fcurve.rna_path;
for (const auto &[from_prop_path, to_prop_path] : fcurve_tint_valid_prop_paths) {
const char *rna_adjustment_prop_path = from_prop_path;
const std::string old_rna_path = fmt::format(
"{}{}", legacy_root_path, rna_adjustment_prop_path);
if (rna_path == old_rna_path) {
has_tint_adjustment_animation = true;
return false;
}
}
for (const auto &[from_prop_path, to_prop_path] : fcurve_thickness_valid_prop_paths) {
const char *rna_prop_rna_adjustment_prop_pathpath = from_prop_path;
const std::string old_rna_path = fmt::format(
"{}{}", legacy_root_path, rna_prop_rna_adjustment_prop_pathpath);
if (rna_path == old_rna_path) {
has_thickness_adjustment_animation = true;
return false;
}
}
return false;
};
legacy_animation_process(*gpd_animdata, adjustment_animation_detection);
has_tint_adjustment = has_tint_adjustment || has_tint_adjustment_animation;
has_thickness_adjustment = has_thickness_adjustment || has_thickness_adjustment_animation;
}
/* Create animdata in destination object if needed. */
if ((has_tint_adjustment_animation || has_thickness_adjustment_animation) &&
!dst_object_animdata)
{
dst_object_animdata = BKE_animdata_ensure_id(&dst_object.id);
}
/* Tint adjustment. */
if (tint_factor > 0.0f) {
if (has_tint_adjustment) {
ModifierData *md = BKE_modifier_new(eModifierType_GreasePencilTint);
GreasePencilTintModifierData *tmd = reinterpret_cast<GreasePencilTintModifierData *>(md);
@ -756,16 +891,59 @@ void layer_adjustments_to_modifiers(Main &bmain,
tmd->factor = tint_factor;
STRNCPY(tmd->influence.layer_name, gpl->info);
char modifier_name[64];
char modifier_name[MAX_NAME];
SNPRINTF(modifier_name, "Tint %s", gpl->info);
STRNCPY(md->name, modifier_name);
BKE_modifier_unique_name(&dst_object.modifiers, md);
BLI_addtail(&dst_object.modifiers, md);
BKE_modifiers_persistent_uid_init(dst_object, *md);
if (has_tint_adjustment_animation) {
char modifier_name_esc[MAX_NAME * 2];
BLI_str_escape(modifier_name_esc, md->name, sizeof(modifier_name_esc));
auto adjustment_tint_path_update = [&](bAction *owner_action, FCurve &fcurve) -> bool {
if (!adjustment_animation_fcurve_is_valid(owner_action, fcurve, legacy_root_path)) {
return false;
}
StringRefNull rna_path = fcurve.rna_path;
for (const auto &[from_prop_path, to_prop_path] : fcurve_tint_valid_prop_paths) {
const char *rna_adjustment_prop_path = from_prop_path;
const char *rna_modifier_prop_path = to_prop_path;
const std::string old_rna_path = fmt::format(
"{}{}", legacy_root_path, rna_adjustment_prop_path);
if (rna_path == old_rna_path) {
const std::string new_rna_path = fmt::format(
"modifiers[\"{}\"]{}", modifier_name_esc, rna_modifier_prop_path);
MEM_freeN(fcurve.rna_path);
fcurve.rna_path = BLI_strdupn(new_rna_path.c_str(), new_rna_path.size());
if (owner_action) {
if (owner_action == gpd_animdata->action) {
fcurves_from_gpd_main_action.append(&fcurve);
}
else {
BLI_assert(owner_action == gpd_animdata->tmpact);
fcurves_from_gpd_tmp_action.append(&fcurve);
}
}
else { /* Driver */
fcurves_from_gpd_drivers.append(&fcurve);
}
return true;
}
}
return false;
};
const bool has_edits = legacy_animation_process(*gpd_animdata,
adjustment_tint_path_update);
BLI_assert(has_edits);
UNUSED_VARS_NDEBUG(has_edits);
}
}
/* Thickness adjustment. */
if (thickness_px != 0) {
if (has_thickness_adjustment) {
/* Convert the "pixel" offset value into a radius value.
* GPv2 used a conversion of 1 "px" = 0.001. */
/* Note: this offset may be negative. */
@ -776,7 +954,7 @@ void layer_adjustments_to_modifiers(Main &bmain,
}
auto *md = reinterpret_cast<NodesModifierData *>(BKE_modifier_new(eModifierType_Nodes));
char modifier_name[64];
char modifier_name[MAX_NAME];
SNPRINTF(modifier_name, "Thickness %s", gpl->info);
STRNCPY(md->modifier.name, modifier_name);
BKE_modifier_unique_name(&dst_object.modifiers, &md->modifier);
@ -790,14 +968,85 @@ void layer_adjustments_to_modifiers(Main &bmain,
bke::idprop::create(DATA_("Socket_2"), radius_offset).release();
auto *ui_data = reinterpret_cast<IDPropertyUIDataFloat *>(
IDP_ui_data_ensure(radius_offset_prop));
ui_data->soft_min = 0.0f;
ui_data->soft_min = 0.0;
ui_data->base.rna_subtype = PROP_TRANSLATION;
IDP_AddToGroup(md->settings.properties, radius_offset_prop);
IDP_AddToGroup(md->settings.properties,
bke::idprop::create(DATA_("Socket_3"), gpl->info).release());
if (has_thickness_adjustment_animation) {
char modifier_name_esc[MAX_NAME * 2];
BLI_str_escape(modifier_name_esc, md->modifier.name, sizeof(modifier_name_esc));
auto adjustment_thickness_path_update = [&](bAction *owner_action,
FCurve &fcurve) -> bool {
if (!adjustment_animation_fcurve_is_valid(owner_action, fcurve, legacy_root_path)) {
return false;
}
StringRefNull rna_path = fcurve.rna_path;
for (const auto &[from_prop_path, to_prop_path] : fcurve_thickness_valid_prop_paths) {
const char *rna_adjustment_prop_path = from_prop_path;
const char *rna_modifier_prop_path = to_prop_path;
const std::string old_rna_path = fmt::format(
"{}{}", legacy_root_path, rna_adjustment_prop_path);
if (rna_path == old_rna_path) {
const std::string new_rna_path = fmt::format(
"modifiers[\"{}\"]{}", modifier_name_esc, rna_modifier_prop_path);
MEM_freeN(fcurve.rna_path);
fcurve.rna_path = BLI_strdupn(new_rna_path.c_str(), new_rna_path.size());
if (owner_action) {
if (owner_action == gpd_animdata->action) {
fcurves_from_gpd_main_action.append(&fcurve);
}
else {
BLI_assert(owner_action == gpd_animdata->tmpact);
fcurves_from_gpd_tmp_action.append(&fcurve);
}
}
else { /* Driver */
fcurves_from_gpd_drivers.append(&fcurve);
}
return true;
}
}
return false;
};
const bool has_edits = legacy_animation_process(*gpd_animdata,
adjustment_thickness_path_update);
BLI_assert(has_edits);
UNUSED_VARS_NDEBUG(has_edits);
}
}
}
if (!fcurves_from_gpd_main_action.is_empty()) {
if (!dst_object_animdata->action) {
dst_object_animdata->action = BKE_action_add(&bmain, gpd_animdata->action->id.name + 2);
}
legacy_fcurves_move(dst_object_animdata->action->curves,
gpd_animdata->action->curves,
fcurves_from_gpd_main_action);
DEG_id_tag_update(&dst_object.id, ID_RECALC_ANIMATION);
DEG_id_tag_update(&src_object_data.id, ID_RECALC_ANIMATION);
}
if (!fcurves_from_gpd_tmp_action.is_empty()) {
if (!dst_object_animdata->tmpact) {
dst_object_animdata->tmpact = BKE_action_add(&bmain, gpd_animdata->tmpact->id.name + 2);
}
legacy_fcurves_move(dst_object_animdata->tmpact->curves,
gpd_animdata->tmpact->curves,
fcurves_from_gpd_tmp_action);
DEG_id_tag_update(&dst_object.id, ID_RECALC_ANIMATION);
DEG_id_tag_update(&src_object_data.id, ID_RECALC_ANIMATION);
}
if (!fcurves_from_gpd_drivers.is_empty()) {
legacy_fcurves_move(
dst_object_animdata->drivers, gpd_animdata->drivers, fcurves_from_gpd_drivers);
DEG_id_tag_update(&dst_object.id, ID_RECALC_ANIMATION);
DEG_id_tag_update(&src_object_data.id, ID_RECALC_ANIMATION);
}
DEG_relations_tag_update(&bmain);
}
@ -805,7 +1054,7 @@ static ModifierData &legacy_object_modifier_common(Object &object,
const ModifierType type,
GpencilModifierData &legacy_md)
{
/* TODO: Copy of most of #ED_object_modifier_add, this should be a BKE_modifiers function
/* TODO: Copy of most of #ed::object::modifier_add, this should be a BKE_modifiers function
* actually. */
const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
@ -838,8 +1087,7 @@ static ModifierData &legacy_object_modifier_common(Object &object,
new_md.ui_expand_flag = legacy_md.ui_expand_flag;
/* Convert animation data if needed. */
AnimData *anim_data = BKE_animdata_from_id(&object.id);
if (anim_data) {
if (AnimData *anim_data = BKE_animdata_from_id(&object.id)) {
char legacy_name_esc[MAX_NAME * 2];
BLI_str_escape(legacy_name_esc, legacy_md.name, sizeof(legacy_name_esc));
const std::string legacy_root_path = fmt::format("grease_pencil_modifiers[\"{}\"]",
@ -847,20 +1095,15 @@ static ModifierData &legacy_object_modifier_common(Object &object,
char new_name_esc[MAX_NAME * 2];
BLI_str_escape(new_name_esc, new_md.name, sizeof(new_name_esc));
auto modifier_path_update = [&](FCurve *fcurve) -> bool {
/* NOTE: This logic will likely need to be re-used in other similar conditions for other
* areas, should be put into its own util then. */
if (!fcurve->rna_path) {
return false;
}
StringRefNull rna_path = fcurve->rna_path;
if (!rna_path.startswith(legacy_root_path)) {
auto modifier_path_update = [&](bAction * /*owner_action*/, FCurve &fcurve) -> bool {
if (!legacy_fcurves_is_valid_for_root_path(fcurve, legacy_root_path)) {
return false;
}
StringRefNull rna_path = fcurve.rna_path;
const std::string new_rna_path = fmt::format(
"modifiers[\"{}\"]{}", new_name_esc, rna_path.substr(int64_t(legacy_root_path.size())));
MEM_freeN(fcurve->rna_path);
fcurve->rna_path = BLI_strdupn(new_rna_path.c_str(), new_rna_path.size());
MEM_freeN(fcurve.rna_path);
fcurve.rna_path = BLI_strdupn(new_rna_path.c_str(), new_rna_path.size());
return true;
};

View File

@ -2003,7 +2003,7 @@ void BKE_image_stamp_buf(Scene *scene,
/* must enable BLF_WORD_WRAP before using */
#define TEXT_SIZE_CHECK_WORD_WRAP(str, w, h) \
((str[0]) && (BLF_boundbox_ex(mono, str, sizeof(str), &wrap.rect, &wrap.info), \
((str[0]) && (BLF_boundbox(mono, str, sizeof(str), &wrap.rect, &wrap.info), \
(void)(h = h_fixed * wrap.info.lines), \
(w = BLI_rcti_size_x(&wrap.rect))))

View File

@ -1022,8 +1022,8 @@ static const char *particle_adrcodes_to_paths(int adrcode, int *r_array_index)
static char *get_rna_access(ID *id,
int blocktype,
int adrcode,
char actname[],
char constname[],
const char actname[],
const char constname[],
Sequence *seq,
int *r_array_index)
{

View File

@ -4228,9 +4228,48 @@ bool BKE_lib_override_library_property_operation_operands_validate(
return true;
}
static bool override_library_is_valid(const ID &id,
const IDOverrideLibrary &liboverride,
ReportList *reports)
{
if (liboverride.reference == nullptr) {
/* This (probably) used to be a template ID, could be linked or local, not an override. */
BKE_reportf(reports,
RPT_WARNING,
"Library override templates have been removed: removing all override data from "
"the data-block '%s'",
id.name);
return false;
}
if (liboverride.reference == &id) {
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
*/
BKE_reportf(reports,
RPT_ERROR,
"Data corruption: data-block '%s' is using itself as library override reference, "
"removing all override data",
id.name);
return false;
}
if (!ID_IS_LINKED(liboverride.reference)) {
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
*/
BKE_reportf(reports,
RPT_ERROR,
"Data corruption: data-block '%s' is using another local data-block ('%s') as "
"library override reference, removing all override data",
id.name,
liboverride.reference->name);
return false;
}
return true;
}
void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports)
{
if (!ID_IS_OVERRIDE_LIBRARY(id)) {
/* Do NOT use `ID_IS_OVERRIDE_LIBRARY` here, since this code also needs to fix broken cases (like
* null reference pointer), which would be skipped by that macro. */
if (id->override_library == nullptr && !ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
return;
}
@ -4238,7 +4277,7 @@ void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports)
IDOverrideLibrary *liboverride = id->override_library;
if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
liboverride = BKE_lib_override_library_get(bmain, id, nullptr, &liboverride_id);
if (!liboverride) {
if (!liboverride || !override_library_is_valid(*liboverride_id, *liboverride, reports)) {
/* Happens in case the given ID is a liboverride-embedded one (actual embedded ID like
* NodeTree or master collection, or shape-keys), used by a totally not-liboverride owner ID.
* Just clear the relevant ID flag.
@ -4252,39 +4291,8 @@ void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports)
/* NOTE: In code deleting liboverride data below, #BKE_lib_override_library_make_local is used
* instead of directly calling #BKE_lib_override_library_free, because the former also handles
* properly 'liboverride embedded' IDs, like root node-trees, or shape-keys. */
if (liboverride->reference == nullptr) {
/* This (probably) used to be a template ID, could be linked or local, not an override. */
BKE_reportf(reports,
RPT_WARNING,
"Library override templates have been removed: removing all override data from "
"the data-block '%s'",
liboverride_id->name);
if (!override_library_is_valid(*liboverride_id, *liboverride, reports)) {
BKE_lib_override_library_make_local(nullptr, liboverride_id);
return;
}
if (liboverride->reference == liboverride_id) {
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
*/
BKE_reportf(reports,
RPT_ERROR,
"Data corruption: data-block '%s' is using itself as library override reference, "
"removing all override data",
liboverride_id->name);
BKE_lib_override_library_make_local(nullptr, liboverride_id);
return;
}
if (!ID_IS_LINKED(liboverride->reference)) {
/* Very serious data corruption, cannot do much about it besides removing the liboverride data.
*/
BKE_reportf(reports,
RPT_ERROR,
"Data corruption: data-block '%s' is using another local data-block ('%s') as "
"library override reference, removing all override data",
liboverride_id->name,
liboverride->reference->name);
BKE_lib_override_library_make_local(nullptr, liboverride_id);
return;
}
}
@ -4293,9 +4301,7 @@ void BKE_lib_override_library_main_validate(Main *bmain, ReportList *reports)
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (ID_IS_OVERRIDE_LIBRARY(id)) {
BKE_lib_override_library_validate(bmain, id, reports);
}
BKE_lib_override_library_validate(bmain, id, reports);
}
FOREACH_MAIN_ID_END;
}

View File

@ -136,7 +136,6 @@ static void mask_blend_write(BlendWriter *writer, ID *id, const void *id_address
static void mask_blend_read_data(BlendDataReader *reader, ID *id)
{
Mask *mask = (Mask *)id;
BLO_read_data_address(reader, &mask->adt);
BLO_read_list(reader, &mask->masklayers);

View File

@ -1005,10 +1005,10 @@ void BKE_mesh_texspace_get_reference(Mesh *mesh,
}
}
float (*BKE_mesh_orco_verts_get(Object *ob))[3]
float (*BKE_mesh_orco_verts_get(const Object *ob))[3]
{
Mesh *mesh = static_cast<Mesh *>(ob->data);
Mesh *tme = mesh->texcomesh ? mesh->texcomesh : mesh;
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
const Mesh *tme = mesh->texcomesh ? mesh->texcomesh : mesh;
/* Get appropriate vertex coordinates */
float(*vcos)[3] = (float(*)[3])MEM_calloc_arrayN(mesh->verts_num, sizeof(*vcos), "orco mesh");

View File

@ -299,9 +299,9 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
mesh->runtime->verts_no_face_cache.tag_dirty();
mesh->runtime->corner_tris_cache.tag_dirty();
mesh->runtime->corner_tri_faces_cache.tag_dirty();
mesh->runtime->shrinkwrap_boundary_cache.tag_dirty();
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
mesh->runtime->shrinkwrap_data.reset();
mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY;
}
@ -331,7 +331,7 @@ void Mesh::tag_edges_split()
}
this->runtime->subsurf_face_dot_tags.clear_and_shrink();
this->runtime->subsurf_optimal_display_edges.clear_and_shrink();
this->runtime->shrinkwrap_data.reset();
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
}
void Mesh::tag_sharpness_changed()
@ -350,6 +350,7 @@ void Mesh::tag_face_winding_changed()
this->runtime->face_normals_cache.tag_dirty();
this->runtime->corner_normals_cache.tag_dirty();
this->runtime->vert_to_corner_map_cache.tag_dirty();
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
}
void Mesh::tag_positions_changed()
@ -357,6 +358,7 @@ void Mesh::tag_positions_changed()
this->runtime->vert_normals_cache.tag_dirty();
this->runtime->face_normals_cache.tag_dirty();
this->runtime->corner_normals_cache.tag_dirty();
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
this->tag_positions_changed_no_normals();
}
@ -365,6 +367,7 @@ void Mesh::tag_positions_changed_no_normals()
free_bvh_cache(*this->runtime);
this->runtime->corner_tris_cache.tag_dirty();
this->runtime->bounds_cache.tag_dirty();
this->runtime->shrinkwrap_boundary_cache.tag_dirty();
}
void Mesh::tag_positions_changed_uniformly()

View File

@ -3137,7 +3137,7 @@ const char *BKE_scene_multiview_view_id_suffix_get(const RenderData *rd, const i
}
void BKE_scene_multiview_view_prefix_get(Scene *scene,
const char *name,
const char *filepath,
char *r_prefix,
const char **r_ext)
{
@ -3146,8 +3146,8 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene,
r_prefix[0] = '\0';
/* Split filename into base name and extension. */
const size_t basename_len = BLI_str_rpartition(name, delims, r_ext, &unused);
/* Split `filepath` into base name and extension. */
const size_t basename_len = BLI_str_rpartition(filepath, delims, r_ext, &unused);
if (*r_ext == nullptr) {
return;
}
@ -3158,9 +3158,9 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene,
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
const size_t suffix_len = strlen(srv->suffix);
if (basename_len >= suffix_len &&
STREQLEN(name + basename_len - suffix_len, srv->suffix, suffix_len))
STREQLEN(filepath + basename_len - suffix_len, srv->suffix, suffix_len))
{
BLI_strncpy(r_prefix, name, basename_len - suffix_len + 1);
BLI_strncpy(r_prefix, filepath, basename_len - suffix_len + 1);
break;
}
}

View File

@ -142,7 +142,7 @@ bool BKE_shrinkwrap_init_tree(
}
if (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
data->boundary = mesh->runtime->shrinkwrap_data.get();
data->boundary = &blender::bke::shrinkwrap::boundary_cache_ensure(*mesh);
}
return true;
@ -153,9 +153,11 @@ void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data)
free_bvhtree_from_mesh(&data->treeData);
}
namespace blender::bke::shrinkwrap {
/* Accumulate edge for average boundary edge direction. */
static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata,
signed char *status,
MutableSpan<int8_t> status,
int index,
const float edge_dir[3],
signed char side)
@ -177,34 +179,28 @@ static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata,
status[index] = (status[index] == 0) ? side : -1;
}
static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Mesh *mesh)
static ShrinkwrapBoundaryData shrinkwrap_build_boundary_data(const Mesh &mesh)
{
using namespace blender;
const blender::Span<float3> positions = mesh->vert_positions();
const blender::Span<int2> edges = mesh->edges();
const Span<int> corner_verts = mesh->corner_verts();
const Span<int> corner_edges = mesh->corner_edges();
const Span<float3> positions = mesh.vert_positions();
const Span<int2> edges = mesh.edges();
const Span<int> corner_verts = mesh.corner_verts();
const Span<int> corner_edges = mesh.corner_edges();
/* Count faces per edge (up to 2). */
char *edge_mode = static_cast<char *>(
MEM_calloc_arrayN(size_t(mesh->edges_num), sizeof(char), __func__));
Array<int8_t> edge_mode(edges.size(), 0);
for (int i = 0; i < mesh->corners_num; i++) {
const int eidx = corner_edges[i];
if (edge_mode[eidx] < 2) {
edge_mode[eidx]++;
for (const int edge : corner_edges) {
if (edge_mode[edge] < 2) {
edge_mode[edge]++;
}
}
/* Build the boundary edge bitmask. */
blender::BitVector<> edge_is_boundary(mesh->edges_num, false);
uint num_boundary_edges = 0;
BitVector<> edge_is_boundary(mesh.edges_num, false);
for (int i = 0; i < mesh->edges_num; i++) {
edge_mode[i] = (edge_mode[i] == 1);
if (edge_mode[i]) {
int num_boundary_edges = 0;
for (const int64_t i : edges.index_range()) {
if (edge_mode[i] == 1) {
edge_is_boundary[i].set();
num_boundary_edges++;
}
@ -212,63 +208,52 @@ static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Me
/* If no boundary, return nullptr. */
if (num_boundary_edges == 0) {
MEM_freeN(edge_mode);
return {};
}
/* Allocate the data object. */
std::unique_ptr<ShrinkwrapBoundaryData> data = std::make_unique<ShrinkwrapBoundaryData>();
data->edge_is_boundary = std::move(edge_is_boundary);
ShrinkwrapBoundaryData data;
/* Build the boundary corner_tris bit-mask. */
const blender::Span<int3> corner_tris = mesh->corner_tris();
const Span<int3> corner_tris = mesh.corner_tris();
blender::BitVector<> tri_has_boundary(corner_tris.size(), false);
BitVector<> tri_has_boundary(corner_tris.size(), false);
for (const int64_t i : corner_tris.index_range()) {
const int3 real_edges = bke::mesh::corner_tri_get_real_edges(
edges, corner_verts, corner_edges, corner_tris[i]);
for (int j = 0; j < 3; j++) {
if (real_edges[j] >= 0 && edge_mode[real_edges[j]]) {
if (real_edges[j] >= 0 && edge_is_boundary[real_edges[j]]) {
tri_has_boundary[i].set();
break;
}
}
}
data->tri_has_boundary = std::move(tri_has_boundary);
/* Find boundary vertices and build a mapping table for compact storage of data. */
Array<int> vert_boundary_id(mesh->verts_num, 0);
for (int i = 0; i < mesh->edges_num; i++) {
if (edge_mode[i]) {
const blender::int2 &edge = edges[i];
Array<int> vert_boundary_id(mesh.verts_num, 0);
for (const int64_t i : edges.index_range()) {
if (edge_is_boundary[i]) {
const int2 &edge = edges[i];
vert_boundary_id[edge[0]] = 1;
vert_boundary_id[edge[1]] = 1;
}
}
uint num_boundary_verts = 0;
for (int i = 0; i < mesh->verts_num; i++) {
vert_boundary_id[i] = (vert_boundary_id[i] != 0) ? int(num_boundary_verts++) : -1;
int boundary_verts_num = 0;
for (const int64_t i : positions.index_range()) {
vert_boundary_id[i] = (vert_boundary_id[i] != 0) ? boundary_verts_num++ : -1;
}
data->vert_boundary_id = vert_boundary_id;
/* Compute average directions. */
Array<ShrinkwrapBoundaryVertData> boundary_verts(num_boundary_verts);
Array<ShrinkwrapBoundaryVertData> boundary_verts(boundary_verts_num);
signed char *vert_status = static_cast<signed char *>(
MEM_calloc_arrayN(num_boundary_verts, sizeof(char), __func__));
for (int i = 0; i < mesh->edges_num; i++) {
if (edge_mode[i]) {
const blender::int2 &edge = edges[i];
Array<int8_t> vert_status(boundary_verts_num);
for (const int64_t i : edges.index_range()) {
if (edge_is_boundary[i]) {
const int2 &edge = edges[i];
float dir[3];
sub_v3_v3v3(dir, positions[edge[1]], positions[edge[0]]);
@ -279,11 +264,9 @@ static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Me
}
}
MEM_freeN(vert_status);
/* Finalize average direction and compute normal. */
const blender::Span<blender::float3> vert_normals = mesh->vert_normals();
for (int i = 0; i < mesh->verts_num; i++) {
const Span<float3> vert_normals = mesh.vert_normals();
for (const int64_t i : positions.index_range()) {
int bidx = vert_boundary_id[i];
if (bidx >= 0) {
@ -298,17 +281,23 @@ static std::unique_ptr<ShrinkwrapBoundaryData> shrinkwrap_build_boundary_data(Me
}
}
data->boundary_verts = std::move(boundary_verts);
data.edge_is_boundary = std::move(edge_is_boundary);
data.tri_has_boundary = std::move(tri_has_boundary);
data.vert_boundary_id = std::move(vert_boundary_id);
data.boundary_verts = std::move(boundary_verts);
MEM_freeN(edge_mode);
return data;
}
void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh)
const ShrinkwrapBoundaryData &boundary_cache_ensure(const Mesh &mesh)
{
mesh->runtime->shrinkwrap_data = shrinkwrap_build_boundary_data(mesh);
mesh.runtime->shrinkwrap_boundary_cache.ensure(
[&](ShrinkwrapBoundaryData &r_data) { r_data = shrinkwrap_build_boundary_data(mesh); });
return mesh.runtime->shrinkwrap_boundary_cache.data();
}
} // namespace blender::bke::shrinkwrap
/**
* Shrink-wrap to the nearest vertex
*

View File

@ -673,7 +673,7 @@ void txt_clean_text(Text *text)
}
}
int txt_get_span(TextLine *from, TextLine *to)
int txt_get_span(TextLine *from, const TextLine *to)
{
int ret = 0;
TextLine *tmp = from;
@ -825,7 +825,7 @@ void txt_move_down(Text *text, const bool sel)
}
}
int txt_calc_tab_left(TextLine *tl, int ch)
int txt_calc_tab_left(const TextLine *tl, int ch)
{
/* do nice left only if there are only spaces */
@ -845,7 +845,7 @@ int txt_calc_tab_left(TextLine *tl, int ch)
return tabsize;
}
int txt_calc_tab_right(TextLine *tl, int ch)
int txt_calc_tab_right(const TextLine *tl, int ch)
{
if (tl->line[ch] == ' ') {
int i;
@ -2270,8 +2270,8 @@ int txt_setcurr_tab_spaces(Text *text, int space)
int text_check_bracket(const char ch)
{
int a;
char opens[] = "([{";
char close[] = ")]}";
const char opens[] = "([{";
const char close[] = ")]}";
for (a = 0; a < (sizeof(opens) - 1); a++) {
if (ch == opens[a]) {

View File

@ -405,7 +405,7 @@ VFont *BKE_vfont_load_exists(Main *bmain, const char *filepath)
return BKE_vfont_load_exists_ex(bmain, filepath, nullptr);
}
static VFont *which_vfont(Curve *cu, CharInfo *info)
static VFont *which_vfont(Curve *cu, const CharInfo *info)
{
switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) {
case CU_CHINFO_BOLD:
@ -435,7 +435,7 @@ VFont *BKE_vfont_builtin_get()
return vfont;
}
static VChar *find_vfont_char(VFontData *vfd, uint character)
static VChar *find_vfont_char(const VFontData *vfd, uint character)
{
return static_cast<VChar *>(BLI_ghash_lookup(vfd->characters, POINTER_FROM_UINT(character)));
}
@ -507,7 +507,7 @@ static void build_underline(Curve *cu,
void BKE_vfont_build_char(Curve *cu,
ListBase *nubase,
uint character,
CharInfo *info,
const CharInfo *info,
float ofsx,
float ofsy,
float rot,
@ -679,7 +679,7 @@ void BKE_vfont_select_clamp(Object *ob)
CLAMP_MAX(ef->selend, ef->len);
}
static float char_width(Curve *cu, VChar *che, CharInfo *info)
static float char_width(Curve *cu, VChar *che, const CharInfo *info)
{
/* The character wasn't found, probably ascii = 0, then the width shall be 0 as well */
if (che == nullptr) {
@ -2006,7 +2006,7 @@ bool BKE_vfont_to_curve_ex(Object *ob,
return data.ok;
}
int BKE_vfont_cursor_to_text_index(Object *ob, float cursor_location[2])
int BKE_vfont_cursor_to_text_index(Object *ob, const float cursor_location[2])
{
Curve *cu = (Curve *)ob->data;
ListBase *r_nubase = &cu->nurb;

View File

@ -383,8 +383,8 @@ VolumeGridType get_type(const VolumeGridData &volume_grid)
return volume_grid.grid_type();
#else
UNUSED_VARS(volume_grid);
#endif
return VOLUME_GRID_UNKNOWN;
#endif
}
int get_channels_num(const VolumeGridType type)

View File

@ -69,7 +69,7 @@ void BLI_args_print_other_doc(struct bArgs *ba);
bool BLI_args_has_other_doc(const struct bArgs *ba);
void BLI_args_print(struct bArgs *ba);
void BLI_args_print(const struct bArgs *ba);
#ifdef __cplusplus
}

View File

@ -32,7 +32,7 @@ struct RNG *BLI_rng_new(unsigned int seed);
* A version of #BLI_rng_new that hashes the seed.
*/
struct RNG *BLI_rng_new_srandom(unsigned int seed);
struct RNG *BLI_rng_copy(struct RNG *rng) ATTR_NONNULL(1);
struct RNG *BLI_rng_copy(const struct RNG *rng) ATTR_NONNULL(1);
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1);
void BLI_rng_seed(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1);

View File

@ -152,7 +152,7 @@ void BLI_args_pass_set(bArgs *ba, int current_pass)
ba->current_pass = current_pass;
}
void BLI_args_print(bArgs *ba)
void BLI_args_print(const bArgs *ba)
{
int i;
for (i = 0; i < ba->argc; i++) {

View File

@ -258,7 +258,7 @@ static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis)
}
}
static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode *x, int axis)
static int bvh_partition(BVHNode **a, int lo, int hi, const BVHNode *x, int axis)
{
int i = lo, j = hi;
while (1) {

View File

@ -191,8 +191,7 @@ void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src)
/* Loop over `ma_src` instead of `ma_dst` since it's likely the destination is larger
* when used for accumulating from multiple sources. */
struct MemBuf *mb_src = ma_src->bufs;
mb_src = ma_src->bufs;
while (mb_src && mb_src->next) {
while (mb_src->next) {
mb_src = mb_src->next;
}
mb_src->next = ma_dst->bufs->next;

View File

@ -317,7 +317,7 @@ bool _bli_array_iter_spiral_square(const void *arr_v,
}
/* For check_bounds. */
int limits[2] = {(arr_shape[0] - 1) * stride[0], stride[0] - stride[1]};
const int limits[2] = {(arr_shape[0] - 1) * stride[0], stride[0] - stride[1]};
int steps = 0;
while (steps < steps_out) {

View File

@ -50,7 +50,7 @@ RNG *BLI_rng_new_srandom(uint seed)
return rng;
}
RNG *BLI_rng_copy(RNG *rng)
RNG *BLI_rng_copy(const RNG *rng)
{
return new RNG(*rng);
}

View File

@ -294,7 +294,7 @@ TEST(expr_pylike, Eval_Ternary1)
TEST(expr_pylike, MultipleArgs)
{
const char *names[3] = {"x", "y", "x"};
double values[3] = {1.0, 2.0, 3.0};
const double values[3] = {1.0, 2.0, 3.0};
ExprPyLike_Parsed *expr = BLI_expr_pylike_parse("x*10 + y", names, ARRAY_SIZE(names));

View File

@ -8,7 +8,7 @@
TEST(math_color, RGBToHSVRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
const float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float hsv[3], rgb[3];
rgb_to_hsv_v(orig_rgb, hsv);
hsv_to_rgb_v(hsv, rgb);
@ -17,7 +17,7 @@ TEST(math_color, RGBToHSVRoundtrip)
TEST(math_color, RGBToHSLRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
const float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float hsl[3], rgb[3];
rgb_to_hsl_v(orig_rgb, hsl);
hsl_to_rgb_v(hsl, rgb);
@ -26,7 +26,7 @@ TEST(math_color, RGBToHSLRoundtrip)
TEST(math_color, RGBToYUVRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
const float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float yuv[3], rgb[3];
rgb_to_yuv(orig_rgb[0], orig_rgb[1], orig_rgb[2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709);
yuv_to_rgb(yuv[0], yuv[1], yuv[2], &rgb[0], &rgb[1], &rgb[2], BLI_YUV_ITU_BT709);
@ -35,7 +35,7 @@ TEST(math_color, RGBToYUVRoundtrip)
TEST(math_color, RGBToYCCRoundtrip)
{
float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
const float orig_rgb[3] = {0.1f, 0.2f, 0.3f};
float ycc[3], rgb[3];
rgb_to_ycc(orig_rgb[0], orig_rgb[1], orig_rgb[2], &ycc[0], &ycc[1], &ycc[2], BLI_YCC_ITU_BT601);

View File

@ -111,7 +111,7 @@ TEST(math_matrix, mul_m3_series)
{0.0f, 0.0f, 5.0f},
};
mul_m3_series(matrix, matrix, matrix, matrix);
float expect[3][3] = {
float const expect[3][3] = {
{8.0f, 0.0f, 0.0f},
{0.0f, 27.0f, 0.0f},
{0.0f, 0.0f, 125.0f},
@ -128,7 +128,7 @@ TEST(math_matrix, mul_m4_series)
{0.0f, 0.0f, 0.0f, 7.0f},
};
mul_m4_series(matrix, matrix, matrix, matrix);
float expect[4][4] = {
float const expect[4][4] = {
{8.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 27.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 125.0f, 0.0f},

View File

@ -8,10 +8,10 @@
TEST(math_solvers, Tridiagonal1)
{
float a[1] = {1}; // ignored
float b[1] = {2};
float c[1] = {1}; // ignored
float d[1] = {4};
const float a[1] = {1}; // ignored
const float b[1] = {2};
const float c[1] = {1}; // ignored
const float d[1] = {4};
float x[1];
EXPECT_TRUE(BLI_tridiagonal_solve(a, b, c, d, x, 1));
@ -20,10 +20,10 @@ TEST(math_solvers, Tridiagonal1)
TEST(math_solvers, Tridiagonal3)
{
float a[3] = {1, 2, 3}; // 1 ignored
float b[3] = {4, 5, 6};
float c[3] = {7, 8, 9}; // 9 ignored
float d[3] = {18, 36, 24};
const float a[3] = {1, 2, 3}; // 1 ignored
const float b[3] = {4, 5, 6};
const float c[3] = {7, 8, 9}; // 9 ignored
const float d[3] = {18, 36, 24};
float x[3];
EXPECT_TRUE(BLI_tridiagonal_solve(a, b, c, d, x, 3));
@ -34,10 +34,10 @@ TEST(math_solvers, Tridiagonal3)
TEST(math_solvers, CyclicTridiagonal1)
{
float a[1] = {1};
float b[1] = {2};
float c[1] = {1};
float d[1] = {4};
const float a[1] = {1};
const float b[1] = {2};
const float c[1] = {1};
const float d[1] = {4};
float x[1];
EXPECT_TRUE(BLI_tridiagonal_solve_cyclic(a, b, c, d, x, 1));
@ -46,10 +46,10 @@ TEST(math_solvers, CyclicTridiagonal1)
TEST(math_solvers, CyclicTridiagonal2)
{
float a[2] = {1, 2};
float b[2] = {3, 4};
float c[2] = {5, 6};
float d[2] = {15, 16};
const float a[2] = {1, 2};
const float b[2] = {3, 4};
const float c[2] = {5, 6};
const float d[2] = {15, 16};
float x[2];
EXPECT_TRUE(BLI_tridiagonal_solve_cyclic(a, b, c, d, x, 2));
@ -59,10 +59,10 @@ TEST(math_solvers, CyclicTridiagonal2)
TEST(math_solvers, CyclicTridiagonal3)
{
float a[3] = {1, 2, 3};
float b[3] = {4, 5, 6};
float c[3] = {7, 8, 9};
float d[3] = {21, 36, 33};
const float a[3] = {1, 2, 3};
const float b[3] = {4, 5, 6};
const float c[3] = {7, 8, 9};
const float d[3] = {21, 36, 33};
float x[3];
EXPECT_TRUE(BLI_tridiagonal_solve_cyclic(a, b, c, d, x, 3));

View File

@ -155,7 +155,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
/** #UserDef.flag */
#define USER_LMOUSESELECT (1 << 14) /* deprecated */
static void do_version_select_mouse(UserDef *userdef, wmKeyMapItem *kmi)
static void do_version_select_mouse(const UserDef *userdef, wmKeyMapItem *kmi)
{
/* Remove select/action mouse from user defined keymaps. */
enum {

View File

@ -580,10 +580,6 @@ if(WITH_COMPOSITOR_CPU)
PRIVATE bf::intern::atomic
)
list(APPEND INC
${CMAKE_CURRENT_BINARY_DIR}/operations
)
if(WITH_OPENIMAGEDENOISE)
add_definitions(-DWITH_OPENIMAGEDENOISE)
add_definitions(-DOIDN_STATIC_LIB)

View File

@ -91,6 +91,7 @@ void DefocusNode::convert_to_operations(NodeConverter &converter,
BokehImageOperation *bokeh = new BokehImageOperation();
bokeh->set_data(bokehdata);
bokeh->set_resolution(math::ceil(data->maxblur) * 2 + 1);
bokeh->delete_data_on_finish();
converter.add_operation(bokeh);
@ -101,7 +102,7 @@ void DefocusNode::convert_to_operations(NodeConverter &converter,
VariableSizeBokehBlurOperation *operation = new VariableSizeBokehBlurOperation();
operation->set_quality(eCompositorQuality::High);
operation->set_max_blur(data->maxblur);
operation->set_threshold(data->bthresh);
operation->set_threshold(0.0f);
converter.add_operation(operation);
converter.add_link(bokeh->get_output_socket(), operation->get_input_socket(1));

View File

@ -4,7 +4,10 @@
#include "COM_BokehImageOperation.h"
#include "BLI_math_geom.h"
#include "BLI_math_base.h"
#include "BLI_math_base.hh"
#include "BLI_math_numbers.hh"
#include "BLI_math_vector.hh"
namespace blender::compositor {
@ -13,91 +16,151 @@ BokehImageOperation::BokehImageOperation()
this->add_output_socket(DataType::Color);
delete_data_ = false;
}
/* The exterior angle is the angle between each two consecutive vertices of the regular polygon
* from its center. */
static float compute_exterior_angle(int sides)
{
return (math::numbers::pi * 2.0f) / sides;
}
static float compute_rotation(float angle, int sides)
{
/* Offset the rotation such that the second vertex of the regular polygon lies on the positive
* y axis, which is 90 degrees minus the angle that it makes with the positive x axis assuming
* the first vertex lies on the positive x axis. */
const float offset = math::numbers::pi / 2.0f - compute_exterior_angle(sides);
return angle - offset;
}
void BokehImageOperation::init_execution()
{
center_[0] = get_width() / 2;
center_[1] = get_height() / 2;
inverse_rounding_ = 1.0f - data_->rounding;
circular_distance_ = get_width() / 2;
flap_rad_ = float(M_PI * 2) / data_->flaps;
flap_rad_add_ = data_->angle;
while (flap_rad_add_ < 0.0f) {
flap_rad_add_ += float(M_PI * 2.0);
}
while (flap_rad_add_ > float(M_PI)) {
flap_rad_add_ -= float(M_PI * 2.0);
}
exterior_angle_ = compute_exterior_angle(data_->flaps);
rotation_ = compute_rotation(data_->angle, data_->flaps);
roundness_ = data_->rounding;
catadioptric_ = data_->catadioptric;
lens_shift_ = data_->lensshift;
}
void BokehImageOperation::detemine_start_point_of_flap(float r[2], int flap_number, float distance)
/* Get the 2D vertex position of the vertex with the given index in the regular polygon
* representing this bokeh. The polygon is rotated by the rotation amount and have a unit
* circumradius. The regular polygon is one whose vertices' exterior angles are given by
* exterior_angle. See the bokeh function for more information. */
float2 BokehImageOperation::get_regular_polygon_vertex_position(int vertex_index)
{
r[0] = sinf(flap_rad_ * flap_number + flap_rad_add_) * distance + center_[0];
r[1] = cosf(flap_rad_ * flap_number + flap_rad_add_) * distance + center_[1];
float angle = exterior_angle_ * vertex_index - rotation_;
return float2(math::cos(angle), math::sin(angle));
}
float BokehImageOperation::is_inside_bokeh(float distance, float x, float y)
/* Find the closest point to the given point on the given line. This assumes the length of the
* given line is not zero. */
float2 BokehImageOperation::closest_point_on_line(float2 point, float2 line_start, float2 line_end)
{
float inside_bokeh = 0.0f;
const float deltaX = x - center_[0];
const float deltaY = y - center_[1];
float closest_point[2];
float line_p1[2];
float line_p2[2];
float point[2];
point[0] = x;
point[1] = y;
const float distance_to_center = len_v2v2(point, center_);
const float bearing = (atan2f(deltaX, deltaY) + float(M_PI * 2.0));
int flap_number = int((bearing - flap_rad_add_) / flap_rad_);
detemine_start_point_of_flap(line_p1, flap_number, distance);
detemine_start_point_of_flap(line_p2, flap_number + 1, distance);
closest_to_line_v2(closest_point, point, line_p1, line_p2);
const float distance_line_to_center = len_v2v2(center_, closest_point);
const float distance_rounding_to_center = inverse_rounding_ * distance_line_to_center +
data_->rounding * distance;
const float catadioptric_distance_to_center = distance_rounding_to_center * data_->catadioptric;
if (distance_rounding_to_center >= distance_to_center &&
catadioptric_distance_to_center <= distance_to_center)
{
if (distance_rounding_to_center - distance_to_center < 1.0f) {
inside_bokeh = (distance_rounding_to_center - distance_to_center);
}
else if (data_->catadioptric != 0.0f &&
distance_to_center - catadioptric_distance_to_center < 1.0f)
{
inside_bokeh = (distance_to_center - catadioptric_distance_to_center);
}
else {
inside_bokeh = 1.0f;
}
}
return inside_bokeh;
float2 line_vector = line_end - line_start;
float2 point_vector = point - line_start;
float line_length_squared = math::dot(line_vector, line_vector);
float parameter = math::dot(point_vector, line_vector) / line_length_squared;
return line_start + line_vector * parameter;
}
/* Compute the value of the bokeh at the given point. The computed bokeh is essentially a regular
* polygon centered in space having the given circumradius. The regular polygon is one whose
* vertices' exterior angles are given by "exterior_angle", which relates to the number of vertices
* n through the equation "exterior angle = 2 pi / n". The regular polygon may additionally morph
* into a shape with the given properties:
*
* - The regular polygon may have a circular hole in its center whose radius is controlled by the
* "catadioptric" value.
* - The regular polygon is rotated by the "rotation" value.
* - The regular polygon can morph into a circle controlled by the "roundness" value, such that it
* becomes a full circle at unit roundness.
*
* The function returns 0 when the point lies inside the regular polygon and 1 otherwise. However,
* at the edges, it returns a narrow band gradient as a form of anti-aliasing. */
float BokehImageOperation::bokeh(float2 point, float circumradius)
{
/* Get the index of the vertex of the regular polygon whose polar angle is maximum but less than
* the polar angle of the given point, taking rotation into account. This essentially finds the
* vertex closest to the given point in the clock-wise direction. */
float angle = floored_fmod(math::atan2(point.y, point.x) + rotation_,
math::numbers::pi_v<float> * 2.0f);
int vertex_index = int(angle / exterior_angle_);
/* Compute the shortest distance between the origin and the polygon edge composed from the
* previously selected vertex and the one following it. */
float2 first_vertex = this->get_regular_polygon_vertex_position(vertex_index) * circumradius;
float2 second_vertex = this->get_regular_polygon_vertex_position(vertex_index + 1) *
circumradius;
float2 closest_point = this->closest_point_on_line(point, first_vertex, second_vertex);
float distance_to_edge = math::length(closest_point);
/* Mix the distance to the edge with the circumradius, making it tend to the distance to a
* circle when roundness tends to 1. */
float distance_to_edge_round = math::interpolate(distance_to_edge, circumradius, roundness_);
/* The point is outside of the bokeh, so we return 0. */
float distance = math::length(point);
if (distance > distance_to_edge_round) {
return 0.0f;
}
/* The point is inside the catadioptric hole and is not part of the bokeh, so we return 0. */
float catadioptric_distance = distance_to_edge_round * catadioptric_;
if (distance < catadioptric_distance) {
return 0.0f;
}
/* The point is very close to the edge of the bokeh, so we return the difference between the
* distance to the edge and the distance as a form of anti-aliasing. */
if (distance_to_edge_round - distance < 1.0f) {
return distance_to_edge_round - distance;
}
/* The point is very close to the edge of the catadioptric hole, so we return the difference
* between the distance to the hole and the distance as a form of anti-aliasing. */
if (catadioptric_ != 0.0f && distance - catadioptric_distance < 1.0f) {
return distance - catadioptric_distance;
}
/* Otherwise, the point is part of the bokeh and we return 1. */
return 1.0f;
}
void BokehImageOperation::update_memory_buffer_partial(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> /*inputs*/)
{
const float shift = data_->lensshift;
const float shift2 = shift / 2.0f;
const float distance = circular_distance_;
/* Since we need the regular polygon to occupy the entirety of the output image, the circumradius
* of the regular polygon is half the width of the output image. */
float circumradius = float(resolution_) / 2.0f;
for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
const float inside_bokeh_max = is_inside_bokeh(distance, it.x, it.y);
const float inside_bokeh_med = is_inside_bokeh(
distance - fabsf(shift2 * distance), it.x, it.y);
const float inside_bokeh_min = is_inside_bokeh(distance - fabsf(shift * distance), it.x, it.y);
if (shift < 0) {
it.out[0] = inside_bokeh_max;
it.out[1] = inside_bokeh_med;
it.out[2] = inside_bokeh_min;
int2 texel = int2(it.x, it.y);
/* Move the texel coordinates such that the regular polygon is centered. */
float2 point = float2(texel) + float2(0.5f) - circumradius;
/* Each of the color channels of the output image contains a bokeh with a different
* circumradius. The largest one occupies the whole image as stated above, while the other two
* have circumradii that are shifted by an amount that is proportional to the "lens_shift"
* value. The alpha channel of the output is the average of all three values. */
float min_shift = math::abs(lens_shift_ * circumradius);
float min = min_shift == circumradius ? 0.0f : this->bokeh(point, circumradius - min_shift);
float median_shift = min_shift / 2.0f;
float median = this->bokeh(point, circumradius - median_shift);
float max = this->bokeh(point, circumradius);
float4 bokeh = float4(min, median, max, (max + median + min) / 3.0f);
/* If the lens shift is negative, swap the min and max bokeh values, which are stored in the
* red and blue channels respectively. Note that we take the absolute value of the lens shift
* above, so the sign of the lens shift only controls this swap. */
if (lens_shift_ < 0.0f) {
std::swap(bokeh.x, bokeh.z);
}
else {
it.out[0] = inside_bokeh_min;
it.out[1] = inside_bokeh_med;
it.out[2] = inside_bokeh_max;
}
it.out[3] = (inside_bokeh_max + inside_bokeh_med + inside_bokeh_min) / 3.0f;
copy_v4_v4(it.out, bokeh);
}
}
@ -111,13 +174,9 @@ void BokehImageOperation::deinit_execution()
}
}
void BokehImageOperation::determine_canvas(const rcti &preferred_area, rcti &r_area)
void BokehImageOperation::determine_canvas(const rcti & /*preferred_area*/, rcti &r_area)
{
BLI_rcti_init(&r_area,
preferred_area.xmin,
preferred_area.xmin + COM_BLUR_BOKEH_PIXELS,
preferred_area.ymin,
preferred_area.ymin + COM_BLUR_BOKEH_PIXELS);
BLI_rcti_init(&r_area, 0, resolution_, 0, resolution_);
}
} // namespace blender::compositor

View File

@ -4,93 +4,30 @@
#pragma once
#include "BLI_math_vector_types.hh"
#include "COM_MultiThreadedOperation.h"
namespace blender::compositor {
/**
* \brief The #BokehImageOperation class is an operation that creates an image useful to mimic the
* internals of a camera.
*
* features:
* - number of flaps
* - angle offset of the flaps
* - rounding of the flaps (also used to make a circular lens)
* - simulate catadioptric
* - simulate lens-shift
*
* Per pixel the algorithm determines the edge of the bokeh on the same line as the center of the
* image and the pixel is evaluating.
*
* The edge is detected by finding the closest point on the direct line between the two nearest
* flap-corners. this edge is interpolated with a full circle. Result of this edge detection is
* stored as the distance between the center of the image and the edge.
*
* catadioptric lenses are simulated to interpolate between the center of the image and the
* distance of the edge. We now have three distances:
* - Distance between the center of the image and the pixel to be evaluated.
* - Distance between the center of the image and the outer-edge.
* - Distance between the center of the image and the inner-edge.
*
* With a simple compare it can be detected if the evaluated pixel is between the outer and inner
* edge.
*/
class BokehImageOperation : public MultiThreadedOperation {
private:
/**
* \brief Settings of the bokeh image
*/
const NodeBokehImage *data_;
/**
* \brief precalculate center of the image
*/
float center_[2];
int resolution_ = COM_BLUR_BOKEH_PIXELS;
/**
* \brief 1.0-rounding
*/
float inverse_rounding_;
float exterior_angle_;
float rotation_;
float roundness_;
float catadioptric_;
float lens_shift_;
/**
* \brief distance of a full circle lens
*/
float circular_distance_;
/**
* \brief radius when the first flap starts
*/
float flap_rad_;
/**
* \brief radians of a single flap
*/
float flap_rad_add_;
/**
* \brief should the data_ field by deleted when this operation is finished
*/
/* See the delete_data_on_finish method. */
bool delete_data_;
/**
* \brief determine the coordinate of a flap corner.
*
* \param r: result in bokeh-image space are stored [x,y]
* \param flap_number: the flap number to calculate
* \param distance: the lens distance is used to simulate lens shifts
*/
void detemine_start_point_of_flap(float r[2], int flap_number, float distance);
/**
* \brief Determine if a coordinate is inside the bokeh image
*
* \param distance: the distance that will be used.
* This parameter is modified a bit to mimic lens shifts.
* \param x: the x coordinate of the pixel to evaluate
* \param y: the y coordinate of the pixel to evaluate
* \return float range 0..1 0 is completely outside
*/
float is_inside_bokeh(float distance, float x, float y);
float2 get_regular_polygon_vertex_position(int vertex_index);
float2 closest_point_on_line(float2 point, float2 line_start, float2 line_end);
float bokeh(float2 point, float circumradius);
public:
BokehImageOperation();
@ -98,21 +35,18 @@ class BokehImageOperation : public MultiThreadedOperation {
void init_execution() override;
void deinit_execution() override;
/**
* \brief determine the resolution of this operation. currently fixed at [COM_BLUR_BOKEH_PIXELS,
* COM_BLUR_BOKEH_PIXELS] \param resolution: \param preferred_resolution:
*/
void determine_canvas(const rcti &preferred_area, rcti &r_area) override;
/**
* \brief set the node data
* \param data:
*/
void set_data(const NodeBokehImage *data)
{
data_ = data;
}
void set_resolution(int resolution)
{
resolution_ = resolution;
}
/**
* \brief delete_data_on_finish
*

View File

@ -87,7 +87,6 @@ void VariableSizeBokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *
const float base_size = do_size_scale_ ? (max_dim / 100.0f) : 1.0f;
const float maximum_size = size_buffer->get_max_value();
const int search_radius = math::clamp(int(maximum_size * base_size), 0, max_blur_);
const int2 bokeh_size = int2(bokeh_buffer->get_width(), bokeh_buffer->get_height());
BuffersIterator<float> it = output->iterate_with({}, area);
for (; !it.is_end(); ++it) {
@ -115,8 +114,8 @@ void VariableSizeBokehBlurOperation::update_memory_buffer_partial(MemoryBuffer *
}
const float2 normalized_texel = (float2(xi, yi) + size + 0.5f) / (size * 2.0f + 1.0f);
const float2 weight_texel = (1.0f - normalized_texel) * float2(bokeh_size - 1);
const float4 weight = bokeh_buffer->get_elem(int(weight_texel.x), int(weight_texel.y));
const float2 weight_texel = 1.0f - normalized_texel;
const float4 weight = bokeh_buffer->texture_bilinear_extend(weight_texel);
const float4 color = input_buffer->get_elem_clamped(it.x + xi, it.y + yi);
accumulated_color += color * weight;
accumulated_weight += weight;

View File

@ -96,7 +96,7 @@ void main()
float circumradius = float(imageSize(output_img).x) / 2.0;
/* Move the texel coordinates such that the regular polygon is centered. */
vec2 point = vec2(texel) - circumradius;
vec2 point = vec2(texel) + vec2(0.5) - circumradius;
/* Each of the color channels of the output image contains a bokeh with a different circumradius.
* The largest one occupies the whole image as stated above, while the other two have circumradii

View File

@ -354,7 +354,7 @@ static void dof_bokeh_pass_init(EEVEE_FramebufferList *fbl,
}
void *owner = (void *)&EEVEE_depth_of_field_init;
int res[2] = {DOF_BOKEH_LUT_SIZE, DOF_BOKEH_LUT_SIZE};
const int res[2] = {DOF_BOKEH_LUT_SIZE, DOF_BOKEH_LUT_SIZE};
DRW_PASS_CREATE(psl->dof_bokeh, DRW_STATE_WRITE_COLOR);
@ -393,7 +393,7 @@ static void dof_setup_pass_init(EEVEE_FramebufferList *fbl,
void *owner = (void *)&EEVEE_depth_of_field_init;
const float *fullres = DRW_viewport_size_get();
int res[2] = {int(divide_ceil_u(fullres[0], 2)), int(divide_ceil_u(fullres[1], 2))};
const int res[2] = {int(divide_ceil_u(fullres[0], 2)), int(divide_ceil_u(fullres[1], 2))};
DRW_PASS_CREATE(psl->dof_setup, DRW_STATE_WRITE_COLOR);
@ -428,8 +428,8 @@ static void dof_flatten_tiles_pass_init(EEVEE_FramebufferList *fbl,
{
void *owner = (void *)&EEVEE_depth_of_field_init;
const float *fullres = DRW_viewport_size_get();
int res[2] = {int(divide_ceil_u(fullres[0], DOF_TILE_DIVISOR)),
int(divide_ceil_u(fullres[1], DOF_TILE_DIVISOR))};
const int res[2] = {int(divide_ceil_u(fullres[0], DOF_TILE_DIVISOR)),
int(divide_ceil_u(fullres[1], DOF_TILE_DIVISOR))};
DRW_PASS_CREATE(psl->dof_flatten_tiles, DRW_STATE_WRITE_COLOR);
@ -464,8 +464,8 @@ static void dof_dilate_tiles_pass_init(EEVEE_FramebufferList *fbl,
{
void *owner = (void *)&EEVEE_depth_of_field_init;
const float *fullres = DRW_viewport_size_get();
int res[2] = {int(divide_ceil_u(fullres[0], DOF_TILE_DIVISOR)),
int(divide_ceil_u(fullres[1], DOF_TILE_DIVISOR))};
const int res[2] = {int(divide_ceil_u(fullres[0], DOF_TILE_DIVISOR)),
int(divide_ceil_u(fullres[1], DOF_TILE_DIVISOR))};
DRW_PASS_CREATE(psl->dof_dilate_tiles_minmax, DRW_STATE_WRITE_COLOR);
DRW_PASS_CREATE(psl->dof_dilate_tiles_minabs, DRW_STATE_WRITE_COLOR);
@ -558,10 +558,12 @@ static void dof_reduce_pass_init(EEVEE_FramebufferList *fbl,
/* This ensure the mipmaps are aligned for the needed 4 mip levels.
* Starts at 2 because already at half resolution. */
int multiple = 2 << (mip_count - 1);
int res[2] = {(multiple * int(divide_ceil_u(fullres[0], multiple))) / 2,
(multiple * int(divide_ceil_u(fullres[1], multiple))) / 2};
const int res[2] = {
(multiple * int(divide_ceil_u(fullres[0], multiple))) / 2,
(multiple * int(divide_ceil_u(fullres[1], multiple))) / 2,
};
int quater_res[2] = {int(divide_ceil_u(fullres[0], 4)), int(divide_ceil_u(fullres[1], 4))};
const int quater_res[2] = {int(divide_ceil_u(fullres[0], 4)), int(divide_ceil_u(fullres[1], 4))};
/* TODO(fclem): Make this dependent of the quality of the gather pass. */
fx->dof_scatter_coc_threshold = 4.0f;
@ -676,11 +678,12 @@ static void dof_gather_pass_init(EEVEE_FramebufferList *fbl,
{
void *owner = (void *)&EEVEE_depth_of_field_init;
const float *fullres = DRW_viewport_size_get();
int res[2] = {int(divide_ceil_u(fullres[0], 2)), int(divide_ceil_u(fullres[1], 2))};
const int res[2] = {int(divide_ceil_u(fullres[0], 2)), int(divide_ceil_u(fullres[1], 2))};
int input_size[2];
GPU_texture_get_mipmap_size(txl->dof_reduced_color, 0, input_size);
float uv_correction_fac[2] = {res[0] / float(input_size[0]), res[1] / float(input_size[1])};
float output_texel_size[2] = {1.0f / res[0], 1.0f / res[1]};
const float uv_correction_fac[2] = {res[0] / float(input_size[0]),
res[1] / float(input_size[1])};
const float output_texel_size[2] = {1.0f / res[0], 1.0f / res[1]};
const bool use_bokeh_tx = (fx->dof_bokeh_gather_lut_tx != nullptr);
{
@ -845,7 +848,7 @@ static void dof_scatter_pass_init(EEVEE_FramebufferList *fbl,
GPU_texture_get_mipmap_size(fx->dof_bg_color_tx, 0, target_size);
/* Draw a sprite for every four half-res pixels. */
int sprite_count = (input_size[0] / 2) * (input_size[1] / 2);
float target_texel_size[2] = {1.0f / target_size[0], 1.0f / target_size[1]};
const float target_texel_size[2] = {1.0f / target_size[0], 1.0f / target_size[1]};
const bool use_bokeh_tx = (fx->dof_bokeh_gather_lut_tx != nullptr);
{

View File

@ -123,7 +123,7 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->vol_history_alpha = (txl->volume_prop_scattering == nullptr) ? 0.0f : 0.95f;
/* Temporal Super sampling jitter */
uint ht_primes[3] = {3, 7, 2};
const uint ht_primes[3] = {3, 7, 2};
uint current_sample = 0;
/* If TAA is in use do not use the history buffer. */

View File

@ -250,7 +250,7 @@ class Instance {
bool is_transforming() const
{
BLI_assert_msg(is_image_render(), "Need to be checked first otherwise this is unsafe");
BLI_assert_msg(!is_image_render(), "Caller need to check, otherwise this is unsafe");
return (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) != 0;
}

View File

@ -202,6 +202,7 @@ class LightProbeModule {
friend class VolumeProbeModule;
friend class PlanarProbeModule;
friend class SphereProbeModule;
friend class BackgroundPipeline;
private:
Instance &inst_;

View File

@ -72,6 +72,11 @@ class LookdevWorld {
{
return parameters_.background_opacity;
}
float background_blur_get()
{
return parameters_.blur;
}
};
/** \} */

View File

@ -24,7 +24,9 @@ namespace blender::eevee {
* Used to draw background.
* \{ */
void BackgroundPipeline::sync(GPUMaterial *gpumat, const float background_opacity)
void BackgroundPipeline::sync(GPUMaterial *gpumat,
const float background_opacity,
const float background_blur)
{
Manager &manager = *inst_.manager;
RenderBuffers &rbufs = inst_.render_buffers;
@ -33,6 +35,9 @@ void BackgroundPipeline::sync(GPUMaterial *gpumat, const float background_opacit
world_ps_.state_set(DRW_STATE_WRITE_COLOR);
world_ps_.material_set(manager, gpumat);
world_ps_.push_constant("world_opacity_fade", background_opacity);
world_ps_.push_constant("world_background_blur", square_f(background_blur));
SphereProbeData &world_data = *static_cast<SphereProbeData *>(&inst_.light_probes.world_sphere_);
world_ps_.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_data.atlas_coord));
world_ps_.bind_texture("utility_tx", inst_.pipelines.utility_tx);
/* RenderPasses & AOVs. Cleared by background (even if bad practice). */
world_ps_.bind_image("rp_color_img", &rbufs.rp_color_tx);
@ -41,6 +46,9 @@ void BackgroundPipeline::sync(GPUMaterial *gpumat, const float background_opacit
/* Required by validation layers. */
world_ps_.bind_resources(inst_.cryptomatte);
world_ps_.bind_resources(inst_.uniform_data);
world_ps_.bind_resources(inst_.sampling);
world_ps_.bind_resources(inst_.sphere_probes);
world_ps_.bind_resources(inst_.volume_probes);
world_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
/* To allow opaque pass rendering over it. */
world_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
@ -74,6 +82,8 @@ void WorldPipeline::sync(GPUMaterial *gpumat)
Manager &manager = *inst_.manager;
pass.material_set(manager, gpumat);
pass.push_constant("world_opacity_fade", 1.0f);
pass.push_constant("world_background_blur", 0.0f);
pass.push_constant("world_coord_packed", int4(0.0f));
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
pass.bind_image("rp_normal_img", dummy_renderpass_tx_);
pass.bind_image("rp_light_img", dummy_renderpass_tx_);
@ -89,6 +99,9 @@ void WorldPipeline::sync(GPUMaterial *gpumat)
/* Required by validation layers. */
pass.bind_resources(inst_.cryptomatte);
pass.bind_resources(inst_.uniform_data);
pass.bind_resources(inst_.sampling);
pass.bind_resources(inst_.sphere_probes);
pass.bind_resources(inst_.volume_probes);
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}

View File

@ -40,7 +40,7 @@ class BackgroundPipeline {
public:
BackgroundPipeline(Instance &inst) : inst_(inst){};
void sync(GPUMaterial *gpumat, float background_opacity);
void sync(GPUMaterial *gpumat, float background_opacity, float background_blur);
void render(View &view);
};

View File

@ -793,12 +793,12 @@ static inline bool is_local_light(eLightType type)
/** --- Shadow Data --- */ \
/** Other parts of the perspective matrix. Assumes symmetric frustum. */ \
float clip_side; \
/** Number of allocated tilemap for this local light. */ \
int tilemaps_count; \
/** Scaling factor to the light shape for shadow ray casting. */ \
float shadow_scale; \
/** Shift to apply to the light origin to get the shadow projection origin. */ \
float shadow_projection_shift; \
/** Number of allocated tilemap for this local light. */ \
int tilemaps_count;
float shadow_projection_shift;
/* Untyped local light data. Gets reinterpreted to LightSpotData and LightAreaData.
* Allow access to local light common data without casting. */
@ -861,12 +861,11 @@ struct LightSunData {
float _pad3;
float _pad4;
float _pad5;
float _pad6;
/** --- Shadow Data --- */
/** Offset of the LOD min in LOD min tile units. */
int2 clipmap_base_offset;
/** Offset of the LOD min in LOD min tile units. Split positive and negative for bit-shift. */
int2 clipmap_base_offset_neg;
int2 clipmap_base_offset_pos;
/** Angle covered by the light shape for shadow ray casting. */
float shadow_angle;
/** Trace distance around the shading point. */
@ -1073,7 +1072,8 @@ static inline LightSunData light_sun_data_get(LightData light)
{
SAFE_BEGIN(LightSunData, is_sun_light(light.type))
SAFE_ASSIGN_FLOAT(radius, radius_squared)
SAFE_ASSIGN_FLOAT_AS_INT2_COMBINE(clipmap_base_offset, _pad0_reserved, _pad1_reserved)
SAFE_ASSIGN_FLOAT_AS_INT2_COMBINE(clipmap_base_offset_neg, shadow_scale, shadow_projection_shift)
SAFE_ASSIGN_FLOAT_AS_INT2_COMBINE(clipmap_base_offset_pos, _pad0_reserved, _pad1_reserved)
SAFE_ASSIGN_FLOAT(shadow_angle, _pad1)
SAFE_ASSIGN_FLOAT(shadow_trace_distance, _pad2)
SAFE_ASSIGN_FLOAT2(clipmap_origin, _pad3)

View File

@ -118,12 +118,14 @@ void ShadowTileMap::sync_cubeface(const float4x4 &object_mat_,
void ShadowTileMap::debug_draw() const
{
/** Used for debug drawing. */
float4 debug_color[6] = {{1.0f, 0.1f, 0.1f, 1.0f},
{0.1f, 1.0f, 0.1f, 1.0f},
{0.0f, 0.2f, 1.0f, 1.0f},
{1.0f, 1.0f, 0.3f, 1.0f},
{0.1f, 0.1f, 0.1f, 1.0f},
{1.0f, 1.0f, 1.0f, 1.0f}};
const float4 debug_color[6] = {
{1.0f, 0.1f, 0.1f, 1.0f},
{0.1f, 1.0f, 0.1f, 1.0f},
{0.0f, 0.2f, 1.0f, 1.0f},
{1.0f, 1.0f, 0.3f, 1.0f},
{0.1f, 0.1f, 0.1f, 1.0f},
{1.0f, 1.0f, 1.0f, 1.0f},
};
float4 color =
debug_color[((projection_type == SHADOW_PROJECTION_CUBEFACE ? cubeface : level) + 9999) % 6];
@ -490,12 +492,13 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera
/* Offset for smooth level transitions. */
light.object_mat.location() = near_point;
/* Offset in tiles from the origin to the center of the first tile-maps. */
/* Offset in tiles from the scene origin to the center of the first tile-maps. */
int2 origin_offset = int2(round(float2(near_point) / tile_size));
/* Offset in tiles between the first and the last tile-maps. */
int2 offset_vector = int2(round(farthest_tilemap_center / tile_size));
light.sun.clipmap_base_offset = (offset_vector * (1 << 16)) / max_ii(levels_range.size() - 1, 1);
light.sun.clipmap_base_offset_pos = (offset_vector * (1 << 16)) /
max_ii(levels_range.size() - 1, 1);
/* \note: cascade_level_range starts the range at the unique LOD to apply to all tile-maps. */
int level = levels_range.first();
@ -504,7 +507,7 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera
/* Equal spacing between cascades layers since we want uniform shadow density. */
int2 level_offset = origin_offset +
shadow_cascade_grid_offset(light.sun.clipmap_base_offset, i);
shadow_cascade_grid_offset(light.sun.clipmap_base_offset_pos, i);
tilemap->sync_orthographic(object_mat_, level_offset, level, 0.0f, SHADOW_PROJECTION_CASCADE);
/* Add shadow tile-maps grouped by lights to the GPU buffer. */
@ -535,8 +538,8 @@ IndexRange ShadowDirectional::clipmap_level_range(const Camera &camera)
{
using namespace blender::math;
/* Take 16 to be able to pack offset into a single int2. */
const int max_tilemap_per_shadows = 16;
/* 32 to be able to pack offset into two single int2. */
const int max_tilemap_per_shadows = 32;
int user_min_level = floorf(log2(min_resolution_));
/* Covers the farthest points of the view. */
@ -586,8 +589,7 @@ void ShadowDirectional::clipmap_tilemaps_distribution(Light &light,
* single integer where one bit contains offset between 2 levels. Then a single bit shift in
* the shader gives the number of tile to offset in the given tile-map space. However we need
* also the sign of the offset for each level offset. To this end, we split the negative
* offsets to a separate int.
* Recovering the offset with: (pos_offset >> lod) - (neg_offset >> lod). */
* offsets to a separate int. */
int2 lvl_offset_next = tilemaps_[lod + 1]->grid_offset;
int2 lvl_offset = tilemaps_[lod]->grid_offset;
int2 lvl_delta = lvl_offset - (lvl_offset_next << 1);
@ -596,9 +598,9 @@ void ShadowDirectional::clipmap_tilemaps_distribution(Light &light,
neg_offset |= math::max(-lvl_delta, int2(0)) << lod;
}
/* Compressing to a single value to save up storage in light data. Number of levels is limited to
* 16 by `clipmap_level_range()` for this reason. */
light.sun.clipmap_base_offset = pos_offset | (neg_offset << 16);
/* Number of levels is limited to 32 by `clipmap_level_range()` for this reason. */
light.sun.clipmap_base_offset_pos = pos_offset;
light.sun.clipmap_base_offset_neg = neg_offset;
float tile_size_max = ShadowDirectional::tile_size_get(levels_range.last());
int2 level_offset_max = tilemaps_[levels_range.size() - 1]->grid_offset;
@ -1333,7 +1335,7 @@ int ShadowModule::max_view_per_tilemap()
potential_view_count += 1;
}
}
int max_view_count = divide_ceil_u(SHADOW_VIEW_MAX, potential_view_count);
int max_view_count = divide_ceil_u(SHADOW_VIEW_MAX, math::max(potential_view_count, 1));
/* For viewport interactivity, have a hard maximum. This allows smoother experience. */
if (inst_.is_transforming() || inst_.is_navigating()) {
max_view_count = math::min(2, max_view_count);

View File

@ -133,8 +133,9 @@ void World::sync()
float opacity = inst_.use_studio_light() ? lookdev_world_.background_opacity_get() :
inst_.film.background_opacity_get();
float background_blur = inst_.use_studio_light() ? lookdev_world_.background_blur_get() : 0.0;
inst_.pipelines.background.sync(gpumat, opacity);
inst_.pipelines.background.sync(gpumat, opacity, background_blur);
inst_.pipelines.world.sync(gpumat);
}

View File

@ -25,6 +25,6 @@ void main()
vec3 P = transform_point(display_data_buf[display_index].plane_to_world, vec3(lP, 0.0));
gl_Position = drw_point_world_to_homogenous(P);
/* Small bias to let the icon draw without Z-fighting. */
gl_Position.z += 0.0001;
/* Small bias to let the probe draw without Z-fighting. */
gl_Position.z -= 0.0001;
}

View File

@ -210,7 +210,10 @@ ShadowDirectionalSampleInfo shadow_directional_sample_info_get(LightData light,
level;
info.clipmap_offset = shadow_decompress_grid_offset(
light.type, light_sun_data_get(light).clipmap_base_offset, info.level_relative);
light.type,
light_sun_data_get(light).clipmap_base_offset_neg,
light_sun_data_get(light).clipmap_base_offset_pos,
info.level_relative);
info.clipmap_origin = light_sun_data_get(light).clipmap_origin;
return info;

View File

@ -30,6 +30,8 @@ void set_clipmap_data(inout LightData light,
void set_clipmap_base_offset(inout LightData light, ivec2 clipmap_base_offset)
{
/* WATCH: Can get out of sync with light_sun_data_get(). */
light.do_not_access_directly.shadow_scale = intBitsToFloat(0);
light.do_not_access_directly.shadow_projection_shift = intBitsToFloat(0);
light.do_not_access_directly._pad0_reserved = intBitsToFloat(clipmap_base_offset.x);
light.do_not_access_directly._pad1_reserved = intBitsToFloat(clipmap_base_offset.y);
}
@ -47,7 +49,7 @@ void main()
EXPECT_EQ(light_sun_data_get(light).clipmap_lod_min, 1);
EXPECT_EQ(light_sun_data_get(light).clipmap_lod_max, 2);
EXPECT_EQ(light_sun_data_get(light).clipmap_origin, vec2(3.0, 4.0));
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(5, 6));
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(5, 6));
}
TEST(eevee_shadow, DirectionalClipmapLevel)
@ -119,7 +121,7 @@ void main()
camera_lP = vec3(0.0, 0.0, 0.0);
/* Follows ShadowDirectional::end_sync(). */
set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(0));
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(0));
/* Test UVs and tile mapping. */
@ -152,7 +154,7 @@ void main()
camera_lP = vec3(2.0, 2.0, 0.0);
/* Follows ShadowDirectional::end_sync(). */
set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(32));
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(32));
lP = vec3(2.00001, 2.00001, 0.0);
coords = shadow_directional_coordinates(light, lP);
@ -278,7 +280,7 @@ void main()
// camera_lP = vec3(2.0, 2.0, 0.0);
/* Follows ShadowDirectional::end_sync(). */
// set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
// EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(32));
// EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(32));
// lP = vec3(2.00001, 2.00001, 0.0);
// coords = shadow_directional_coordinates(light, lP);

View File

@ -176,13 +176,16 @@ struct ShadowCoordinates {
};
/* Retain sign bit and avoid costly int division. */
ivec2 shadow_decompress_grid_offset(eLightType light_type, ivec2 offset, int level_relative)
ivec2 shadow_decompress_grid_offset(eLightType light_type,
ivec2 offset_neg,
ivec2 offset_pos,
int level_relative)
{
if (light_type == LIGHT_SUN_ORTHO) {
return shadow_cascade_grid_offset(offset, level_relative);
return shadow_cascade_grid_offset(offset_pos, level_relative);
}
else {
return ((offset & 0xFFFF) >> level_relative) - ((offset >> 16) >> level_relative);
return (offset_pos >> level_relative) - (offset_neg >> level_relative);
}
}
@ -203,7 +206,10 @@ ShadowCoordinates shadow_directional_coordinates_at_level(LightData light, vec3
/* Compute offset in tile. */
ivec2 clipmap_offset = shadow_decompress_grid_offset(
light.type, light_sun_data_get(light).clipmap_base_offset, level_relative);
light.type,
light_sun_data_get(light).clipmap_base_offset_neg,
light_sun_data_get(light).clipmap_base_offset_pos,
level_relative);
ret.uv = lP.xy - light_sun_data_get(light).clipmap_origin;
ret.uv /= exp2(float(ret.lod_relative));

View File

@ -252,7 +252,10 @@ ShadowTracingSample shadow_map_trace_sample(ShadowMapTracingState state,
/* Compute offset in tile. */
ivec2 clipmap_offset = shadow_decompress_grid_offset(
ray.light.type, light_sun_data_get(ray.light).clipmap_base_offset, level_relative);
ray.light.type,
light_sun_data_get(ray.light).clipmap_base_offset_neg,
light_sun_data_get(ray.light).clipmap_base_offset_pos,
level_relative);
/* Translate tilemap UVs to its origin. */
tilemap_uv -= vec2(clipmap_offset) / float(SHADOW_TILEMAP_RES);
/* Clamp to avoid out of tilemap access. */

View File

@ -63,8 +63,7 @@ void init_globals_curves()
/* Random cosine normal distribution on the hair surface. */
float noise = utility_tx_fetch(utility_tx, gl_FragCoord.xy, UTIL_BLUE_NOISE_LAYER).x;
# ifdef EEVEE_SAMPLING_DATA
/* Needs to check for SAMPLING_DATA,
* otherwise Surfel and World (?!?!) shader validation fails. */
/* Needs to check for SAMPLING_DATA, otherwise surfel shader validation fails. */
noise = fract(noise + sampling_rng_1D_get(SAMPLING_CURVES_U));
# endif
cos_theta = noise * 2.0 - 1.0;

View File

@ -13,6 +13,9 @@
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_colorspace_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_reflection_probe_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_lightprobe_volume_eval_lib.glsl)
vec4 closure_to_rgba(Closure cl)
{
@ -38,6 +41,23 @@ void main()
out_background.rgb = colorspace_safe_color(g_emission) * (1.0 - g_holdout);
out_background.a = saturate(average(g_transmittance)) * g_holdout;
if (g_data.ray_type == RAY_TYPE_CAMERA && world_background_blur != 0.0 &&
world_opacity_fade != 0.0)
{
float base_lod = sphere_probe_roughness_to_lod(world_background_blur);
float lod = max(1.0, base_lod);
float mix_factor = min(1.0, base_lod);
SphereProbeUvArea world_atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
vec4 probe_color = reflection_probes_sample(-g_data.N, lod, world_atlas_coord);
out_background.rgb = mix(out_background.rgb, probe_color.rgb, mix_factor);
SphericalHarmonicL1 volume_irradiance = lightprobe_irradiance_sample(
g_data.P, vec3(0.0), g_data.Ng);
vec3 radiance_sh = spherical_harmonics_evaluate_lambert(-g_data.N, volume_irradiance);
float radiance_mix_factor = sphere_probe_roughness_to_mix_fac(world_background_blur);
out_background.rgb = mix(out_background.rgb, radiance_sh, radiance_mix_factor);
}
/* World opacity. */
out_background = mix(vec4(0.0, 0.0, 0.0, 1.0), out_background, world_opacity_fade);

View File

@ -218,9 +218,14 @@ GPU_SHADER_CREATE_INFO(eevee_surf_depth)
GPU_SHADER_CREATE_INFO(eevee_surf_world)
.push_constant(Type::FLOAT, "world_opacity_fade")
.push_constant(Type::FLOAT, "world_background_blur")
.push_constant(Type::IVEC4, "world_coord_packed")
.fragment_out(0, Type::VEC4, "out_background")
.fragment_source("eevee_surf_world_frag.glsl")
.additional_info("eevee_global_ubo",
"eevee_reflection_probe_data",
"eevee_volume_probe_data",
"eevee_sampling_data",
/* Optionally added depending on the material. */
// "eevee_render_pass_out",
// "eevee_cryptomatte_out",

View File

@ -701,7 +701,7 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
visible_strokes.foreach_index([&](const int stroke_i) {
const IndexRange points = points_by_curve[stroke_i];
const int material_index = stroke_materials[stroke_i];
MaterialGPencilStyle *gp_style = BKE_object_material_get(ob, material_index + 1)->gp_style;
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, material_index + 1);
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
const bool show_stroke = ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0);

View File

@ -330,7 +330,7 @@ static void OVERLAY_outline_grease_pencil(OVERLAY_PrivateData *pd, Scene *scene,
visible_strokes.foreach_index([&](const int stroke_i) {
const IndexRange points = points_by_curve[stroke_i];
const int material_index = stroke_materials[stroke_i];
MaterialGPencilStyle *gp_style = BKE_object_material_get(ob, material_index + 1)->gp_style;
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, material_index + 1);
const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
if (hide_material) {

View File

@ -26,11 +26,11 @@ void ShaderCache::release()
ShaderCache::ShaderCache()
{
std::string geometries[] = {"_mesh", "_curves", "_ptcloud"};
std::string pipelines[] = {"_opaque", "_transparent"};
std::string lightings[] = {"_flat", "_studio", "_matcap"};
std::string shaders[] = {"_material", "_texture"};
std::string clip[] = {"_no_clip", "_clip"};
const std::string geometries[] = {"_mesh", "_curves", "_ptcloud"};
const std::string pipelines[] = {"_opaque", "_transparent"};
const std::string lightings[] = {"_flat", "_studio", "_matcap"};
const std::string shaders[] = {"_material", "_texture"};
const std::string clip[] = {"_no_clip", "_clip"};
static_assert(std::size(geometries) == geometry_type_len);
static_assert(std::size(pipelines) == pipeline_type_len);
static_assert(std::size(lightings) == lighting_type_len);
@ -49,9 +49,9 @@ ShaderCache::ShaderCache()
}
}
std::string cavity[] = {"_no_cavity", "_cavity"};
std::string curvature[] = {"_no_curvature", "_curvature"};
std::string shadow[] = {"_no_shadow", "_shadow"};
const std::string cavity[] = {"_no_cavity", "_cavity"};
const std::string curvature[] = {"_no_curvature", "_curvature"};
const std::string shadow[] = {"_no_shadow", "_shadow"};
for (auto l : IndexRange(lighting_type_len)) {
for (auto ca : IndexRange(2) /*cavity*/) {
@ -64,9 +64,9 @@ ShaderCache::ShaderCache()
}
}
std::string pass[] = {"_fail", "_pass"};
std::string manifold[] = {"_no_manifold", "_manifold"};
std::string caps[] = {"_no_caps", "_caps"};
const std::string pass[] = {"_fail", "_pass"};
const std::string manifold[] = {"_no_manifold", "_manifold"};
const std::string caps[] = {"_no_caps", "_caps"};
for (auto p : IndexRange(2) /*pass*/) {
for (auto m : IndexRange(2) /*manifold*/) {
@ -77,10 +77,10 @@ ShaderCache::ShaderCache()
}
}
std::string smoke[] = {"_object", "_smoke"};
std::string interpolation[] = {"_linear", "_cubic", "_closest"};
std::string coba[] = {"_no_coba", "_coba"};
std::string slice[] = {"_no_slice", "_slice"};
const std::string smoke[] = {"_object", "_smoke"};
const std::string interpolation[] = {"_linear", "_cubic", "_closest"};
const std::string coba[] = {"_no_coba", "_coba"};
const std::string slice[] = {"_no_slice", "_slice"};
for (auto sm : IndexRange(2) /*smoke*/) {
for (auto i : IndexRange(3) /*interpolation*/) {

View File

@ -56,40 +56,46 @@ void ShadowPass::ShadowView::setup(View &view, float3 light_direction, bool forc
const int z_pos = 4; /* Near */
const int z_neg = 2; /* Far */
int3 corner_faces[8] = {{x_neg, y_neg, z_pos},
{x_neg, y_neg, z_neg},
{x_neg, y_pos, z_neg},
{x_neg, y_pos, z_pos},
{x_pos, y_neg, z_pos},
{x_pos, y_neg, z_neg},
{x_pos, y_pos, z_neg},
{x_pos, y_pos, z_pos}};
const int3 corner_faces[8] = {
{x_neg, y_neg, z_pos},
{x_neg, y_neg, z_neg},
{x_neg, y_pos, z_neg},
{x_neg, y_pos, z_pos},
{x_pos, y_neg, z_pos},
{x_pos, y_neg, z_neg},
{x_pos, y_pos, z_neg},
{x_pos, y_pos, z_pos},
};
int2 edge_faces[12] = {{x_neg, y_neg},
{x_neg, z_neg},
{x_neg, y_pos},
{x_neg, z_pos},
{y_neg, x_pos},
{z_neg, x_pos},
{y_pos, x_pos},
{z_pos, x_pos},
{y_neg, z_pos},
{z_neg, y_neg},
{y_pos, z_neg},
{z_pos, y_pos}};
const int2 edge_faces[12] = {
{x_neg, y_neg},
{x_neg, z_neg},
{x_neg, y_pos},
{x_neg, z_pos},
{y_neg, x_pos},
{z_neg, x_pos},
{y_pos, x_pos},
{z_pos, x_pos},
{y_neg, z_pos},
{z_neg, y_neg},
{y_pos, z_neg},
{z_pos, y_pos},
};
int2 edge_corners[12] = {{0, 1},
{1, 2},
{2, 3},
{3, 0},
{4, 5},
{5, 6},
{6, 7},
{7, 4},
{0, 4},
{1, 5},
{2, 6},
{3, 7}};
const int2 edge_corners[12] = {
{0, 1},
{1, 2},
{2, 3},
{3, 0},
{4, 5},
{5, 6},
{6, 7},
{7, 4},
{0, 4},
{1, 5},
{2, 6},
{3, 7},
};
BoundBox frustum_corners;
DRW_culling_frustum_corners_get(nullptr, &frustum_corners);

View File

@ -501,7 +501,7 @@ std::string Draw::serialize() const
")";
}
std::string DrawMulti::serialize(std::string line_prefix) const
std::string DrawMulti::serialize(const std::string &line_prefix) const
{
DrawMultiBuf::DrawGroupBuf &groups = multi_draw_buf->group_buf_;

View File

@ -371,7 +371,7 @@ struct DrawMulti {
uint uuid;
void execute(RecordingState &state) const;
std::string serialize(std::string line_prefix) const;
std::string serialize(const std::string &line_prefix) const;
};
struct DrawIndirect {

View File

@ -3365,6 +3365,7 @@ static int click_select_channel_object(bContext *C,
bAnimListElem *ale,
const short /* eEditKeyframes_Select or -1 */ selectmode)
{
using namespace blender::ed;
Scene *scene = ac->scene;
ViewLayer *view_layer = ac->view_layer;
Base *base = (Base *)ale->data;
@ -3377,7 +3378,7 @@ static int click_select_channel_object(bContext *C,
if (selectmode == SELECT_INVERT) {
/* swap select */
ED_object_base_select(base, BA_INVERT);
object::base_select(base, object::BA_INVERT);
if (adt) {
adt->flag ^= ADT_UI_SELECTED;
@ -3393,14 +3394,14 @@ static int click_select_channel_object(bContext *C,
BKE_view_layer_synced_ensure(scene, view_layer);
/* TODO: should this deselect all other types of channels too? */
LISTBASE_FOREACH (Base *, b, BKE_view_layer_object_bases_get(view_layer)) {
ED_object_base_select(b, BA_DESELECT);
object::base_select(b, object::BA_DESELECT);
if (b->object->adt) {
b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
}
}
/* select object now */
ED_object_base_select(base, BA_SELECT);
object::base_select(base, object::BA_SELECT);
if (adt) {
adt->flag |= ADT_UI_SELECTED;
}
@ -3410,7 +3411,7 @@ static int click_select_channel_object(bContext *C,
*
* Ensure we exit edit-mode on whatever object was active before
* to avoid getting stuck there, see: #48747. */
ED_object_base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */
object::base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */
/* Similar to outliner, do not change active element when selecting elements in range. */
if ((adt) && (adt->flag & ADT_UI_SELECTED) && (selectmode != SELECT_EXTEND_RANGE)) {

View File

@ -509,7 +509,7 @@ static void draw_marker(const uiFontStyle *fstyle,
draw_marker_name(text_color, fstyle, marker, xpos, xmax, name_y);
}
static void draw_markers_background(rctf *rect)
static void draw_markers_background(const rctf *rect)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@ -1304,6 +1304,7 @@ static int select_timeline_marker_frame(ListBase *markers,
static void select_marker_camera_switch(
bContext *C, bool camera, bool extend, ListBase *markers, int cfra)
{
using namespace blender::ed;
#ifdef DURIAN_CAMERA_SWITCH
if (camera) {
BLI_assert(CTX_data_mode_enum(C) == CTX_MODE_OBJECT);
@ -1329,9 +1330,9 @@ static void select_marker_camera_switch(
if (marker->frame == cfra) {
base = BKE_view_layer_base_find(view_layer, marker->camera);
if (base) {
ED_object_base_select(base, eObjectSelect_Mode(sel));
object::base_select(base, object::eObjectSelect_Mode(sel));
if (sel) {
ED_object_base_activate(C, base);
object::base_activate(C, base);
}
}
}

View File

@ -198,7 +198,7 @@ static int insert_key_with_keyingset(bContext *C, wmOperator *op, KeyingSet *ks)
* updated since the last switching to the edit mode will be keyframed correctly
*/
if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
ED_object_mode_set(C, OB_MODE_OBJECT);
blender::ed::object::mode_set(C, OB_MODE_OBJECT);
ob_edit_mode = true;
}
@ -214,7 +214,7 @@ static int insert_key_with_keyingset(bContext *C, wmOperator *op, KeyingSet *ks)
/* restore the edit mode if necessary */
if (ob_edit_mode) {
ED_object_mode_set(C, OB_MODE_EDIT);
blender::ed::object::mode_set(C, OB_MODE_EDIT);
}
/* report failure or do updates? */

View File

@ -66,7 +66,7 @@ bArmature *ED_armature_context(const bContext *C)
CTX_data_pointer_get_type(C, "armature", &RNA_Armature).data);
if (armature == nullptr) {
Object *object = ED_object_active_context(C);
Object *object = blender::ed::object::context_active_object(C);
if (object && object->type == OB_ARMATURE) {
armature = static_cast<bArmature *>(object->data);
}

View File

@ -493,7 +493,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op)
}
/* Free the old object data */
ED_object_base_free_and_unlink(bmain, scene, ob_iter);
blender::ed::object::base_free_and_unlink(bmain, scene, ob_iter);
}
}
CTX_DATA_END;
@ -735,7 +735,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* Only duplicate linked armature but take into account
* user preferences for duplicating actions. */
short dupflag = USER_DUP_ARM | (U.dupflag & USER_DUP_ACT);
Base *base_new = ED_object_add_duplicate(
Base *base_new = blender::ed::object::add_duplicate(
bmain, scene, view_layer, base_old, eDupli_ID_Flags(dupflag));
Object *ob_new = base_new->object;

View File

@ -1092,7 +1092,7 @@ bool ED_armature_edit_select_pick_bone(
BKE_view_layer_synced_ensure(scene, view_layer);
if (BKE_view_layer_active_base_get(view_layer) != basact) {
ED_object_base_activate(C, basact);
blender::ed::object::base_activate(C, basact);
}
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);

View File

@ -243,19 +243,19 @@ static void envelope_bone_weighting(Object *ob,
/* add the vert to the deform group if (weight != 0.0) */
if (distance != 0.0f) {
ED_vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
blender::ed::object::vgroup_vert_add(ob, dgroup, i, distance, WEIGHT_REPLACE);
}
else {
ED_vgroup_vert_remove(ob, dgroup, i);
blender::ed::object::vgroup_vert_remove(ob, dgroup, i);
}
/* do same for mirror */
if (dgroupflip && dgroupflip[j] && iflip != -1) {
if (distance != 0.0f) {
ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance, WEIGHT_REPLACE);
blender::ed::object::vgroup_vert_add(ob, dgroupflip[j], iflip, distance, WEIGHT_REPLACE);
}
else {
ED_vgroup_vert_remove(ob, dgroupflip[j], iflip);
blender::ed::object::vgroup_vert_remove(ob, dgroupflip[j], iflip);
}
}
}
@ -492,7 +492,7 @@ void ED_object_vgroup_calc_from_armature(ReportList *reports,
if (defbase_add) {
/* It's possible there are DWeights outside the range of the current
* object's deform groups. In this case the new groups won't be empty #33889. */
ED_vgroup_data_clamp_range(static_cast<ID *>(ob->data), defbase_tot);
blender::ed::object::vgroup_data_clamp_range(static_cast<ID *>(ob->data), defbase_tot);
}
}
else if (ELEM(mode, ARM_GROUPS_ENVELOPE, ARM_GROUPS_AUTO)) {

View File

@ -366,7 +366,7 @@ static bool bone_collection_assign_named_mode_specific(bContext *C,
static bool bone_collection_assign_poll(bContext *C)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return false;
}
@ -399,7 +399,7 @@ static bool bone_collection_assign_poll(bContext *C)
/* Assign selected pchans to the bone collection that the user selects */
static int bone_collection_assign_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return OPERATOR_CANCELLED;
}
@ -469,7 +469,7 @@ void ARMATURE_OT_collection_assign(wmOperatorType *ot)
static bool bone_collection_create_and_assign_poll(bContext *C)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return false;
}
@ -498,7 +498,7 @@ static bool bone_collection_create_and_assign_poll(bContext *C)
/* Assign selected pchans to the bone collection that the user selects */
static int bone_collection_create_and_assign_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return OPERATOR_CANCELLED;
}
@ -565,7 +565,7 @@ void ARMATURE_OT_collection_create_and_assign(wmOperatorType *ot)
static int bone_collection_unassign_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return OPERATOR_CANCELLED;
}
@ -626,7 +626,7 @@ void ARMATURE_OT_collection_unassign(wmOperatorType *ot)
static int bone_collection_unassign_named_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return OPERATOR_CANCELLED;
}
@ -712,7 +712,7 @@ static bool editbone_is_member(const EditBone *ebone, const BoneCollection *bcol
static bool armature_bone_select_poll(bContext *C)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr || ob->type != OB_ARMATURE) {
return false;
}
@ -784,7 +784,7 @@ static void bone_collection_select(bContext *C,
static int bone_collection_select_exec(bContext *C, wmOperator * /*op*/)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return OPERATOR_CANCELLED;
}
@ -816,7 +816,7 @@ void ARMATURE_OT_collection_select(wmOperatorType *ot)
static int bone_collection_deselect_exec(bContext *C, wmOperator * /*op*/)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return OPERATOR_CANCELLED;
}
@ -891,7 +891,7 @@ static int add_or_move_to_collection_exec(bContext *C,
const assign_bone_func assign_func_bone,
const assign_ebone_func assign_func_ebone)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob->mode == OB_MODE_POSE) {
ob = ED_pose_object_from_context(C);
}
@ -953,7 +953,7 @@ static int assign_to_collection_exec(bContext *C, wmOperator *op)
static bool move_to_collection_poll(bContext *C)
{
Object *ob = ED_object_context(C);
Object *ob = blender::ed::object::context_object(C);
if (ob == nullptr) {
return false;
}
@ -1062,7 +1062,7 @@ static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *
bool is_move_operation;
std::tie(parent_bcoll_index, is_move_operation) = menu_custom_data_decode(menu_custom_data);
const Object *ob = ED_object_context(C);
const Object *ob = blender::ed::object::context_object(C);
const bArmature *arm = static_cast<bArmature *>(ob->data);
/* The "Create a new collection" mode of this operator has its own menu, and should thus be

View File

@ -737,9 +737,9 @@ void heat_bone_weighting(Object *ob,
continue;
}
ED_vgroup_vert_remove(ob, dgrouplist[j], a);
blender::ed::object::vgroup_vert_remove(ob, dgrouplist[j], a);
if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
blender::ed::object::vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
}
}
}
@ -765,16 +765,16 @@ void heat_bone_weighting(Object *ob,
if (bbone) {
if (solution > 0.0f) {
ED_vgroup_vert_add(ob, dgrouplist[j], a, solution, WEIGHT_ADD);
blender::ed::object::vgroup_vert_add(ob, dgrouplist[j], a, solution, WEIGHT_ADD);
}
}
else {
weight = heat_limit_weight(solution);
if (weight > 0.0f) {
ED_vgroup_vert_add(ob, dgrouplist[j], a, weight, WEIGHT_REPLACE);
blender::ed::object::vgroup_vert_add(ob, dgrouplist[j], a, weight, WEIGHT_REPLACE);
}
else {
ED_vgroup_vert_remove(ob, dgrouplist[j], a);
blender::ed::object::vgroup_vert_remove(ob, dgrouplist[j], a);
}
}
@ -782,16 +782,18 @@ void heat_bone_weighting(Object *ob,
if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
if (bbone) {
if (solution > 0.0f) {
ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], solution, WEIGHT_ADD);
blender::ed::object::vgroup_vert_add(
ob, dgroupflip[j], vertsflipped[a], solution, WEIGHT_ADD);
}
}
else {
weight = heat_limit_weight(solution);
if (weight > 0.0f) {
ED_vgroup_vert_add(ob, dgroupflip[j], vertsflipped[a], weight, WEIGHT_REPLACE);
blender::ed::object::vgroup_vert_add(
ob, dgroupflip[j], vertsflipped[a], weight, WEIGHT_REPLACE);
}
else {
ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
blender::ed::object::vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
}
}
}
@ -809,17 +811,17 @@ void heat_bone_weighting(Object *ob,
continue;
}
weight = ED_vgroup_vert_weight(ob, dgrouplist[j], a);
weight = blender::ed::object::vgroup_vert_weight(ob, dgrouplist[j], a);
weight = heat_limit_weight(weight);
if (weight <= 0.0f) {
ED_vgroup_vert_remove(ob, dgrouplist[j], a);
blender::ed::object::vgroup_vert_remove(ob, dgrouplist[j], a);
}
if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
weight = ED_vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
weight = blender::ed::object::vgroup_vert_weight(ob, dgroupflip[j], vertsflipped[a]);
weight = heat_limit_weight(weight);
if (weight <= 0.0f) {
ED_vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
blender::ed::object::vgroup_vert_remove(ob, dgroupflip[j], vertsflipped[a]);
}
}
}

View File

@ -66,7 +66,7 @@ Object *ED_pose_object_from_context(bContext *C)
/* Since this call may also be used from the buttons window,
* we need to check for where to get the object. */
if (area && area->spacetype == SPACE_PROPERTIES) {
ob = ED_object_active_context(C);
ob = blender::ed::object::context_active_object(C);
}
else {
ob = BKE_object_pose_armature_get(CTX_data_active_object(C));

View File

@ -234,7 +234,7 @@ bool ED_armature_pose_select_pick_bone(const Scene *scene,
/* In weight-paint we select the associated vertex group too. */
if (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) {
if (bone == arm->act_bone) {
ED_vgroup_select_by_name(ob_act, bone->name);
blender::ed::object::vgroup_select_by_name(ob_act, bone->name);
DEG_id_tag_update(&ob_act->id, ID_RECALC_GEOMETRY);
}
}
@ -304,7 +304,7 @@ void ED_armature_pose_select_in_wpaint_mode(const Scene *scene,
if ((base_arm != nullptr) && (base_arm != base_select) &&
(base_arm->flag & BASE_SELECTED))
{
ED_object_base_select(base_arm, BA_DESELECT);
blender::ed::object::base_select(base_arm, blender::ed::object::BA_DESELECT);
}
}
}
@ -322,14 +322,14 @@ void ED_armature_pose_select_in_wpaint_mode(const Scene *scene,
if ((base_arm != nullptr) && (base_arm != base_select) &&
(base_arm->flag & BASE_SELECTED))
{
ED_object_base_select(base_arm, BA_DESELECT);
blender::ed::object::base_select(base_arm, blender::ed::object::BA_DESELECT);
}
}
}
}
}
if ((base_select->flag & BASE_SELECTED) == 0) {
ED_object_base_select(base_select, BA_SELECT);
blender::ed::object::base_select(base_select, blender::ed::object::BA_SELECT);
}
}
@ -1181,7 +1181,7 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op)
/* In weight-paint we select the associated vertex group too. */
if (is_weight_paint) {
ED_vgroup_select_by_name(ob_active, pchan_mirror_act->name);
blender::ed::object::vgroup_select_by_name(ob_active, pchan_mirror_act->name);
DEG_id_tag_update(&ob_active->id, ID_RECALC_GEOMETRY);
}
}

View File

@ -19,7 +19,6 @@
struct AssetLibraryReference;
struct bContext;
namespace blender::asset_system {
class AssetLibrary;
class AssetRepresentation;

View File

@ -12,7 +12,6 @@
struct ID;
struct Main;
namespace blender::asset_system {
class AssetRepresentation;
}

View File

@ -14,10 +14,9 @@
struct AssetHandle;
struct AssetLibraryReference;
struct AssetLibraryReference;
struct bContext;
struct ID;
struct ImBuf;
struct bContext;
struct wmNotifier;
struct wmRegionListenerParams;
namespace blender::asset_system {
@ -84,7 +83,7 @@ void storage_exit();
AssetHandle asset_handle_get_by_index(const AssetLibraryReference *library_reference,
int asset_index);
blender::asset_system::AssetRepresentation *asset_get_by_index(
asset_system::AssetRepresentation *asset_get_by_index(
const AssetLibraryReference &library_reference, int asset_index);
bool asset_image_is_loading(const AssetLibraryReference *library_reference,

View File

@ -9,9 +9,9 @@
#pragma once
struct AssetMetaData;
struct bContext;
struct ID;
struct Main;
struct bContext;
namespace blender::ed::asset {

View File

@ -17,8 +17,8 @@ struct bContextDataResult;
struct BlendDataReader;
struct BlendWriter;
struct Main;
struct wmWindowManager;
struct RegionPollParams;
struct wmWindowManager;
namespace blender::ed::asset::shelf {

View File

@ -16,8 +16,6 @@
#include "ED_asset_import.hh"
using namespace blender;
namespace blender::ed::asset {
ID *asset_local_id_ensure_imported(Main &bmain, const asset_system::AssetRepresentation &asset)

View File

@ -632,8 +632,8 @@ int AssetLibraryIndex::remove_broken_index_files()
}
int num_files_deleted = 0;
for (StringRef files_to_remove : files_to_remove) {
if (delete_file_index(files_to_remove)) {
for (StringRef filepath : files_to_remove) {
if (delete_file_index(filepath)) {
num_files_deleted++;
}
}

Some files were not shown because too many files have changed in this diff Show More