Anim: Detailed report if no keyframes have been inserted #119201

Merged
Christoph Lendenfeld merged 13 commits from ChrisLend/blender:return_keying_result into main 2024-04-09 09:39:25 +02:00
142 changed files with 1014 additions and 687 deletions
Showing only changes of commit 862ea9eab3 - 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

@ -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

@ -1014,17 +1014,15 @@ class IMAGE_PT_snapping(Panel):
layout = self.layout
col = layout.column()
col.label(text="Snapping")
col.label(text="Snap Target")
col.prop(tool_settings, "snap_uv_element", expand=True)
if tool_settings.snap_uv_element != 'INCREMENT':
col.label(text="Target")
col.label(text="Snap Base")
row = col.row(align=True)
row.prop(tool_settings, "snap_target", expand=True)
col.separator()
if 'INCREMENT' in tool_settings.snap_uv_element:
col.prop(tool_settings, "use_snap_uv_grid_absolute")
col.label(text="Affect")
row = col.row(align=True)

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

@ -6573,8 +6573,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':
@ -6599,8 +6598,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

@ -261,58 +261,41 @@ static void get_keyframe_values_create_reports(ReportList *reports,
MEM_freeN(str_failed_indices);
}
/**
* Retrieve current property values to keyframe,
* possibly applying NLA correction when necessary.
*
* \param r_successful_remaps: Enables bits for indices which are both intended to be remapped and
* were successfully remapped. Bitmap allocated so it must be freed afterward.
*/
static Vector<float> get_keyframe_values(ReportList *reports,
PointerRNA ptr,
PropertyRNA *prop,
int index,
NlaKeyframingContext *nla_context,
eInsertKeyFlags flag,
const AnimationEvalContext *anim_eval_context,
bool *r_force_all,
blender::BitVector<> &r_successful_remaps)
static Vector<float> get_keyframe_values(PointerRNA *ptr, PropertyRNA *prop, const bool visual_key)
{
Vector<float> values;
if ((flag & INSERTKEY_MATRIX) && visualkey_can_use(&ptr, prop)) {
if (visual_key && visualkey_can_use(ptr, prop)) {
/* Visual-keying is only available for object and pchan datablocks, as
* it works by keyframing using a value extracted from the final matrix
* instead of using the kt system to extract a value.
*/
values = visualkey_get_values(&ptr, prop);
values = visualkey_get_values(ptr, prop);
}
else {
values = get_rna_values(&ptr, prop);
values = get_rna_values(ptr, prop);
}
r_successful_remaps.resize(values.size());
/* adjust the value for NLA factors */
BKE_animsys_nla_remap_keyframe_values(nla_context,
&ptr,
prop,
values.as_mutable_span(),
index,
anim_eval_context,
r_force_all,
r_successful_remaps);
get_keyframe_values_create_reports(reports,
ptr,
prop,
index,
values.size(),
r_force_all ? *r_force_all : false,
r_successful_remaps);
return values;
}
static BitVector<> nla_map_keyframe_values_and_generate_reports(
const MutableSpan<float> values,
const int index,
PointerRNA &ptr,
PropertyRNA &prop,
NlaKeyframingContext *nla_context,
const AnimationEvalContext *anim_eval_context,
ReportList *reports,
bool *force_all)
{
BitVector<> successful_remaps(values.size(), false);
BKE_animsys_nla_remap_keyframe_values(
nla_context, &ptr, &prop, values, index, anim_eval_context, force_all, successful_remaps);
get_keyframe_values_create_reports(
reports, ptr, &prop, index, values.size(), false, successful_remaps);
return successful_remaps;
}
/**
* Move the point where a key is about to be inserted to be inside the main cycle range.
* Returns the type of the cycle if it is enabled and valid.
@ -487,9 +470,18 @@ bool insert_keyframe_direct(ReportList *reports,
update_autoflags_fcurve_direct(fcu, prop);
const int index = fcu->array_index;
BitVector<> successful_remaps;
Vector<float> values = get_keyframe_values(
reports, ptr, prop, index, nla_context, flag, anim_eval_context, nullptr, successful_remaps);
const bool visual_keyframing = flag & INSERTKEY_MATRIX;
Vector<float> values = get_keyframe_values(&ptr, prop, visual_keyframing);
BitVector<> successful_remaps = nla_map_keyframe_values_and_generate_reports(
values.as_mutable_span(),
index,
ptr,
*prop,
nla_context,
anim_eval_context,
reports,
nullptr);
float current_value = 0.0f;
if (index >= 0 && index < values.size()) {
@ -616,17 +608,19 @@ int insert_keyframe(Main *bmain,
const float nla_mapped_frame = nla_time_remap(
anim_eval_context, &id_ptr, adt, act, &nla_cache, &nla_context);
const bool visual_keyframing = flag & INSERTKEY_MATRIX;
Vector<float> values = get_keyframe_values(&ptr, prop, visual_keyframing);
bool force_all;
BitVector successful_remaps;
Vector<float> values = get_keyframe_values(reports,
ptr,
prop,
array_index,
nla_context,
flag,
anim_eval_context,
&force_all,
successful_remaps);
BitVector<> successful_remaps = nla_map_keyframe_values_and_generate_reports(
values.as_mutable_span(),
array_index,
ptr,
*prop,
nla_context,
anim_eval_context,
reports,
&force_all);
CombinedKeyingResult combined_result;
@ -992,25 +986,6 @@ CombinedKeyingResult insert_key_action(Main *bmain,
return combined_result;
}
static blender::Vector<float> get_keyframe_values(PointerRNA *ptr,
PropertyRNA *prop,
const bool visual_key)
{
Vector<float> values;
if (visual_key && visualkey_can_use(ptr, prop)) {
/* Visual-keying is only available for object and pchan datablocks, as
* it works by keyframing using a value extracted from the final matrix
* instead of using the kt system to extract a value.
*/
values = visualkey_get_values(ptr, prop);
}
else {
values = get_rna_values(ptr, prop);
}
return values;
}
CombinedKeyingResult insert_key_rna(PointerRNA *rna_pointer,
const blender::Span<std::string> rna_paths,
const float scene_frame,
@ -1032,9 +1007,11 @@ CombinedKeyingResult insert_key_rna(PointerRNA *rna_pointer,
/* Keyframing functions can deal with the nla_context being a nullptr. */
ListBase nla_cache = {nullptr, nullptr};
NlaKeyframingContext *nla_context = nullptr;
if (adt && adt->action == action) {
PointerRNA id_pointer = RNA_id_pointer_create(id);
nla_context = BKE_animsys_get_nla_keyframing_context(
&nla_cache, rna_pointer, adt, &anim_eval_context);
&nla_cache, &id_pointer, adt, &anim_eval_context);
}
const float nla_frame = BKE_nla_tweakedit_remap(adt, scene_frame, NLATIME_CONVERT_UNMAP);

View File

@ -237,7 +237,7 @@ typedef struct NlaKeyframingContext NlaKeyframingContext;
*
* \param cache: List used to cache contexts for reuse when keying
* multiple channels in one operation.
* \param ptr: RNA pointer to the Object with the animation.
* \param ptr: RNA pointer to the ID with the animation.
* \return Keyframing context, or NULL if not necessary.
*/
struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(

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

@ -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

@ -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

@ -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

@ -3673,6 +3673,11 @@ void nlasnapshot_blend_get_inverted_lower_snapshot(NlaEvalData *eval_data,
NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
ListBase *cache, PointerRNA *ptr, AnimData *adt, const AnimationEvalContext *anim_eval_context)
{
/* The PointerRNA needs to point to an ID because animsys_evaluate_nla_for_keyframing uses
* F-Curve paths to resolve properties. Since F-Curve paths are always relative to the ID this
* would fail if the PointerRNA was e.g. a bone. */
BLI_assert(RNA_struct_is_ID(ptr->type));
/* No remapping needed if NLA is off or no action. */
if ((adt == nullptr) || (adt->action == nullptr) || (adt->nla_tracks.first == nullptr) ||
(adt->flag & ADT_NLA_EVAL_OFF))

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);
}
@ -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

@ -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

@ -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

@ -3154,7 +3154,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)
{
@ -3163,8 +3163,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;
}
@ -3175,9 +3175,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

@ -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

@ -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

@ -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

@ -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

@ -150,7 +150,11 @@ void PlanarProbeModule::viewport_draw(View &view, GPUFrameBuffer *view_fb)
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
viewport_display_ps_.framebuffer_set(&view_fb);
viewport_display_ps_.shader_set(inst_.shaders.static_shader_get(DISPLAY_PROBE_PLANAR));
bind_resources(viewport_display_ps_);
SphereProbeData &world_data = *static_cast<SphereProbeData *>(&inst_.light_probes.world_sphere_);
viewport_display_ps_.push_constant("world_coord_packed",
reinterpret_cast<int4 *>(&world_data.atlas_coord));
viewport_display_ps_.bind_resources(*this);
viewport_display_ps_.bind_resources(inst_.sphere_probes);
viewport_display_ps_.bind_ssbo("display_data_buf", display_data_buf_);
viewport_display_ps_.draw_procedural(GPU_PRIM_TRIS, 1, display_data_buf_.size() * 6);

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

@ -2,9 +2,24 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma BLENDER_REQUIRE(draw_view_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_reflection_probe_lib.glsl)
void main()
{
vec2 uv = gl_FragCoord.xy / vec2(textureSize(planar_radiance_tx, 0).xy);
out_color = texture(planar_radiance_tx, vec3(uv, probe_index));
float depth = texture(planar_depth_tx, vec3(uv, probe_index)).r;
if (depth == 1.0) {
vec3 ndc = drw_screen_to_ndc(vec3(uv, 0.0));
vec3 wP = drw_point_ndc_to_world(ndc);
vec3 V = drw_world_incident_vector(wP);
vec3 R = -reflect(V, probe_normal);
SphereProbeUvArea world_atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
out_color = reflection_probes_sample(R, 0.0, world_atlas_coord);
}
else {
out_color = texture(planar_radiance_tx, vec3(uv, probe_index));
}
out_color.a = 0.0;
}

View File

@ -22,9 +22,11 @@ void main()
probe_index = display_data_buf[display_index].probe_index;
vec3 P = transform_point(display_data_buf[display_index].plane_to_world, vec3(lP, 0.0));
mat4 plane_to_world = display_data_buf[display_index].plane_to_world;
probe_normal = safe_normalize(plane_to_world[2].xyz);
vec3 P = transform_point(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

@ -78,10 +78,16 @@ GPU_SHADER_CREATE_INFO(eevee_display_probe_reflection)
.fragment_out(0, Type::VEC4, "out_color")
.do_static_compilation(true);
GPU_SHADER_INTERFACE_INFO(eevee_display_probe_planar_iface, "").flat(Type::INT, "probe_index");
GPU_SHADER_INTERFACE_INFO(eevee_display_probe_planar_iface, "")
.flat(Type::VEC3, "probe_normal")
.flat(Type::INT, "probe_index");
GPU_SHADER_CREATE_INFO(eevee_display_probe_planar)
.additional_info("eevee_shared", "draw_view", "eevee_lightprobe_planar_data")
.push_constant(Type::IVEC4, "world_coord_packed")
.additional_info("eevee_shared",
"draw_view",
"eevee_lightprobe_planar_data",
"eevee_reflection_probe_data")
.storage_buf(0, Qualifier::READ, "PlanarProbeDisplayData", "display_data_buf[]")
.vertex_source("eevee_display_probe_planar_vert.glsl")
.vertex_out(eevee_display_probe_planar_iface)

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

@ -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);

View File

@ -670,7 +670,7 @@ static void text_insert_unicode_confirm(bContext *C, void *arg_block, void *arg_
if (val > 31 && val < 0x10FFFF) {
Object *obedit = CTX_data_edit_object(C);
if (obedit) {
char32_t utf32[2] = {val, 0};
const char32_t utf32[2] = {val, 0};
font_paste_wchar(obedit, utf32, 1, nullptr);
text_update_edited(C, obedit, FO_EDIT);
}

View File

@ -535,7 +535,7 @@ static void GIZMO_GT_arrow_3d(wmGizmoType *gzt)
gzt->struct_size = sizeof(ArrowGizmo3D);
/* rna */
static EnumPropertyItem rna_enum_draw_style_items[] = {
static const EnumPropertyItem rna_enum_draw_style_items[] = {
{ED_GIZMO_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""},
{ED_GIZMO_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
{ED_GIZMO_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
@ -543,12 +543,12 @@ static void GIZMO_GT_arrow_3d(wmGizmoType *gzt)
{ED_GIZMO_ARROW_STYLE_PLANE, "PLANE", 0, "Plane", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem rna_enum_draw_options_items[] = {
static const EnumPropertyItem rna_enum_draw_options_items[] = {
{ED_GIZMO_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""},
{ED_GIZMO_ARROW_DRAW_FLAG_ORIGIN, "ORIGIN", 0, "Origin", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem rna_enum_transform_items[] = {
static const EnumPropertyItem rna_enum_transform_items[] = {
{ED_GIZMO_ARROW_XFORM_FLAG_INVERTED, "INVERT", 0, "Inverted", ""},
{ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
{0, nullptr, 0, nullptr, nullptr},

View File

@ -398,7 +398,7 @@ static void GIZMO_GT_button_2d(wmGizmoType *gzt)
gzt->struct_size = sizeof(ButtonGizmo2D);
/* rna */
static EnumPropertyItem rna_enum_draw_options[] = {
static const EnumPropertyItem rna_enum_draw_options[] = {
{ED_GIZMO_BUTTON_SHOW_OUTLINE, "OUTLINE", 0, "Outline", ""},
{ED_GIZMO_BUTTON_SHOW_BACKDROP, "BACKDROP", 0, "Backdrop", ""},
{ED_GIZMO_BUTTON_SHOW_HELPLINE, "HELPLINE", 0, "Help Line", ""},

View File

@ -1329,24 +1329,24 @@ static void GIZMO_GT_cage_2d(wmGizmoType *gzt)
gzt->struct_size = sizeof(wmGizmo);
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
static const EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_GIZMO_CAGE2D_STYLE_BOX_TRANSFORM, "BOX_TRANSFORM", 0, "Box Transform", ""},
{ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem rna_enum_transform[] = {
static const EnumPropertyItem rna_enum_transform[] = {
{ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem rna_enum_draw_options[] = {
static const EnumPropertyItem rna_enum_draw_options[] = {
{ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static float unit_v2[2] = {1.0f, 1.0f};
static const float unit_v2[2] = {1.0f, 1.0f};
RNA_def_float_vector(
gzt->srna, "dimensions", 2, unit_v2, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");

View File

@ -644,22 +644,22 @@ static void GIZMO_GT_cage_3d(wmGizmoType *gzt)
gzt->struct_size = sizeof(wmGizmo);
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
static const EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_CAGE3D_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_GIZMO_CAGE3D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem rna_enum_transform[] = {
static const EnumPropertyItem rna_enum_transform[] = {
{ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem rna_enum_draw_options[] = {
static const EnumPropertyItem rna_enum_draw_options[] = {
{ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static float unit_v3[3] = {1.0f, 1.0f, 1.0f};
static const float unit_v3[3] = {1.0f, 1.0f, 1.0f};
RNA_def_float_vector(
gzt->srna, "dimensions", 3, unit_v3, 0, FLT_MAX, "Dimensions", "", 0.0f, FLT_MAX);
RNA_def_enum_flag(gzt->srna, "transform", rna_enum_transform, 0, "Transform Options", "");

View File

@ -682,7 +682,7 @@ static void GIZMO_GT_dial_3d(wmGizmoType *gzt)
gzt->struct_size = sizeof(wmGizmo);
/* rna */
static EnumPropertyItem rna_enum_draw_options[] = {
static const EnumPropertyItem rna_enum_draw_options[] = {
{ED_GIZMO_DIAL_DRAW_FLAG_CLIP, "CLIP", 0, "Clipped", ""},
{ED_GIZMO_DIAL_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
{ED_GIZMO_DIAL_DRAW_FLAG_FILL_SELECT, "FILL_SELECT", 0, "Use fill for selection test", ""},

View File

@ -449,12 +449,12 @@ static void GIZMO_GT_move_3d(wmGizmoType *gzt)
gzt->struct_size = sizeof(MoveGizmo3D);
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
static const EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_MOVE_STYLE_RING_2D, "RING_2D", 0, "Ring", ""},
{ED_GIZMO_MOVE_STYLE_CROSS_2D, "CROSS_2D", 0, "Ring", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static EnumPropertyItem rna_enum_draw_options[] = {
static const EnumPropertyItem rna_enum_draw_options[] = {
{ED_GIZMO_MOVE_DRAW_FLAG_FILL, "FILL", 0, "Filled", ""},
{ED_GIZMO_MOVE_DRAW_FLAG_FILL_SELECT, "FILL_SELECT", 0, "Use fill for selection test", ""},
{ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW, "ALIGN_VIEW", 0, "Align View", ""},

View File

@ -256,7 +256,7 @@ static void GIZMO_GT_primitive_3d(wmGizmoType *gzt)
gzt->struct_size = sizeof(PrimitiveGizmo3D);
static EnumPropertyItem rna_enum_draw_style[] = {
static const EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_PRIMITIVE_STYLE_PLANE, "PLANE", 0, "Plane", ""},
{ED_GIZMO_PRIMITIVE_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{ED_GIZMO_PRIMITIVE_STYLE_ANNULUS, "ANNULUS", 0, "Annulus", ""},

View File

@ -2786,7 +2786,7 @@ static int gpencil_dissolve_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_dissolve(wmOperatorType *ot)
{
static EnumPropertyItem prop_gpencil_dissolve_types[] = {
static const EnumPropertyItem prop_gpencil_dissolve_types[] = {
{GP_DISSOLVE_POINTS, "POINTS", 0, "Dissolve", "Dissolve selected points"},
{GP_DISSOLVE_BETWEEN,
"BETWEEN",

View File

@ -258,8 +258,11 @@ static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_
}
}
static bool extended_bbox_overlap(
float min1[3], float max1[3], float min2[3], float max2[3], float extend)
static bool extended_bbox_overlap(const float min1[3],
const float max1[3],
const float min2[3],
const float max2[3],
float extend)
{
for (int axis = 0; axis < 3; axis++) {
float intersection_min = max_ff(min1[axis], min2[axis]) - extend;

View File

@ -1574,7 +1574,7 @@ static bool gpencil_do_curve_circle_sel(bContext *C,
const int my,
const int radius,
const bool select,
rcti *rect,
const rcti *rect,
const float diff_mat[4][4],
const int selectmode)
{

View File

@ -123,14 +123,14 @@ bGPdata **ED_annotation_data_get_pointers_direct(ID *screen_id,
SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
switch (area->spacetype) {
case SPACE_PROPERTIES: /* properties */
case SPACE_INFO: /* header info */
case SPACE_INFO: /* header info */
{
return nullptr;
}
case SPACE_TOPBAR: /* Top-bar */
case SPACE_VIEW3D: /* 3D-View */
case SPACE_TOPBAR: /* Top-bar */
case SPACE_VIEW3D: /* 3D-View */
case SPACE_PROPERTIES: /* properties */
{
if (r_ptr) {
*r_ptr = RNA_id_pointer_create(&scene->id);

View File

@ -1138,7 +1138,7 @@ static int gpencil_stroke_reset_vertex_color_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_stroke_reset_vertex_color(wmOperatorType *ot)
{
static EnumPropertyItem mode_types_items[] = {
static const EnumPropertyItem mode_types_items[] = {
{GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Reset Vertex Color to Stroke only"},
{GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Reset Vertex Color to Fill only"},
{GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke & Fill", "Reset Vertex Color to Stroke and Fill"},

View File

@ -1108,7 +1108,7 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C,
static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVertexpaintData *gso)
{
ToolSettings *ts = CTX_data_tool_settings(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Object *obact = gso->object;
bool changed = false;

View File

@ -80,7 +80,7 @@ void initNumInput(NumInput *n);
/**
* \param str: Must be NUM_STR_REP_LEN * (idx_max + 1) length.
*/
void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings);
void outputNumInput(NumInput *n, char *str, const UnitSettings *unit_settings);
bool hasNumInput(const NumInput *n);
/**
* \warning \a vec must be set beforehand otherwise we risk uninitialized vars.

View File

@ -87,7 +87,7 @@ void ED_slider_status_string_get(const tSlider *slider,
char *status_string,
size_t size_of_status_string);
float ED_slider_factor_get(tSlider *slider);
float ED_slider_factor_get(const tSlider *slider);
void ED_slider_factor_set(tSlider *slider, float factor);
/** One bool value for each side of the slider. Allows to enable overshoot only on one side. */
@ -98,11 +98,11 @@ void ED_slider_allow_overshoot_set(tSlider *slider, bool lower, bool upper);
*/
void ED_slider_factor_bounds_set(tSlider *slider, float lower_bound, float upper_bound);
bool ED_slider_allow_increments_get(tSlider *slider);
bool ED_slider_allow_increments_get(const tSlider *slider);
void ED_slider_allow_increments_set(tSlider *slider, bool value);
void ED_slider_mode_set(tSlider *slider, SliderMode mode);
SliderMode ED_slider_mode_get(tSlider *slider);
SliderMode ED_slider_mode_get(const tSlider *slider);
void ED_slider_unit_set(tSlider *slider, const char *unit);
/* ************** XXX OLD CRUFT WARNING ************* */

View File

@ -148,7 +148,7 @@ void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], const
* \param lens: The view lens angle set for cameras and lights, normally from View3D.lens.
*/
void ED_view3d_from_object(
const Object *ob, float ofs[3], float quat[4], float *dist, float *lens);
const Object *ob, float ofs[3], float quat[4], const float *dist, float *lens);
/**
* Set the object transformation from #RegionView3D members.
* \param depsgraph: The depsgraph to get the evaluated object parent

View File

@ -589,7 +589,7 @@ void ui_draw_but_HISTOGRAM(ARegion * /*region*/,
#undef HISTOGRAM_TOT_GRID_LINES
static void waveform_draw_one(float *waveform, int waveform_num, const float col[3])
static void waveform_draw_one(const float *waveform, int waveform_num, const float col[3])
{
GPUVertFormat format = {0};
const uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@ -609,7 +609,7 @@ static void waveform_draw_one(float *waveform, int waveform_num, const float col
GPU_batch_discard(batch);
}
static void waveform_draw_rgb(float *waveform, int waveform_num, float *col)
static void waveform_draw_rgb(const float *waveform, int waveform_num, const float *col)
{
GPUVertFormat format = {0};
const uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@ -629,7 +629,7 @@ static void waveform_draw_rgb(float *waveform, int waveform_num, float *col)
GPU_batch_discard(batch);
}
static void circle_draw_rgb(float *points, int tot_points, float *col, GPUPrimType prim)
static void circle_draw_rgb(float *points, int tot_points, const float *col, GPUPrimType prim)
{
GPUVertFormat format = {0};
const uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@ -904,7 +904,7 @@ static void vectorscope_draw_target(
float y, u, v;
float tangle = 0.0f, tampli;
float dangle, dampli;
char labelstr[2] = {label, '\0'};
const char labelstr[2] = {label, '\0'};
rgb_to_yuv(colf[0], colf[1], colf[2], &y, &u, &v, BLI_YUV_ITU_BT709);

View File

@ -246,73 +246,30 @@ class LayerViewItem : public AbstractTreeViewItem {
{
uiBut *but = uiItemL_ex(
&row, layer_.name().c_str(), ICON_OUTLINER_DATA_GP_LAYER, false, false);
if (layer_.is_locked() || !layer_.parent_group().is_visible()) {
if (!layer_.is_editable()) {
UI_but_disable(but, "Layer is locked or not visible");
}
}
void build_layer_buttons(uiLayout &row)
{
uiBut *but;
uiLayout *sub;
PointerRNA layer_ptr = RNA_pointer_create(&grease_pencil_.id, &RNA_GreasePencilLayer, &layer_);
uiBlock *block = uiLayoutGetBlock(&row);
sub = uiLayoutRow(&row, true);
uiLayoutSetActive(sub, layer_.parent_group().use_masks());
const int icon_mask = (layer_.base.flag & GP_LAYER_TREE_NODE_HIDE_MASKS) == 0 ?
ICON_CLIPUV_DEHLT :
ICON_CLIPUV_HLT;
uiItemR(sub, &layer_ptr, "use_masks", UI_ITEM_R_ICON_ONLY, nullptr, icon_mask);
const int icon = (layer_.base.flag & GP_LAYER_TREE_NODE_HIDE_MASKS) == 0 ? ICON_CLIPUV_DEHLT :
ICON_CLIPUV_HLT;
but = uiDefIconButR(block,
UI_BTYPE_ICON_TOGGLE,
0,
icon,
0,
0,
UI_UNIT_X,
UI_UNIT_Y,
&layer_ptr,
"use_masks",
0,
0.0f,
0.0f,
nullptr);
if (layer_.parent_group().use_masks()) {
UI_but_flag_enable(but, UI_BUT_INACTIVE);
}
sub = uiLayoutRow(&row, true);
uiLayoutSetActive(sub, layer_.parent_group().is_visible());
uiItemR(sub, &layer_ptr, "hide", UI_ITEM_R_ICON_ONLY, nullptr, ICON_NONE);
but = uiDefIconButR(block,
UI_BTYPE_ICON_TOGGLE,
0,
ICON_NONE,
0,
0,
UI_UNIT_X,
UI_UNIT_Y,
&layer_ptr,
"hide",
0,
0.0f,
0.0f,
nullptr);
if (!layer_.parent_group().is_visible()) {
UI_but_flag_enable(but, UI_BUT_INACTIVE);
}
but = uiDefIconButR(block,
UI_BTYPE_ICON_TOGGLE,
0,
ICON_NONE,
0,
0,
UI_UNIT_X,
UI_UNIT_Y,
&layer_ptr,
"lock",
0,
0.0f,
0.0f,
nullptr);
if (layer_.parent_group().is_locked()) {
UI_but_flag_enable(but, UI_BUT_INACTIVE);
}
sub = uiLayoutRow(&row, true);
uiLayoutSetActive(sub, !layer_.parent_group().is_locked());
uiItemR(sub, &layer_ptr, "lock", UI_ITEM_R_ICON_ONLY, nullptr, ICON_NONE);
}
};
@ -372,21 +329,37 @@ class LayerGroupViewItem : public AbstractTreeViewItem {
{
uiItemS_ex(&row, 0.8f);
uiBut *but = uiItemL_ex(&row, group_.name().c_str(), ICON_FILE_FOLDER, false, false);
if (group_.is_locked()) {
UI_but_disable(but, "Layer Group is locked");
if (!group_.is_editable()) {
UI_but_disable(but, "Layer Group is locked or not visible");
}
}
void build_layer_group_buttons(uiLayout &row)
{
uiLayout *sub;
PointerRNA group_ptr = RNA_pointer_create(
&grease_pencil_.id, &RNA_GreasePencilLayerGroup, &group_);
const int icon = (group_.base.flag & GP_LAYER_TREE_NODE_HIDE_MASKS) == 0 ? ICON_CLIPUV_DEHLT :
ICON_CLIPUV_HLT;
uiItemR(&row, &group_ptr, "use_masks", UI_ITEM_R_ICON_ONLY, nullptr, icon);
uiItemR(&row, &group_ptr, "hide", UI_ITEM_R_ICON_ONLY, nullptr, ICON_NONE);
uiItemR(&row, &group_ptr, "lock", UI_ITEM_R_ICON_ONLY, nullptr, ICON_NONE);
sub = uiLayoutRow(&row, true);
if (group_.as_node().parent_group()) {
uiLayoutSetActive(sub, group_.as_node().parent_group()->use_masks());
}
const int icon_mask = (group_.base.flag & GP_LAYER_TREE_NODE_HIDE_MASKS) == 0 ?
ICON_CLIPUV_DEHLT :
ICON_CLIPUV_HLT;
uiItemR(sub, &group_ptr, "use_masks", UI_ITEM_R_ICON_ONLY, nullptr, icon_mask);
sub = uiLayoutRow(&row, true);
if (group_.as_node().parent_group()) {
uiLayoutSetActive(sub, group_.as_node().parent_group()->is_visible());
}
uiItemR(sub, &group_ptr, "hide", UI_ITEM_R_ICON_ONLY, nullptr, ICON_NONE);
sub = uiLayoutRow(&row, true);
if (group_.as_node().parent_group()) {
uiLayoutSetActive(sub, !group_.as_node().parent_group()->is_locked());
}
uiItemR(sub, &group_ptr, "lock", UI_ITEM_R_ICON_ONLY, nullptr, ICON_NONE);
}
};

View File

@ -144,7 +144,7 @@ static const char *strdup_memarena(MemArena *memarena, const char *str)
return str_dst;
}
static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str)
static const char *strdup_memarena_from_dynstr(MemArena *memarena, const DynStr *dyn_str)
{
const uint str_size = BLI_dynstr_get_len(dyn_str) + 1;
char *str_dst = (char *)BLI_memarena_alloc(memarena, str_size);

View File

@ -3611,7 +3611,12 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
BLI_assert(sort_map[i] != -1);
}
if (ob->mode == OB_MODE_EDIT) {
if (ob->type == OB_GREASE_PENCIL) {
/* For Grease Pencil objects we don't have to do anything, because all drawings in the object
* store their own set of #vertex_group_names. So changing the vertex group order on object
* level is just a UI matter, no remapping in drawings is needed. */
}
else if (ob->mode == OB_MODE_EDIT) {
if (ob->type == OB_MESH) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);

View File

@ -643,7 +643,7 @@ static Scene *preview_prepare_scene(
/* new UI convention: draw is in pixel space already. */
/* uses UI_BTYPE_ROUNDBOX button in block to get the rect */
static bool ed_preview_draw_rect(
Scene *scene, ScrArea *area, int split, int first, rcti *rect, rcti *newrect)
Scene *scene, ScrArea *area, int split, int first, const rcti *rect, rcti *newrect)
{
Render *re;
RenderView *rv;

View File

@ -191,7 +191,7 @@ static void brush_painter_cache_2d_free(BrushPainterCache *cache)
}
}
static void brush_imbuf_tex_co(rctf *mapping, int x, int y, float texco[3])
static void brush_imbuf_tex_co(const rctf *mapping, int x, int y, float texco[3])
{
texco[0] = mapping->xmin + x * mapping->xmax;
texco[1] = mapping->ymin + y * mapping->ymax;

View File

@ -1010,6 +1010,8 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
vwpaint::update_cache_invariants(C, vp, ss, op, mouse);
vwpaint::init_session_data(ts, ob);
/* Brush may have changed after initialization. */
brush = BKE_paint_brush(&vp->paint);
if (ELEM(brush->weightpaint_tool, WPAINT_TOOL_SMEAR, WPAINT_TOOL_BLUR)) {
wpd->precomputed_weight = (float *)MEM_mallocN(sizeof(float) * mesh->verts_num, __func__);
}

View File

@ -812,12 +812,13 @@ static void buttons_area_listener(const wmSpaceTypeListenerParams *params)
}
break;
case NC_GPENCIL:
switch (wmn->data) {
case ND_DATA:
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED, NA_RENAME)) {
ED_area_tag_redraw(area);
}
break;
if (wmn->data == ND_DATA) {
if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED, NA_RENAME)) {
ED_area_tag_redraw(area);
}
}
else if (wmn->action == NA_EDITED) {
ED_area_tag_redraw(area);
}
break;
case NC_NODE:

View File

@ -1280,7 +1280,7 @@ static void console_modal_select_apply(bContext *C, wmOperator *op, const wmEven
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
SetConsoleCursor *scu = static_cast<SetConsoleCursor *>(op->customdata);
int sel_prev[2] = {sc->sel_start, sc->sel_end};
const int sel_prev[2] = {sc->sel_start, sc->sel_end};
console_cursor_set_to_pos(sc, region, scu, event);

View File

@ -184,7 +184,7 @@ static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
* NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise the controls don't
* have a consistent appearance (due to off-pixel alignments).
*/
static void draw_cross(float position[2], float scale[2], uint attr_id)
static void draw_cross(float position[2], const float scale[2], uint attr_id)
{
GPU_matrix_push();
GPU_matrix_translate_2fv(position);

View File

@ -2025,8 +2025,8 @@ struct tBtwOperatorData {
ListBase anim_data; /* bAnimListElem */
};
static int btw_calculate_sample_count(BezTriple *right_bezt,
BezTriple *left_bezt,
static int btw_calculate_sample_count(const BezTriple *right_bezt,
const BezTriple *left_bezt,
const int filter_order,
const int samples_per_frame)
{

View File

@ -1004,6 +1004,14 @@ static void image_header_region_listener(const wmRegionListenerParams *params)
ED_region_tag_redraw(region);
}
break;
case NC_GPENCIL:
if (wmn->data & ND_GPENCIL_EDITMODE) {
ED_region_tag_redraw(region);
}
else if (wmn->action == NA_EDITED) {
ED_region_tag_redraw(region);
}
break;
}
}

View File

@ -509,7 +509,7 @@ static size_t label_str_get(const Sequence *seq,
static bool label_rect_get(const bContext *C,
const Sequence *seq,
const SeqRetimingKey *key,
char *label_str,
const char *label_str,
const size_t label_len,
rctf *rect)
{

View File

@ -123,7 +123,7 @@ ImBuf *make_waveform_view_from_ibuf(const ImBuf *ibuf)
* overhead, so instead get luma coefficients as 16-bit integers. */
float coeffs[3];
IMB_colormanagement_get_luminance_coefficients(coeffs);
int muls[3] = {int(coeffs[0] * 65535), int(coeffs[1] * 65535), int(coeffs[2] * 65535)};
const int muls[3] = {int(coeffs[0] * 65535), int(coeffs[1] * 65535), int(coeffs[2] * 65535)};
/* Parallel over x, since each column is easily independent from others. */
threading::parallel_for(IndexRange(ibuf->x), 32, [&](IndexRange x_range) {

View File

@ -37,7 +37,7 @@ struct ThumbnailDrawJob {
SeqRenderData context;
GHash *sequences_ghash;
Scene *scene;
rctf *view_area;
const rctf *view_area;
float pixelx;
float pixely;
float thumb_height;
@ -59,7 +59,7 @@ static void thumbnail_freejob(void *data)
{
ThumbnailDrawJob *tj = static_cast<ThumbnailDrawJob *>(data);
BLI_ghash_free(tj->sequences_ghash, nullptr, thumbnail_hash_data_free);
MEM_freeN(tj->view_area);
MEM_freeN((void *)tj->view_area);
MEM_freeN(tj);
}
@ -69,7 +69,7 @@ static void thumbnail_endjob(void *data)
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, tj->scene);
}
static bool check_seq_need_thumbnails(const Scene *scene, Sequence *seq, rctf *view_area)
static bool check_seq_need_thumbnails(const Scene *scene, Sequence *seq, const rctf *view_area)
{
if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) {
return false;

View File

@ -1013,7 +1013,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *b
CLAMP(st->runtime->scroll_region_select.ymax, pix_bottom_margin, region->winy - pix_top_margin);
}
static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
static void draw_textscroll(const SpaceText *st, const rcti *scroll, const rcti *back)
{
bTheme *btheme = UI_GetTheme();
uiWidgetColors wcol = btheme->tui.wcol_scroll;

View File

@ -1572,7 +1572,8 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c
sub_v3_v3v3(mat[3], dvec, ofs);
}
void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
void ED_view3d_from_object(
const Object *ob, float ofs[3], float quat[4], const float *dist, float *lens)
{
ED_view3d_from_m4(ob->object_to_world().ptr(), ofs, quat, dist);

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