Attributes: Integrate implicit sharing with the attribute API #107059

Merged
Jacques Lucke merged 8 commits from HooglyBoogly/blender:implicit-sharing-attribute-api into main 2023-04-19 11:21:21 +02:00
14 changed files with 445 additions and 61 deletions
Showing only changes of commit 39314fe9d8 - Show all commits

View File

@ -335,18 +335,6 @@ if(WITH_CYCLES AND (WITH_CYCLES_DEVICE_ONEAPI OR (WITH_CYCLES_EMBREE AND EMBREE_
unset(_sycl_runtime_libraries)
endif()
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
if(WITH_CYCLES_ONEAPI_BINARIES)
set(cycles_kernel_oneapi_lib_suffix "_aot")
else()
set(cycles_kernel_oneapi_lib_suffix "_jit")
endif()
list(APPEND PLATFORM_BUNDLED_LIBRARIES
${CMAKE_CURRENT_BINARY_DIR}/intern/cycles/kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so
)
unset(cycles_kernel_oneapi_lib_suffix)
endif()
if(WITH_OPENVDB)
find_package(OpenVDB)
set_and_warn_library_found("OpenVDB" OPENVDB_FOUND WITH_OPENVDB)

View File

@ -1105,18 +1105,6 @@ if(WITH_CYCLES AND (WITH_CYCLES_DEVICE_ONEAPI OR (WITH_CYCLES_EMBREE AND EMBREE_
set(SYCL_LIBRARIES optimized ${SYCL_LIBRARY} debug ${SYCL_LIBRARY_DEBUG})
endif()
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
if(WITH_CYCLES_ONEAPI_BINARIES)
set(cycles_kernel_oneapi_lib_suffix "_aot")
else()
set(cycles_kernel_oneapi_lib_suffix "_jit")
endif()
list(APPEND PLATFORM_BUNDLED_LIBRARIES
${CMAKE_CURRENT_BINARY_DIR}/intern/cycles/kernel/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.dll
)
unset(cycles_kernel_oneapi_lib_suffix)
endif()
# Environment variables to run precompiled executables that needed libraries.
list(JOIN PLATFORM_BUNDLED_LIBRARY_DIRS ";" _library_paths)

View File

@ -907,13 +907,22 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
DEPENDS ${cycles_oneapi_kernel_sources})
endif()
# For the Cycles standalone put libraries next to the Cycles application.
if(NOT WITH_BLENDER)
if(WIN32)
delayed_install("" "${cycles_kernel_oneapi_lib}" ${CYCLES_INSTALL_PATH})
else()
delayed_install("" "${cycles_kernel_oneapi_lib}" ${CYCLES_INSTALL_PATH}/lib)
endif()
# For the Cycles standalone put libraries next to the Cycles application.
set(cycles_oneapi_target_path ${CYCLES_INSTALL_PATH})
else()
# For Blender put the libraries next to the Blender executable.
#
# Note that the installation path in the delayed_install is relative to the versioned folder,
# which means we need to go one level up.
set(cycles_oneapi_target_path "../")
endif()
# install dynamic libraries required at runtime
if(WIN32)
delayed_install("" "${cycles_kernel_oneapi_lib}" ${cycles_oneapi_target_path})
elseif(UNIX AND NOT APPLE)
delayed_install("" "${cycles_kernel_oneapi_lib}" ${cycles_oneapi_target_path}/lib)
endif()
add_custom_target(cycles_kernel_oneapi ALL DEPENDS ${cycles_kernel_oneapi_lib})

View File

@ -538,6 +538,7 @@ class FILEBROWSER_MT_context_menu(FileBrowserMenu, Menu):
layout.operator("file.next", text="Forward")
layout.operator("file.parent", text="Go to Parent")
layout.operator("file.refresh", text="Refresh")
layout.menu("FILEBROWSER_MT_operations_menu")
layout.separator()

View File

@ -171,7 +171,6 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
* if the stored type is the same as the attribute type.
*/
class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
using UpdateOnRead = void (*)(const void *owner);
using UpdateOnChange = void (*)(void *owner);
const eCustomDataType stored_type_;
const CustomDataAccessInfo custom_data_access_;

View File

@ -113,6 +113,33 @@ ENUM_OPERATORS(eFileAttributes, FILE_ATTR_HARDLINK);
/** \} */
/* -------------------------------------------------------------------- */
/** \name External File Operations
* \{ */
typedef enum FileExternalOperation {
FILE_EXTERNAL_OPERATION_OPEN = 0,
FILE_EXTERNAL_OPERATION_FOLDER_OPEN,
/* Following are Windows-only: */
FILE_EXTERNAL_OPERATION_EDIT,
FILE_EXTERNAL_OPERATION_NEW,
FILE_EXTERNAL_OPERATION_FIND,
FILE_EXTERNAL_OPERATION_SHOW,
FILE_EXTERNAL_OPERATION_PLAY,
FILE_EXTERNAL_OPERATION_BROWSE,
FILE_EXTERNAL_OPERATION_PREVIEW,
FILE_EXTERNAL_OPERATION_PRINT,
FILE_EXTERNAL_OPERATION_INSTALL,
FILE_EXTERNAL_OPERATION_RUNAS,
FILE_EXTERNAL_OPERATION_PROPERTIES,
FILE_EXTERNAL_OPERATION_FOLDER_FIND,
FILE_EXTERNAL_OPERATION_FOLDER_CMD,
} FileExternalOperation;
bool BLI_file_external_operation_supported(const char *filepath, FileExternalOperation operation);
bool BLI_file_external_operation_execute(const char *filepath, FileExternalOperation operation);
/* -------------------------------------------------------------------- */
/** \name Directories
* \{ */

View File

@ -89,6 +89,11 @@ bool BLI_windows_register_blend_extension(bool background);
void BLI_windows_get_default_root_dir(char root_dir[4]);
int BLI_windows_get_executable_dir(char *str);
/* ShellExecute Helpers. */
bool BLI_windows_external_operation_supported(const char *filepath, const char *operation);
bool BLI_windows_external_operation_execute(const char *filepath, const char *operation);
#ifdef __cplusplus
}
#endif

View File

@ -46,6 +46,71 @@
#include "BLI_sys_types.h" /* for intptr_t support */
#include "BLI_utildefines.h"
#ifdef WIN32
/* Text string used as the "verb" for Windows shell operations. */
static char *windows_operation_string(FileExternalOperation operation)
{
switch (operation) {
case FILE_EXTERNAL_OPERATION_OPEN:
return "open";
case FILE_EXTERNAL_OPERATION_FOLDER_OPEN:
return "open";
case FILE_EXTERNAL_OPERATION_EDIT:
return "edit";
case FILE_EXTERNAL_OPERATION_NEW:
return "new";
case FILE_EXTERNAL_OPERATION_FIND:
return "find";
case FILE_EXTERNAL_OPERATION_SHOW:
return "show";
case FILE_EXTERNAL_OPERATION_PLAY:
return "play";
case FILE_EXTERNAL_OPERATION_BROWSE:
return "browse";
case FILE_EXTERNAL_OPERATION_PREVIEW:
return "preview";
case FILE_EXTERNAL_OPERATION_PRINT:
return "print";
case FILE_EXTERNAL_OPERATION_INSTALL:
return "install";
case FILE_EXTERNAL_OPERATION_RUNAS:
return "runas";
case FILE_EXTERNAL_OPERATION_PROPERTIES:
return "properties";
case FILE_EXTERNAL_OPERATION_FOLDER_FIND:
return "find";
case FILE_EXTERNAL_OPERATION_FOLDER_CMD:
return "cmd";
}
BLI_assert_unreachable();
return "";
}
#endif
bool BLI_file_external_operation_supported(const char *filepath, FileExternalOperation operation)
{
#ifdef WIN32
char *opstring = windows_operation_string(operation);
return BLI_windows_external_operation_supported(filepath, opstring);
#else
return false;
#endif
}
bool BLI_file_external_operation_execute(const char *filepath, FileExternalOperation operation)
{
#ifdef WIN32
char *opstring = windows_operation_string(operation);
if (BLI_windows_external_operation_supported(filepath, opstring) &&
BLI_windows_external_operation_execute(filepath, opstring)) {
return true;
}
return false;
#else
return false;
#endif
}
size_t BLI_file_zstd_from_mem_at_pos(
void *buf, size_t len, FILE *file, size_t file_offset, int compression_level)
{

View File

@ -11,10 +11,12 @@
# include <conio.h>
# include <stdio.h>
# include <stdlib.h>
# include <shlwapi.h>
# include "MEM_guardedalloc.h"
# define WIN32_SKIP_HKEY_PROTECTION /* Need to use HKEY. */
# include "BLI_fileops.h"
# include "BLI_path_util.h"
# include "BLI_string.h"
# include "BLI_utildefines.h"
@ -178,6 +180,62 @@ bool BLI_windows_register_blend_extension(const bool background)
return true;
}
/* Check the registry to see if there is an operation association to a file
* extension. Extension *should almost always contain a dot like ".txt",
* but this does allow querying non - extensions *like "Directory", "Drive",
* "AllProtocols", etc - anything in Classes with a "shell" branch.
*/
static bool BLI_windows_file_operation_is_registered(const char *extension, const char *operation)
{
HKEY hKey;
HRESULT hr = AssocQueryKey(ASSOCF_INIT_IGNOREUNKNOWN,
ASSOCKEY_SHELLEXECCLASS,
(LPCTSTR)extension,
(LPCTSTR)operation,
&hKey);
if (SUCCEEDED(hr)) {
RegCloseKey(hKey);
return true;
}
return false;
}
bool BLI_windows_external_operation_supported(const char *filepath, const char *operation)
{
if (STREQ(operation, "open") || STREQ(operation, "properties")) {
return true;
}
if (BLI_is_dir(filepath)) {
return BLI_windows_file_operation_is_registered("Directory", operation);
}
const char *extension = BLI_path_extension(filepath);
return BLI_windows_file_operation_is_registered(extension, operation);
}
bool BLI_windows_external_operation_execute(const char *filepath, char *operation)
{
WCHAR wpath[FILE_MAX];
if (conv_utf_8_to_16(filepath, wpath, ARRAY_SIZE(wpath)) != 0) {
return false;
}
WCHAR woperation[FILE_MAX];
if (conv_utf_8_to_16(operation, woperation, ARRAY_SIZE(woperation)) != 0) {
return false;
}
SHELLEXECUTEINFOW shellinfo = {0};
shellinfo.cbSize = sizeof(SHELLEXECUTEINFO);
shellinfo.fMask = SEE_MASK_INVOKEIDLIST;
shellinfo.lpVerb = woperation;
shellinfo.lpFile = wpath;
shellinfo.nShow = SW_SHOW;
return ShellExecuteExW(&shellinfo);
}
void BLI_windows_get_default_root_dir(char root[4])
{
char str[MAX_PATH + 1];

View File

@ -256,43 +256,21 @@ static void curves_batch_cache_ensure_edit_points_pos(const bke::CurvesGeometry
}
static void curves_batch_cache_ensure_edit_points_selection(const bke::CurvesGeometry &curves,
const eAttrDomain selection_domain,
CurvesBatchCache &cache)
{
static GPUVertFormat format_data = {0};
static uint selection_id;
if (format_data.attr_len == 0) {
selection_id = GPU_vertformat_attr_add(
&format_data, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format_data, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
}
GPU_vertbuf_init_with_format(cache.edit_points_selection, &format_data);
GPU_vertbuf_data_alloc(cache.edit_points_selection, curves.points_num());
MutableSpan<float> data(static_cast<float *>(GPU_vertbuf_get_data(cache.edit_points_selection)),
curves.points_num());
const OffsetIndices points_by_curve = curves.points_by_curve();
const VArray<bool> selection = *curves.attributes().lookup_or_default<bool>(
".selection", selection_domain, true);
switch (selection_domain) {
case ATTR_DOMAIN_POINT:
for (const int point_i : selection.index_range()) {
const float point_selection = selection[point_i] ? 1.0f : 0.0f;
GPU_vertbuf_attr_set(cache.edit_points_selection, selection_id, point_i, &point_selection);
}
break;
case ATTR_DOMAIN_CURVE:
for (const int curve_i : curves.curves_range()) {
const float curve_selection = selection[curve_i] ? 1.0f : 0.0f;
const IndexRange points = points_by_curve[curve_i];
for (const int point_i : points) {
GPU_vertbuf_attr_set(
cache.edit_points_selection, selection_id, point_i, &curve_selection);
}
}
break;
default:
break;
}
const VArray<float> attribute = *curves.attributes().lookup_or_default<float>(
".selection", ATTR_DOMAIN_POINT, true);
attribute.materialize(data);
}
static void curves_batch_cache_ensure_edit_lines(const bke::CurvesGeometry &curves,
@ -773,8 +751,7 @@ void DRW_curves_batch_cache_create_requested(Object *ob)
curves_batch_cache_ensure_edit_points_pos(curves_orig, deformation.positions, cache);
}
if (DRW_vbo_requested(cache.edit_points_selection)) {
curves_batch_cache_ensure_edit_points_selection(
curves_orig, eAttrDomain(curves_id->selection_domain), cache);
curves_batch_cache_ensure_edit_points_selection(curves_orig, cache);
}
if (DRW_ibo_requested(cache.edit_lines_ibo)) {
curves_batch_cache_ensure_edit_lines(curves_orig, cache);

View File

@ -66,6 +66,10 @@ void FILE_OT_bookmark_move(struct wmOperatorType *ot);
void FILE_OT_reset_recent(wmOperatorType *ot);
void FILE_OT_hidedot(struct wmOperatorType *ot);
void FILE_OT_execute(struct wmOperatorType *ot);
void FILE_OT_external_operation(struct wmOperatorType *ot);
void file_external_operations_menu_register(void);
/**
* Variation of #FILE_OT_execute that accounts for some mouse specific handling.
* Otherwise calls the same logic.

View File

@ -19,6 +19,8 @@
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BLT_translation.h"
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
@ -1768,6 +1770,258 @@ bool file_draw_check_exists(SpaceFile *sfile)
/** \} */
/* -------------------------------------------------------------------- */
/** \name External operations that can performed on files.
* \{ */
static const EnumPropertyItem file_external_operation[] = {
{FILE_EXTERNAL_OPERATION_OPEN, "OPEN", 0, "Open", "Open the file"},
{FILE_EXTERNAL_OPERATION_FOLDER_OPEN, "FOLDER_OPEN", 0, "Open Folder", "Open the folder"},
{FILE_EXTERNAL_OPERATION_EDIT, "EDIT", 0, "Edit", "Edit the file"},
{FILE_EXTERNAL_OPERATION_NEW, "NEW", 0, "New", "Create a new file of this type"},
{FILE_EXTERNAL_OPERATION_FIND, "FIND", 0, "Find File", "Search for files of this type"},
{FILE_EXTERNAL_OPERATION_SHOW, "SHOW", 0, "Show", "Show this file"},
{FILE_EXTERNAL_OPERATION_PLAY, "PLAY", 0, "Play", "Play this file"},
{FILE_EXTERNAL_OPERATION_BROWSE, "BROWSE", 0, "Browse", "Browse this file"},
{FILE_EXTERNAL_OPERATION_PREVIEW, "PREVIEW", 0, "Preview", "Preview this file"},
{FILE_EXTERNAL_OPERATION_PRINT, "PRINT", 0, "Print", "Print this file"},
{FILE_EXTERNAL_OPERATION_INSTALL, "INSTALL", 0, "Install", "Install this file"},
{FILE_EXTERNAL_OPERATION_RUNAS, "RUNAS", 0, "Run As User", "Run as specific user"},
{FILE_EXTERNAL_OPERATION_PROPERTIES,
"PROPERTIES",
0,
"Properties",
"Show OS Properties for this item"},
{FILE_EXTERNAL_OPERATION_FOLDER_FIND,
"FOLDER_FIND",
0,
"Find in Folder",
"Search for items in this folder"},
{FILE_EXTERNAL_OPERATION_FOLDER_CMD,
"CMD",
0,
"Command Prompt Here",
"Open a command prompt here"},
{0, NULL, 0, NULL, NULL}};
static int file_external_operation_exec(bContext *C, wmOperator *op)
{
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
char filepath[FILE_MAX];
RNA_property_string_get(op->ptr, prop, filepath);
const FileExternalOperation operation = (FileExternalOperation)RNA_enum_get(op->ptr,
"operation");
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_WAIT);
#ifdef WIN32
if (BLI_file_external_operation_execute(filepath, operation)) {
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
return OPERATOR_FINISHED;
}
#else
wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
PointerRNA op_props;
WM_operator_properties_create_ptr(&op_props, ot);
RNA_string_set(&op_props, "filepath", filepath);
if (WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, NULL) ==
OPERATOR_FINISHED) {
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
return OPERATOR_FINISHED;
}
#endif
BKE_reportf(
op->reports, RPT_ERROR, "Failure to perform exernal file operation on \"%s\"", filepath);
WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT);
return OPERATOR_CANCELLED;
}
static char *file_external_operation_description(bContext *UNUSED(C),
wmOperatorType *UNUSED(ot),
PointerRNA *ptr)
{
const char *description = "";
RNA_enum_description(file_external_operation, RNA_enum_get(ptr, "operation"), &description);
return BLI_strdup(description);
}
void FILE_OT_external_operation(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "External File Operation";
ot->idname = "FILE_OT_external_operation";
ot->description = "Perform external operation on a file or folder";
/* api callbacks */
ot->exec = file_external_operation_exec;
ot->get_description = file_external_operation_description;
/* flags */
ot->flag = OPTYPE_REGISTER; /* No undo! */
/* properties */
prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "File or folder path", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_enum(ot->srna,
"operation",
file_external_operation,
0,
"Operation",
"Operation to perform on the file or path");
}
static void file_os_operations_menu_item(uiLayout *layout,
wmOperatorType *ot,
const char *path,
FileExternalOperation operation)
{
#ifdef WIN32
if (!BLI_file_external_operation_supported(path, operation)) {
return;
}
#else
if (!ELEM(operation, FILE_EXTERNAL_OPERATION_OPEN, FILE_EXTERNAL_OPERATION_FOLDER_OPEN)) {
return;
}
#endif
const char *title = "";
RNA_enum_name(file_external_operation, operation, &title);
PointerRNA props_ptr;
uiItemFullO_ptr(layout, ot, title, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr);
RNA_string_set(&props_ptr, "filepath", path);
if (operation) {
RNA_enum_set(&props_ptr, "operation", operation);
}
}
static void file_os_operations_menu_draw(const bContext *C_const, Menu *menu)
{
bContext *C = (bContext *)C_const;
/* File browsing only operator (not asset browsing). */
if (!ED_operator_file_browsing_active(C)) {
return;
}
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
if (!sfile || !params) {
return;
}
char dir[FILE_MAX_LIBEXTRA];
if (filelist_islibrary(sfile->files, dir, NULL)) {
return;
}
int numfiles = filelist_files_ensure(sfile->files);
FileDirEntry *fileentry = NULL;
int num_selected = 0;
for (int i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
fileentry = filelist_file(sfile->files, i);
num_selected++;
}
}
if (!fileentry || num_selected > 1) {
return;
}
char path[FILE_MAX_LIBEXTRA];
filelist_file_get_full_path(sfile->files, fileentry, path);
const char *root = filelist_dir(sfile->files);
uiLayout *layout = menu->layout;
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
wmOperatorType *ot = WM_operatortype_find("FILE_OT_external_operation", true);
if (fileentry->typeflag & FILE_TYPE_DIR) {
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_FOLDER_OPEN);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_FOLDER_CMD);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_PROPERTIES);
}
else {
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_OPEN);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_EDIT);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_NEW);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_FIND);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_SHOW);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_PLAY);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_BROWSE);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_PREVIEW);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_PRINT);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_INSTALL);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_RUNAS);
file_os_operations_menu_item(layout, ot, root, FILE_EXTERNAL_OPERATION_FOLDER_OPEN);
file_os_operations_menu_item(layout, ot, root, FILE_EXTERNAL_OPERATION_FOLDER_CMD);
file_os_operations_menu_item(layout, ot, path, FILE_EXTERNAL_OPERATION_PROPERTIES);
}
}
static bool file_os_operations_menu_poll(const bContext *C_const, MenuType *UNUSED(mt))
{
bContext *C = (bContext *)C_const;
/* File browsing only operator (not asset browsing). */
if (!ED_operator_file_browsing_active(C)) {
return false;
}
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_active_params(sfile);
if (sfile && params) {
char dir[FILE_MAX_LIBEXTRA];
if (filelist_islibrary(sfile->files, dir, NULL)) {
return false;
}
int numfiles = filelist_files_ensure(sfile->files);
int num_selected = 0;
for (int i = 0; i < numfiles; i++) {
if (filelist_entry_select_index_get(sfile->files, i, CHECK_ALL)) {
num_selected++;
}
}
if (num_selected > 1) {
CTX_wm_operator_poll_msg_set(C, "More than one item is selected");
}
else if (num_selected < 1) {
CTX_wm_operator_poll_msg_set(C, "No items are selected");
}
else {
return true;
}
}
return false;
}
void file_external_operations_menu_register(void)
{
MenuType *mt;
mt = MEM_callocN(sizeof(MenuType), "spacetype file menu file operations");
strcpy(mt->idname, "FILEBROWSER_MT_operations_menu");
strcpy(mt->label, N_("External"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = file_os_operations_menu_draw;
mt->poll = file_os_operations_menu_poll;
WM_menutype_add(mt);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Execute File Window Operator
* \{ */

View File

@ -613,6 +613,7 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_start_filter);
WM_operatortype_append(FILE_OT_edit_directory_path);
WM_operatortype_append(FILE_OT_view_selected);
WM_operatortype_append(FILE_OT_external_operation);
}
/* NOTE: do not add .blend file reading on this level */
@ -1063,6 +1064,7 @@ void ED_spacetype_file(void)
art->draw = file_tools_region_draw;
BLI_addhead(&st->regiontypes, art);
file_tool_props_region_panels_register(art);
file_external_operations_menu_register();
BKE_spacetype_register(st);
}

View File

@ -2371,6 +2371,13 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons
RNA_property_collection_begin(&self->ptr, self->prop, &iter);
for (int i = 0; iter.valid; RNA_property_collection_next(&iter), i++) {
PropertyRNA *nameprop = RNA_struct_name_property(iter.ptr.type);
BLI_assert_msg(
nameprop,
"Attempted to use a string to index into a collection of items with no 'nameproperty'.");
if (nameprop == NULL) {
/* For non-debug builds, bail if there's no 'nameproperty' to check. */
break;
}
char *nameptr = RNA_property_string_get_alloc(
&iter.ptr, nameprop, name, sizeof(name), &namelen);
if ((keylen == namelen) && STREQ(nameptr, keyname)) {