Curves: Add edit mode operator to set attribute values #105076
|
@ -1826,7 +1826,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
|
|||
if (!window->m_mousePresent) {
|
||||
WINTAB_PRINTF("HWND %p mouse enter\n", window->getHWND());
|
||||
TRACKMOUSEEVENT tme = {sizeof(tme)};
|
||||
tme.dwFlags = TME_LEAVE;
|
||||
/* Request WM_MOUSELEAVE message when the cursor leaves the client area, and
|
||||
* WM_MOUSEHOVER message after 50ms when in the client area. */
|
||||
tme.dwFlags = TME_LEAVE | TME_HOVER;
|
||||
tme.dwHoverTime = 50;
|
||||
tme.hwndTrack = hwnd;
|
||||
TrackMouseEvent(&tme);
|
||||
window->m_mousePresent = true;
|
||||
|
@ -1843,6 +1846,35 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
|
|||
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEHOVER: {
|
||||
/* Mouse Tracking is now off. TrackMouseEvent restarts in MouseMove. */
|
||||
window->m_mousePresent = false;
|
||||
|
||||
/* Auto-focus only occurs within Blender windows, not with _other_ applications. */
|
||||
HWND old_hwnd = ::GetFocus();
|
||||
if (hwnd != old_hwnd) {
|
||||
HWND new_parent = ::GetParent(hwnd);
|
||||
HWND old_parent = ::GetParent(old_hwnd);
|
||||
if (hwnd == old_parent || old_hwnd == new_parent) {
|
||||
/* Child to its parent, parent to its child. */
|
||||
::SetFocus(hwnd);
|
||||
}
|
||||
else if (new_parent != HWND_DESKTOP && new_parent == old_parent) {
|
||||
/* Between siblings of same parent. */
|
||||
::SetFocus(hwnd);
|
||||
}
|
||||
else if (!new_parent && !old_parent) {
|
||||
/* Between main windows that don't overlap. */
|
||||
RECT new_rect, old_rect, dest_rect;
|
||||
::GetWindowRect(hwnd, &new_rect);
|
||||
::GetWindowRect(old_hwnd, &old_rect);
|
||||
if (!IntersectRect(&dest_rect, &new_rect, &old_rect)) {
|
||||
::SetFocus(hwnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEWHEEL: {
|
||||
/* The WM_MOUSEWHEEL message is sent to the focus window
|
||||
* when the mouse wheel is rotated. The DefWindowProc
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
import bpy
|
||||
from bpy.types import Panel, Menu
|
||||
from bpy.types import Panel, Menu, UIList
|
||||
from rna_prop_ui import PropertyPanel
|
||||
|
||||
from bl_ui.properties_animviz import (
|
||||
|
@ -91,6 +91,16 @@ class DATA_MT_bone_group_context_menu(Menu):
|
|||
layout.operator("pose.group_sort", icon='SORTALPHA')
|
||||
|
||||
|
||||
class DATA_UL_bone_groups(UIList):
|
||||
def draw_item(self, _context, layout, _data, item, _icon, _active_data, _active_propname, _index):
|
||||
layout.prop(item, "name", text="", emboss=False, icon='GROUP_BONE')
|
||||
|
||||
if item.is_custom_color_set or item.color_set == 'DEFAULT':
|
||||
layout.prop(item, "color_set", icon_only=True, icon="COLOR")
|
||||
else:
|
||||
layout.prop(item, "color_set", icon_only=True)
|
||||
|
||||
|
||||
class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
|
||||
bl_label = "Bone Groups"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
@ -111,8 +121,9 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
|
|||
rows = 1
|
||||
if group:
|
||||
rows = 4
|
||||
|
||||
row.template_list(
|
||||
"UI_UL_list",
|
||||
"DATA_UL_bone_groups",
|
||||
"bone_groups",
|
||||
pose,
|
||||
"bone_groups",
|
||||
|
@ -121,6 +132,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
|
|||
rows=rows,
|
||||
)
|
||||
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("pose.group_add", icon='ADD', text="")
|
||||
col.operator("pose.group_remove", icon='REMOVE', text="")
|
||||
|
@ -130,17 +142,20 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
|
|||
col.operator("pose.group_move", icon='TRIA_UP', text="").direction = 'UP'
|
||||
col.operator("pose.group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
split = layout.split()
|
||||
if group.is_custom_color_set:
|
||||
col = layout.column()
|
||||
split = col.split(factor=0.4)
|
||||
|
||||
col = split.column()
|
||||
col.prop(group, "color_set")
|
||||
if group.color_set:
|
||||
col = split.column()
|
||||
sub = col.row(align=True)
|
||||
sub.enabled = group.is_custom_color_set # only custom colors are editable
|
||||
sub.prop(group.colors, "normal", text="")
|
||||
sub.prop(group.colors, "select", text="")
|
||||
sub.prop(group.colors, "active", text="")
|
||||
row = col.row()
|
||||
row.alignment = 'RIGHT'
|
||||
row.label(text="Custom Colors")
|
||||
|
||||
col = split.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(group.colors, "normal", text="")
|
||||
row.prop(group.colors, "select", text="")
|
||||
row.prop(group.colors, "active", text="")
|
||||
|
||||
row = layout.row()
|
||||
|
||||
|
@ -258,6 +273,7 @@ classes = (
|
|||
DATA_PT_skeleton,
|
||||
DATA_MT_bone_group_context_menu,
|
||||
DATA_PT_bone_groups,
|
||||
DATA_UL_bone_groups,
|
||||
DATA_PT_motion_paths,
|
||||
DATA_PT_motion_paths_display,
|
||||
DATA_PT_display,
|
||||
|
|
|
@ -1091,17 +1091,6 @@ static void blf_glyph_calc_rect(rcti *rect, GlyphBLF *g, const int x, const int
|
|||
rect->ymax = rect->ymin - g->dims[1];
|
||||
}
|
||||
|
||||
static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const int y)
|
||||
{
|
||||
/* Intentionally check with `g->advance`, because this is the
|
||||
* width used by BLF_width. This allows that the text slightly
|
||||
* overlaps the clipping border to achieve better alignment. */
|
||||
rect->xmin = x;
|
||||
rect->xmax = rect->xmin + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]);
|
||||
rect->ymin = y;
|
||||
rect->ymax = rect->ymin - g->dims[1];
|
||||
}
|
||||
|
||||
static void blf_glyph_calc_rect_shadow(
|
||||
rcti *rect, GlyphBLF *g, const int x, const int y, FontBLF *font)
|
||||
{
|
||||
|
@ -1213,9 +1202,10 @@ void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, const int x,
|
|||
|
||||
if (font->flags & BLF_CLIPPING) {
|
||||
rcti rect_test;
|
||||
blf_glyph_calc_rect_test(&rect_test, g, x, y);
|
||||
BLI_rcti_translate(&rect_test, font->pos[0], font->pos[1]);
|
||||
|
||||
rect_test.xmin = x + font->pos[0] + g->pos[0] + 1;
|
||||
rect_test.xmax = rect_test.xmin + g->dims[0] - 2;
|
||||
rect_test.ymin = y + font->pos[1];
|
||||
rect_test.ymax = rect_test.ymin + g->pos[1];
|
||||
if (!BLI_rcti_inside_rcti(&font->clip_rec, &rect_test)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -250,6 +250,88 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
|
|||
|
||||
/* ********** */
|
||||
|
||||
/**
|
||||
* When transfering color attributes, also transfer the active color attribute string.
|
||||
* If a match can't be found, use the first color layer that can be found (to ensure a valid string
|
||||
* is set).
|
||||
*/
|
||||
static void data_transfer_mesh_attributes_transfer_active_color_string(
|
||||
Mesh *mesh_dst, Mesh *mesh_src, const eAttrDomainMask mask_domain, const int data_type)
|
||||
{
|
||||
if (mesh_dst->active_color_attribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *active_color_src = BKE_id_attributes_active_color_name(&mesh_src->id);
|
||||
|
||||
if ((data_type == CD_PROP_COLOR) &&
|
||||
!BKE_id_attribute_search(&mesh_src->id, active_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
return;
|
||||
}
|
||||
else if ((data_type == CD_PROP_BYTE_COLOR) &&
|
||||
!BKE_id_attribute_search(&mesh_src->id, active_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((data_type == CD_PROP_COLOR) &&
|
||||
BKE_id_attribute_search(&mesh_dst->id, active_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
mesh_dst->active_color_attribute = BLI_strdup(active_color_src);
|
||||
}
|
||||
else if ((data_type == CD_PROP_BYTE_COLOR) &&
|
||||
BKE_id_attribute_search(&mesh_dst->id, active_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
mesh_dst->active_color_attribute = BLI_strdup(active_color_src);
|
||||
}
|
||||
else {
|
||||
CustomDataLayer *first_color_layer = BKE_id_attribute_from_index(
|
||||
&mesh_dst->id, 0, mask_domain, CD_MASK_COLOR_ALL);
|
||||
if (first_color_layer != nullptr) {
|
||||
mesh_dst->active_color_attribute = BLI_strdup(first_color_layer->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When transfering color attributes, also transfer the default color attribute string.
|
||||
* If a match cant be found, use the first color layer that can be found (to ensure a valid string
|
||||
* is set).
|
||||
*/
|
||||
static void data_transfer_mesh_attributes_transfer_default_color_string(
|
||||
Mesh *mesh_dst, Mesh *mesh_src, const eAttrDomainMask mask_domain, const int data_type)
|
||||
{
|
||||
if (mesh_dst->default_color_attribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *default_color_src = BKE_id_attributes_default_color_name(&mesh_src->id);
|
||||
|
||||
if ((data_type == CD_PROP_COLOR) &&
|
||||
!BKE_id_attribute_search(&mesh_src->id, default_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
return;
|
||||
}
|
||||
else if ((data_type == CD_PROP_BYTE_COLOR) &&
|
||||
!BKE_id_attribute_search(&mesh_src->id, default_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((data_type == CD_PROP_COLOR) &&
|
||||
BKE_id_attribute_search(&mesh_dst->id, default_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
mesh_dst->default_color_attribute = BLI_strdup(default_color_src);
|
||||
}
|
||||
else if ((data_type == CD_PROP_BYTE_COLOR) &&
|
||||
BKE_id_attribute_search(&mesh_dst->id, default_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
|
||||
mesh_dst->default_color_attribute = BLI_strdup(default_color_src);
|
||||
}
|
||||
else {
|
||||
CustomDataLayer *first_color_layer = BKE_id_attribute_from_index(
|
||||
&mesh_dst->id, 0, mask_domain, CD_MASK_COLOR_ALL);
|
||||
if (first_color_layer != nullptr) {
|
||||
mesh_dst->default_color_attribute = BLI_strdup(first_color_layer->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ********** */
|
||||
|
||||
/* Generic pre/post processing, only used by custom loop normals currently. */
|
||||
|
||||
static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
|
||||
|
@ -1124,6 +1206,14 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph,
|
|||
fromlayers,
|
||||
tolayers,
|
||||
nullptr);
|
||||
/* Make sure we have active/defaut color layers if none existed before.
|
||||
* Use the active/defaut from src (if it was transferred), otherwise the first. */
|
||||
if (ELEM(cddata_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) {
|
||||
data_transfer_mesh_attributes_transfer_active_color_string(
|
||||
me_dst, me_src, ATTR_DOMAIN_MASK_POINT, cddata_type);
|
||||
data_transfer_mesh_attributes_transfer_default_color_string(
|
||||
me_dst, me_src, ATTR_DOMAIN_MASK_POINT, cddata_type);
|
||||
}
|
||||
}
|
||||
if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
|
||||
const int num_elem_dst = me_dst->totedge;
|
||||
|
@ -1164,6 +1254,14 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph,
|
|||
fromlayers,
|
||||
tolayers,
|
||||
nullptr);
|
||||
/* Make sure we have active/defaut color layers if none existed before.
|
||||
* Use the active/defaut from src (if it was transferred), otherwise the first. */
|
||||
if (ELEM(cddata_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) {
|
||||
data_transfer_mesh_attributes_transfer_active_color_string(
|
||||
me_dst, me_src, ATTR_DOMAIN_MASK_CORNER, cddata_type);
|
||||
data_transfer_mesh_attributes_transfer_default_color_string(
|
||||
me_dst, me_src, ATTR_DOMAIN_MASK_CORNER, cddata_type);
|
||||
}
|
||||
}
|
||||
if (DT_DATATYPE_IS_POLY(dtdata_type)) {
|
||||
const int num_elem_dst = me_dst->totpoly;
|
||||
|
|
|
@ -102,7 +102,7 @@ Closure closure_eval(ClosureTranslucent translucent)
|
|||
}
|
||||
|
||||
CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDF, Glossy)
|
||||
Closure closure_eval(ClosureReflection reflection)
|
||||
Closure closure_eval(ClosureReflection reflection, const bool do_output_ssr)
|
||||
{
|
||||
/* Glue with the old system. */
|
||||
CLOSURE_VARS_DECLARE_1(Glossy);
|
||||
|
@ -113,12 +113,22 @@ Closure closure_eval(ClosureReflection reflection)
|
|||
CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy);
|
||||
|
||||
Closure closure = CLOSURE_DEFAULT;
|
||||
if (!output_ssr(reflection)) {
|
||||
|
||||
bool output_radiance = true;
|
||||
if (do_output_ssr) {
|
||||
output_radiance = !output_ssr(reflection);
|
||||
}
|
||||
if (output_radiance) {
|
||||
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
return closure;
|
||||
}
|
||||
|
||||
Closure closure_eval(ClosureReflection reflection)
|
||||
{
|
||||
return closure_eval(reflection, true);
|
||||
}
|
||||
|
||||
CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction)
|
||||
Closure closure_eval(ClosureRefraction refraction)
|
||||
{
|
||||
|
@ -155,6 +165,13 @@ Closure closure_eval(ClosureTransparency transparency)
|
|||
CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction)
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
|
||||
{
|
||||
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(refraction);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
closure.radiance += closure_reflection.radiance;
|
||||
return closure;
|
||||
#else
|
||||
/* Glue with the old system. */
|
||||
CLOSURE_VARS_DECLARE_2(Glossy, Refraction);
|
||||
|
||||
|
@ -172,12 +189,19 @@ Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
|
|||
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
return closure;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Dielectric BSDF */
|
||||
CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy)
|
||||
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
|
||||
{
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(diffuse);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
closure.radiance += closure_reflection.radiance;
|
||||
return closure;
|
||||
#else
|
||||
/* Glue with the old system. */
|
||||
CLOSURE_VARS_DECLARE_2(Diffuse, Glossy);
|
||||
|
||||
|
@ -198,6 +222,7 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
|
|||
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
return closure;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Specular BSDF */
|
||||
|
@ -206,6 +231,13 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
|||
ClosureReflection reflection,
|
||||
ClosureReflection clearcoat)
|
||||
{
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(diffuse);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
Closure closure_clearcoat = closure_eval(clearcoat, false);
|
||||
closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance;
|
||||
return closure;
|
||||
#else
|
||||
/* Glue with the old system. */
|
||||
CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy);
|
||||
|
||||
|
@ -229,6 +261,7 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
|||
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
return closure;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Principled BSDF */
|
||||
|
@ -238,6 +271,15 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
|||
ClosureReflection clearcoat,
|
||||
ClosureRefraction refraction)
|
||||
{
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(diffuse);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
Closure closure_clearcoat = closure_eval(clearcoat, false);
|
||||
Closure closure_refraction = closure_eval(refraction);
|
||||
closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance +
|
||||
closure_refraction.radiance;
|
||||
return closure;
|
||||
#else
|
||||
/* Glue with the old system. */
|
||||
CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction);
|
||||
|
||||
|
@ -263,11 +305,18 @@ Closure closure_eval(ClosureDiffuse diffuse,
|
|||
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
return closure;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy)
|
||||
Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
|
||||
{
|
||||
#if defined(DO_SPLIT_CLOSURE_EVAL)
|
||||
Closure closure = closure_eval(clearcoat);
|
||||
Closure closure_reflection = closure_eval(reflection);
|
||||
closure.radiance += closure_reflection.radiance;
|
||||
return closure;
|
||||
#else
|
||||
/* Glue with the old system. */
|
||||
CLOSURE_VARS_DECLARE_2(Glossy, Glossy);
|
||||
|
||||
|
@ -284,6 +333,7 @@ Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
|
|||
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
|
||||
}
|
||||
return closure;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Not supported for surface shaders. */
|
||||
|
|
|
@ -16,6 +16,14 @@ typedef struct CommonUniformBlock CommonUniformBlock;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* NOTE: AMD-based macOS platforms experience performance and correctness issues with EEVEE
|
||||
* material closure evaluation. Using singular closure evaluation, rather than the compound
|
||||
* function calls reduces register overflow, by limiting the simultaneous number of live
|
||||
* registers used by the virtual GPU function stack. */
|
||||
#if (defined(GPU_METAL) && defined(GPU_ATI))
|
||||
# define DO_SPLIT_CLOSURE_EVAL 1
|
||||
#endif
|
||||
|
||||
struct CommonUniformBlock {
|
||||
mat4 pastViewProjectionMatrix;
|
||||
vec4 hizUvScale; /* To correct mip level texel misalignment */
|
||||
|
|
|
@ -6532,6 +6532,8 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
|
|||
va_list args;
|
||||
uiStringInfo *si;
|
||||
|
||||
PointerRNA *opptr = UI_but_operator_ptr_get(but);
|
||||
|
||||
const EnumPropertyItem *items = nullptr, *item = nullptr;
|
||||
int totitems;
|
||||
bool free_items = false;
|
||||
|
@ -6610,10 +6612,13 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
|
|||
}
|
||||
else if (but->optype) {
|
||||
if (type == BUT_GET_RNA_LABEL) {
|
||||
tmp = BLI_strdup(WM_operatortype_name(but->optype, but->opptr));
|
||||
tmp = BLI_strdup(WM_operatortype_name(but->optype, opptr));
|
||||
}
|
||||
else {
|
||||
tmp = WM_operatortype_description(C, but->optype, but->opptr);
|
||||
bContextStore *previous_ctx = CTX_store_get(C);
|
||||
CTX_store_set(C, but->context);
|
||||
tmp = WM_operatortype_description(C, but->optype, opptr);
|
||||
CTX_store_set(C, previous_ctx);
|
||||
}
|
||||
}
|
||||
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
|
||||
|
@ -6696,7 +6701,6 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
|
|||
int(ui_but_value_get(but));
|
||||
}
|
||||
else if (but->optype) {
|
||||
PointerRNA *opptr = UI_but_operator_ptr_get(but);
|
||||
wmOperatorType *ot = but->optype;
|
||||
|
||||
/* So the context is passed to `itemf` functions. */
|
||||
|
|
|
@ -970,9 +970,9 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust
|
|||
|
||||
const uint pos3d = GPU_vertformat_attr_add(format3d, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
const uint col3d = GPU_vertformat_attr_add(format3d, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
|
||||
const uint siz3d = GPU_vertformat_attr_add(format3d, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
|
||||
immUniform1f("size", 4.0f);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
|
||||
immBegin(GPU_PRIM_POINTS, points_wo.size());
|
||||
|
||||
float3 brush_origin_wo = math::transform_point(op_data.curves_to_world_mat, op_data.pos_cu);
|
||||
|
@ -990,6 +990,7 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust
|
|||
const float dist_to_point_re = math::distance(pos_re, brush_origin_re);
|
||||
const float alpha = 1.0f - ((dist_to_point_re - dist_to_inner_border_re) / alpha_border_re);
|
||||
|
||||
immAttr1f(siz3d, 3.0f);
|
||||
immAttr4f(col3d, 0.9f, 0.9f, 0.9f, alpha);
|
||||
immVertex3fv(pos3d, pos_wo);
|
||||
}
|
||||
|
|
|
@ -456,6 +456,22 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static char *node_add_group_asset_get_description(struct bContext *C,
|
||||
struct wmOperatorType * /*op*/,
|
||||
struct PointerRNA * /*values*/)
|
||||
{
|
||||
bool is_valid;
|
||||
const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid);
|
||||
if (!is_valid) {
|
||||
return nullptr;
|
||||
}
|
||||
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&handle);
|
||||
if (!asset_data.description) {
|
||||
return nullptr;
|
||||
}
|
||||
return BLI_strdup(asset_data.description);
|
||||
}
|
||||
|
||||
void NODE_OT_add_group_asset(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Add Node Group Asset";
|
||||
|
@ -464,6 +480,7 @@ void NODE_OT_add_group_asset(wmOperatorType *ot)
|
|||
|
||||
ot->invoke = node_add_group_asset_invoke;
|
||||
ot->poll = node_add_group_poll;
|
||||
ot->get_description = node_add_group_asset_get_description;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
}
|
||||
|
|
|
@ -1106,6 +1106,7 @@ static void draw_rotation_guide(const RegionView3D *rv3d)
|
|||
/* -- draw rotation center -- */
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
|
||||
immUniform1f("size", 7.0f);
|
||||
immUniform4fv("color", float4(color));
|
||||
immBegin(GPU_PRIM_POINTS, 1);
|
||||
immAttr4ubv(col, color);
|
||||
immVertex3fv(pos, o);
|
||||
|
|
|
@ -154,6 +154,12 @@ struct RealizeCurveInfo {
|
|||
* curves.
|
||||
*/
|
||||
VArray<int> resolution;
|
||||
|
||||
/**
|
||||
* The resolution attribute must be filled with the default value if it does not exist on some
|
||||
* curves.
|
||||
*/
|
||||
Span<float> nurbs_weight;
|
||||
};
|
||||
|
||||
/** Start indices in the final output curves data-block. */
|
||||
|
@ -208,6 +214,7 @@ struct AllCurvesInfo {
|
|||
bool create_handle_postion_attributes = false;
|
||||
bool create_radius_attribute = false;
|
||||
bool create_resolution_attribute = false;
|
||||
bool create_nurbs_weight_attribute = false;
|
||||
};
|
||||
|
||||
/** Collects all tasks that need to be executed to realize all instances. */
|
||||
|
@ -1159,6 +1166,7 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate(
|
|||
attributes_to_propagate);
|
||||
attributes_to_propagate.remove("position");
|
||||
attributes_to_propagate.remove("radius");
|
||||
attributes_to_propagate.remove("nurbs_weight");
|
||||
attributes_to_propagate.remove("resolution");
|
||||
attributes_to_propagate.remove("handle_right");
|
||||
attributes_to_propagate.remove("handle_left");
|
||||
|
@ -1220,20 +1228,20 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
|
|||
}
|
||||
}
|
||||
|
||||
/* Retrieve the radius attribute, if it exists. */
|
||||
if (attributes.contains("radius")) {
|
||||
curve_info.radius =
|
||||
attributes.lookup<float>("radius", ATTR_DOMAIN_POINT).get_internal_span();
|
||||
info.create_radius_attribute = true;
|
||||
}
|
||||
|
||||
/* Retrieve the resolution attribute, if it exists. */
|
||||
if (attributes.contains("nurbs_weight")) {
|
||||
curve_info.nurbs_weight =
|
||||
attributes.lookup<float>("nurbs_weight", ATTR_DOMAIN_POINT).get_internal_span();
|
||||
info.create_nurbs_weight_attribute = true;
|
||||
}
|
||||
curve_info.resolution = curves.resolution();
|
||||
if (attributes.contains("resolution")) {
|
||||
info.create_resolution_attribute = true;
|
||||
}
|
||||
|
||||
/* Retrieve handle position attributes, if they exist. */
|
||||
if (attributes.contains("handle_right")) {
|
||||
curve_info.handle_left =
|
||||
attributes.lookup<float3>("handle_left", ATTR_DOMAIN_POINT).get_internal_span();
|
||||
|
@ -1255,6 +1263,7 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
|
|||
MutableSpan<float3> all_handle_left,
|
||||
MutableSpan<float3> all_handle_right,
|
||||
MutableSpan<float> all_radii,
|
||||
MutableSpan<float> all_nurbs_weights,
|
||||
MutableSpan<int> all_resolutions)
|
||||
{
|
||||
const RealizeCurveInfo &curves_info = *task.curve_info;
|
||||
|
@ -1285,14 +1294,20 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
|
|||
}
|
||||
}
|
||||
|
||||
/* Copy radius attribute with 1.0 default if it doesn't exist. */
|
||||
auto copy_point_span_with_default =
|
||||
[&](const Span<float> src, MutableSpan<float> all_dst, const float value) {
|
||||
if (src.is_empty()) {
|
||||
all_dst.slice(dst_point_range).fill(value);
|
||||
}
|
||||
else {
|
||||
all_dst.slice(dst_point_range).copy_from(src);
|
||||
}
|
||||
};
|
||||
if (all_curves_info.create_radius_attribute) {
|
||||
if (curves_info.radius.is_empty()) {
|
||||
all_radii.slice(dst_point_range).fill(1.0f);
|
||||
}
|
||||
else {
|
||||
all_radii.slice(dst_point_range).copy_from(curves_info.radius);
|
||||
}
|
||||
copy_point_span_with_default(curves_info.radius, all_radii, 1.0f);
|
||||
}
|
||||
if (all_curves_info.create_nurbs_weight_attribute) {
|
||||
copy_point_span_with_default(curves_info.nurbs_weight, all_nurbs_weights, 1.0f);
|
||||
}
|
||||
|
||||
if (all_curves_info.create_resolution_attribute) {
|
||||
|
@ -1385,13 +1400,15 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
|
|||
ATTR_DOMAIN_POINT);
|
||||
}
|
||||
|
||||
/* Prepare radius attribute if necessary. */
|
||||
SpanAttributeWriter<float> radius;
|
||||
if (all_curves_info.create_radius_attribute) {
|
||||
radius = dst_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
|
||||
}
|
||||
|
||||
/* Prepare resolution attribute if necessary. */
|
||||
SpanAttributeWriter<float> nurbs_weight;
|
||||
if (all_curves_info.create_nurbs_weight_attribute) {
|
||||
nurbs_weight = dst_attributes.lookup_or_add_for_write_only_span<float>("nurbs_weight",
|
||||
ATTR_DOMAIN_POINT);
|
||||
}
|
||||
SpanAttributeWriter<int> resolution;
|
||||
if (all_curves_info.create_resolution_attribute) {
|
||||
resolution = dst_attributes.lookup_or_add_for_write_only_span<int>("resolution",
|
||||
|
@ -1412,6 +1429,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
|
|||
handle_left.span,
|
||||
handle_right.span,
|
||||
radius.span,
|
||||
nurbs_weight.span,
|
||||
resolution.span);
|
||||
}
|
||||
});
|
||||
|
@ -1432,6 +1450,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
|
|||
point_ids.finish();
|
||||
radius.finish();
|
||||
resolution.finish();
|
||||
nurbs_weight.finish();
|
||||
handle_left.finish();
|
||||
handle_right.finish();
|
||||
}
|
||||
|
|
|
@ -308,24 +308,23 @@ static bke::CurvesGeometry convert_curves_to_bezier(
|
|||
dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
|
||||
const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve();
|
||||
|
||||
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
|
||||
MutableSpan<float3> dst_positions = dst_curves.positions_for_write();
|
||||
MutableSpan<float3> dst_handles_l = dst_curves.handle_positions_left_for_write();
|
||||
MutableSpan<float3> dst_handles_r = dst_curves.handle_positions_right_for_write();
|
||||
MutableSpan<int8_t> dst_types_l = dst_curves.handle_types_left_for_write();
|
||||
MutableSpan<int8_t> dst_types_r = dst_curves.handle_types_right_for_write();
|
||||
MutableSpan<float> dst_weights = dst_curves.nurbs_weights_for_write();
|
||||
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
|
||||
Set<std::string> attributes_to_skip = {
|
||||
"position", "handle_type_left", "handle_type_right", "handle_right", "handle_left"};
|
||||
if (!dst_curves.has_curve_with_type(CURVE_TYPE_NURBS)) {
|
||||
attributes_to_skip.add_new("nurbs_weight");
|
||||
}
|
||||
Vector<bke::AttributeTransferData> generic_attributes = bke::retrieve_attributes_for_transfer(
|
||||
src_attributes,
|
||||
dst_attributes,
|
||||
ATTR_DOMAIN_MASK_POINT,
|
||||
propagation_info,
|
||||
{"position",
|
||||
"handle_type_left",
|
||||
"handle_type_right",
|
||||
"handle_right",
|
||||
"handle_left",
|
||||
"nurbs_weight"});
|
||||
attributes_to_skip);
|
||||
|
||||
auto catmull_rom_to_bezier = [&](IndexMask selection) {
|
||||
bke::curves::fill_points<int8_t>(
|
||||
|
@ -396,7 +395,6 @@ static bke::CurvesGeometry convert_curves_to_bezier(
|
|||
dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_l);
|
||||
bke::curves::fill_points<int8_t>(
|
||||
dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_r);
|
||||
bke::curves::fill_points<float>(dst_points_by_curve, selection, 0.0f, dst_weights);
|
||||
|
||||
threading::parallel_for(selection.index_range(), 64, [&](IndexRange range) {
|
||||
for (const int i : selection.slice(range)) {
|
||||
|
@ -513,7 +511,7 @@ static bke::CurvesGeometry convert_curves_to_nurbs(
|
|||
"nurbs_weight"});
|
||||
|
||||
auto fill_weights_if_necessary = [&](const IndexMask selection) {
|
||||
if (!src_curves.nurbs_weights().is_empty()) {
|
||||
if (src_attributes.contains("nurbs_weight")) {
|
||||
bke::curves::fill_points(
|
||||
dst_points_by_curve, selection, 1.0f, dst_curves.nurbs_weights_for_write());
|
||||
}
|
||||
|
|
|
@ -951,14 +951,16 @@ void GPU_material_compile(GPUMaterial *mat)
|
|||
* As PSOs do not always match for default shaders, we limit warming for PSO
|
||||
* configurations to ensure compile time remains fast, as these first
|
||||
* entries will be the most commonly used PSOs. As not all PSOs are necessarily
|
||||
* required immediately, this limit should remain low (1-3 at most).
|
||||
* */
|
||||
* required immediately, this limit should remain low (1-3 at most). */
|
||||
if (mat->default_mat != NULL && mat->default_mat != mat) {
|
||||
if (mat->default_mat->pass != NULL) {
|
||||
GPUShader *parent_sh = GPU_pass_shader_get(mat->default_mat->pass);
|
||||
if (parent_sh) {
|
||||
GPU_shader_set_parent(sh, parent_sh);
|
||||
GPU_shader_warm_cache(sh, 1);
|
||||
/* Skip warming if cached pass is identical to the default material. */
|
||||
if (mat->default_mat->pass != mat->pass && parent_sh != sh) {
|
||||
GPU_shader_set_parent(sh, parent_sh);
|
||||
GPU_shader_warm_cache(sh, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@ static void test_gpu_shader_compute_ssbo()
|
|||
EXPECT_NE(shader, nullptr);
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
/* Construct IBO. */
|
||||
/* Construct SSBO. */
|
||||
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
|
||||
SIZE * sizeof(uint32_t), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
|
||||
GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo_binding(shader, "data_out"));
|
||||
|
|
|
@ -119,6 +119,10 @@ void VKDescriptorSet::update(VkDevice vk_device)
|
|||
descriptor_writes.append(write_descriptor);
|
||||
}
|
||||
|
||||
BLI_assert_msg(image_infos.size() + buffer_infos.size() == descriptor_writes.size(),
|
||||
"Not all changes have been converted to a write descriptor. Check "
|
||||
"`Binding::is_buffer` and `Binding::is_image`.");
|
||||
|
||||
vkUpdateDescriptorSets(
|
||||
vk_device, descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
#include "vk_common.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
class VKStorageBuffer;
|
||||
class VKVertexBuffer;
|
||||
class VKIndexBuffer;
|
||||
class VKShaderInterface;
|
||||
class VKStorageBuffer;
|
||||
class VKTexture;
|
||||
class VKVertexBuffer;
|
||||
|
||||
/**
|
||||
* In vulkan shader resources (images and buffers) are grouped in descriptor sets.
|
||||
|
@ -26,7 +27,7 @@ class VKTexture;
|
|||
* The resources inside a descriptor set can be updated and bound per set.
|
||||
*
|
||||
* Currently Blender only supports a single descriptor set per shader, but it is planned to be able
|
||||
* to use 2 descriptor sets per shader. Only for each #blender::gpu::shader::Frequency.
|
||||
* to use 2 descriptor sets per shader. One for each #blender::gpu::shader::Frequency.
|
||||
*/
|
||||
class VKDescriptorSet : NonCopyable {
|
||||
struct Binding;
|
||||
|
@ -50,9 +51,12 @@ class VKDescriptorSet : NonCopyable {
|
|||
*/
|
||||
uint32_t binding;
|
||||
|
||||
Location() = default;
|
||||
Location(uint32_t binding) : binding(binding)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
Location() = default;
|
||||
Location(const ShaderInput *shader_input) : binding(shader_input->location)
|
||||
{
|
||||
}
|
||||
|
@ -68,6 +72,7 @@ class VKDescriptorSet : NonCopyable {
|
|||
}
|
||||
|
||||
friend struct Binding;
|
||||
friend class VKShaderInterface;
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -24,9 +24,9 @@ void VKIndexBuffer::bind_as_ssbo(uint binding)
|
|||
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, shader_input);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
|
||||
}
|
||||
|
||||
void VKIndexBuffer::read(uint32_t *data) const
|
||||
|
|
|
@ -326,10 +326,10 @@ static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifie
|
|||
}
|
||||
|
||||
static void print_resource(std::ostream &os,
|
||||
const ShaderInput &shader_input,
|
||||
const VKDescriptorSet::Location location,
|
||||
const ShaderCreateInfo::Resource &res)
|
||||
{
|
||||
os << "layout(binding = " << shader_input.location;
|
||||
os << "layout(binding = " << static_cast<uint32_t>(location);
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
|
||||
os << ", " << to_string(res.image.format);
|
||||
}
|
||||
|
@ -379,12 +379,8 @@ static void print_resource(std::ostream &os,
|
|||
const VKShaderInterface &shader_interface,
|
||||
const ShaderCreateInfo::Resource &res)
|
||||
{
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(res);
|
||||
if (shader_input == nullptr) {
|
||||
BLI_assert_msg(shader_input, "Cannot find shader input for resource");
|
||||
return;
|
||||
}
|
||||
print_resource(os, *shader_input, res);
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(res);
|
||||
print_resource(os, location, res);
|
||||
}
|
||||
|
||||
static void print_resource_alias(std::ostream &os, const ShaderCreateInfo::Resource &res)
|
||||
|
@ -860,10 +856,10 @@ static VkDescriptorType descriptor_type(const shader::ShaderCreateInfo::Resource
|
|||
}
|
||||
|
||||
static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding(
|
||||
const ShaderInput &shader_input, const shader::ShaderCreateInfo::Resource &resource)
|
||||
const VKDescriptorSet::Location location, const shader::ShaderCreateInfo::Resource &resource)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding binding = {};
|
||||
binding.binding = shader_input.location;
|
||||
binding.binding = location;
|
||||
binding.descriptorType = descriptor_type(resource);
|
||||
binding.descriptorCount = 1;
|
||||
binding.stageFlags = VK_SHADER_STAGE_ALL;
|
||||
|
@ -878,13 +874,8 @@ static void add_descriptor_set_layout_bindings(
|
|||
Vector<VkDescriptorSetLayoutBinding> &r_bindings)
|
||||
{
|
||||
for (const shader::ShaderCreateInfo::Resource &resource : resources) {
|
||||
const ShaderInput *shader_input = interface.shader_input_get(resource);
|
||||
if (shader_input == nullptr) {
|
||||
BLI_assert_msg(shader_input, "Cannot find shader input for resource.");
|
||||
continue;
|
||||
}
|
||||
|
||||
r_bindings.append(create_descriptor_set_layout_binding(*shader_input, resource));
|
||||
const VKDescriptorSet::Location location = interface.descriptor_set_location(resource);
|
||||
r_bindings.append(create_descriptor_set_layout_binding(location, resource));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1033,12 +1024,6 @@ std::string VKShader::vertex_interface_declare(const shader::ShaderCreateInfo &i
|
|||
ss << "layout(location = " << attr.index << ") ";
|
||||
ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
|
||||
}
|
||||
/* NOTE(D4490): Fix a bug where shader without any vertex attributes do not behave correctly.
|
||||
*/
|
||||
if (GPU_type_matches_ex(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL) &&
|
||||
info.vertex_inputs_.is_empty()) {
|
||||
ss << "in float gpu_dummy_workaround;\n";
|
||||
}
|
||||
ss << "\n/* Interfaces. */\n";
|
||||
int location = 0;
|
||||
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
|
||||
|
|
|
@ -41,7 +41,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
}
|
||||
}
|
||||
/* Make sure that the image slots don't overlap with the sampler slots.*/
|
||||
image_offset_ += 1;
|
||||
image_offset_++;
|
||||
|
||||
int32_t input_tot_len = ubo_len_ + uniform_len_ + ssbo_len_;
|
||||
inputs_ = static_cast<ShaderInput *>(
|
||||
|
@ -51,14 +51,11 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
name_buffer_ = (char *)MEM_mallocN(info.interface_names_size_, "name_buffer");
|
||||
uint32_t name_buffer_offset = 0;
|
||||
|
||||
int location = 0;
|
||||
|
||||
/* Uniform blocks */
|
||||
for (const ShaderCreateInfo::Resource &res : all_resources) {
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
|
||||
copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot;
|
||||
input->location = input->binding = res.slot;
|
||||
input++;
|
||||
}
|
||||
}
|
||||
|
@ -67,14 +64,12 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
for (const ShaderCreateInfo::Resource &res : all_resources) {
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) {
|
||||
copy_input_name(input, res.sampler.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot;
|
||||
input->location = input->binding = res.slot;
|
||||
input++;
|
||||
}
|
||||
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
|
||||
copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot + image_offset_;
|
||||
input->location = input->binding = res.slot + image_offset_;
|
||||
input++;
|
||||
}
|
||||
}
|
||||
|
@ -83,13 +78,57 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
for (const ShaderCreateInfo::Resource &res : all_resources) {
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) {
|
||||
copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot;
|
||||
input->location = input->binding = res.slot;
|
||||
input++;
|
||||
}
|
||||
}
|
||||
|
||||
sort_inputs();
|
||||
|
||||
/* Determine the descriptor set locations after the inputs have been sorted.*/
|
||||
descriptor_set_locations_ = Array<VKDescriptorSet::Location>(input_tot_len);
|
||||
uint32_t descriptor_set_location = 0;
|
||||
for (ShaderCreateInfo::Resource &res : all_resources) {
|
||||
const ShaderInput *input = shader_input_get(res);
|
||||
descriptor_set_location_update(input, descriptor_set_location++);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t shader_input_index(const ShaderInput *shader_inputs,
|
||||
const ShaderInput *shader_input)
|
||||
{
|
||||
int32_t index = (shader_input - shader_inputs);
|
||||
return index;
|
||||
}
|
||||
|
||||
void VKShaderInterface::descriptor_set_location_update(const ShaderInput *shader_input,
|
||||
const VKDescriptorSet::Location location)
|
||||
{
|
||||
int32_t index = shader_input_index(inputs_, shader_input);
|
||||
descriptor_set_locations_[index] = location;
|
||||
}
|
||||
|
||||
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
||||
const ShaderInput *shader_input) const
|
||||
{
|
||||
int32_t index = shader_input_index(inputs_, shader_input);
|
||||
return descriptor_set_locations_[index];
|
||||
}
|
||||
|
||||
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource &resource) const
|
||||
{
|
||||
const ShaderInput *shader_input = shader_input_get(resource);
|
||||
BLI_assert(shader_input);
|
||||
return descriptor_set_location(shader_input);
|
||||
}
|
||||
|
||||
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const
|
||||
{
|
||||
const ShaderInput *shader_input = shader_input_get(bind_type, binding);
|
||||
BLI_assert(shader_input);
|
||||
return descriptor_set_location(shader_input);
|
||||
}
|
||||
|
||||
const ShaderInput *VKShaderInterface::shader_input_get(
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_array.hh"
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
#include "gpu_shader_interface.hh"
|
||||
|
||||
#include "vk_descriptor_set.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
class VKShaderInterface : public ShaderInterface {
|
||||
private:
|
||||
|
@ -21,11 +25,19 @@ class VKShaderInterface : public ShaderInterface {
|
|||
* overlapping.
|
||||
*/
|
||||
uint32_t image_offset_ = 0;
|
||||
Array<VKDescriptorSet::Location> descriptor_set_locations_;
|
||||
|
||||
public:
|
||||
VKShaderInterface() = default;
|
||||
|
||||
void init(const shader::ShaderCreateInfo &info);
|
||||
|
||||
const VKDescriptorSet::Location descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource &resource) const;
|
||||
const VKDescriptorSet::Location descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Retrieve the shader input for the given resource.
|
||||
*
|
||||
|
@ -35,5 +47,9 @@ class VKShaderInterface : public ShaderInterface {
|
|||
const ShaderInput *shader_input_get(const shader::ShaderCreateInfo::Resource &resource) const;
|
||||
const ShaderInput *shader_input_get(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
|
||||
const VKDescriptorSet::Location descriptor_set_location(const ShaderInput *shader_input) const;
|
||||
void descriptor_set_location_update(const ShaderInput *shader_input,
|
||||
const VKDescriptorSet::Location location);
|
||||
};
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
|
|
@ -34,9 +34,9 @@ void VKStorageBuffer::bind(int slot)
|
|||
}
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot);
|
||||
shader->pipeline_get().descriptor_set_get().bind(*this, shader_input);
|
||||
shader->pipeline_get().descriptor_set_get().bind(*this, location);
|
||||
}
|
||||
|
||||
void VKStorageBuffer::unbind()
|
||||
|
|
|
@ -227,8 +227,9 @@ void VKTexture::image_bind(int binding)
|
|||
}
|
||||
VKContext &context = *VKContext::get();
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
VKDescriptorSet::Location location(shader->interface_get().shader_input_get(
|
||||
shader::ShaderCreateInfo::Resource::BindType::IMAGE, binding));
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::IMAGE, binding);
|
||||
shader->pipeline_get().descriptor_set_get().image_bind(*this, location);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ void VKVertexBuffer::bind_as_ssbo(uint binding)
|
|||
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, shader_input);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
|
||||
}
|
||||
|
||||
void VKVertexBuffer::bind_as_texture(uint /*binding*/)
|
||||
|
|
|
@ -491,6 +491,8 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
|||
}
|
||||
BKE_id_attributes_active_color_set(
|
||||
&me->id, CustomData_get_layer_name(&me->ldata, CD_PROP_BYTE_COLOR, 0));
|
||||
BKE_id_attributes_default_color_set(
|
||||
&me->id, CustomData_get_layer_name(&me->ldata, CD_PROP_BYTE_COLOR, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -475,12 +475,19 @@ static USDPrimReader *get_usd_reader(CacheReader *reader,
|
|||
return usd_reader;
|
||||
}
|
||||
|
||||
USDMeshReadParams create_mesh_read_params(const double motion_sample_time, const int read_flags)
|
||||
{
|
||||
USDMeshReadParams params = {};
|
||||
params.motion_sample_time = motion_sample_time;
|
||||
params.read_flags = read_flags;
|
||||
return params;
|
||||
}
|
||||
|
||||
struct Mesh *USD_read_mesh(struct CacheReader *reader,
|
||||
struct Object *ob,
|
||||
struct Mesh *existing_mesh,
|
||||
const double time,
|
||||
const char **err_str,
|
||||
const int read_flag)
|
||||
const USDMeshReadParams params,
|
||||
const char **err_str)
|
||||
{
|
||||
USDGeomReader *usd_reader = dynamic_cast<USDGeomReader *>(get_usd_reader(reader, ob, err_str));
|
||||
|
||||
|
@ -488,7 +495,7 @@ struct Mesh *USD_read_mesh(struct CacheReader *reader,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return usd_reader->read_mesh(existing_mesh, time, read_flag, err_str);
|
||||
return usd_reader->read_mesh(existing_mesh, params, err_str);
|
||||
}
|
||||
|
||||
bool USD_mesh_topology_changed(CacheReader *reader,
|
||||
|
|
|
@ -162,8 +162,7 @@ void USDCurvesReader::read_curve_sample(Curve *cu, const double motionSampleTime
|
|||
}
|
||||
|
||||
Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
|
||||
const double motionSampleTime,
|
||||
const int /* read_flag */,
|
||||
const USDMeshReadParams params,
|
||||
const char ** /* err_str */)
|
||||
{
|
||||
if (!curve_prim_) {
|
||||
|
@ -176,11 +175,11 @@ Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
|
|||
|
||||
pxr::VtIntArray usdCounts;
|
||||
|
||||
vertexAttr.Get(&usdCounts, motionSampleTime);
|
||||
vertexAttr.Get(&usdCounts, params.motion_sample_time);
|
||||
int num_subcurves = usdCounts.size();
|
||||
|
||||
pxr::VtVec3fArray usdPoints;
|
||||
pointsAttr.Get(&usdPoints, motionSampleTime);
|
||||
pointsAttr.Get(&usdPoints, params.motion_sample_time);
|
||||
|
||||
int vertex_idx = 0;
|
||||
int curve_idx;
|
||||
|
@ -204,7 +203,7 @@ Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
|
|||
|
||||
if (!same_topology) {
|
||||
BKE_nurbList_free(&curve->nurb);
|
||||
read_curve_sample(curve, motionSampleTime);
|
||||
read_curve_sample(curve, params.motion_sample_time);
|
||||
}
|
||||
else {
|
||||
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
|
||||
|
|
|
@ -36,8 +36,7 @@ class USDCurvesReader : public USDGeomReader {
|
|||
void read_curve_sample(Curve *cu, double motionSampleTime);
|
||||
|
||||
Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
USDMeshReadParams params,
|
||||
const char **err_str) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ class USDGeomReader : public USDXformReader {
|
|||
}
|
||||
|
||||
virtual Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
USDMeshReadParams params,
|
||||
const char **err_str) = 0;
|
||||
|
||||
virtual bool topology_changed(const Mesh * /* existing_mesh */, double /* motionSampleTime */)
|
||||
|
|
|
@ -194,8 +194,9 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
|
|||
Mesh *mesh = (Mesh *)object_->data;
|
||||
|
||||
is_initial_load_ = true;
|
||||
Mesh *read_mesh = this->read_mesh(
|
||||
mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
|
||||
const USDMeshReadParams params = create_mesh_read_params(motionSampleTime, import_params_.mesh_read_flag);
|
||||
|
||||
Mesh *read_mesh = this->read_mesh(mesh, params, nullptr);
|
||||
|
||||
is_initial_load_ = false;
|
||||
if (read_mesh != mesh) {
|
||||
|
@ -222,7 +223,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
|
|||
}
|
||||
|
||||
USDXformReader::read_object_data(bmain, motionSampleTime);
|
||||
}
|
||||
} // namespace blender::io::usd
|
||||
|
||||
bool USDMeshReader::valid() const
|
||||
{
|
||||
|
@ -767,8 +768,7 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
|
|||
}
|
||||
|
||||
Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
||||
const double motionSampleTime,
|
||||
const int read_flag,
|
||||
const USDMeshReadParams params,
|
||||
const char ** /* err_str */)
|
||||
{
|
||||
if (!mesh_prim_) {
|
||||
|
@ -785,7 +785,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
std::vector<pxr::TfToken> uv_tokens;
|
||||
|
||||
/* Currently we only handle UV primvars. */
|
||||
if (read_flag & MOD_MESHSEQ_READ_UV) {
|
||||
if (params.read_flags & MOD_MESHSEQ_READ_UV) {
|
||||
|
||||
std::vector<pxr::UsdGeomPrimvar> primvars = primvarsAPI.GetPrimvars();
|
||||
|
||||
|
@ -838,9 +838,9 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
* the topology is consistent, as in the Alembic importer. */
|
||||
|
||||
ImportSettings settings;
|
||||
settings.read_flag |= read_flag;
|
||||
settings.read_flag |= params.read_flags;
|
||||
|
||||
if (topology_changed(existing_mesh, motionSampleTime)) {
|
||||
if (topology_changed(existing_mesh, params.motion_sample_time)) {
|
||||
new_mesh = true;
|
||||
active_mesh = BKE_mesh_new_nomain_from_template(
|
||||
existing_mesh, positions_.size(), 0, 0, face_indices_.size(), face_counts_.size());
|
||||
|
@ -850,7 +850,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
}
|
||||
}
|
||||
|
||||
read_mesh_sample(&settings, active_mesh, motionSampleTime, new_mesh || is_initial_load_);
|
||||
read_mesh_sample(&settings, active_mesh, params.motion_sample_time, new_mesh || is_initial_load_);
|
||||
|
||||
if (new_mesh) {
|
||||
/* Here we assume that the number of materials doesn't change, i.e. that
|
||||
|
@ -862,7 +862,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
|
|||
bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write();
|
||||
bke::SpanAttributeWriter<int> material_indices =
|
||||
attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);
|
||||
assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map);
|
||||
assign_facesets_to_material_indices(params.motion_sample_time, material_indices.span, &mat_map);
|
||||
material_indices.finish();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,7 @@ class USDMeshReader : public USDGeomReader {
|
|||
void read_object_data(Main *bmain, double motionSampleTime) override;
|
||||
|
||||
struct Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
USDMeshReadParams params,
|
||||
const char **err_str) override;
|
||||
|
||||
bool topology_changed(const Mesh *existing_mesh, double motionSampleTime) override;
|
||||
|
|
|
@ -165,8 +165,7 @@ void USDNurbsReader::read_curve_sample(Curve *cu, const double motionSampleTime)
|
|||
}
|
||||
|
||||
Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
|
||||
const double motionSampleTime,
|
||||
const int /* read_flag */,
|
||||
const USDMeshReadParams params,
|
||||
const char ** /* err_str */)
|
||||
{
|
||||
pxr::UsdGeomCurves curve_prim_(prim_);
|
||||
|
@ -177,11 +176,11 @@ Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
|
|||
|
||||
pxr::VtIntArray usdCounts;
|
||||
|
||||
vertexAttr.Get(&usdCounts, motionSampleTime);
|
||||
vertexAttr.Get(&usdCounts, params.motion_sample_time);
|
||||
int num_subcurves = usdCounts.size();
|
||||
|
||||
pxr::VtVec3fArray usdPoints;
|
||||
pointsAttr.Get(&usdPoints, motionSampleTime);
|
||||
pointsAttr.Get(&usdPoints, params.motion_sample_time);
|
||||
|
||||
int vertex_idx = 0;
|
||||
int curve_idx;
|
||||
|
@ -205,7 +204,7 @@ Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
|
|||
|
||||
if (!same_topology) {
|
||||
BKE_nurbList_free(&curve->nurb);
|
||||
read_curve_sample(curve, motionSampleTime);
|
||||
read_curve_sample(curve, params.motion_sample_time);
|
||||
}
|
||||
else {
|
||||
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
|
||||
|
|
|
@ -36,8 +36,7 @@ class USDNurbsReader : public USDGeomReader {
|
|||
void read_curve_sample(Curve *cu, double motionSampleTime);
|
||||
|
||||
Mesh *read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int read_flag,
|
||||
USDMeshReadParams params,
|
||||
const char **err_str) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -45,9 +45,10 @@ void USDShapeReader::create_object(Main *bmain, double /*motionSampleTime*/)
|
|||
|
||||
void USDShapeReader::read_object_data(Main *bmain, double motionSampleTime)
|
||||
{
|
||||
const USDMeshReadParams params = create_mesh_read_params(motionSampleTime,
|
||||
import_params_.mesh_read_flag);
|
||||
Mesh *mesh = (Mesh *)object_->data;
|
||||
Mesh *read_mesh = this->read_mesh(
|
||||
mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
|
||||
Mesh *read_mesh = this->read_mesh(mesh, params, nullptr);
|
||||
|
||||
if (read_mesh != mesh) {
|
||||
BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_);
|
||||
|
@ -124,8 +125,7 @@ bool USDShapeReader::read_mesh_values(double motionSampleTime,
|
|||
}
|
||||
|
||||
Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int /*read_flag*/,
|
||||
const USDMeshReadParams params,
|
||||
const char ** /*err_str*/)
|
||||
{
|
||||
pxr::VtIntArray face_indices;
|
||||
|
@ -136,7 +136,8 @@ Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh,
|
|||
}
|
||||
|
||||
/* Should have a good set of data by this point-- copy over. */
|
||||
Mesh *active_mesh = mesh_from_prim(existing_mesh, motionSampleTime, face_indices, face_counts);
|
||||
Mesh *active_mesh = mesh_from_prim(
|
||||
existing_mesh, params.motion_sample_time, face_indices, face_counts);
|
||||
if (active_mesh == existing_mesh) {
|
||||
return existing_mesh;
|
||||
}
|
||||
|
|
|
@ -48,8 +48,7 @@ class USDShapeReader : public USDGeomReader {
|
|||
void create_object(Main *bmain, double /*motionSampleTime*/) override;
|
||||
void read_object_data(Main *bmain, double motionSampleTime) override;
|
||||
Mesh *read_mesh(Mesh *existing_mesh,
|
||||
double motionSampleTime,
|
||||
int /*read_flag*/,
|
||||
USDMeshReadParams params,
|
||||
const char ** /*err_str*/) override;
|
||||
bool is_time_varying();
|
||||
|
||||
|
|
|
@ -86,6 +86,16 @@ struct USDImportParams {
|
|||
bool import_all_materials;
|
||||
};
|
||||
|
||||
/* This struct is in place to store the mesh sequence parameters needed when reading a data from a
|
||||
* usd file for the mesh sequence cache.
|
||||
*/
|
||||
typedef struct USDMeshReadParams {
|
||||
double motion_sample_time; /* USD TimeCode in frames. */
|
||||
int read_flags; /* MOD_MESHSEQ_xxx value that is set from MeshSeqCacheModifierData.read_flag. */
|
||||
} USDMeshReadParams;
|
||||
|
||||
USDMeshReadParams create_mesh_read_params(double motion_sample_time, int read_flags);
|
||||
|
||||
/* The USD_export takes a as_background_job parameter, and returns a boolean.
|
||||
*
|
||||
* When as_background_job=true, returns false immediately after scheduling
|
||||
|
@ -121,9 +131,8 @@ void USD_get_transform(struct CacheReader *reader, float r_mat[4][4], float time
|
|||
struct Mesh *USD_read_mesh(struct CacheReader *reader,
|
||||
struct Object *ob,
|
||||
struct Mesh *existing_mesh,
|
||||
double time,
|
||||
const char **err_str,
|
||||
int read_flag);
|
||||
USDMeshReadParams params,
|
||||
const char **err_str);
|
||||
|
||||
bool USD_mesh_topology_changed(struct CacheReader *reader,
|
||||
const struct Object *ob,
|
||||
|
|
|
@ -401,6 +401,7 @@ void MeshFromGeometry::create_colors(Mesh *mesh)
|
|||
CustomDataLayer *color_layer = BKE_id_attribute_new(
|
||||
&mesh->id, "Color", CD_PROP_COLOR, ATTR_DOMAIN_POINT, nullptr);
|
||||
BKE_id_attributes_active_color_set(&mesh->id, color_layer->name);
|
||||
BKE_id_attributes_default_color_set(&mesh->id, color_layer->name);
|
||||
float4 *colors = (float4 *)color_layer->data;
|
||||
int offset = mesh_geometry_.vertex_index_min_ - block.start_vertex_index;
|
||||
for (int i = 0, n = mesh_geometry_.get_vertex_count(); i != n; ++i) {
|
||||
|
|
|
@ -2292,6 +2292,13 @@ static PointerRNA rna_Mesh_vertex_color_new(struct Mesh *me,
|
|||
if (index != -1) {
|
||||
ldata = rna_mesh_ldata_helper(me);
|
||||
cdl = &ldata->layers[CustomData_get_layer_index_n(ldata, CD_PROP_BYTE_COLOR, index)];
|
||||
|
||||
if (!me->active_color_attribute) {
|
||||
me->active_color_attribute = BLI_strdup(cdl->name);
|
||||
}
|
||||
if (!me->default_color_attribute) {
|
||||
me->default_color_attribute = BLI_strdup(cdl->name);
|
||||
}
|
||||
}
|
||||
|
||||
RNA_pointer_create(&me->id, &RNA_MeshLoopColorLayer, cdl, &ptr);
|
||||
|
|
|
@ -245,12 +245,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
|||
# endif
|
||||
break;
|
||||
}
|
||||
case CACHEFILE_TYPE_USD:
|
||||
case CACHEFILE_TYPE_USD: {
|
||||
# ifdef WITH_USD
|
||||
result = USD_read_mesh(
|
||||
mcmd->reader, ctx->object, mesh, time * FPS, &err_str, mcmd->read_flag);
|
||||
const USDMeshReadParams params = create_mesh_read_params(time * FPS, mcmd->read_flag);
|
||||
result = USD_read_mesh(mcmd->reader, ctx->object, mesh, params, &err_str);
|
||||
# endif
|
||||
break;
|
||||
}
|
||||
case CACHE_FILE_TYPE_INVALID:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -834,15 +834,21 @@ static void initialize_group_input(NodesModifierData &nmd,
|
|||
}
|
||||
}
|
||||
|
||||
static const lf::FunctionNode &find_viewer_lf_node(const bNode &viewer_bnode)
|
||||
static const lf::FunctionNode *find_viewer_lf_node(const bNode &viewer_bnode)
|
||||
{
|
||||
return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree())
|
||||
->mapping.viewer_node_map.lookup(&viewer_bnode);
|
||||
if (const blender::nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
|
||||
blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree())) {
|
||||
return lf_graph_info->mapping.viewer_node_map.lookup_default(&viewer_bnode, nullptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static const lf::FunctionNode &find_group_lf_node(const bNode &group_bnode)
|
||||
static const lf::FunctionNode *find_group_lf_node(const bNode &group_bnode)
|
||||
{
|
||||
return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree())
|
||||
->mapping.group_node_map.lookup(&group_bnode);
|
||||
if (const blender::nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
|
||||
blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree())) {
|
||||
return lf_graph_info->mapping.group_node_map.lookup_default(&group_bnode, nullptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void find_side_effect_nodes_for_viewer_path(
|
||||
|
@ -888,15 +894,22 @@ static void find_side_effect_nodes_for_viewer_path(
|
|||
if (found_viewer_node == nullptr) {
|
||||
return;
|
||||
}
|
||||
const lf::FunctionNode *lf_viewer_node = find_viewer_lf_node(*found_viewer_node);
|
||||
if (lf_viewer_node == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not only mark the viewer node as having side effects, but also all group nodes it is contained
|
||||
* in. */
|
||||
r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(),
|
||||
&find_viewer_lf_node(*found_viewer_node));
|
||||
r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), lf_viewer_node);
|
||||
compute_context_builder.pop();
|
||||
while (!compute_context_builder.is_empty()) {
|
||||
r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(),
|
||||
&find_group_lf_node(*group_node_stack.pop()));
|
||||
const lf::FunctionNode *lf_group_node = find_group_lf_node(*group_node_stack.pop());
|
||||
if (lf_group_node == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), lf_group_node);
|
||||
compute_context_builder.pop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,31 @@ static Array<float> accumulated_lengths_curve_domain(const bke::CurvesGeometry &
|
|||
return lengths;
|
||||
}
|
||||
|
||||
static Array<float> calculate_curve_parameters(const bke::CurvesGeometry &curves)
|
||||
{
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
Array<float> lengths = accumulated_lengths_curve_domain(curves);
|
||||
|
||||
const int last_index = curves.curves_num() - 1;
|
||||
const float total_length = lengths.last() + curves.evaluated_length_total_for_curve(
|
||||
last_index, cyclic[last_index]);
|
||||
if (total_length > 0.0f) {
|
||||
const float factor = 1.0f / total_length;
|
||||
for (float &value : lengths) {
|
||||
value *= factor;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* It is arbitrary what to do in those rare cases when all the points are
|
||||
* in the same position. In this case we are just arbitrarily giving a valid
|
||||
* value in the range based on the curve index. */
|
||||
for (const int i : lengths.index_range()) {
|
||||
lengths[i] = i / (lengths.size() - 1.0f);
|
||||
}
|
||||
}
|
||||
return lengths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of each control point along each curve, starting at zero for the first point.
|
||||
* Importantly, this is different than the length at each evaluated point. The implementation is
|
||||
|
@ -55,7 +80,9 @@ static Array<float> accumulated_lengths_curve_domain(const bke::CurvesGeometry &
|
|||
* - NURBS Curves: Treat the control points as if they were a poly curve, because there
|
||||
* is no obvious mapping from each control point to a specific evaluated point.
|
||||
*/
|
||||
static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves)
|
||||
static Array<float> calculate_point_lengths(
|
||||
const bke::CurvesGeometry &curves,
|
||||
const FunctionRef<void(MutableSpan<float>, float)> postprocess_lengths_for_curve)
|
||||
{
|
||||
curves.ensure_evaluated_lengths();
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
|
@ -68,26 +95,31 @@ static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves)
|
|||
threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
|
||||
for (const int i_curve : range) {
|
||||
const IndexRange points = points_by_curve[i_curve];
|
||||
const Span<float> evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve,
|
||||
cyclic[i_curve]);
|
||||
const bool is_cyclic = cyclic[i_curve];
|
||||
const Span<float> evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve, is_cyclic);
|
||||
MutableSpan<float> lengths = result.as_mutable_span().slice(points);
|
||||
lengths.first() = 0.0f;
|
||||
|
||||
float total;
|
||||
switch (types[i_curve]) {
|
||||
case CURVE_TYPE_CATMULL_ROM: {
|
||||
const int resolution = resolutions[i_curve];
|
||||
for (const int i : IndexRange(points.size()).drop_back(1)) {
|
||||
lengths[i + 1] = evaluated_lengths[resolution * (i + 1) - 1];
|
||||
}
|
||||
total = evaluated_lengths.last();
|
||||
break;
|
||||
}
|
||||
case CURVE_TYPE_POLY:
|
||||
lengths.drop_front(1).copy_from(evaluated_lengths.take_front(lengths.size() - 1));
|
||||
total = evaluated_lengths.last();
|
||||
break;
|
||||
case CURVE_TYPE_BEZIER: {
|
||||
const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
|
||||
for (const int i : IndexRange(points.size()).drop_back(1)) {
|
||||
lengths[i + 1] = evaluated_lengths[offsets[i + 1] - 1];
|
||||
}
|
||||
total = evaluated_lengths.last();
|
||||
break;
|
||||
}
|
||||
case CURVE_TYPE_NURBS: {
|
||||
|
@ -98,115 +130,44 @@ static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves)
|
|||
length += math::distance(positions[i], positions[i + 1]);
|
||||
}
|
||||
lengths.last() = length;
|
||||
if (is_cyclic) {
|
||||
length += math::distance(positions.first(), positions.last());
|
||||
}
|
||||
total = length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
postprocess_lengths_for_curve(lengths, total);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static VArray<float> construct_curve_parameter_varray(const bke::CurvesGeometry &curves,
|
||||
const IndexMask /*mask*/,
|
||||
const eAttrDomain domain)
|
||||
static void convert_lengths_to_factors(MutableSpan<float> lengths, const float total_curve_length)
|
||||
{
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Array<float> result = curve_length_point_domain(curves);
|
||||
MutableSpan<float> lengths = result.as_mutable_span();
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
|
||||
threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
|
||||
for (const int i_curve : range) {
|
||||
MutableSpan<float> curve_lengths = lengths.slice(points_by_curve[i_curve]);
|
||||
const float total_length = curve_lengths.last();
|
||||
if (total_length > 0.0f) {
|
||||
const float factor = 1.0f / total_length;
|
||||
for (float &value : curve_lengths) {
|
||||
value *= factor;
|
||||
}
|
||||
}
|
||||
else if (curve_lengths.size() == 1) {
|
||||
/* The curve is a single point. */
|
||||
curve_lengths[0] = 0.0f;
|
||||
}
|
||||
else {
|
||||
/* It is arbitrary what to do in those rare cases when all the points are
|
||||
* in the same position. In this case we are just arbitrarily giving a valid
|
||||
* value in the range based on the point index. */
|
||||
for (const int i : curve_lengths.index_range()) {
|
||||
curve_lengths[i] = i / (curve_lengths.size() - 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return VArray<float>::ForContainer(std::move(result));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
Array<float> lengths = accumulated_lengths_curve_domain(curves);
|
||||
|
||||
const int last_index = curves.curves_num() - 1;
|
||||
const float total_length = lengths.last() + curves.evaluated_length_total_for_curve(
|
||||
last_index, cyclic[last_index]);
|
||||
if (total_length > 0.0f) {
|
||||
const float factor = 1.0f / total_length;
|
||||
for (float &value : lengths) {
|
||||
value *= factor;
|
||||
}
|
||||
if (total_curve_length > 0.0f) {
|
||||
const float factor = 1.0f / total_curve_length;
|
||||
for (float &value : lengths.drop_front(1)) {
|
||||
value *= factor;
|
||||
}
|
||||
else {
|
||||
/* It is arbitrary what to do in those rare cases when all the points are
|
||||
* in the same position. In this case we are just arbitrarily giving a valid
|
||||
* value in the range based on the curve index. */
|
||||
for (const int i : lengths.index_range()) {
|
||||
lengths[i] = i / (lengths.size() - 1.0f);
|
||||
}
|
||||
}
|
||||
else if (lengths.size() == 1) {
|
||||
/* The curve is a single point. */
|
||||
lengths[0] = 0.0f;
|
||||
}
|
||||
else {
|
||||
/* It is arbitrary what to do in those rare cases when all the
|
||||
* points are in the same position. In this case we are just
|
||||
* arbitrarily giving a valid
|
||||
* value in the range based on the point index. */
|
||||
for (const int i : lengths.index_range()) {
|
||||
lengths[i] = i / (lengths.size() - 1.0f);
|
||||
}
|
||||
return VArray<float>::ForContainer(std::move(lengths));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static VArray<float> construct_curve_length_parameter_varray(const bke::CurvesGeometry &curves,
|
||||
const IndexMask /*mask*/,
|
||||
const eAttrDomain domain)
|
||||
static Array<float> calculate_point_parameters(const bke::CurvesGeometry &curves)
|
||||
{
|
||||
curves.ensure_evaluated_lengths();
|
||||
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Array<float> lengths = curve_length_point_domain(curves);
|
||||
return VArray<float>::ForContainer(std::move(lengths));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
Array<float> lengths = accumulated_lengths_curve_domain(curves);
|
||||
return VArray<float>::ForContainer(std::move(lengths));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static VArray<int> construct_index_on_spline_varray(const bke::CurvesGeometry &curves,
|
||||
const IndexMask /*mask*/,
|
||||
const eAttrDomain domain)
|
||||
{
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Array<int> result(curves.points_num());
|
||||
MutableSpan<int> span = result.as_mutable_span();
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
|
||||
for (const int i_curve : range) {
|
||||
MutableSpan<int> indices = span.slice(points_by_curve[i_curve]);
|
||||
for (const int i : indices.index_range()) {
|
||||
indices[i] = i;
|
||||
}
|
||||
}
|
||||
});
|
||||
return VArray<int>::ForContainer(std::move(result));
|
||||
}
|
||||
return {};
|
||||
return calculate_point_lengths(curves, convert_lengths_to_factors);
|
||||
}
|
||||
|
||||
class CurveParameterFieldInput final : public bke::CurvesFieldInput {
|
||||
|
@ -218,14 +179,21 @@ class CurveParameterFieldInput final : public bke::CurvesFieldInput {
|
|||
|
||||
GVArray get_varray_for_context(const bke::CurvesGeometry &curves,
|
||||
const eAttrDomain domain,
|
||||
IndexMask mask) const final
|
||||
const IndexMask /*mask*/) const final
|
||||
{
|
||||
return construct_curve_parameter_varray(curves, mask, domain);
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return VArray<float>::ForContainer(calculate_point_parameters(curves));
|
||||
case ATTR_DOMAIN_CURVE:
|
||||
return VArray<float>::ForContainer(calculate_curve_parameters(curves));
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
{
|
||||
/* Some random constant hash. */
|
||||
return 29837456298;
|
||||
}
|
||||
|
||||
|
@ -245,14 +213,22 @@ class CurveLengthParameterFieldInput final : public bke::CurvesFieldInput {
|
|||
|
||||
GVArray get_varray_for_context(const bke::CurvesGeometry &curves,
|
||||
const eAttrDomain domain,
|
||||
IndexMask mask) const final
|
||||
const IndexMask /*mask*/) const final
|
||||
{
|
||||
return construct_curve_length_parameter_varray(curves, mask, domain);
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return VArray<float>::ForContainer(calculate_point_lengths(
|
||||
curves, [](MutableSpan<float> /*lengths*/, const float /*total*/) {}));
|
||||
case ATTR_DOMAIN_CURVE:
|
||||
return VArray<float>::ForContainer(accumulated_lengths_curve_domain(curves));
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
{
|
||||
/* Some random constant hash. */
|
||||
return 345634563454;
|
||||
}
|
||||
|
||||
|
@ -271,14 +247,26 @@ class IndexOnSplineFieldInput final : public bke::CurvesFieldInput {
|
|||
|
||||
GVArray get_varray_for_context(const bke::CurvesGeometry &curves,
|
||||
const eAttrDomain domain,
|
||||
IndexMask mask) const final
|
||||
const IndexMask /*mask*/) const final
|
||||
{
|
||||
return construct_index_on_spline_varray(curves, mask, domain);
|
||||
if (domain != ATTR_DOMAIN_POINT) {
|
||||
return {};
|
||||
}
|
||||
Array<int> result(curves.points_num());
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
|
||||
for (const int i_curve : range) {
|
||||
MutableSpan<int> indices = result.as_mutable_span().slice(points_by_curve[i_curve]);
|
||||
for (const int i : indices.index_range()) {
|
||||
indices[i] = i;
|
||||
}
|
||||
}
|
||||
});
|
||||
return VArray<int>::ForContainer(std::move(result));
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
{
|
||||
/* Some random constant hash. */
|
||||
return 4536246522;
|
||||
}
|
||||
|
||||
|
|
|
@ -3669,22 +3669,26 @@ static void wm_paintcursor_test(bContext *C, const wmEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEvent *event)
|
||||
static eHandlerActionFlag wm_event_drag_and_drop_test(wmWindowManager *wm,
|
||||
wmWindow *win,
|
||||
wmEvent *event)
|
||||
{
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
|
||||
if (BLI_listbase_is_empty(&wm->drags)) {
|
||||
return;
|
||||
return WM_HANDLER_CONTINUE;
|
||||
}
|
||||
|
||||
if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) {
|
||||
screen->do_draw_drag = true;
|
||||
}
|
||||
else if (event->type == EVT_ESCKEY) {
|
||||
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
|
||||
wm_drags_exit(wm, win);
|
||||
WM_drag_free_list(&wm->drags);
|
||||
|
||||
screen->do_draw_drag = true;
|
||||
|
||||
return WM_HANDLER_BREAK;
|
||||
}
|
||||
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
|
||||
event->type = EVT_DROP;
|
||||
|
@ -3703,6 +3707,8 @@ static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEv
|
|||
/* Restore cursor (disabled, see `wm_dragdrop.cc`) */
|
||||
// WM_cursor_modal_restore(win);
|
||||
}
|
||||
|
||||
return WM_HANDLER_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4025,7 +4031,7 @@ void wm_event_do_handlers(bContext *C)
|
|||
}
|
||||
|
||||
/* Check dragging, creates new event or frees, adds draw tag. */
|
||||
wm_event_drag_and_drop_test(wm, win, event);
|
||||
action |= wm_event_drag_and_drop_test(wm, win, event);
|
||||
|
||||
if ((action & WM_HANDLER_BREAK) == 0) {
|
||||
/* NOTE: setting sub-window active should be done here,
|
||||
|
|
Loading…
Reference in New Issue