Cycles: new Microfacet-based Hair BSDF with elliptical cross-section support #105600

Merged
Weizhen Huang merged 114 commits from weizhen/blender:microfacet_hair into main 2023-08-18 12:46:20 +02:00
59 changed files with 634 additions and 350 deletions
Showing only changes of commit a903e7bb32 - Show all commits

View File

@ -2,4 +2,4 @@ ${CommitTitle}
${CommitBody}
Pull Request #${PullRequestIndex}
Pull Request: https://projects.blender.org/blender/blender/pulls/${PullRequestIndex}

View File

@ -1,3 +1,3 @@
${PullRequestTitle}
Pull Request #${PullRequestIndex}
Pull Request: https://projects.blender.org/blender/blender/pulls/${PullRequestIndex}

View File

@ -1673,7 +1673,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
driver_version = "470"
col.label(text=iface_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
icon='BLANK1', translate=False)
col.label(text="and NVIDIA driver version %s or newer" % driver_version,
col.label(text=iface_("and NVIDIA driver version %s or newer") % driver_version,
icon='BLANK1', translate=False)
elif device_type == 'HIP':
if True:
@ -1719,7 +1719,8 @@ class CyclesPreferences(bpy.types.AddonPreferences):
.replace('(TM)', unicodedata.lookup('TRADE MARK SIGN'))
.replace('(tm)', unicodedata.lookup('TRADE MARK SIGN'))
.replace('(R)', unicodedata.lookup('REGISTERED SIGN'))
.replace('(C)', unicodedata.lookup('COPYRIGHT SIGN'))
.replace('(C)', unicodedata.lookup('COPYRIGHT SIGN')),
translate=False
)
def draw_impl(self, layout, context):

View File

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

View File

@ -230,9 +230,10 @@ ccl_device_inline float3 sample_wh(
const float3 wi_wm = make_float3(dot(wi, s), dot(wi, t), dot(wi, n));
float discard;
const float3 wh_wm = microfacet_sample_stretched<m_type>(
kg, wi_wm, roughness, roughness, rand.x, rand.y, &discard);
const float3 wh_wm =
(m_type == MicrofacetType::GGX) ?
microfacet_ggx_sample_vndf(wi_wm, roughness, roughness, rand.x, rand.y) :
microfacet_beckmann_sample_vndf(wi_wm, roughness, roughness, rand.x, rand.y);
const float3 wh = wh_wm.x * s + wh_wm.y * t + wh_wm.z * n;
return wh;
@ -372,14 +373,15 @@ ccl_device float3 bsdf_microfacet_hair_eval_r(ccl_private const ShaderClosure *s
/* Integrate using Composite Simpson's 1/3 rule. */
float integral = 0.0f;
for (size_t i = 0; i <= intervals; i++) {
const float gamma_m = gamma_m_min + i * res;
const float3 wm = sphg_dir(tilt, gamma_m, b);
if (microfacet_visible(wi, wo, make_float3(wm.x, 0.0f, wm.z), wh)) {
const float weight = (i == 0 || i == intervals) ? 0.5f : (i % 2 + 1);
integral += weight * bsdf_D<m_type>(roughness2, dot(wm, wh)) *
bsdf_G<m_type>(roughness2, dot(wi, wm), dot(wo, wm)) * arc_length(e2, gamma_m);
/* NOTE: using separable masking and shadowing as one factor cancels out in `sample()`. */
const float G = bsdf_G<m_type>(roughness2, dot(wm, wi)) *
bsdf_G<m_type>(roughness2, dot(wm, wo));
integral += weight * bsdf_D<m_type>(roughness2, dot(wm, wh)) * G * arc_length(e2, gamma_m);
}
}
@ -472,8 +474,8 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt(KernelGlobals kg,
const float cos_mi1 = dot(wi, wmi);
const float cos_mo1 = dot(-wt, wmi);
const float cos_mi2 = dot(-wt, wmt);
const float G1 = bsdf_G<m_type>(roughness2, cos_mi1, cos_mo1);
if (G1 == 0.0f || !microfacet_visible(wi, -wt, wmi_, wh1)) {
const float G1o = bsdf_G<m_type>(roughness2, cos_mo1);
if (!microfacet_visible(wi, -wt, wmi, wh1) || !microfacet_visible(wi, -wt, wmi_, wh1)) {
continue;
}
@ -498,10 +500,11 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt(KernelGlobals kg,
const float T2 = 1.0f - fresnel_dielectric_cos(cos_hi2, inv_eta);
const float D2 = bsdf_D<m_type>(roughness2, cos_mh2);
const float G2 = bsdf_G<m_type>(roughness2, cos_mi2, cos_mo2);
const float G2 = bsdf_G<m_type>(roughness2, cos_mi2) *
bsdf_G<m_type>(roughness2, cos_mo2);
const float3 result = weight * T1 * T2 * D2 * G2 * A_t / cos_mo1 * cos_mi1 * cos_hi2 *
cos_ho2 * sqr(rcp_norm_wh2) * bsdf_G1<m_type>(roughness2, cos_mo1);
const float3 result = weight * T1 * T2 * D2 * G1o * G2 * A_t / cos_mo1 * cos_mi1 *
cos_hi2 * cos_ho2 * sqr(rcp_norm_wh2);
if (isfinite_safe(result)) {
S_tt += bsdf->extra->TT * result * arc_length(e2, gamma_mt);
@ -527,9 +530,8 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt(KernelGlobals kg,
/* Total internal reflection. */
continue;
}
const float cos_mo2 = dot(-wtr, wmt);
const float G2 = bsdf_G<m_type>(roughness2, cos_mi2, cos_mo2);
if (G2 == 0.0f || !microfacet_visible(-wt, -wtr, wmt_, wh2)) {
if (!microfacet_visible(-wt, -wtr, wmt, wh2) || !microfacet_visible(-wt, -wtr, wmt_, wh2)) {
continue;
}
@ -538,12 +540,12 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt(KernelGlobals kg,
const float3 wmtr = sphg_dir(-tilt, gamma_mtr, b);
const float3 wmtr_ = sphg_dir(0.0f, gamma_mtr, b);
const float G3 = bsdf_G<m_type>(roughness2, dot(wtr, wmtr), dot(-wo, wmtr));
float3 wh3 = wtr + inv_eta * wo;
const float rcp_norm_wh3 = 1.0f / len(wh3);
wh3 *= rcp_norm_wh3;
const float cos_mh3 = dot(wmtr, wh3);
if (cos_mh3 < 0.0f || G3 == 0.0f || !microfacet_visible(wtr, -wo, wmtr_, wh3)) {
if (cos_mh3 < 0.0f || !microfacet_visible(wtr, -wo, wmtr, wh3) ||
!microfacet_visible(wtr, -wo, wmtr_, wh3)) {
continue;
}
@ -558,9 +560,14 @@ ccl_device float3 bsdf_microfacet_hair_eval_tt_trt(KernelGlobals kg,
2.0f * cosf(phi_tr - gamma_mt) :
-len(to_point(gamma_mtr, b) - to_point(gamma_mt, b))));
const float3 result = weight * T1 * R2 * T3 * D3 * G3 * A_t * A_tr / (cos_mo1 * cos_mo2) *
cos_mi1 * cos_mi2 * cos_hi3 * cos_ho3 * sqr(rcp_norm_wh3) *
bsdf_G<m_type>(roughness2, cos_mo1, cos_mo2);
const float cos_mo2 = dot(wmt, -wtr);
const float G2o = bsdf_G<m_type>(roughness2, cos_mo2);
const float G3 = bsdf_G<m_type>(roughness2, dot(wmtr, wtr)) *
bsdf_G<m_type>(roughness2, dot(wmtr, -wo));
const float3 result = weight * T1 * R2 * T3 * D3 * G1o * G2o * G3 * A_t * A_tr /
(cos_mo1 * cos_mo2) * cos_mi1 * cos_mi2 * cos_hi3 * cos_ho3 *
sqr(rcp_norm_wh3);
if (isfinite_safe(result)) {
S_trt += bsdf->extra->TRT * result * arc_length(e2, gamma_mtr);
@ -575,8 +582,7 @@ template<MicrofacetType m_type>
ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
ccl_private const ShaderClosure *sc,
ccl_private ShaderData *sd,
float randu,
float randv,
float3 rand,
ccl_private Spectrum *eval,
ccl_private float3 *wo,
ccl_private float *pdf,
@ -630,10 +636,9 @@ ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
const float roughness2 = sqr(roughness);
/* Generate samples. */
float sample_lobe = randu;
const float sample_h = randv;
const float2 sample_h1 = make_float2(lcg_step_float(&sd->lcg_state),
lcg_step_float(&sd->lcg_state));
float sample_lobe = rand.x;
const float sample_h = rand.y;
const float2 sample_h1 = make_float2(rand.z, lcg_step_float(&sd->lcg_state));
const float2 sample_h2 = make_float2(lcg_step_float(&sd->lcg_state),
lcg_step_float(&sd->lcg_state));
const float2 sample_h3 = make_float2(lcg_step_float(&sd->lcg_state),
@ -690,7 +695,7 @@ ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
float3 TT = zero_float3();
float3 TRT = zero_float3();
if (dot(wt, wh2) < 0.0f && dot(wmt, wt) < 0.0f && microfacet_visible(-wt, -wtr, wmt_, wh2)) {
if (dot(wh2, -wt) > 0.0f && dot(wmt, -wt) > 0.0f && microfacet_visible(-wt, -wtr, wmt_, wh2)) {
const float3 mu_a = bsdf->sigma;
const float3 A_t = exp(mu_a / cos_theta(wt) *
(is_circular ?
@ -704,7 +709,7 @@ ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
wtt = -refract_angle(-wt, wh2, cos_theta_t2, *eta);
if (dot(wtt, wmt) < 0.0f && cos_theta_t2 != 0.0f) {
if (dot(wmt, -wtt) > 0.0f && cos_theta_t2 != 0.0f) {
TT = bsdf->extra->TT * T1 * A_t * T2;
}
@ -721,7 +726,7 @@ ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
wtrt = -refract_angle(wtr, wh3, cos_theta_t3, *eta);
if (cos_theta_t3 != 0.0f && dot(wtr, wh3) > 0.0f && dot(wmtr, wtr) > 0.0f &&
dot(wtrt, wmtr) < 0.0f &&
dot(wmtr, -wtrt) > 0.0f &&
microfacet_visible(wtr, -wtrt, make_float3(wmtr.x, 0.0f, wmtr.z), wh3)) {
const float3 T3 = make_float3(1.0f - R3);
@ -755,7 +760,7 @@ ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
*eval = rgb_to_spectrum(R / r * total_energy);
if (microfacet_visible(wi, wr, wmi_, wh1)) {
visibility = bsdf_G1<m_type>(roughness2, dot(wr, wmi));
visibility = bsdf_G<m_type>(roughness2, dot(wmi, wr));
}
label |= LABEL_REFLECT;
@ -765,7 +770,8 @@ ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
*eval = rgb_to_spectrum(TT / tt * total_energy);
if (microfacet_visible(wi, -wt, wmi_, wh1) && microfacet_visible(-wt, -wtt, wmt_, wh2)) {
visibility = bsdf_G<m_type>(roughness2, dot(-wt, wmi), dot(-wtt, wmt));
visibility = bsdf_G<m_type>(roughness2, dot(wmi, -wt)) *
bsdf_G<m_type>(roughness2, dot(wmt, -wtt));

I think this is only used if we actually sample TRRT? The compiler should probably optimize that by itself though I guess.

I think this is only used if we actually sample TRRT? The compiler should probably optimize that by itself though I guess.
}
label |= LABEL_TRANSMIT;
@ -775,8 +781,9 @@ ccl_device int bsdf_microfacet_hair_sample(const KernelGlobals kg,
*eval = rgb_to_spectrum(TRT / trt * total_energy);
if (microfacet_visible(wi, -wt, wmi_, wh1)) {
visibility = bsdf_G<m_type>(roughness2, dot(-wt, wmi), dot(-wtr, wmt)) *
bsdf_G1<m_type>(roughness2, dot(-wtrt, wmtr));
visibility = bsdf_G<m_type>(roughness2, dot(wmi, -wt)) *
bsdf_G<m_type>(roughness2, dot(wmt, -wtr)) *
bsdf_G<m_type>(roughness2, dot(wmtr, -wtrt));
}
label |= LABEL_TRANSMIT;
@ -845,8 +852,7 @@ ccl_device Spectrum bsdf_microfacet_hair_eval(KernelGlobals kg,
ccl_device int bsdf_microfacet_hair_sample(KernelGlobals kg,
ccl_private const ShaderClosure *sc,
ccl_private ShaderData *sd,
float randu,
float randv,
float3 rand,
ccl_private Spectrum *eval,
weizhen marked this conversation as resolved Outdated

Does this TODO refer to the PR, or it more general?
I think it's fine to keep it like this for now, just want to make sure it's not overlooked.

Does this TODO refer to the PR, or it more general? I think it's fine to keep it like this for now, just want to make sure it's not overlooked.

In the original implementation the pdf involves sampling microfacets, it is as costly as evaluating the BSDF itself, and it is also just an approximation, so not sure if it's worth it and how to do it better. As pdf is only used for MIS, it doesn't influence the correctness of the model, so left as a TODO as a future improvement.

In the original implementation the pdf involves sampling microfacets, it is as costly as evaluating the BSDF itself, and it is also just an approximation, so not sure if it's worth it and how to do it better. As pdf is only used for MIS, it doesn't influence the correctness of the model, so left as a TODO as a future improvement.
ccl_private float3 *wo,
ccl_private float *pdf,
@ -857,10 +863,10 @@ ccl_device int bsdf_microfacet_hair_sample(KernelGlobals kg,
if (bsdf->distribution_type == NODE_MICROFACET_HAIR_BECKMANN) {
return bsdf_microfacet_hair_sample<MicrofacetType::BECKMANN>(
kg, sc, sd, randu, randv, eval, wo, pdf, sampled_roughness, eta);
kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
}
return bsdf_microfacet_hair_sample<MicrofacetType::GGX>(
kg, sc, sd, randu, randv, eval, wo, pdf, sampled_roughness, eta);
kg, sc, sd, rand, eval, wo, pdf, sampled_roughness, eta);
}
/* Implements Filter Glossy by capping the effective roughness. */

View File

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

View File

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

View File

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

View File

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

View File

@ -501,9 +501,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
Recursively get strings, needed in case we have "Blah" + "Blah", passed as an argument in that case it won't
evaluate to a string. However, break on some kind of stopper nodes, like e.g. Subscript.
"""
# New in py 3.8: all constants are of type 'ast.Constant'.
# 'ast.Str' will have to be removed when we officially switch to this version.
if type(node) in {ast.Str, getattr(ast, "Constant", None)}:
if type(node) == ast.Constant:
eval_str = ast.literal_eval(node)
if eval_str and type(eval_str) == str:
yield (is_split, eval_str, (node,))
@ -692,6 +690,15 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
else:
continue
# Skip function if it's marked as not translatable.
do_translate = True
for kw in node.keywords:
if kw.arg == "translate" and not kw.value.value:
do_translate = False
break
if not do_translate:
continue
func_args = func_translate_args.get(func_id, {})
# First try to get i18n contexts, for every possible msgid id.

View File

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

View File

@ -2,7 +2,10 @@
import bpy
from bpy.types import Menu
from bl_ui import node_add_menu
from bpy.app.translations import pgettext_iface as iface_
from bpy.app.translations import (
pgettext_iface as iface_,
contexts as i18n_contexts,
)
class NODE_MT_geometry_node_GEO_ATTRIBUTE(Menu):
@ -238,6 +241,7 @@ class NODE_MT_geometry_node_GEO_INPUT(Menu):
class NODE_MT_geometry_node_GEO_INPUT_CONSTANT(Menu):
bl_idname = "NODE_MT_geometry_node_GEO_INPUT_CONSTANT"
bl_label = "Constant"
bl_translation_context = i18n_contexts.id_nodetree
def draw(self, _context):
layout = self.layout

View File

@ -79,6 +79,7 @@ class TEXT_HT_footer(Header):
text=iface_("Text: External")
if text.library
else iface_("Text: Internal"),
translate=False
)

View File

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

View File

@ -342,7 +342,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name)
BLI_strncpy(masklay->name, name, sizeof(masklay->name));
}
else {
strcpy(masklay->name, "MaskLayer");
strcpy(masklay->name, DATA_("MaskLayer"));
}
BLI_addtail(&mask->masklayers, masklay);

View File

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

View File

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

View File

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

View File

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

View File

@ -130,6 +130,8 @@ const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid
#define BLT_I18NCONTEXT_VIRTUAL_REALITY "Virtual reality"
#define BLT_I18NCONTEXT_CONSTRAINT "Constraint"
#define BLT_I18NCONTEXT_COLOR "Color"
#define BLT_I18NCONTEXT_AMOUNT "Amount"
#define BLT_I18NCONTEXT_UNIT "Unit"
/* Helper for bpy.app.i18n object... */
typedef struct {
@ -198,6 +200,8 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_VIRTUAL_REALITY, "virtual_reality"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_CONSTRAINT, "constraint"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_COLOR, "color"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_AMOUNT, "amount"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_UNIT, "unit"), \
{ \
NULL, NULL, NULL \
} \

View File

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

View File

@ -2437,7 +2437,7 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
draw_bone_box(ctx, nullptr, pchan, arm, boneflag, constflag, select_id);
}
}
else {
else if (arm->drawtype == ARM_OCTA) {
draw_bone_update_disp_matrix_default(nullptr, pchan);
if (!is_pose_select || pchan_culling_test_octohedral(view, ob, pchan)) {
draw_bone_octahedral(ctx, nullptr, pchan, arm, boneflag, constflag, select_id);

View File

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

View File

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

View File

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

View File

@ -3877,7 +3877,7 @@ static void ui_but_update_ex(uiBut *but, const bool validate)
case UI_BTYPE_KEY_EVENT: {
const char *str;
if (but->flag & UI_SELECT) {
str = "Press a key";
str = IFACE_("Press a key");
}
else {
UI_GET_BUT_VALUE_INIT(but, value);
@ -3910,7 +3910,7 @@ static void ui_but_update_ex(uiBut *but, const bool validate)
(void)str; /* UNUSED */
}
else {
BLI_strncpy(but->drawstr, "Press a key", UI_MAX_DRAW_STR);
BLI_strncpy(but->drawstr, IFACE_("Press a key"), UI_MAX_DRAW_STR);
}
}
else {

View File

@ -2810,8 +2810,10 @@ void TEXT_OT_scroll(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(
PropertyRNA *prop;
prop = RNA_def_int(
ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
}
/** \} */
@ -2915,8 +2917,10 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
/* properties */
RNA_def_int(
PropertyRNA *prop;
prop = RNA_def_int(
ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100);
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
}
/** \} */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -146,12 +146,21 @@ void solve_length_and_collision_constraints(const OffsetIndices<int> points_by_c
float slide_direction_length_cu;
const float3 normalized_slide_direction_cu = math::normalize_and_get_length(
slide_direction_cu, slide_direction_length_cu);
const float slide_normal_length_sq_cu = math::length_squared(slide_normal_cu);
/* Use pythagorian theorem to determine how far to slide. */
const float slide_distance_cu = std::sqrt(pow2f(goal_segment_length_cu) -
math::length_squared(slide_normal_cu)) -
slide_direction_length_cu;
positions_cu[point_i] = plane_pos_cu + normalized_slide_direction_cu * slide_distance_cu;
if (pow2f(goal_segment_length_cu) > slide_normal_length_sq_cu) {
/* Use pythagorian theorem to determine how far to slide. */
const float slide_distance_cu = std::sqrt(pow2f(goal_segment_length_cu) -
slide_normal_length_sq_cu) -
slide_direction_length_cu;
positions_cu[point_i] = plane_pos_cu +
normalized_slide_direction_cu * slide_distance_cu;
}
else {
/* Minimum distance is larger than allowed segment length.
* The unilateral collision constraint is satisfied by just clamping segment length. */
positions_cu[point_i] = prev_pos_cu + math::normalize(old_pos_su - prev_pos_cu) * goal_segment_length_cu;
}
}
if (used_iterations == max_collisions) {
revert_curve = true;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2556,6 +2556,8 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "curve_preset", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_curve_preset_items);
RNA_def_property_ui_text(prop, "Curve Preset", "");
RNA_def_property_translation_context(prop,
BLT_I18NCONTEXT_ID_CURVES); /* Abusing id_curves :/ */
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "deform_target", PROP_ENUM, PROP_NONE);

View File

@ -8,6 +8,8 @@
#include "DNA_cachefile_types.h"
#include "DNA_scene_types.h"
#include "BLT_translation.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@ -364,6 +366,7 @@ static void rna_def_cachefile(BlenderRNA *brna)
"Velocity Unit",
"Define how the velocity vectors are interpreted with regard to time, 'frame' means "
"the delta time is 1 frame, 'second' means the delta time is 1 / FPS");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UNIT);
RNA_def_property_update(prop, 0, "rna_CacheFile_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);

View File

@ -1821,6 +1821,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_range(prop, 1, 5);
RNA_def_property_ui_text(
prop, "Number", "Particle number factor (higher value results in more particles)");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_AMOUNT);
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "particle_min", PROP_INT, PROP_NONE);

View File

@ -2948,6 +2948,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_range(prop, 0, 1000000, 1, -1);
RNA_def_property_ui_text(prop, "Number", "Total number of particles");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_AMOUNT);
RNA_def_property_update(prop, 0, "rna_Particle_reset");
prop = RNA_def_property(

View File

@ -6440,6 +6440,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "hair_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, hair_shape_type_items);
RNA_def_property_ui_text(prop, "Curves Shape Type", "Curves shape type");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVES);
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_render_update");
prop = RNA_def_property(srna, "hair_subdiv", PROP_INT, PROP_NONE);

View File

@ -237,6 +237,7 @@ static void rna_def_text(BlenderRNA *brna)
prop = RNA_def_property(srna, "lines", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "TextLine");
RNA_def_property_ui_text(prop, "Lines", "Lines of text");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT);
prop = RNA_def_property(srna, "current_line", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);

View File

@ -664,6 +664,7 @@ static void rna_def_volume(BlenderRNA *brna)
"Velocity Unit",
"Define how the velocity vectors are interpreted with regard to time, 'frame' means "
"the delta time is 1 frame, 'second' means the delta time is 1 / FPS");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UNIT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "velocity_scale", PROP_FLOAT, PROP_NONE);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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