Vulkan: Clearing Storage Buffers #105487
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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'}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -6,6 +6,7 @@ set(INC
|
|||
cached_resources
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../blentranslation
|
||||
../../gpu
|
||||
../../imbuf
|
||||
../../makesdna
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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_) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -276,6 +276,10 @@ extern TransConvertTypeInfo TransConvertType_SequencerImage;
|
|||
|
||||
extern TransConvertTypeInfo TransConvertType_Tracking;
|
||||
|
||||
/* transform_convert_tracking_curves.c */
|
||||
|
||||
extern TransConvertTypeInfo TransConvertType_TrackingCurves;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -31,7 +31,6 @@ class VKShaderInterface : public ShaderInterface {
|
|||
|
||||
VKPushConstants::Layout push_constants_layout_;
|
||||
|
||||
|
||||
public:
|
||||
VKShaderInterface() = default;
|
||||
|
||||
|
|
|
@ -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*/,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 ¶ms)
|
||||
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
Loading…
Reference in New Issue