Vulkan: Clearing Storage Buffers #105487

Merged
Jeroen Bakker merged 94 commits from Jeroen-Bakker/blender:vulkan-storage-buffer-clear into main 2023-03-17 13:48:50 +01:00
70 changed files with 1016 additions and 470 deletions
Showing only changes of commit 53d92d7704 - Show all commits

View File

@ -35,7 +35,7 @@ struct BVHReferenceCompare {
/* Compare two references.
*
* Returns value is similar to return value of strcmp().
* Returns value is similar to return value of `strcmp()`.
*/
__forceinline int compare(const BVHReference &ra, const BVHReference &rb) const
{

View File

@ -494,7 +494,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc,
float3 H;
float cos_NH, cos_HI;
float3 local_H, local_I, X, Y; /* Nneeded for anisotropic microfacets later. */
float3 local_H, local_I, X, Y; /* Needed for anisotropic microfacets later. */
if (m_singular) {
H = N;
cos_NH = 1.0f;

View File

@ -979,7 +979,7 @@ ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
for (int ci = 0; ci < sd_mnee->num_closure; ci++) {
ccl_private ShaderClosure *bsdf = &sd_mnee->closure[ci];
if (CLOSURE_IS_REFRACTIVE(bsdf->type)) {
/* Note that Glass closures are treates as refractive further below. */
/* Note that Glass closures are treated as refractive further below. */
found_refractive_microfacet_bsdf = true;
ccl_private MicrofacetBsdf *microfacet_bsdf = (ccl_private MicrofacetBsdf *)bsdf;

View File

@ -177,20 +177,53 @@ typedef enum {
typedef enum {
GHOST_kEventUnknown = 0,
GHOST_kEventCursorMove, /* Mouse move event. */
GHOST_kEventButtonDown, /* Mouse button event. */
GHOST_kEventButtonUp, /* Mouse button event. */
GHOST_kEventWheel, /* Mouse wheel event. */
GHOST_kEventTrackpad, /* Trackpad event. */
/** Mouse move event.
*
* \note #GHOST_GetEventData returns #GHOST_TEventCursorData.
*/
GHOST_kEventCursorMove,
/** Mouse button down event. */
GHOST_kEventButtonDown,
/** Mouse button up event. */
GHOST_kEventButtonUp,
/**
* Mouse wheel event.
*
* \note #GHOST_GetEventData returns #GHOST_TEventWheelData.
*/
GHOST_kEventWheel,
/**
* Trackpad event.
*
* \note #GHOST_GetEventData returns #GHOST_TEventTrackpadData.
*/
GHOST_kEventTrackpad,
#ifdef WITH_INPUT_NDOF
GHOST_kEventNDOFMotion, /* N degree of freedom device motion event. */
GHOST_kEventNDOFButton, /* N degree of freedom device button event. */
/**
* N degree of freedom device motion event.
*
* \note #GHOST_GetEventData returns #GHOST_TEventNDOFMotionData.
*/
GHOST_kEventNDOFMotion,
/**
* N degree of freedom device button event.
*
* \note #GHOST_GetEventData returns #GHOST_TEventNDOFButtonData.
*/
GHOST_kEventNDOFButton,
#endif
/**
* Keyboard up/down events.
*
* Includes repeat events, check #GHOST_TEventKeyData::is_repeat
* if detecting repeat events is needed.
*
* \note #GHOST_GetEventData returns #GHOST_TEventKeyData.
*/
GHOST_kEventKeyDown,
GHOST_kEventKeyUp,
// GHOST_kEventKeyAuto,
GHOST_kEventQuitRequest,

View File

@ -20,11 +20,13 @@ enum TransformType {
TRANSFORM_SRGB_TO_LINEAR,
TRANSFORM_SCALE,
TRANSFORM_EXPONENT,
TRANSFORM_NONE,
TRANSFORM_UNKNOWN,
};
#define COLORSPACE_LINEAR ((OCIO_ConstColorSpaceRcPtr *)1)
#define COLORSPACE_SRGB ((OCIO_ConstColorSpaceRcPtr *)2)
#define COLORSPACE_DATA ((OCIO_ConstColorSpaceRcPtr *)3)
typedef struct OCIO_PackedImageDescription {
float *data;
@ -165,6 +167,8 @@ OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcP
return COLORSPACE_LINEAR;
else if (strcmp(name, "sRGB") == 0)
return COLORSPACE_SRGB;
else if (strcmp(name, "data") == 0)
return COLORSPACE_DATA;
return NULL;
}
@ -179,6 +183,9 @@ int FallbackImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, con
else if (cs == COLORSPACE_SRGB) {
return 1;
}
else if (cs == COLORSPACE_DATA) {
return 2;
}
return -1;
}
@ -314,7 +321,10 @@ OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(OCIO_ConstCo
OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName);
OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName);
FallbackTransform transform;
if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) {
if (cs_src == COLORSPACE_DATA || cs_dst == COLORSPACE_DATA) {
transform.type = TRANSFORM_NONE;
}
else if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) {
transform.type = TRANSFORM_LINEAR_TO_SRGB;
}
else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) {
@ -433,6 +443,9 @@ const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
else if (cs == COLORSPACE_SRGB) {
return "sRGB";
}
else if (cs == COLORSPACE_DATA) {
return "data";
}
return NULL;
}

View File

@ -13,8 +13,8 @@ from bpy.props import (
class SCENE_OT_freestyle_fill_range_by_selection(Operator):
"""Fill the Range Min/Max entries by the min/max distance between selected mesh objects and the source object """
"""(either a user-specified object or the active camera)"""
"""Fill the Range Min/Max entries by the min/max distance between selected mesh objects and the source object """ \
"""(either a user-specified object or the active camera)"""
bl_idname = "scene.freestyle_fill_range_by_selection"
bl_label = "Fill Range by Selection"
bl_options = {'INTERNAL'}

View File

@ -21,6 +21,8 @@ struct FCurve;
struct PathResolvedRNA;
struct PointerRNA;
struct PropertyRNA;
struct Scene;
struct ViewLayer;
/* ************** F-Curve Drivers ***************** */
@ -59,6 +61,32 @@ void fcurve_free_driver(struct FCurve *fcu);
*/
struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
/**
* Get property from which the specific property can be found from.
*
* This depends on the type of `dvar`:
*
* - For the Single Property the `r_prop` is a pointer to an ID, which is used to resolve the
* target rna_path.
*
* - For Transform Channel, Rotational Difference, Distance the `r_prop` is a pointer to an
* object from which transformation is read.
*
* - For Context Property the `r_prop` points to a resolved data corresponding to the
* dtar->context_property accessed from the given evaluated context. This could either be an ID
* property for Active Scene, or a data property for Active View Layer.
*
* If the target property can not be resolved false is returned.
*/
typedef struct DriverTargetContext {
struct Scene *scene;
struct ViewLayer *view_layer;
} DriverTargetContext;
bool driver_get_target_property(const DriverTargetContext *driver_target_context,
struct DriverVar *dvar,
struct DriverTarget *dtar,
struct PointerRNA *r_prop);
/**
* Copy driver variables from src_vars list to dst_vars list.
*/
@ -102,11 +130,15 @@ struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver);
/**
* Evaluate a Driver Variable to get a value that contributes to the final.
*/
float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar);
float driver_get_variable_value(const struct AnimationEvalContext *anim_eval_context,
struct ChannelDriver *driver,
struct DriverVar *dvar);
/**
* Same as 'dtar_get_prop_val'. but get the RNA property.
*/
bool driver_get_variable_property(struct ChannelDriver *driver,
bool driver_get_variable_property(const struct AnimationEvalContext *anim_eval_context,
struct ChannelDriver *driver,
struct DriverVar *dvar,
struct DriverTarget *dtar,
struct PointerRNA *r_ptr,
struct PropertyRNA **r_prop,

View File

@ -271,9 +271,20 @@ typedef struct bNodeType {
/** Check and update if internal ID data has changed. */
void (*group_update_func)(struct bNodeTree *ntree, struct bNode *node);
/** Initialize a new node instance of this type after creation. */
/**
* Initialize a new node instance of this type after creation.
*
* \note Assignments to `node->id` must not increment the user of the ID.
* This is handled by the caller of this callback.
*/
void (*initfunc)(struct bNodeTree *ntree, struct bNode *node);
/** Free the node instance. */
/**
* Free the node instance.
*
* \note Access to `node->id` must be avoided in this function as this is called
* while freeing #Main, the state of this ID is undefined.
* Higher level logic to remove the node handles the user-count.
*/
void (*freefunc)(struct bNode *node);
/** Make a copy of the node instance. */
void (*copyfunc)(struct bNodeTree *dest_ntree,

View File

@ -409,6 +409,9 @@ void BKE_curve_init(Curve *cu, const short curve_type)
cu->resolv = 4;
}
cu->bevel_profile = nullptr;
/* Initialize the offset to 1.0, to compensate for it being set to -1.0
in the property getter. */
cu->offset = 1.0f;
}
Curve *BKE_curve_add(Main *bmain, const char *name, int type)

View File

@ -10,6 +10,7 @@
#include "DNA_anim_types.h"
#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_alloca.h"
#include "BLI_expr_pylike_eval.h"
@ -31,11 +32,14 @@
#include "RNA_access.h"
#include "RNA_path.h"
#include "RNA_prototypes.h"
#include "atomic_ops.h"
#include "CLG_log.h"
#include "DEG_depsgraph_query.h"
#ifdef WITH_PYTHON
# include "BPY_extern.h"
#endif
@ -53,7 +57,9 @@ static CLG_LogRef LOG = {"bke.fcurve"};
/* TypeInfo for Driver Variables (dvti) */
typedef struct DriverVarTypeInfo {
/* Evaluation callback. */
float (*get_value)(ChannelDriver *driver, DriverVar *dvar);
float (*get_value)(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
DriverVar *dvar);
/* Allocation of target slots. */
int num_targets; /* Number of target slots required. */
@ -73,27 +79,89 @@ typedef struct DriverVarTypeInfo {
/** \name Driver Target Utilities
* \{ */
static DriverTargetContext driver_target_context_from_animation_context(
const AnimationEvalContext *anim_eval_context)
{
DriverTargetContext driver_target_context;
driver_target_context.scene = DEG_get_evaluated_scene(anim_eval_context->depsgraph);
driver_target_context.view_layer = DEG_get_evaluated_view_layer(anim_eval_context->depsgraph);
return driver_target_context;
}
/* Specialized implementation of driver_get_target_property() used for the
* DVAR_TYPE_CONTEXT_PROP variable type. */
static bool driver_get_target_context_property(const DriverTargetContext *driver_target_context,
DriverTarget *dtar,
PointerRNA *r_property_ptr)
{
switch (dtar->context_property) {
case DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE:
RNA_id_pointer_create(&driver_target_context->scene->id, r_property_ptr);
return true;
case DTAR_CONTEXT_PROPERTY_ACTIVE_VIEW_LAYER: {
RNA_pointer_create(&driver_target_context->scene->id,
&RNA_ViewLayer,
driver_target_context->view_layer,
r_property_ptr);
return true;
}
}
BLI_assert_unreachable();
/* Reset to a NULL RNA pointer.
* This allows to more gracefully handle issues with unsupported configuration (forward
* compatibility. for example). */
/* TODO(sergey): Replace with utility null-RNA-pointer creation once that is available. */
r_property_ptr->data = NULL;
r_property_ptr->type = NULL;
r_property_ptr->owner_id = NULL;
return false;
}
bool driver_get_target_property(const DriverTargetContext *driver_target_context,
DriverVar *dvar,
DriverTarget *dtar,
PointerRNA *r_prop)
{
if (dvar->type == DVAR_TYPE_CONTEXT_PROP) {
return driver_get_target_context_property(driver_target_context, dtar, r_prop);
}
if (dtar->id == NULL) {
return false;
}
RNA_id_pointer_create(dtar->id, r_prop);
return true;
}
/**
* Helper function to obtain a value using RNA from the specified source
* (for evaluating drivers).
*/
static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
static float dtar_get_prop_val(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
DriverVar *dvar,
DriverTarget *dtar)
{
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
ID *id;
int index = -1;
float value = 0.0f;
/* Sanity check. */
if (ELEM(NULL, driver, dtar)) {
if (driver == NULL) {
return 0.0f;
}
id = dtar->id;
/* Error check for missing pointer. */
if (id == NULL) {
/* Get property to resolve the target from.
* Naming is a bit confusing, but this is what is exposed as "Prop" or "Context Property" in
* interface. */
const DriverTargetContext driver_target_context = driver_target_context_from_animation_context(
anim_eval_context);
PointerRNA property_ptr;
if (!driver_get_target_property(&driver_target_context, dvar, dtar, &property_ptr)) {
if (G.debug & G_DEBUG) {
CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path);
}
@ -103,16 +171,18 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return 0.0f;
}
/* Get RNA-pointer for the ID-block given in target. */
RNA_id_pointer_create(id, &id_ptr);
/* Get property to read from, and get value as appropriate. */
if (!RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
PointerRNA value_ptr;
PropertyRNA *value_prop;
int index = -1;
float value = 0.0f;
if (!RNA_path_resolve_property_full(
&property_ptr, dtar->rna_path, &value_ptr, &value_prop, &index)) {
/* Path couldn't be resolved. */
if (G.debug & G_DEBUG) {
CLOG_ERROR(&LOG,
"Driver Evaluation Error: cannot resolve target for %s -> %s",
id->name,
property_ptr.owner_id->name,
dtar->rna_path);
}
@ -121,14 +191,14 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return 0.0f;
}
if (RNA_property_array_check(prop)) {
if (RNA_property_array_check(value_prop)) {
/* Array. */
if (index < 0 || index >= RNA_property_array_length(&ptr, prop)) {
if (index < 0 || index >= RNA_property_array_length(&value_ptr, value_prop)) {
/* Out of bounds. */
if (G.debug & G_DEBUG) {
CLOG_ERROR(&LOG,
"Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)",
id->name,
property_ptr.owner_id->name,
dtar->rna_path,
index);
}
@ -138,15 +208,15 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return 0.0f;
}
switch (RNA_property_type(prop)) {
switch (RNA_property_type(value_prop)) {
case PROP_BOOLEAN:
value = (float)RNA_property_boolean_get_index(&ptr, prop, index);
value = (float)RNA_property_boolean_get_index(&value_ptr, value_prop, index);
break;
case PROP_INT:
value = (float)RNA_property_int_get_index(&ptr, prop, index);
value = (float)RNA_property_int_get_index(&value_ptr, value_prop, index);
break;
case PROP_FLOAT:
value = RNA_property_float_get_index(&ptr, prop, index);
value = RNA_property_float_get_index(&value_ptr, value_prop, index);
break;
default:
break;
@ -154,18 +224,18 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
}
else {
/* Not an array. */
switch (RNA_property_type(prop)) {
switch (RNA_property_type(value_prop)) {
case PROP_BOOLEAN:
value = (float)RNA_property_boolean_get(&ptr, prop);
value = (float)RNA_property_boolean_get(&value_ptr, value_prop);
break;
case PROP_INT:
value = (float)RNA_property_int_get(&ptr, prop);
value = (float)RNA_property_int_get(&value_ptr, value_prop);
break;
case PROP_FLOAT:
value = RNA_property_float_get(&ptr, prop);
value = RNA_property_float_get(&value_ptr, value_prop);
break;
case PROP_ENUM:
value = (float)RNA_property_enum_get(&ptr, prop);
value = (float)RNA_property_enum_get(&value_ptr, value_prop);
break;
default:
break;
@ -177,16 +247,16 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return value;
}
bool driver_get_variable_property(ChannelDriver *driver,
bool driver_get_variable_property(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
DriverVar *dvar,
DriverTarget *dtar,
PointerRNA *r_ptr,
PropertyRNA **r_prop,
int *r_index)
{
PointerRNA id_ptr;
PointerRNA ptr;
PropertyRNA *prop;
ID *id;
int index = -1;
/* Sanity check. */
@ -194,10 +264,11 @@ bool driver_get_variable_property(ChannelDriver *driver,
return false;
}
id = dtar->id;
/* Error check for missing pointer. */
if (id == NULL) {
/* Get RNA-pointer for the data-block given in target. */
const DriverTargetContext driver_target_context = driver_target_context_from_animation_context(
anim_eval_context);
PointerRNA target_ptr;
if (!driver_get_target_property(&driver_target_context, dvar, dtar, &target_ptr)) {
if (G.debug & G_DEBUG) {
CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path);
}
@ -207,15 +278,12 @@ bool driver_get_variable_property(ChannelDriver *driver,
return false;
}
/* Get RNA-pointer for the ID-block given in target. */
RNA_id_pointer_create(id, &id_ptr);
/* Get property to read from, and get value as appropriate. */
if (dtar->rna_path == NULL || dtar->rna_path[0] == '\0') {
ptr = PointerRNA_NULL;
prop = NULL; /* OK. */
}
else if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) {
else if (RNA_path_resolve_full(&target_ptr, dtar->rna_path, &ptr, &prop, &index)) {
/* OK. */
}
else {
@ -223,7 +291,7 @@ bool driver_get_variable_property(ChannelDriver *driver,
if (G.debug & G_DEBUG) {
CLOG_ERROR(&LOG,
"Driver Evaluation Error: cannot resolve target for %s -> %s",
id->name,
target_ptr.owner_id->name,
dtar->rna_path);
}
@ -276,14 +344,18 @@ static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)
* \{ */
/* Evaluate 'single prop' driver variable. */
static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar)
static float dvar_eval_singleProp(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
DriverVar *dvar)
{
/* Just evaluate the first target slot. */
return dtar_get_prop_val(driver, &dvar->targets[0]);
return dtar_get_prop_val(anim_eval_context, driver, dvar, &dvar->targets[0]);
}
/* Evaluate 'rotation difference' driver variable. */
static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
static float dvar_eval_rotDiff(const AnimationEvalContext *UNUSED(anim_eval_context),
ChannelDriver *driver,
DriverVar *dvar)
{
short valid_targets = driver_check_valid_targets(driver, dvar);
@ -344,7 +416,9 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
*
* TODO: this needs to take into account space conversions.
*/
static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
static float dvar_eval_locDiff(const AnimationEvalContext *UNUSED(anim_eval_context),
ChannelDriver *driver,
DriverVar *dvar)
{
float loc1[3] = {0.0f, 0.0f, 0.0f};
float loc2[3] = {0.0f, 0.0f, 0.0f};
@ -446,7 +520,9 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/**
* Evaluate 'transform channel' driver variable.
*/
static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
static float dvar_eval_transChan(const AnimationEvalContext *UNUSED(anim_eval_context),
ChannelDriver *driver,
DriverVar *dvar)
{
DriverTarget *dtar = &dvar->targets[0];
Object *ob = (Object *)dtar->id;
@ -578,6 +654,15 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
return mat[3][dtar->transChan];
}
/* Evaluate 'context prop' driver variable. */
static float dvar_eval_contextProp(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
DriverVar *dvar)
{
/* Just evaluate the first target slot. */
return dtar_get_prop_val(anim_eval_context, driver, dvar, &dvar->targets[0]);
}
/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */
static void quaternion_to_angles(float quat[4], int channel)
{
@ -675,6 +760,12 @@ static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
{"Object/Bone"}, /* UI names for targets */
{DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* Flags. */
END_DVAR_TYPEDEF,
BEGIN_DVAR_TYPEDEF(DVAR_TYPE_CONTEXT_PROP) dvar_eval_contextProp, /* Eval callback. */
1, /* Number of targets used. */
{"Property"}, /* UI names for targets */
{0} /* Flags. */
END_DVAR_TYPEDEF,
};
/* Get driver variable typeinfo */
@ -972,7 +1063,8 @@ static bool driver_check_simple_expr_depends_on_time(ExprPyLike_Parsed *expr)
return BLI_expr_pylike_is_using_param(expr, VAR_INDEX_FRAME);
}
static bool driver_evaluate_simple_expr(ChannelDriver *driver,
static bool driver_evaluate_simple_expr(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
ExprPyLike_Parsed *expr,
float *result,
float time)
@ -985,7 +1077,7 @@ static bool driver_evaluate_simple_expr(ChannelDriver *driver,
vars[VAR_INDEX_FRAME] = time;
LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
vars[i++] = driver_get_variable_value(driver, dvar);
vars[i++] = driver_get_variable_value(anim_eval_context, driver, dvar);
}
/* Evaluate expression. */
@ -1042,7 +1134,8 @@ static bool driver_compile_simple_expr(ChannelDriver *driver)
/* Try using the simple expression evaluator to compute the result of the driver.
* On success, stores the result and returns true; on failure result is set to 0. */
static bool driver_try_evaluate_simple_expr(ChannelDriver *driver,
static bool driver_try_evaluate_simple_expr(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
ChannelDriver *driver_orig,
float *result,
float time)
@ -1051,7 +1144,8 @@ static bool driver_try_evaluate_simple_expr(ChannelDriver *driver,
return driver_compile_simple_expr(driver_orig) &&
BLI_expr_pylike_is_valid(driver_orig->expr_simple) &&
driver_evaluate_simple_expr(driver, driver_orig->expr_simple, result, time);
driver_evaluate_simple_expr(
anim_eval_context, driver, driver_orig->expr_simple, result, time);
}
bool BKE_driver_has_simple_expression(ChannelDriver *driver)
@ -1121,7 +1215,9 @@ void BKE_driver_invalidate_expression(ChannelDriver *driver,
/** \name Driver Evaluation
* \{ */
float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
float driver_get_variable_value(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver,
DriverVar *dvar)
{
const DriverVarTypeInfo *dvti;
@ -1136,7 +1232,7 @@ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
dvti = get_dvar_typeinfo(dvar->type);
if (dvti && dvti->get_value) {
dvar->curval = dvti->get_value(driver, dvar);
dvar->curval = dvti->get_value(anim_eval_context, driver, dvar);
}
else {
dvar->curval = 0.0f;
@ -1145,7 +1241,8 @@ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar)
return dvar->curval;
}
static void evaluate_driver_sum(ChannelDriver *driver)
static void evaluate_driver_sum(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver)
{
DriverVar *dvar;
@ -1153,7 +1250,7 @@ static void evaluate_driver_sum(ChannelDriver *driver)
if (BLI_listbase_is_single(&driver->variables)) {
/* Just one target, so just use that. */
dvar = driver->variables.first;
driver->curval = driver_get_variable_value(driver, dvar);
driver->curval = driver_get_variable_value(anim_eval_context, driver, dvar);
return;
}
@ -1163,7 +1260,7 @@ static void evaluate_driver_sum(ChannelDriver *driver)
/* Loop through targets, adding (hopefully we don't get any overflow!). */
for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
value += driver_get_variable_value(driver, dvar);
value += driver_get_variable_value(anim_eval_context, driver, dvar);
tot++;
}
@ -1176,7 +1273,8 @@ static void evaluate_driver_sum(ChannelDriver *driver)
}
}
static void evaluate_driver_min_max(ChannelDriver *driver)
static void evaluate_driver_min_max(const AnimationEvalContext *anim_eval_context,
ChannelDriver *driver)
{
DriverVar *dvar;
float value = 0.0f;
@ -1184,7 +1282,7 @@ static void evaluate_driver_min_max(ChannelDriver *driver)
/* Loop through the variables, getting the values and comparing them to existing ones. */
for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
/* Get value. */
float tmp_val = driver_get_variable_value(driver, dvar);
float tmp_val = driver_get_variable_value(anim_eval_context, driver, dvar);
/* Store this value if appropriate. */
if (dvar->prev) {
@ -1221,8 +1319,11 @@ static void evaluate_driver_python(PathResolvedRNA *anim_rna,
if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) {
driver->curval = 0.0f;
}
else if (!driver_try_evaluate_simple_expr(
driver, driver_orig, &driver->curval, anim_eval_context->eval_time)) {
else if (!driver_try_evaluate_simple_expr(anim_eval_context,
driver,
driver_orig,
&driver->curval,
anim_eval_context->eval_time)) {
#ifdef WITH_PYTHON
/* This evaluates the expression using Python, and returns its result:
* - on errors it reports, then returns 0.0f. */
@ -1250,11 +1351,11 @@ float evaluate_driver(PathResolvedRNA *anim_rna,
switch (driver->type) {
case DRIVER_TYPE_AVERAGE: /* Average values of driver targets. */
case DRIVER_TYPE_SUM: /* Sum values of driver targets. */
evaluate_driver_sum(driver);
evaluate_driver_sum(anim_eval_context, driver);
break;
case DRIVER_TYPE_MIN: /* Smallest value. */
case DRIVER_TYPE_MAX: /* Largest value. */
evaluate_driver_min_max(driver);
evaluate_driver_min_max(anim_eval_context, driver);
break;
case DRIVER_TYPE_PYTHON: /* Expression. */
evaluate_driver_python(anim_rna, driver, driver_orig, anim_eval_context);

View File

@ -2053,19 +2053,22 @@ bool nodeFindNodeTry(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r
bNode *nodeFindRootParent(bNode *node)
{
if (node->parent) {
return nodeFindRootParent(node->parent);
bNode *parent_iter = node;
while (parent_iter->parent != nullptr) {
parent_iter = parent_iter->parent;
}
return node->type == NODE_FRAME ? node : nullptr;
if (parent_iter->type != NODE_FRAME) {
return nullptr;
}
return parent_iter;
}
bool nodeIsParentAndChild(const bNode *parent, const bNode *child)
{
if (parent == child) {
return true;
}
if (child->parent) {
return nodeIsParentAndChild(parent, child->parent);
for (const bNode *child_iter = child; child_iter; child_iter = child_iter->parent) {
if (child_iter == parent) {
return true;
}
}
return false;
}
@ -2551,26 +2554,26 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
void nodeToView(const bNode *node, const float x, const float y, float *rx, float *ry)
{
if (node->parent) {
nodeToView(node->parent, x + node->locx, y + node->locy, rx, ry);
}
else {
*rx = x + node->locx;
*ry = y + node->locy;
float mapping_x = 0.0f;
float mapping_y = 0.0f;
for (const bNode *node_iter = node; node_iter; node_iter = node_iter->parent) {
mapping_x += node_iter->locx;
mapping_y += node_iter->locy;
}
*rx = mapping_x + x;
*ry = mapping_y + y;
}
void nodeFromView(const bNode *node, const float x, const float y, float *rx, float *ry)
{
if (node->parent) {
nodeFromView(node->parent, x, y, rx, ry);
*rx -= node->locx;
*ry -= node->locy;
}
else {
*rx = x - node->locx;
*ry = y - node->locy;
float mapping_x = 0.0f;
float mapping_y = 0.0f;
for (const bNode *node_iter = node; node_iter; node_iter = node_iter->parent) {
mapping_x += node_iter->locx;
mapping_y += node_iter->locy;
}
*rx = -mapping_x + x;
*ry = -mapping_y + y;
}
void nodeAttachNode(bNodeTree *ntree, bNode *node, bNode *parent)

View File

@ -1517,10 +1517,9 @@ void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track,
MovieTrackingMarker *marker_next = marker + 1;
if (marker_next->framenr == marker->framenr + 1) {
/* currently only do subframing inside tracked ranges, do not extrapolate tracked segments
/* Currently only do sub-framing inside tracked ranges, do not extrapolate tracked segments
* could be changed when / if mask parent would be interpolating position in-between
* tracked segments
*/
* tracked segments. */
float fac = (framenr - int(framenr)) / (marker_next->framenr - marker->framenr);

View File

@ -310,7 +310,7 @@ static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
/** \} */
/* -------------------------------------------------------------------- */
/** \name Autotrack context initialization.
/** \name Auto-Track Context Initialization
* \{ */
static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker)

View File

@ -383,7 +383,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixe
rgb_frame = context->current_frame;
}
/* Copy the Blender pixels into the FFmpeg datastructure, taking care of endianness and flipping
/* Copy the Blender pixels into the FFMPEG data-structure, taking care of endianness and flipping
* the image vertically. */
int linesize = rgb_frame->linesize[0];
for (int y = 0; y < height; y++) {

View File

@ -6,6 +6,7 @@ set(INC
cached_resources
../../blenkernel
../../blenlib
../../blentranslation
../../gpu
../../imbuf
../../makesdna

View File

@ -1192,29 +1192,46 @@ void DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcurve, int driver_index
void DepsgraphNodeBuilder::build_driver_variables(ID *id, FCurve *fcurve)
{
build_driver_id_property(id, fcurve->rna_path);
PointerRNA id_ptr;
RNA_id_pointer_create(id, &id_ptr);
build_driver_id_property(id_ptr, fcurve->rna_path);
DriverTargetContext driver_target_context;
driver_target_context.scene = graph_->scene;
driver_target_context.view_layer = graph_->view_layer;
LISTBASE_FOREACH (DriverVar *, dvar, &fcurve->driver->variables) {
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
if (dtar->id == nullptr) {
PointerRNA target_prop;
if (!driver_get_target_property(&driver_target_context, dvar, dtar, &target_prop)) {
continue;
}
build_id(dtar->id);
build_driver_id_property(dtar->id, dtar->rna_path);
/* Property is always expected to be resolved to a non-null RNA property, which is always
* relative to some ID. */
BLI_assert(target_prop.owner_id);
ID *target_id = target_prop.owner_id;
build_id(target_id);
build_driver_id_property(target_prop, dtar->rna_path);
}
DRIVER_TARGETS_LOOPER_END;
}
}
void DepsgraphNodeBuilder::build_driver_id_property(ID *id, const char *rna_path)
void DepsgraphNodeBuilder::build_driver_id_property(const PointerRNA &target_prop,
const char *rna_path_from_target_prop)
{
if (id == nullptr || rna_path == nullptr) {
if (rna_path_from_target_prop == nullptr || rna_path_from_target_prop[0] == '\0') {
return;
}
PointerRNA id_ptr, ptr;
PointerRNA ptr;
PropertyRNA *prop;
int index;
RNA_id_pointer_create(id, &id_ptr);
if (!RNA_path_resolve_full(&id_ptr, rna_path, &ptr, &prop, &index)) {
if (!RNA_path_resolve_full(&target_prop, rna_path_from_target_prop, &ptr, &prop, &index)) {
return;
}
if (prop == nullptr) {

View File

@ -49,6 +49,7 @@ struct bNodeSocket;
struct bNodeTree;
struct bPoseChannel;
struct bSound;
struct PointerRNA;
namespace blender::deg {
@ -207,6 +208,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
*/
virtual void build_animation_images(ID *id);
virtual void build_action(bAction *action);
/**
* Build graph node(s) for Driver
* \param id: ID-Block that driver is attached to
@ -214,8 +216,22 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
* \param driver_index: Index in animation data drivers list
*/
virtual void build_driver(ID *id, FCurve *fcurve, int driver_index);
virtual void build_driver_variables(ID *id, FCurve *fcurve);
virtual void build_driver_id_property(ID *id, const char *rna_path);
/* Build operations of a property value from which is read by a driver target.
*
* The driver target points to a data-block (or a sub-data-block like View Layer).
* This data-block is presented in the interface as a "Prop" and its resolved RNA pointer is
* passed here as `target_prop`.
*
* The tricky part (and a bit confusing naming) is that the driver target accesses a property of
* the `target_prop` to get its value. The property which is read to give an actual target value
* is denoted by its RNA path relative to the `target_prop`. In the interface it is called "Path"
* and here it is called `rna_path_from_target_prop`. */
virtual void build_driver_id_property(const PointerRNA &target_prop,
const char *rna_path_from_target_prop);
virtual void build_parameters(ID *id);
virtual void build_dimensions(Object *object);
virtual void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con);

View File

@ -1743,16 +1743,30 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
fcu->rna_path ? fcu->rna_path : "",
fcu->array_index);
const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
const RNAPathKey self_key(id, rna_path, RNAPointerSource::ENTRY);
DriverTargetContext driver_target_context;
driver_target_context.scene = graph_->scene;
driver_target_context.view_layer = graph_->view_layer;
LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
/* Only used targets. */
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
ID *target_id = dtar->id;
if (target_id == nullptr) {
PointerRNA target_prop;
if (!driver_get_target_property(&driver_target_context, dvar, dtar, &target_prop)) {
continue;
}
/* Property is always expected to be resolved to a non-null RNA property, which is always
* relative to some ID. */
BLI_assert(target_prop.owner_id);
ID *target_id = target_prop.owner_id;
build_id(target_id);
build_driver_id_property(target_id, dtar->rna_path);
build_driver_id_property(target_prop, dtar->rna_path);
Object *object = nullptr;
if (GS(target_id->name) == ID_OB) {
object = (Object *)target_id;
@ -1849,16 +1863,17 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
}
}
void DepsgraphRelationBuilder::build_driver_id_property(ID *id, const char *rna_path)
void DepsgraphRelationBuilder::build_driver_id_property(const PointerRNA &target_prop,
const char *rna_path_from_target_prop)
{
if (id == nullptr || rna_path == nullptr) {
if (rna_path_from_target_prop == nullptr || rna_path_from_target_prop[0] == '\0') {
return;
}
PointerRNA id_ptr, ptr;
PointerRNA ptr;
PropertyRNA *prop;
int index;
RNA_id_pointer_create(id, &id_ptr);
if (!RNA_path_resolve_full(&id_ptr, rna_path, &ptr, &prop, &index)) {
if (!RNA_path_resolve_full(&target_prop, rna_path_from_target_prop, &ptr, &prop, &index)) {
return;
}
if (prop == nullptr) {

View File

@ -171,7 +171,20 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_driver(ID *id, FCurve *fcurve);
virtual void build_driver_data(ID *id, FCurve *fcurve);
virtual void build_driver_variables(ID *id, FCurve *fcurve);
virtual void build_driver_id_property(ID *id, const char *rna_path);
/* Build operations of a property value from which is read by a driver target.
*
* The driver target points to a data-block (or a sub-data-block like View Layer).
* This data-block is presented in the interface as a "Prop" and its resolved RNA pointer is
* passed here as `target_prop`.
*
* The tricky part (and a bit confusing naming) is that the driver target accesses a property of
* the `target_prop` to get its value. The property which is read to give an actual target value
* is denoted by its RNA path relative to the `target_prop`. In the interface it is called "Path"
* and here it is called `rna_path_from_target_prop`. */
virtual void build_driver_id_property(const PointerRNA &target_prop,
const char *rna_path_from_target_prop);
virtual void build_parameters(ID *id);
virtual void build_dimensions(Object *object);
virtual void build_world(World *world);

View File

@ -241,7 +241,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
}
/**
* Reset for each "redraw". When rendering using ogl render,
* Reset for each "redraw". When rendering using OpenGL render,
* we accumulate the redraw inside the drawing loop in eevee_draw_scene().
*/
if (DRW_state_is_opengl_render()) {

View File

@ -840,11 +840,11 @@ void ShadowModule::end_sync()
u.clip.clip_far_stored = 0.0f;
u.clip.clip_near = int(0xFF7FFFFFu ^ 0x7FFFFFFFu); /* floatBitsToOrderedInt(-FLT_MAX) */
u.clip.clip_far = 0x7F7FFFFF; /* floatBitsToOrderedInt(FLT_MAX) */
GPU_storagebuf_clear(tilemap_pool.tilemaps_clip, GPU_RGBA32I, GPU_DATA_INT, &u.i);
GPU_storagebuf_clear_int(tilemap_pool.tilemaps_clip, u.i, 4);
/* Clear cached page buffer. */
int2 data = {-1, -1};
GPU_storagebuf_clear(pages_cached_data_, GPU_RG32I, GPU_DATA_INT, &data);
GPU_storagebuf_clear_int(pages_cached_data_, data, 2);
/* Reset info to match new state. */
pages_infos_data_.page_free_count = shadow_page_len_;

View File

@ -106,7 +106,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
/* Complementary Depth Pass */
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
if (show_retopology) {
/* Do not cull backfaces for retopology depth pass.
/* Do not cull back-faces for retopology depth pass.
* This prevents edit overlays from appearing behind any faces.
* Doing so reduces visual clutter. */
state &= ~DRW_STATE_CULL_BACK;
@ -162,9 +162,9 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
&pd->edit_mesh_faces_cage_grp[i];
state = state_common;
if (show_retopology) {
/* Cull backfaces for retopology face pass.
* This makes it so backfaces are not drawn.
* Doing so lets us distinguish backfaces from frontfaces. */
/* Cull back-faces for retopology face pass.
* This makes it so back-faces are not drawn.
* Doing so lets us distinguish back-faces from front-faces. */
state |= DRW_STATE_CULL_BACK;
}
DRW_PASS_CREATE(*edit_face_ps, state | pd->clipping_state);

View File

@ -577,7 +577,7 @@ static void write_render_z_output(struct RenderLayer *layer,
int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
/* Convert ogl depth [0..1] to view Z [near..far] */
/* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(nullptr)) {
for (float &z : MutableSpan(rp->rect, pix_num)) {
if (z == 1.0f) {

View File

@ -120,7 +120,7 @@ static void workbench_render_result_z(struct RenderLayer *rl,
int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
/* Convert ogl depth [0..1] to view Z [near..far] */
/* Convert GPU depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(NULL)) {
for (int i = 0; i < pix_num; i++) {
if (rp->rect[i] == 1.0f) {

View File

@ -225,9 +225,9 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds,
if (current_pass_type_ == ShadowPass::PASS) {
/* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
pass_visibility_buf_.resize(words_len);
GPU_storagebuf_clear(pass_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(pass_visibility_buf_, &data, 1);
fail_visibility_buf_.resize(words_len);
GPU_storagebuf_clear(fail_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(fail_visibility_buf_, &data, 1);
}
else if (current_pass_type_ == ShadowPass::FAIL) {
/* Already computed in the ShadowPass::PASS */
@ -236,7 +236,7 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds,
}
else {
visibility_buf_.resize(words_len);
GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(visibility_buf_, &data, 1);
}
if (do_visibility_) {

View File

@ -281,7 +281,7 @@ void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool d
visibility_buf_.resize(words_len);
uint32_t data = 0xFFFFFFFFu;
GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(visibility_buf_, &data, 1);
if (do_visibility_) {
GPUShader *shader = DRW_shader_draw_visibility_compute_get();

View File

@ -902,6 +902,29 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE);
}
/* Settings for 'Context Property' driver variable type. */
static void graph_panel_driverVar__contextProp(uiLayout *layout, ID *id, DriverVar *dvar)
{
DriverTarget *dtar = &dvar->targets[0];
/* Initialize RNA pointer to the target. */
PointerRNA dtar_ptr;
RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
/* Target Property. */
{
uiLayout *row = uiLayoutRow(layout, false);
uiItemR(row, &dtar_ptr, "context_property", 0, NULL, ICON_NONE);
}
/* Target Path */
{
uiLayout *col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID));
uiTemplatePathBuilder(col, &dtar_ptr, "data_path", NULL, IFACE_("Path"));
}
}
/* ----------------------------------------------------------------- */
/* property driven by the driver - duplicates Active FCurve, but useful for clarity */
@ -1213,6 +1236,9 @@ static void graph_draw_driver_settings_panel(uiLayout *layout,
case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */
graph_panel_driverVar__transChan(box, id, dvar);
break;
case DVAR_TYPE_CONTEXT_PROP: /* context property */
graph_panel_driverVar__contextProp(box, id, dvar);
break;
}
/* 3) value of variable */

View File

@ -181,6 +181,23 @@ void ED_node_tag_update_id(ID *id)
namespace blender::ed::space_node {
static const char *node_socket_get_translation_context(const bNodeSocket &socket)
{
/* The node is not explicitly defined. */
if (socket.runtime->declaration == nullptr) {
return nullptr;
}
blender::StringRefNull translation_context = socket.runtime->declaration->translation_context;
/* Default context. */
if (translation_context.is_empty()) {
return nullptr;
}
return translation_context.data();
}
static void node_socket_add_tooltip_in_node_editor(const bNodeTree &ntree,
const bNodeSocket &sock,
uiLayout &layout);
@ -380,8 +397,14 @@ static void node_update_basis(const bContext &C,
/* Align output buttons to the right. */
uiLayout *row = uiLayoutRow(layout, true);
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
const char *socket_label = nodeSocketLabel(socket);
socket->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label));
const char *socket_translation_context = node_socket_get_translation_context(*socket);
socket->typeinfo->draw((bContext *)&C,
row,
&sockptr,
&nodeptr,
CTX_IFACE_(socket_translation_context, socket_label));
node_socket_add_tooltip_in_node_editor(ntree, *socket, *row);
@ -514,7 +537,12 @@ static void node_update_basis(const bContext &C,
uiLayout *row = uiLayoutRow(layout, true);
const char *socket_label = nodeSocketLabel(socket);
socket->typeinfo->draw((bContext *)&C, row, &sockptr, &nodeptr, IFACE_(socket_label));
const char *socket_translation_context = node_socket_get_translation_context(*socket);
socket->typeinfo->draw((bContext *)&C,
row,
&sockptr,
&nodeptr,
CTX_IFACE_(socket_translation_context, socket_label));
node_socket_add_tooltip_in_node_editor(ntree, *socket, *row);

View File

@ -51,6 +51,7 @@ set(SRC
transform_convert_sequencer.c
transform_convert_sequencer_image.c
transform_convert_tracking.c
transform_convert_tracking_curves.c
transform_draw_cursors.c
transform_generics.c
transform_gizmo_2d.c

View File

@ -624,7 +624,9 @@ static bool transform_modal_item_poll(const wmOperator *op, int value)
return false;
}
if (value == TFM_MODAL_TRANSLATE && t->mode == TFM_TRANSLATION) {
return false;
/* The tracking transform in MovieClip has an alternate translate that modifies the offset
* of the tracks. */
return t->data_type == &TransConvertType_Tracking;
}
if (value == TFM_MODAL_ROTATE && t->mode == TFM_ROTATION) {
return false;
@ -987,16 +989,16 @@ int transformEvent(TransInfo *t, const wmEvent *event)
t->redraw |= TREDRAW_HARD;
handled = true;
}
else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) {
restoreTransObjects(t);
t->flag ^= T_ALT_TRANSFORM;
t->redraw |= TREDRAW_HARD;
handled = true;
}
}
else {
if (t->mode == TFM_TRANSLATION) {
if (t->data_type == &TransConvertType_Tracking) {
restoreTransObjects(t);
t->flag ^= T_ALT_TRANSFORM;
t->redraw |= TREDRAW_HARD;
handled = true;
}
break;
}
restoreTransObjects(t);

View File

@ -932,6 +932,9 @@ static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj
}
if (t->spacetype == SPACE_CLIP) {
if (t->options & CTX_MOVIECLIP) {
if (t->region->regiontype == RGN_TYPE_PREVIEW) {
return &TransConvertType_TrackingCurves;
}
return &TransConvertType_Tracking;
}
if (t->options & CTX_MASK) {

View File

@ -276,6 +276,10 @@ extern TransConvertTypeInfo TransConvertType_SequencerImage;
extern TransConvertTypeInfo TransConvertType_Tracking;
/* transform_convert_tracking_curves.c */
extern TransConvertTypeInfo TransConvertType_TrackingCurves;
#ifdef __cplusplus
}
#endif

View File

@ -9,26 +9,24 @@
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
#include "BKE_node.h"
#include "BKE_node_tree_update.h"
#include "BKE_tracking.h"
#include "ED_clip.h"
#include "WM_api.h"
#include "WM_types.h"
#include "transform.h"
#include "transform_convert.h"
typedef struct TransDataTracking {
int mode, flag;
int mode;
int flag;
/* tracks transformation from main window */
int area;
@ -41,18 +39,13 @@ typedef struct TransDataTracking {
int framenr;
MovieTrackingMarker *markers;
/* marker transformation from curves editor */
float *prev_pos, scale;
short coord;
MovieTrackingTrack *track;
MovieTrackingPlaneTrack *plane_track;
} TransDataTracking;
enum transDataTracking_Mode {
transDataTracking_ModeTracks = 0,
transDataTracking_ModeCurves = 1,
transDataTracking_ModePlaneTracks = 2,
transDataTracking_ModePlaneTracks = 1,
};
/* -------------------------------------------------------------------- */
@ -379,139 +372,8 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t)
}
}
static void markerToTransCurveDataInit(TransData *td,
TransData2D *td2d,
TransDataTracking *tdt,
MovieTrackingTrack *track,
MovieTrackingMarker *marker,
MovieTrackingMarker *prev_marker,
short coord,
float size)
{
float frames_delta = (marker->framenr - prev_marker->framenr);
tdt->flag = marker->flag;
marker->flag &= ~MARKER_TRACKED;
tdt->mode = transDataTracking_ModeCurves;
tdt->coord = coord;
tdt->scale = 1.0f / size * frames_delta;
tdt->prev_pos = prev_marker->pos;
tdt->track = track;
/* calculate values depending on marker's speed */
td2d->loc[0] = marker->framenr;
td2d->loc[1] = (marker->pos[coord] - prev_marker->pos[coord]) * size / frames_delta;
td2d->loc[2] = 0.0f;
td2d->loc2d = marker->pos; /* current location */
td->flag = 0;
td->loc = td2d->loc;
copy_v3_v3(td->center, td->loc);
copy_v3_v3(td->iloc, td->loc);
memset(td->axismtx, 0, sizeof(td->axismtx));
td->axismtx[2][2] = 1.0f;
td->ext = NULL;
td->val = NULL;
td->flag |= TD_SELECTED;
td->dist = 0.0;
unit_m3(td->mtx);
unit_m3(td->smtx);
}
static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
{
TransData *td;
TransData2D *td2d;
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
TransDataTracking *tdt;
int width, height;
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
/* count */
tc->data_len = 0;
if ((sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) == 0) {
return;
}
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
for (int i = 1; i < track->markersnr; i++) {
const MovieTrackingMarker *marker = &track->markers[i];
const MovieTrackingMarker *prev_marker = &track->markers[i - 1];
if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) {
continue;
}
if (marker->flag & MARKER_GRAPH_SEL_X) {
tc->data_len += 1;
}
if (marker->flag & MARKER_GRAPH_SEL_Y) {
tc->data_len += 1;
}
}
}
}
if (tc->data_len == 0) {
return;
}
td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
"TransTracking TransData2D");
tc->custom.type.data = tdt = MEM_callocN(tc->data_len * sizeof(TransDataTracking),
"TransTracking TransDataTracking");
tc->custom.type.free_cb = transDataTrackingFree;
/* create actual data */
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
for (int i = 1; i < track->markersnr; i++) {
MovieTrackingMarker *marker = &track->markers[i];
MovieTrackingMarker *prev_marker = &track->markers[i - 1];
if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) {
continue;
}
if (marker->flag & MARKER_GRAPH_SEL_X) {
markerToTransCurveDataInit(
td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
td += 1;
td2d += 1;
tdt += 1;
}
if (marker->flag & MARKER_GRAPH_SEL_Y) {
markerToTransCurveDataInit(
td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
td += 1;
td2d += 1;
tdt += 1;
}
}
}
}
}
static void createTransTrackingData(bContext *C, TransInfo *t)
{
ARegion *region = CTX_wm_region(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
int width, height;
@ -530,13 +392,7 @@ static void createTransTrackingData(bContext *C, TransInfo *t)
return;
}
if (region->regiontype == RGN_TYPE_PREVIEW) {
/* transformation was called from graph editor */
createTransTrackingCurvesData(C, t);
}
else {
createTransTrackingTracksData(C, t);
}
createTransTrackingTracksData(C, t);
}
/** \} */
@ -574,24 +430,6 @@ static void cancelTransTracking(TransInfo *t)
i += 2;
}
}
else if (tdt->mode == transDataTracking_ModeCurves) {
MovieTrackingTrack *track = tdt->track;
MovieTrackingMarker *marker, *prev_marker;
int a;
for (a = 1; a < track->markersnr; a++) {
marker = &track->markers[a];
prev_marker = &track->markers[a - 1];
if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) {
continue;
}
if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
marker->flag = tdt->flag;
}
}
}
else if (tdt->mode == transDataTracking_ModePlaneTracks) {
MovieTrackingPlaneTrack *plane_track = tdt->plane_track;
MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track,
@ -675,9 +513,6 @@ static void flushTransTracking(TransInfo *t)
}
}
}
else if (tdt->mode == transDataTracking_ModeCurves) {
td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
}
else if (tdt->mode == transDataTracking_ModePlaneTracks) {
td2d->loc2d[0] = td2d->loc[0] / t->aspect[0];
td2d->loc2d[1] = td2d->loc[1] / t->aspect[1];

View File

@ -0,0 +1,301 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
/** \file
* \ingroup edtransform
*/
#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
#include "BKE_node_tree_update.h"
#include "BKE_tracking.h"
#include "ED_clip.h"
#include "WM_api.h"
#include "transform.h"
#include "transform_convert.h"
typedef struct TransDataTrackingCurves {
int flag;
/* marker transformation from curves editor */
float *prev_pos;
float scale;
short coord;
MovieTrackingTrack *track;
} TransDataTrackingCurves;
/* -------------------------------------------------------------------- */
/** \name Clip Editor Motion Tracking Transform Creation
* \{ */
static void markerToTransCurveDataInit(TransData *td,
TransData2D *td2d,
TransDataTrackingCurves *tdt,
MovieTrackingTrack *track,
MovieTrackingMarker *marker,
MovieTrackingMarker *prev_marker,
short coord,
float size)
{
float frames_delta = (marker->framenr - prev_marker->framenr);
tdt->flag = marker->flag;
marker->flag &= ~MARKER_TRACKED;
tdt->coord = coord;
tdt->scale = 1.0f / size * frames_delta;
tdt->prev_pos = prev_marker->pos;
tdt->track = track;
/* calculate values depending on marker's speed */
td2d->loc[0] = marker->framenr;
td2d->loc[1] = (marker->pos[coord] - prev_marker->pos[coord]) * size / frames_delta;
td2d->loc[2] = 0.0f;
td2d->loc2d = marker->pos; /* current location */
td->flag = 0;
td->loc = td2d->loc;
copy_v3_v3(td->center, td->loc);
copy_v3_v3(td->iloc, td->loc);
memset(td->axismtx, 0, sizeof(td->axismtx));
td->axismtx[2][2] = 1.0f;
td->ext = NULL;
td->val = NULL;
td->flag |= TD_SELECTED;
td->dist = 0.0;
unit_m3(td->mtx);
unit_m3(td->smtx);
}
static void createTransTrackingCurvesData(bContext *C, TransInfo *t)
{
TransData *td;
TransData2D *td2d;
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
const MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking);
TransDataTrackingCurves *tdt;
int width, height;
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
/* count */
tc->data_len = 0;
if ((sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) == 0) {
return;
}
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
for (int i = 1; i < track->markersnr; i++) {
const MovieTrackingMarker *marker = &track->markers[i];
const MovieTrackingMarker *prev_marker = &track->markers[i - 1];
if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) {
continue;
}
if (marker->flag & MARKER_GRAPH_SEL_X) {
tc->data_len += 1;
}
if (marker->flag & MARKER_GRAPH_SEL_Y) {
tc->data_len += 1;
}
}
}
}
if (tc->data_len == 0) {
return;
}
td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData");
td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
"TransTracking TransData2D");
tc->custom.type.data = tdt = MEM_callocN(tc->data_len * sizeof(TransDataTrackingCurves),
"TransTracking TransDataTracking");
tc->custom.type.free_cb = NULL;
/* create actual data */
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
for (int i = 1; i < track->markersnr; i++) {
MovieTrackingMarker *marker = &track->markers[i];
MovieTrackingMarker *prev_marker = &track->markers[i - 1];
if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) {
continue;
}
if (marker->flag & MARKER_GRAPH_SEL_X) {
markerToTransCurveDataInit(
td, td2d, tdt, track, marker, &track->markers[i - 1], 0, width);
td += 1;
td2d += 1;
tdt += 1;
}
if (marker->flag & MARKER_GRAPH_SEL_Y) {
markerToTransCurveDataInit(
td, td2d, tdt, track, marker, &track->markers[i - 1], 1, height);
td += 1;
td2d += 1;
tdt += 1;
}
}
}
}
}
static void createTransTrackingCurves(bContext *C, TransInfo *t)
{
ARegion *region = CTX_wm_region(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
int width, height;
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
tc->data_len = 0;
if (!clip) {
return;
}
BKE_movieclip_get_size(clip, &sc->user, &width, &height);
if (width == 0 || height == 0) {
return;
}
/* transformation was called from graph editor */
BLI_assert(region->regiontype == RGN_TYPE_PREVIEW);
createTransTrackingCurvesData(C, t);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name recalc Motion Tracking TransData
* \{ */
static void cancelTransTrackingCurves(TransInfo *t)
{
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
TransDataTrackingCurves *tdt_array = tc->custom.type.data;
int i = 0;
while (i < tc->data_len) {
TransDataTrackingCurves *tdt = &tdt_array[i];
{
MovieTrackingTrack *track = tdt->track;
MovieTrackingMarker *marker, *prev_marker;
int a;
for (a = 1; a < track->markersnr; a++) {
marker = &track->markers[a];
prev_marker = &track->markers[a - 1];
if ((marker->flag & MARKER_DISABLED) || (prev_marker->flag & MARKER_DISABLED)) {
continue;
}
if (marker->flag & (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y)) {
marker->flag = tdt->flag;
}
}
}
i++;
}
}
static void flushTransTrackingCurves(TransInfo *t)
{
TransData *td;
TransData2D *td2d;
TransDataTrackingCurves *tdt;
int td_index;
if (t->state == TRANS_CANCEL) {
cancelTransTrackingCurves(t);
}
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
/* flush to 2d vector from internally used 3d vector */
for (td_index = 0, td = tc->data, td2d = tc->data_2d, tdt = tc->custom.type.data;
td_index < tc->data_len;
td_index++, td2d++, td++, tdt++) {
{
td2d->loc2d[tdt->coord] = tdt->prev_pos[tdt->coord] + td2d->loc[1] * tdt->scale;
}
}
}
static void recalcData_tracking_curves(TransInfo *t)
{
SpaceClip *sc = t->area->spacedata.first;
if (ED_space_clip_check_show_trackedit(sc)) {
MovieClip *clip = ED_space_clip_get_clip(sc);
flushTransTrackingCurves(t);
DEG_id_tag_update(&clip->id, 0);
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Special After Transform Tracking
* \{ */
static void special_aftertrans_update__movieclip_for_curves(bContext *C, TransInfo *t)
{
SpaceClip *sc = t->area->spacedata.first;
MovieClip *clip = ED_space_clip_get_clip(sc);
if (t->scene->nodetree != NULL) {
/* Tracks can be used for stabilization nodes,
* flush update for such nodes.
*/
if (t->context != NULL) {
Main *bmain = CTX_data_main(C);
BKE_ntree_update_tag_id_changed(bmain, &clip->id);
BKE_ntree_update_main(bmain, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
}
}
}
/** \} */
TransConvertTypeInfo TransConvertType_TrackingCurves = {
/*flags*/ (T_POINTS | T_2D_EDIT),
/*createTransData*/ createTransTrackingCurves,
/*recalcData*/ recalcData_tracking_curves,
/*special_aftertrans_update*/ special_aftertrans_update__movieclip_for_curves,
};

View File

@ -594,7 +594,7 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
Object *ob,
BMEditMesh *em,
const UnwrapOptions *options,
UnwrapResultInfo *result_info)
int *r_count_failed = nullptr)
{
/* pointers to modifier data for unwrap control */
SubsurfModifierData *smd_real;
@ -666,8 +666,8 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
nullptr;
}
/* Prepare and feed faces to the solver */
for (const int i : subsurf_polys.index_range()) {
/* Prepare and feed faces to the solver. */
for (const int64_t i : subsurf_polys.index_range()) {
const MPoly &poly = subsurf_polys[i];
ParamKey key, vkeys[4];
bool pin[4], select[4];
@ -717,8 +717,8 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
blender::geometry::uv_parametrizer_face_add(handle, key, 4, vkeys, co, uv, pin, select);
}
/* these are calculated from original mesh too */
for (const int i : subsurf_edges.index_range()) {
/* These are calculated from original mesh too. */
for (const int64_t i : subsurf_edges.index_range()) {
if ((edgeMap[i] != nullptr) && BM_elem_flag_test(edgeMap[i], BM_ELEM_SEAM)) {
const MEdge *edge = &subsurf_edges[i];
ParamKey vkeys[2];
@ -728,11 +728,8 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene,
}
}
blender::geometry::uv_parametrizer_construct_end(handle,
options->fill_holes,
options->topology_from_uvs,
result_info ? &result_info->count_failed :
nullptr);
blender::geometry::uv_parametrizer_construct_end(
handle, options->fill_holes, options->topology_from_uvs, r_count_failed);
/* cleanup */
MEM_freeN(faceMap);
@ -1804,7 +1801,8 @@ static void uvedit_unwrap(const Scene *scene,
ParamHandle *handle;
if (use_subsurf) {
handle = construct_param_handle_subsurfed(scene, obedit, em, options, result_info);
handle = construct_param_handle_subsurfed(
scene, obedit, em, options, result_info ? &result_info->count_failed : nullptr);
}
else {
handle = construct_param_handle(

View File

@ -28,12 +28,12 @@ static float pack_islands_scale_margin(const Span<PackIsland *> &island_vector,
for (const int64_t index : island_vector.index_range()) {
PackIsland *island = island_vector[index];
BoxPack *box = &box_array[index];
box->index = (int)index;
box->index = int(index);
box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin;
box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin;
}
float max_u, max_v;
BLI_box_pack_2d(box_array, (int)island_vector.size(), &max_u, &max_v);
BLI_box_pack_2d(box_array, int(island_vector.size()), &max_u, &max_v);
return max_ff(max_u, max_v);
}

View File

@ -313,15 +313,15 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *framebuffer, char err_out[256])
/** \} */
/* -------------------------------------------------------------------- */
/** \name Empty framebuffer
/** \name Empty frame-buffer
*
* An empty framebuffer is a framebuffer with no attachments. This allow to rasterize geometry
* An empty frame-buffer is a frame-buffer with no attachments. This allow to rasterize geometry
* without creating any dummy attachments and write some computation results using other means
* (SSBOs, Images).
* \{ */
/**
* Default size is used if the framebuffer contains no attachments.
* Default size is used if the frame-buffer contains no attachments.
* It needs to be re-specified each time an attachment is added.
*/
void GPU_framebuffer_default_size(GPUFrameBuffer *framebuffer, int width, int height);
@ -349,7 +349,7 @@ void GPU_framebuffer_viewport_set(
void GPU_framebuffer_viewport_get(GPUFrameBuffer *framebuffer, int r_viewport[4]);
/**
* Reset a framebuffer viewport bounds to its attachment(s) size.
* Reset a frame-buffer viewport bounds to its attachment(s) size.
* \note Viewport and scissor size is stored per frame-buffer.
*/
void GPU_framebuffer_viewport_reset(GPUFrameBuffer *framebuffer);
@ -361,7 +361,7 @@ void GPU_framebuffer_viewport_reset(GPUFrameBuffer *framebuffer);
* \{ */
/**
* Clear the framebuffer attachments.
* Clear the frame-buffer attachments.
* \a buffers controls the types of attachments to clear. Setting GPU_COLOR_BIT will clear *all*
* the color attachment.
* Each attachment gets cleared to the value of its type:
@ -438,19 +438,19 @@ void GPU_framebuffer_clear_color_depth_stencil(GPUFrameBuffer *fb,
void GPU_framebuffer_multi_clear(GPUFrameBuffer *framebuffer, const float (*clear_colors)[4]);
/**
* Clear all color attachment textures of the active framebuffer with the given red, green, blue,
* Clear all color attachment textures of the active frame-buffer with the given red, green, blue,
* alpha values.
* \note `GPU_write_mask`, and stencil test do not affect this command.
* \note Viewport and scissor regions affect this command but are not efficient nor recommended.
* DEPRECATED: Use `GPU_framebuffer_clear_color` with explicit framebuffer.
* DEPRECATED: Use `GPU_framebuffer_clear_color` with explicit frame-buffer.
*/
void GPU_clear_color(float red, float green, float blue, float alpha);
/**
* Clear the depth attachment texture of the active framebuffer with the given depth value.
* Clear the depth attachment texture of the active frame-buffer with the given depth value.
* \note `GPU_write_mask`, and stencil test do not affect this command.
* \note Viewport and scissor regions affect this command but are not efficient nor recommended.
* DEPRECATED: Use `GPU_framebuffer_clear_color` with explicit framebuffer.
* DEPRECATED: Use `GPU_framebuffer_clear_color` with explicit frame-buffer.
*/
void GPU_clear_depth(float depth);
@ -467,7 +467,7 @@ const char *GPU_framebuffer_get_name(GPUFrameBuffer *framebuffer);
/* -------------------------------------------------------------------- */
/** \name Python API & meta-data
*
* These are not intrinsic properties of a framebuffer but they are stored inside the
* These are not intrinsic properties of a frame-buffer but they are stored inside the
* gpu::FrameBuffer structure for tracking purpose.
* \{ */
@ -481,8 +481,8 @@ void GPU_framebuffer_py_reference_set(GPUFrameBuffer *framebuffer, void **py_ref
#endif
/**
* Keep a stack of bound framebuffer to allow scoped binding of framebuffer in python.
* This is also used by #GPUOffScreen to save/restore the current framebuffers.
* Keep a stack of bound frame-buffer to allow scoped binding of frame-buffer in python.
* This is also used by #GPUOffScreen to save/restore the current frame-buffers.
* \note This isn't thread safe.
*/
/* TODO(fclem): This has nothing to do with the GPU module and should be move to the pyGPU module.
@ -547,7 +547,7 @@ void GPU_frontbuffer_read_pixels(
* The attachments types are chosen by \a blit_buffers .
* Only one color buffer can by copied at a time and its index is chosen by \a read_slot and \a
* write_slot.
* The source and destination framebuffers dimensions have to match.
* The source and destination frame-buffers dimensions have to match.
* DEPRECATED: Prefer using `GPU_texture_copy()`.
*/
void GPU_framebuffer_blit(GPUFrameBuffer *fb_read,

View File

@ -39,12 +39,24 @@ void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot);
void GPU_storagebuf_unbind(GPUStorageBuf *ssbo);
void GPU_storagebuf_unbind_all(void);
void GPU_storagebuf_clear(GPUStorageBuf *ssbo,
eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data);
void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo);
/**
* Clear the content of the buffer using the given #clear_data. #clear_data will be used as a
* repeatable pattern.
*
* NOTE: clear_data_len must be in range 1 to 4 (inclusive).
*/
void GPU_storagebuf_clear_uint(GPUStorageBuf *ssbo, uint32_t *clear_data, int clear_data_len);
/**
* Clear the content of the buffer using the given #clear_data. #clear_data will be used as a
* repeatable pattern.
*
* NOTE: clear_data_len must be in range 1 to 4 (inclusive).
*/
void GPU_storagebuf_clear_int(GPUStorageBuf *ssbo, int32_t *clear_data, int clear_data_len);
/**
* Read back content of the buffer to CPU for inspection.
* Slow! Only use for inspection / debugging.

View File

@ -417,7 +417,7 @@ void GPU_framebuffer_clear_color(GPUFrameBuffer *fb, const float clear_col[4])
void GPU_framebuffer_clear_depth(GPUFrameBuffer *fb, float clear_depth)
{
GPU_framebuffer_clear(fb, GPU_DEPTH_BIT, NULL, clear_depth, 0x00);
GPU_framebuffer_clear(fb, GPU_DEPTH_BIT, nullptr, clear_depth, 0x00);
}
void GPU_framebuffer_clear_color_depth(GPUFrameBuffer *fb,
@ -429,12 +429,12 @@ void GPU_framebuffer_clear_color_depth(GPUFrameBuffer *fb,
void GPU_framebuffer_clear_stencil(GPUFrameBuffer *fb, uint clear_stencil)
{
GPU_framebuffer_clear(fb, GPU_STENCIL_BIT, NULL, 0.0f, clear_stencil);
GPU_framebuffer_clear(fb, GPU_STENCIL_BIT, nullptr, 0.0f, clear_stencil);
}
void GPU_framebuffer_clear_depth_stencil(GPUFrameBuffer *fb, float clear_depth, uint clear_stencil)
{
GPU_framebuffer_clear(fb, GPU_DEPTH_BIT | GPU_STENCIL_BIT, NULL, clear_depth, clear_stencil);
GPU_framebuffer_clear(fb, GPU_DEPTH_BIT | GPU_STENCIL_BIT, nullptr, clear_depth, clear_stencil);
}
void GPU_framebuffer_clear_color_depth_stencil(GPUFrameBuffer *fb,

View File

@ -89,18 +89,22 @@ void GPU_storagebuf_unbind_all()
/* FIXME */
}
void GPU_storagebuf_clear(GPUStorageBuf *ssbo,
eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data)
{
unwrap(ssbo)->clear(internal_format, data_format, data);
}
void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo)
{
uint32_t data = 0u;
GPU_storagebuf_clear(ssbo, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(ssbo, &data, 1);
}
void GPU_storagebuf_clear_int(GPUStorageBuf *ssbo, int32_t *clear_data, int clear_data_len)
{
uint32_t *clear_data_uint = static_cast<uint32_t *>(static_cast<void *>(clear_data));
GPU_storagebuf_clear_uint(ssbo, clear_data_uint, clear_data_len);
}
void GPU_storagebuf_clear_uint(GPUStorageBuf *ssbo, uint32_t *clear_data, int clear_data_len)
{
BLI_assert(clear_data_len >= 1 && clear_data_len <= 4);
unwrap(ssbo)->clear(blender::Span<uint32_t>(clear_data, clear_data_len));
}
void GPU_storagebuf_copy_sub_from_vertbuf(

View File

@ -7,6 +7,7 @@
#pragma once
#include "BLI_span.hh"
#include "BLI_sys_types.h"
struct GPUStorageBuf;
@ -42,9 +43,7 @@ class StorageBuf {
virtual void update(const void *data) = 0;
virtual void bind(int slot) = 0;
virtual void unbind() = 0;
virtual void clear(eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data) = 0;
virtual void clear(Span<uint32_t> data) = 0;
virtual void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) = 0;
virtual void read(void *data) = 0;
};

View File

@ -117,27 +117,39 @@ void GLStorageBuf::unbind()
slot_ = 0;
}
void GLStorageBuf::clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data)
void GLStorageBuf::clear(Span<uint32_t> data)
{
if (ssbo_id_ == 0) {
this->init();
}
GLenum internal_format = GL_R32UI;
GLenum format = GL_RED_INTEGER;
if (data.size() == 1) {
internal_format = GL_R32UI;
format = GL_RED_INTEGER;
}
else if (data.size() == 2) {
internal_format = GL_RG32UI;
format = GL_RG_INTEGER;
}
else if (data.size() == 3) {
internal_format = GL_RGB32UI;
format = GL_RGB_INTEGER;
}
else if (data.size() == 4) {
internal_format = GL_RGBA32UI;
format = GL_RGBA_INTEGER;
}
if (GLContext::direct_state_access_support) {
glClearNamedBufferData(ssbo_id_,
to_gl_internal_format(internal_format),
to_gl_data_format(internal_format),
to_gl(data_format),
data);
glClearNamedBufferData(ssbo_id_, internal_format, format, GL_UNSIGNED_INT, data.data());
}
else {
/* WATCH(@fclem): This should be ok since we only use clear outside of drawing functions. */
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_id_);
glClearBufferData(GL_SHADER_STORAGE_BUFFER,
to_gl_internal_format(internal_format),
to_gl_data_format(internal_format),
to_gl(data_format),
data);
glClearBufferData(
GL_SHADER_STORAGE_BUFFER, internal_format, format, GL_UNSIGNED_INT, data.data());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
}

View File

@ -33,7 +33,7 @@ class GLStorageBuf : public StorageBuf {
void update(const void *data) override;
void bind(int slot) override;
void unbind() override;
void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override;
void clear(Span<uint32_t> data) override;
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
void read(void *data) override;

View File

@ -143,8 +143,8 @@ static void do_push_constants_test(const char *info_name, const int num_calls_si
shader.update_push_constants(call_data);
shader.dispatch();
}
/* All calls will be "simultaneously" in flight. First readback will wait until the dispatches
* have finished execution.*/
/* All calls will be "simultaneously" in flight. First read-back will wait until the dispatches
* have finished execution. */
for (const int call_index : IndexRange(num_calls_simultaneously)) {
CallData &call_data = shader.call_datas[call_index];
call_data.read_back();
@ -152,7 +152,7 @@ static void do_push_constants_test(const char *info_name, const int num_calls_si
}
}
/* Test case with single call as sanity check, before we make it more interesting.*/
/* Test case with single call as sanity check, before we make it more interesting. */
static void test_push_constants()
{
do_push_constants_test("gpu_push_constants_test");
@ -180,7 +180,7 @@ GPU_TEST(push_constants_512bytes)
#if 0
/* Schedule multiple simultaneously. */
/* These test have been disabled for now as this will to be solved in a separate PR.
* - DescriptorSets may not be altered, when they are in the command queue or being executed.
* - `DescriptorSets` may not be altered, when they are in the command queue or being executed.
*/
static void test_push_constants_multiple()
{
@ -207,4 +207,4 @@ static void test_push_constants_multiple_512bytes()
GPU_TEST(push_constants_multiple_512bytes)
#endif
} // namespace blender::gpu::tests
} // namespace blender::gpu::tests

View File

@ -74,7 +74,7 @@ static void test_storage_buffer_clear_zero()
GPU_TEST(storage_buffer_clear_zero);
template<eGPUTextureFormat TextureFormat> static void storage_buffer_clear_uniform()
template<int DataLen> static void storage_buffer_clear_int_uniform()
{
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__);
@ -82,38 +82,29 @@ template<eGPUTextureFormat TextureFormat> static void storage_buffer_clear_unifo
/* Read back data from SSBO. */
int4 clear_data = {-1, -1, -1, -1};
GPU_storagebuf_clear(ssbo, TextureFormat, GPU_DATA_INT, &clear_data);
GPU_storagebuf_clear_int(ssbo, clear_data, DataLen);
/* Check if data is the same. */
Vector<int32_t> read_data;
read_data.resize(SIZE, 0);
GPU_storagebuf_read(ssbo, read_data.data());
for (int i : IndexRange(SIZE)) {
EXPECT_EQ(clear_data[i % 4], read_data[i]);
EXPECT_EQ(clear_data[i % DataLen], read_data[i]);
}
GPU_storagebuf_free(ssbo);
}
static void test_storage_buffer_clear_RGBA32I_uniform()
static void test_storage_buffer_clear_int_uniform()
{
storage_buffer_clear_uniform<GPU_RGBA32I>();
storage_buffer_clear_int_uniform<1>();
storage_buffer_clear_int_uniform<2>();
storage_buffer_clear_int_uniform<3>();
storage_buffer_clear_int_uniform<4>();
}
GPU_TEST(storage_buffer_clear_RGBA32I_uniform);
GPU_TEST(storage_buffer_clear_int_uniform);
static void test_storage_buffer_clear_RG32I_uniform()
{
storage_buffer_clear_uniform<GPU_RG32I>();
}
GPU_TEST(storage_buffer_clear_RG32I_uniform);
static void test_storage_buffer_clear_RG32UI_uniform()
{
storage_buffer_clear_uniform<GPU_RG32UI>();
}
GPU_TEST(storage_buffer_clear_RG32UI_uniform);
static void test_storage_buffer_clear_RGBAI32()
static void test_storage_buffer_clear_non_uniform()
{
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__);
@ -121,7 +112,7 @@ static void test_storage_buffer_clear_RGBAI32()
/* Read back data from SSBO. */
int4 clear_data = {-1, -2, -3, -4};
GPU_storagebuf_clear(ssbo, GPU_RGBA32I, GPU_DATA_INT, &clear_data);
GPU_storagebuf_clear_int(ssbo, clear_data, 4);
/* Check if data is the same. */
Vector<int32_t> read_data;
@ -133,6 +124,6 @@ static void test_storage_buffer_clear_RGBAI32()
GPU_storagebuf_free(ssbo);
}
GPU_TEST(storage_buffer_clear_RGBAI32);
GPU_TEST(storage_buffer_clear_non_uniform);
} // namespace blender::gpu::tests

View File

@ -90,7 +90,7 @@ static bool is_uniform(Span<uint32_t> data)
{
BLI_assert(!data.is_empty());
uint32_t expected_value = data[0];
for (uint32_t value : data) {
for (uint32_t value : data.drop_front(1)) {
if (value != expected_value) {
return false;
}
@ -98,26 +98,11 @@ static bool is_uniform(Span<uint32_t> data)
return true;
}
static bool can_use_fill_command(eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data)
{
/* TODO: See `validate_data_format` what we should support. */
BLI_assert(ELEM(data_format, GPU_DATA_INT, GPU_DATA_UINT, GPU_DATA_FLOAT));
UNUSED_VARS_NDEBUG(data_format);
const uint32_t element_size = to_bytesize(internal_format);
const uint32_t num_components = element_size / sizeof(uint32_t);
return is_uniform(Span<uint32_t>(static_cast<uint32_t *>(data), num_components));
}
void VKBuffer::clear(VKContext &context,
eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data)
void VKBuffer::clear(VKContext &context, Span<uint32_t> data)
{
VKCommandBuffer &command_buffer = context.command_buffer_get();
if (can_use_fill_command(internal_format, data_format, data)) {
command_buffer.fill(*this, *static_cast<uint32_t *>(data));
if (is_uniform(data)) {
command_buffer.fill(*this, *data.begin());
return;
}

View File

@ -34,10 +34,7 @@ class VKBuffer {
GPUUsageType usage,
VkBufferUsageFlagBits buffer_usage);
bool update(VKContext &context, const void *data);
void clear(VKContext &context,
eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data);
void clear(VKContext &context, Span<uint32_t> data);
bool free(VKContext &context);
bool map(VKContext &context, void **r_mapped_memory) const;
void unmap(VKContext &context) const;

View File

@ -31,7 +31,6 @@ class VKShaderInterface : public ShaderInterface {
VKPushConstants::Layout push_constants_layout_;
public:
VKShaderInterface() = default;

View File

@ -47,15 +47,13 @@ void VKStorageBuffer::unbind()
{
}
void VKStorageBuffer::clear(eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data)
void VKStorageBuffer::clear(Span<uint32_t> data)
{
VKContext &context = *VKContext::get();
if (!buffer_.is_allocated()) {
allocate(context);
}
buffer_.clear(context, internal_format, data_format, data);
buffer_.clear(context, data);
}
void VKStorageBuffer::copy_sub(VertBuf * /*src*/,

View File

@ -30,7 +30,7 @@ class VKStorageBuffer : public StorageBuf {
void update(const void *data) override;
void bind(int slot) override;
void unbind() override;
void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override;
void clear(Span<uint32_t> data) override;
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
void read(void *data) override;

View File

@ -23,10 +23,10 @@ namespace blender::io::ply {
std::unique_ptr<PlyData> import_ply_ascii(fstream &file, PlyHeader *header);
/**
* Loads the information from the PLY file in ASCII format to the PlyData datastructure.
* Loads the information from the PLY file in ASCII format to the #PlyData data-structure.
* \param file: The PLY file that was opened.
* \param header: The information in the PLY header.
* \return The PlyData datastructure that can be used for conversion to a Mesh.
* \return The #PlyData data-structure that can be used for conversion to a Mesh.
*/
PlyData load_ply_ascii(fstream &file, const PlyHeader *header);

View File

@ -17,15 +17,15 @@ namespace blender::io::ply {
* The function that gets called from the importer.
* \param file: The PLY file that was opened.
* \param header: The information in the PLY header.
* \return The PlyData datastructure that can be used for conversion to a Mesh.
* \return The #PlyData data-structure that can be used for conversion to a #Mesh.
*/
std::unique_ptr<PlyData> import_ply_binary(fstream &file, const PlyHeader *header);
/**
* Loads the information from the PLY file in binary format to the PlyData datastructure.
* Loads the information from the PLY file in binary format to the #PlyData data-structure.
* \param file: The PLY file that was opened.
* \param header: The information in the PLY header.
* \return The PlyData datastructure that can be used for conversion to a Mesh.
* \return The #PlyData data-structure that can be used for conversion to a Mesh.
*/
PlyData load_ply_binary(fstream &file, const PlyHeader *header);

View File

@ -12,7 +12,7 @@
namespace blender::io::ply {
/**
* Converts the PlyData datastructure to a mesh.
* Converts the #PlyData data-structure to a mesh.
* \param data: The PLY data.
* \return The mesh that can be used inside blender.
*/

View File

@ -3,6 +3,7 @@
#include "testing/testing.h"
#include "tests/blendfile_loading_base_test.h"
#include "BKE_appdir.h"
#include "BKE_blender_version.h"
#include "DEG_depsgraph.h"
@ -31,6 +32,26 @@ class PlyExportTest : public BlendfileLoadingBaseTest {
depsgraph_create(eval_mode);
return true;
}
protected:
void SetUp() override
{
BlendfileLoadingBaseTest::SetUp();
BKE_tempdir_init("");
}
void TearDown() override
{
BlendfileLoadingBaseTest::TearDown();
BKE_tempdir_session_purge();
}
std::string get_temp_ply_filename(const std::string &filename)
{
return std::string(BKE_tempdir_session()) + "/" + filename;
}
};
static std::unique_ptr<PlyData> load_cube(PLYExportParams &params)
@ -103,7 +124,7 @@ static std::vector<char> read_temp_file_in_vectorchar(const std::string &file_pa
TEST_F(PlyExportTest, WriteHeaderAscii)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = true;
_params.export_normals = false;
@ -141,7 +162,7 @@ TEST_F(PlyExportTest, WriteHeaderAscii)
TEST_F(PlyExportTest, WriteHeaderBinary)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = false;
_params.export_normals = false;
@ -179,7 +200,7 @@ TEST_F(PlyExportTest, WriteHeaderBinary)
TEST_F(PlyExportTest, WriteVerticesAscii)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = true;
_params.export_normals = false;
@ -211,7 +232,7 @@ TEST_F(PlyExportTest, WriteVerticesAscii)
TEST_F(PlyExportTest, WriteVerticesBinary)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = false;
_params.export_normals = false;
@ -253,7 +274,7 @@ TEST_F(PlyExportTest, WriteVerticesBinary)
TEST_F(PlyExportTest, WriteFacesAscii)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = true;
_params.export_normals = false;
@ -283,7 +304,7 @@ TEST_F(PlyExportTest, WriteFacesAscii)
TEST_F(PlyExportTest, WriteFacesBinary)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = false;
_params.export_normals = false;
@ -326,7 +347,7 @@ TEST_F(PlyExportTest, WriteFacesBinary)
TEST_F(PlyExportTest, WriteVertexNormalsAscii)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = true;
_params.export_normals = true;
@ -358,7 +379,7 @@ TEST_F(PlyExportTest, WriteVertexNormalsAscii)
TEST_F(PlyExportTest, WriteVertexNormalsBinary)
{
std::string filePath = blender::tests::flags_test_release_dir() + "/" + temp_file_path;
std::string filePath = get_temp_ply_filename(temp_file_path);
PLYExportParams _params;
_params.ascii_format = false;
_params.export_normals = true;

View File

@ -322,6 +322,13 @@ typedef struct DriverTarget {
short flag;
/** Type of ID-block that this target can use. */
int idtype;
/* Context-dependent property of a "Context Property" type target.
* The `rna_path` of this property is used as a target.
* This is a value of enumerator #eDriverTarget_ContextProperty. */
int context_property;
int _pad1;
} DriverTarget;
/** Driver Target flags. */
@ -386,6 +393,11 @@ typedef enum eDriverTarget_RotationMode {
DTAR_ROTMODE_EULER_MAX = DTAR_ROTMODE_EULER_ZYX,
} eDriverTarget_RotationMode;
typedef enum eDriverTarget_ContextProperty {
DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE = 0,
DTAR_CONTEXT_PROPERTY_ACTIVE_VIEW_LAYER = 1,
} eDriverTarget_ContextProperty;
/* --- */
/* maximum number of driver targets per variable */
@ -432,6 +444,8 @@ typedef enum eDriverVar_Types {
DVAR_TYPE_LOC_DIFF,
/** 'final' transform for object/bones */
DVAR_TYPE_TRANSFORM_CHAN,
/** Property within a current evaluation context */
DVAR_TYPE_CONTEXT_PROP,
/**
* Maximum number of variable types.

View File

@ -243,7 +243,7 @@ typedef struct bArmatureConstraint {
ListBase targets;
} bArmatureConstraint;
/* Single-target subobject constraints --------------------- */
/* Single-target sub-object constraints --------------------- */
/* Track To Constraint */
typedef struct bTrackToConstraint {

View File

@ -20,7 +20,7 @@
.pathlen = 100, \
.resolu = 12, \
.resolv = 12, \
.offset = 1.0, \
.offset = 0.0, \
.wordspace = 1.0, \
.spacing = 1.0f, \
.linedist = 1.0, \

View File

@ -330,7 +330,11 @@ typedef struct bNode {
int16_t custom1, custom2;
float custom3, custom4;
/** Optional link to libdata. */
/**
* Optional link to libdata.
*
* \see #bNodeType::initfunc & #bNodeType::freefunc for details on ID user-count.
*/
struct ID *id;
/** Custom data struct for node properties for storage in files. */

View File

@ -161,6 +161,20 @@ const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[] = {
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_driver_target_context_property_items[] = {
{DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE,
"ACTIVE_SCENE",
ICON_NONE,
"Active Scene",
"Currently evaluating scene"},
{DTAR_CONTEXT_PROPERTY_ACTIVE_VIEW_LAYER,
"ACTIVE_VIEW_LAYER",
ICON_NONE,
"Active View Layer",
"Currently evaluating view layer"},
{0, NULL, 0, NULL, NULL},
};
#ifdef RNA_RUNTIME
# include "WM_api.h"
@ -1879,6 +1893,14 @@ static void rna_def_drivertarget(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_local_space_items);
RNA_def_property_ui_text(prop, "Transform Space", "Space in which transforms are used");
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
prop = RNA_def_property(srna, "context_property", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "context_property");
RNA_def_property_enum_items(prop, rna_enum_driver_target_context_property_items);
RNA_def_property_enum_default(prop, DTAR_CONTEXT_PROPERTY_ACTIVE_SCENE);
RNA_def_property_ui_text(
prop, "Context Property", "Type of a context-dependent data-block to access property from");
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
}
static void rna_def_drivervar(BlenderRNA *brna)
@ -1907,6 +1929,11 @@ static void rna_def_drivervar(BlenderRNA *brna)
ICON_DRIVER_DISTANCE,
"Distance",
"Distance between two bones or objects"},
{DVAR_TYPE_CONTEXT_PROP,
"CONTEXT_PROP",
ICON_RNA,
"Context Property",
"Use the value from some RNA property within the current evaluation context"},
{0, NULL, 0, NULL, NULL},
};

View File

@ -16,14 +16,14 @@
*
* The main missing features in this code compared to the paper are:
*
* + No mesh evolution. The paper suggests iteratively subsurfing the
* - No mesh evolution. The paper suggests iteratively subdivision-surfacing the
* skin output and adapting the output to better conform with the
* spheres of influence surrounding each vertex.
*
* + No mesh fairing. The paper suggests re-aligning output edges to
* - No mesh fairing. The paper suggests re-aligning output edges to
* follow principal mesh curvatures.
*
* + No auxiliary balls. These would serve to influence mesh
* - No auxiliary balls. These would serve to influence mesh
* evolution, which as noted above is not implemented.
*
* The code also adds some features not present in the paper:

View File

@ -8,6 +8,8 @@
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
#include "BLT_translation.h"
#include "DNA_node_types.h"
struct bNode;
@ -145,6 +147,7 @@ class SocketDeclaration {
std::string name;
std::string identifier;
std::string description;
std::string translation_context;
/** Defined by whether the socket is part of the node's input or
* output socket declaration list. Included here for convenience. */
eNodeSocketInOut in_out;
@ -275,6 +278,12 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder {
return *(Self *)this;
}
Self &translation_context(std::string value = BLT_I18NCONTEXT_DEFAULT)
{
decl_->translation_context = std::move(value);
return *(Self *)this;
}
Self &no_muted_links(bool value = true)
{
decl_->no_mute_links = value;

View File

@ -33,7 +33,8 @@ namespace blender::nodes::node_composite_keyingscreen_cc {
static void cmp_node_keyingscreen_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Color>(N_("Screen"));
b.add_output<decl::Color>(CTX_N_(BLT_I18NCONTEXT_ID_SCREEN, "Screen"))
.translation_context(BLT_I18NCONTEXT_ID_SCREEN);
}
static void node_composit_init_keyingscreen(const bContext *C, PointerRNA *ptr)

View File

@ -688,7 +688,8 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
/* Support for any RNA data. */
#ifdef USE_RNA_AS_PYOBJECT
if (dvar->type == DVAR_TYPE_SINGLE_PROP) {
driver_arg = pyrna_driver_get_variable_value(driver, &dvar->targets[0]);
driver_arg = pyrna_driver_get_variable_value(
anim_eval_context, driver, dvar, &dvar->targets[0]);
if (driver_arg == NULL) {
driver_arg = PyFloat_FromDouble(0.0);
@ -714,7 +715,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna,
#endif
{
/* Try to get variable value. */
const float tval = driver_get_variable_value(driver, dvar);
const float tval = driver_get_variable_value(anim_eval_context, driver, dvar);
driver_arg = PyFloat_FromDouble((double)tval);
}

View File

@ -20,14 +20,17 @@
#include "bpy_rna_driver.h" /* own include */
PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct DriverTarget *dtar)
PyObject *pyrna_driver_get_variable_value(const struct AnimationEvalContext *anim_eval_context,
struct ChannelDriver *driver,
struct DriverVar *dvar,
struct DriverTarget *dtar)
{
PyObject *driver_arg = NULL;
PointerRNA ptr;
PropertyRNA *prop = NULL;
int index;
if (driver_get_variable_property(driver, dtar, &ptr, &prop, &index)) {
if (driver_get_variable_property(anim_eval_context, driver, dvar, dtar, &ptr, &prop, &index)) {
if (prop) {
if (index != -1) {
if (index < RNA_property_array_length(&ptr, prop) && index >= 0) {

View File

@ -17,7 +17,10 @@ extern "C" {
/**
* A version of #driver_get_variable_value which returns a #PyObject.
*/
PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct DriverTarget *dtar);
PyObject *pyrna_driver_get_variable_value(const struct AnimationEvalContext *anim_eval_context,
struct ChannelDriver *driver,
struct DriverVar *dvar,
struct DriverTarget *dtar);
PyObject *pyrna_driver_self_from_anim_rna(struct PathResolvedRNA *anim_rna);
bool pyrna_driver_is_equal_anim_rna(const struct PathResolvedRNA *anim_rna,

View File

@ -54,7 +54,7 @@ typedef struct RenderView {
float *rectf;
/* if this exists, result of composited layers */
float *rectz;
/* optional, 32 bits version of picture, used for sequencer, ogl render and image curves */
/* optional, 32 bits version of picture, used for sequencer, OpenGL render and image curves */
int *rect32;
} RenderView;
@ -105,7 +105,7 @@ typedef struct RenderResult {
/* The following rect32, rectf and rectz buffers are for temporary storage only,
* for RenderResult structs created in #RE_AcquireResultImage - which do not have RenderView */
/* optional, 32 bits version of picture, used for ogl render and image curves */
/* Optional, 32 bits version of picture, used for OpenGL render and image curves. */
int *rect32;
/* if this exists, a copy of one of layers, or result of composited layers */
float *rectf;

View File

@ -116,7 +116,7 @@ bool RE_engine_is_external(const Render *re)
bool RE_engine_is_opengl(RenderEngineType *render_type)
{
/* TODO: refine? Can we have ogl render engine without ogl render pipeline? */
/* TODO: refine? Can we have OpenGL render engine without OpenGL render pipeline? */
return (render_type->draw_engine != nullptr) &&
DRW_engine_render_support(render_type->draw_engine);
}

View File

@ -862,7 +862,7 @@ void RE_test_break_cb(Render *re, void *handle, bool (*f)(void *handle))
void RE_gl_context_create(Render *re)
{
/* Needs to be created in the main ogl thread. */
/* Needs to be created in the main OpenGL thread. */
re->gl_context = WM_opengl_context_create();
/* So we activate the window's one afterwards. */
wm_window_reset_drawable();
@ -870,7 +870,7 @@ void RE_gl_context_create(Render *re)
void RE_gl_context_destroy(Render *re)
{
/* Needs to be called from the thread which used the ogl context for rendering. */
/* Needs to be called from the thread which used the OpenGL context for rendering. */
if (re->gl_context) {
if (re->gpu_context) {
WM_opengl_context_activate(re->gl_context);

View File

@ -713,7 +713,18 @@ typedef struct wmEvent {
/** Custom data type, stylus, 6-DOF, see `wm_event_types.h`. */
short custom;
short customdata_free;
/** Ascii, unicode, mouse-coords, angles, vectors, NDOF data, drag-drop info. */
/**
* The #wmEvent::type implies the following #wmEvent::custodata.
*
* - #EVT_ACTIONZONE_AREA / #EVT_ACTIONZONE_FULLSCREEN / #EVT_ACTIONZONE_FULLSCREEN:
* Uses #sActionzoneData.
* - #EVT_DROP: uses #ListBase of #wmDrag (also #wmEvent::custom == #EVT_DATA_DRAGDROP).
* Typically set to #wmWindowManger::drags.
* - #EVT_FILESELECT: uses #wmOperator.
* - #EVT_XR_ACTION: uses #wmXrActionData (also #wmEvent::custom == #EVT_DATA_XR).
* - #NDOF_MOTION: uses #wmNDOFMotionData (also #wmEvent::custom == #EVT_DATA_NDOF_MOTION).
* - #TIMER: uses #wmTimer (also #wmEvent::custom == #EVT_DATA_TIMER).
*/
void *customdata;
/* Previous State. */
@ -849,7 +860,7 @@ typedef enum {
/** Do not attempt to free custom-data pointer even if non-NULL. */
WM_TIMER_NO_FREE_CUSTOM_DATA = 1 << 0,
/* Internal falgs, should not be used outside of WM code. */
/* Internal flags, should not be used outside of WM code. */
/** This timer has been tagged for removal and deletion, handled by WM code to ensure timers are
* deleted in a safe context. */
WM_TIMER_TAGGED_FOR_REMOVAL = 1 << 16,

View File

@ -271,18 +271,18 @@ void WM_gizmotype_target_property_def(wmGizmoType *gzt,
int data_type,
int array_length)
{
wmGizmoPropertyType *mpt;
BLI_assert(WM_gizmotype_target_property_find(gzt, idname) == NULL);
const uint idname_size = strlen(idname) + 1;
mpt = MEM_callocN(sizeof(wmGizmoPropertyType) + idname_size, __func__);
memcpy(mpt->idname, idname, idname_size);
mpt->data_type = data_type;
mpt->array_length = array_length;
mpt->index_in_type = gzt->target_property_defs_len;
wmGizmoPropertyType *gz_prop_type = MEM_callocN(sizeof(wmGizmoPropertyType) + idname_size,
__func__);
memcpy(gz_prop_type->idname, idname, idname_size);
gz_prop_type->data_type = data_type;
gz_prop_type->array_length = array_length;
gz_prop_type->index_in_type = gzt->target_property_defs_len;
gzt->target_property_defs_len += 1;
BLI_addtail(&gzt->target_property_defs, mpt);
BLI_addtail(&gzt->target_property_defs, gz_prop_type);
}
/** \} */