Anim: Detailed report if no keyframes have been inserted #119201
|
@ -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)) \
|
||||
{ \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
{
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -202,6 +202,7 @@ class LightProbeModule {
|
|||
friend class VolumeProbeModule;
|
||||
friend class PlanarProbeModule;
|
||||
friend class SphereProbeModule;
|
||||
friend class BackgroundPipeline;
|
||||
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
|
|
@ -72,6 +72,11 @@ class LookdevWorld {
|
|||
{
|
||||
return parameters_.background_opacity;
|
||||
}
|
||||
|
||||
float background_blur_get()
|
||||
{
|
||||
return parameters_.blur;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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*/) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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", ""},
|
||||
|
|
|
@ -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", "");
|
||||
|
|
|
@ -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", "");
|
||||
|
|
|
@ -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", ""},
|
||||
|
|
|
@ -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", ""},
|
||||
|
|
|
@ -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", ""},
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 ************* */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue