forked from bartvdbraak/blender
WorkSpace: UI filtering for add-ons
Allows for each workspace to have it's own add-ons on display. Filtering for: Panels, Menus, Keymaps & Manipulators. Automatically applies to add-ons at the moment. Access from workspace, toggled off by default once enabled, add-ons can be white-listed. See D3076
This commit is contained in:
parent
80d1d9629e
commit
d937d06c02
@ -352,6 +352,11 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
|
||||
# 2) try register collected modules
|
||||
# removed, addons need to handle own registration now.
|
||||
|
||||
|
||||
from _bpy import _bl_owner_id_get, _bl_owner_id_set
|
||||
owner_id_prev = _bl_owner_id_get()
|
||||
_bl_owner_id_set(module_name)
|
||||
|
||||
# 3) try run the modules register function
|
||||
try:
|
||||
mod.register()
|
||||
@ -363,6 +368,8 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
|
||||
if default_set:
|
||||
_addon_remove(module_name)
|
||||
return None
|
||||
finally:
|
||||
_bl_owner_id_set(owner_id_prev)
|
||||
|
||||
# * OK loaded successfully! *
|
||||
mod.__addon_enabled__ = True
|
||||
|
@ -766,7 +766,23 @@ class _GenericUI:
|
||||
# ensure menus always get default context
|
||||
operator_context_default = self.layout.operator_context
|
||||
|
||||
# Support filtering out by owner
|
||||
workspace = context.workspace
|
||||
if workspace.use_filter_by_owner:
|
||||
owner_names = {owner_id.name for owner_id in workspace.owner_ids}
|
||||
else:
|
||||
owner_names = None
|
||||
|
||||
for func in draw_ls._draw_funcs:
|
||||
|
||||
# Begin 'owner_id' filter.
|
||||
if owner_names is not None:
|
||||
owner_id = getattr(func, "_owner", None)
|
||||
if owner_id is not None:
|
||||
if func._owner not in owner_names:
|
||||
continue
|
||||
# End 'owner_id' filter.
|
||||
|
||||
# so bad menu functions don't stop
|
||||
# the entire menu from drawing
|
||||
try:
|
||||
@ -782,6 +798,13 @@ class _GenericUI:
|
||||
|
||||
return draw_funcs
|
||||
|
||||
@staticmethod
|
||||
def _dyn_owner_apply(draw_func):
|
||||
from _bpy import _bl_owner_id_get
|
||||
owner_id = _bl_owner_id_get()
|
||||
if owner_id is not None:
|
||||
draw_func._owner = owner_id
|
||||
|
||||
@classmethod
|
||||
def is_extended(cls):
|
||||
return bool(getattr(cls.draw, "_draw_funcs", None))
|
||||
@ -793,6 +816,7 @@ class _GenericUI:
|
||||
takes the same arguments as the menus draw function
|
||||
"""
|
||||
draw_funcs = cls._dyn_ui_initialize()
|
||||
cls._dyn_owner_apply(draw_func)
|
||||
draw_funcs.append(draw_func)
|
||||
|
||||
@classmethod
|
||||
@ -802,6 +826,7 @@ class _GenericUI:
|
||||
the menus draw function
|
||||
"""
|
||||
draw_funcs = cls._dyn_ui_initialize()
|
||||
cls._dyn_owner_apply(draw_func)
|
||||
draw_funcs.insert(0, draw_func)
|
||||
|
||||
@classmethod
|
||||
|
@ -1887,6 +1887,37 @@ class WM_OT_addon_disable(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class WM_OT_owner_enable(Operator):
|
||||
"""Enable workspace owner ID"""
|
||||
bl_idname = "wm.owner_enable"
|
||||
bl_label = "Enable Add-on"
|
||||
|
||||
owner_id = StringProperty(
|
||||
name="UI Tag",
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
workspace = context.workspace
|
||||
workspace.owner_ids.new(self.owner_id)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class WM_OT_owner_disable(Operator):
|
||||
"""Enable workspace owner ID"""
|
||||
bl_idname = "wm.owner_disable"
|
||||
bl_label = "Disable UI Tag"
|
||||
|
||||
owner_id = StringProperty(
|
||||
name="UI Tag",
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
workspace = context.workspace
|
||||
owner_id = workspace.owner_ids[self.owner_id]
|
||||
workspace.owner_ids.remove(owner_id)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class WM_OT_theme_install(Operator):
|
||||
"""Load and apply a Blender XML theme file"""
|
||||
bl_idname = "wm.theme_install"
|
||||
@ -2384,5 +2415,7 @@ classes = (
|
||||
WM_OT_properties_remove,
|
||||
WM_OT_sysinfo,
|
||||
WM_OT_theme_install,
|
||||
WM_OT_owner_disable,
|
||||
WM_OT_owner_enable,
|
||||
WM_OT_url_open,
|
||||
)
|
||||
|
@ -61,6 +61,62 @@ class WORKSPACE_PT_workspace(WorkSpaceButtonsPanel, Panel):
|
||||
layout.prop(view_render, "engine", text="")
|
||||
|
||||
|
||||
class WORKSPACE_PT_owner_ids(WorkSpaceButtonsPanel, Panel):
|
||||
bl_label = "Show/Hide Add-ons"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_header(self, context):
|
||||
workspace = context.workspace
|
||||
self.layout.prop(workspace, "use_filter_by_owner", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
# align just to pack more tightly
|
||||
col = layout.box().column(align=True)
|
||||
|
||||
workspace = context.workspace
|
||||
userpref = context.user_preferences
|
||||
|
||||
col.active = workspace.use_filter_by_owner
|
||||
|
||||
import addon_utils
|
||||
addon_map = {
|
||||
mod.__name__: ("%s: %s" % (mod.bl_info["category"], mod.bl_info["name"]))
|
||||
for mod in addon_utils.modules()
|
||||
}
|
||||
owner_ids = {owner_id.name for owner_id in workspace.owner_ids}
|
||||
|
||||
for addon in userpref.addons:
|
||||
module_name = addon.module
|
||||
text = addon_map[module_name]
|
||||
is_enabled = module_name in owner_ids
|
||||
row = col.row()
|
||||
row.operator(
|
||||
"wm.owner_disable" if is_enabled else "wm.owner_enable",
|
||||
icon='CHECKBOX_HLT' if is_enabled else 'CHECKBOX_DEHLT',
|
||||
text="",
|
||||
emboss=False,
|
||||
).owner_id = module_name
|
||||
row.label(text)
|
||||
if is_enabled:
|
||||
owner_ids.remove(module_name)
|
||||
|
||||
# Detect unused
|
||||
if owner_ids:
|
||||
layout.label(text="Unknown add-ons", icon='ERROR')
|
||||
col = layout.box().column(align=True)
|
||||
for module_name in sorted(owner_ids):
|
||||
row = col.row()
|
||||
row.operator(
|
||||
"wm.owner_disable",
|
||||
icon='CHECKBOX_HLT',
|
||||
text="",
|
||||
emboss=False,
|
||||
).owner_id = module_name
|
||||
row.label(module_name)
|
||||
|
||||
|
||||
|
||||
class WORKSPACE_PT_custom_props(WorkSpaceButtonsPanel, PropertyPanel, Panel):
|
||||
_context_path = "workspace"
|
||||
_property_type = bpy.types.WorkSpace
|
||||
@ -69,6 +125,7 @@ class WORKSPACE_PT_custom_props(WorkSpaceButtonsPanel, PropertyPanel, Panel):
|
||||
classes = (
|
||||
WORKSPACE_PT_context,
|
||||
WORKSPACE_PT_workspace,
|
||||
WORKSPACE_PT_owner_ids,
|
||||
WORKSPACE_PT_custom_props,
|
||||
)
|
||||
|
||||
|
@ -194,6 +194,7 @@ typedef struct PanelType {
|
||||
char translation_context[BKE_ST_MAXNAME];
|
||||
char context[BKE_ST_MAXNAME]; /* for buttons window */
|
||||
char category[BKE_ST_MAXNAME]; /* for category tabs */
|
||||
char owner_id[BKE_ST_MAXNAME]; /* for work-spaces to selectively show. */
|
||||
int space_type;
|
||||
int region_type;
|
||||
|
||||
@ -264,6 +265,7 @@ typedef struct MenuType {
|
||||
char idname[BKE_ST_MAXNAME]; /* unique name */
|
||||
char label[BKE_ST_MAXNAME]; /* for button text */
|
||||
char translation_context[BKE_ST_MAXNAME];
|
||||
char owner_id[BKE_ST_MAXNAME]; /* optional, see: #wmOwnerID */
|
||||
const char *description;
|
||||
|
||||
/* verify if the menu should draw or not */
|
||||
|
@ -136,6 +136,9 @@ void BKE_workspace_update_object_mode(
|
||||
struct Object *BKE_workspace_edit_object(
|
||||
struct WorkSpace *workspace, struct Scene *scene);
|
||||
|
||||
bool BKE_workspace_owner_id_check(
|
||||
const struct WorkSpace *workspace, const char *owner_id) ATTR_NONNULL();
|
||||
|
||||
#undef GETTER_ATTRS
|
||||
#undef SETTER_ATTRS
|
||||
|
||||
|
@ -169,6 +169,7 @@ void BKE_workspace_free(WorkSpace *workspace)
|
||||
BKE_workspace_relations_free(&workspace->hook_layout_relations);
|
||||
BKE_workspace_relations_free(&workspace->scene_viewlayer_relations);
|
||||
|
||||
BLI_freelistN(&workspace->owner_ids);
|
||||
BLI_freelistN(&workspace->layouts);
|
||||
BLI_freelistN(&workspace->transform_orientations);
|
||||
|
||||
@ -535,3 +536,16 @@ Object *BKE_workspace_edit_object(WorkSpace *workspace, Scene *scene)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool BKE_workspace_owner_id_check(
|
||||
const WorkSpace *workspace, const char *owner_id)
|
||||
{
|
||||
if ((*owner_id == '\0') ||
|
||||
((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
/* we could use hash lookup, for now this list is highly under < ~16 items. */
|
||||
return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL;
|
||||
}
|
||||
}
|
||||
|
@ -2904,6 +2904,7 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main
|
||||
link_list(fd, &workspace->hook_layout_relations);
|
||||
link_list(fd, &workspace->scene_viewlayer_relations);
|
||||
link_list(fd, BKE_workspace_transform_orientations_get(workspace));
|
||||
link_list(fd, &workspace->owner_ids);
|
||||
|
||||
for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first;
|
||||
relation;
|
||||
|
@ -3781,6 +3781,7 @@ static void write_workspace(WriteData *wd, WorkSpace *workspace)
|
||||
writelist(wd, DATA, WorkSpaceLayout, layouts);
|
||||
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations);
|
||||
writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations);
|
||||
writelist(wd, DATA, wmOwnerID, &workspace->owner_ids);
|
||||
writelist(wd, DATA, TransformOrientation, transform_orientations);
|
||||
}
|
||||
|
||||
|
@ -41,10 +41,10 @@
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_linklist_stack.h"
|
||||
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_types.h"
|
||||
@ -1824,6 +1824,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
|
||||
|
||||
void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int contextnr, const bool vertical)
|
||||
{
|
||||
const WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
uiStyle *style = UI_style_get_dpi();
|
||||
uiBlock *block;
|
||||
@ -1874,6 +1875,11 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we're tagged, only use compatible. */
|
||||
if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* draw panel */
|
||||
if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
|
||||
BLI_SMALLSTACK_PUSH(pt_stack, pt);
|
||||
|
@ -312,6 +312,7 @@ typedef struct wmKeyMap {
|
||||
char idname[64]; /* global editor keymaps, or for more per space/region */
|
||||
short spaceid; /* same IDs as in DNA_space_types.h */
|
||||
short regionid; /* see above */
|
||||
char owner_id[64]; /* optional, see: #wmOwnerID */
|
||||
|
||||
short flag; /* general flags */
|
||||
short kmi_id; /* last kmi id */
|
||||
|
@ -77,6 +77,12 @@ typedef struct WorkSpaceLayout {
|
||||
char name[64] DNA_PRIVATE_WORKSPACE; /* MAX_NAME */
|
||||
} WorkSpaceLayout;
|
||||
|
||||
/** Optional tags, which features to use, aligned with #bAddon names by convention. */
|
||||
typedef struct wmOwnerID {
|
||||
struct wmOwnerID *next, *prev;
|
||||
char name[64] DNA_PRIVATE_WORKSPACE; /* MAX_NAME */
|
||||
} wmOwnerID;
|
||||
|
||||
typedef struct WorkSpace {
|
||||
ID id;
|
||||
|
||||
@ -86,6 +92,9 @@ typedef struct WorkSpace {
|
||||
ListBase hook_layout_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */
|
||||
ListBase scene_viewlayer_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */
|
||||
|
||||
/* Feature tagging (use for addons) */
|
||||
ListBase owner_ids DNA_PRIVATE_WORKSPACE_READ_WRITE; /* wmOwnerID */
|
||||
|
||||
/* Custom transform orientations */
|
||||
ListBase transform_orientations DNA_PRIVATE_WORKSPACE;
|
||||
|
||||
@ -154,6 +163,7 @@ typedef struct WorkSpaceInstanceHook {
|
||||
|
||||
typedef enum eWorkSpaceFlags {
|
||||
WORKSPACE_USE_SCENE_SETTINGS = (1 << 0),
|
||||
WORKSPACE_USE_FILTER_BY_ORIGIN = (1 << 1),
|
||||
} eWorkSpaceFlags;
|
||||
|
||||
#endif /* __DNA_WORKSPACE_TYPES_H__ */
|
||||
|
@ -719,6 +719,7 @@ extern StructRNA RNA_WipeSequence;
|
||||
extern StructRNA RNA_WireframeModifier;
|
||||
extern StructRNA RNA_WoodTexture;
|
||||
extern StructRNA RNA_WorkSpace;
|
||||
extern StructRNA RNA_wmOwnerIDs;
|
||||
extern StructRNA RNA_World;
|
||||
extern StructRNA RNA_WorldAmbientOcclusion;
|
||||
extern StructRNA RNA_WorldLighting;
|
||||
@ -1303,6 +1304,10 @@ void RNA_property_override_status(
|
||||
PointerRNA *ptr, PropertyRNA *prop, const int index,
|
||||
bool *r_overridable, bool *r_overridden, bool *r_mandatory, bool *r_locked);
|
||||
|
||||
void RNA_struct_state_owner_set(const char *name);
|
||||
const char *RNA_struct_state_owner_get(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -505,7 +505,6 @@ typedef struct ExtensionRNA {
|
||||
StructRNA *srna;
|
||||
StructCallbackFunc call;
|
||||
StructFreeFunc free;
|
||||
|
||||
} ExtensionRNA;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -7723,3 +7723,22 @@ bool RNA_path_resolved_create(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static char rna_struct_state_owner[64];
|
||||
void RNA_struct_state_owner_set(const char *name)
|
||||
{
|
||||
if (name) {
|
||||
BLI_strncpy(rna_struct_state_owner, name, sizeof(rna_struct_state_owner));
|
||||
}
|
||||
else {
|
||||
rna_struct_state_owner[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
const char *RNA_struct_state_owner_get(void)
|
||||
{
|
||||
if (rna_struct_state_owner[0]) {
|
||||
return rna_struct_state_owner;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -267,6 +267,13 @@ static StructRNA *rna_Panel_register(
|
||||
else
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
|
||||
{
|
||||
const char *owner_id = RNA_struct_state_owner_get();
|
||||
if (owner_id) {
|
||||
BLI_strncpy(pt->owner_id, owner_id, sizeof(pt->owner_id));
|
||||
}
|
||||
}
|
||||
|
||||
/* update while blender is running */
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
|
||||
@ -773,6 +780,13 @@ static StructRNA *rna_Menu_register(
|
||||
mt->poll = (have_function[0]) ? menu_poll : NULL;
|
||||
mt->draw = (have_function[1]) ? menu_draw : NULL;
|
||||
|
||||
{
|
||||
const char *owner_id = RNA_struct_state_owner_get();
|
||||
if (owner_id) {
|
||||
BLI_strncpy(mt->owner_id, owner_id, sizeof(mt->owner_id));
|
||||
}
|
||||
}
|
||||
|
||||
WM_menutype_add(mt);
|
||||
|
||||
/* update while blender is running */
|
||||
@ -1023,6 +1037,10 @@ static void rna_def_panel(BlenderRNA *brna)
|
||||
RNA_def_property_string_sdna(prop, NULL, "type->category");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
|
||||
prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
|
||||
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
|
||||
RNA_def_property_enum_items(prop, rna_enum_space_type_items);
|
||||
@ -1290,6 +1308,10 @@ static void rna_def_menu(BlenderRNA *brna)
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
|
||||
|
||||
prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
|
||||
RNA_define_verify_sdna(1);
|
||||
}
|
||||
|
||||
|
@ -2253,6 +2253,10 @@ static void rna_def_keyconfig(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Name", "Name of the key map");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "owner_id");
|
||||
RNA_def_property_ui_text(prop, "Owner", "Internal owner");
|
||||
|
||||
prop = RNA_def_property(srna, "space_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "spaceid");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
@ -806,6 +806,13 @@ static StructRNA *rna_ManipulatorGroup_register(
|
||||
wmManipulatorGroupType *wgt = WM_manipulatorgrouptype_append_ptr(
|
||||
BPY_RNA_manipulatorgroup_wrapper, (void *)&dummywgt);
|
||||
|
||||
{
|
||||
const char *owner_id = RNA_struct_state_owner_get();
|
||||
if (owner_id) {
|
||||
BLI_strncpy(wgt->owner_id, owner_id, sizeof(wgt->owner_id));
|
||||
}
|
||||
}
|
||||
|
||||
if (wgt->flag & WM_MANIPULATORGROUPTYPE_PERSISTENT) {
|
||||
WM_manipulator_group_type_add_ptr_ex(wgt, mmap_type);
|
||||
|
||||
@ -1204,6 +1211,10 @@ static void rna_def_manipulatorgroup(BlenderRNA *brna)
|
||||
RNA_def_property_flag(prop, PROP_REGISTER);
|
||||
RNA_def_property_ui_text(prop, "Region Type", "The region where the panel is going to be used in");
|
||||
|
||||
prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
|
||||
/* bl_options */
|
||||
static EnumPropertyItem manipulatorgroup_flag_items[] = {
|
||||
{WM_MANIPULATORGROUPTYPE_3D, "3D", 0, "3D",
|
||||
|
@ -52,6 +52,10 @@
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
static void rna_window_update_all(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
}
|
||||
|
||||
void rna_workspace_screens_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
@ -79,8 +83,94 @@ static PointerRNA rna_workspace_transform_orientations_item_get(CollectionProper
|
||||
return rna_pointer_inherit_refine(&iter->parent, &RNA_TransformOrientation, transform_orientation);
|
||||
}
|
||||
|
||||
/* workspace.owner_ids */
|
||||
|
||||
static wmOwnerID *rna_WorkSpace_owner_ids_new(
|
||||
WorkSpace *workspace, const char *name)
|
||||
{
|
||||
wmOwnerID *owner_id = MEM_callocN(sizeof(*owner_id), __func__);
|
||||
BLI_addtail(&workspace->owner_ids, owner_id);
|
||||
BLI_strncpy(owner_id->name, name, sizeof(owner_id->name));
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
return owner_id;
|
||||
}
|
||||
|
||||
static void rna_WorkSpace_owner_ids_remove(
|
||||
WorkSpace *workspace, ReportList *reports, PointerRNA *wstag_ptr)
|
||||
{
|
||||
wmOwnerID *owner_id = wstag_ptr->data;
|
||||
if (BLI_remlink_safe(&workspace->owner_ids, owner_id) == false) {
|
||||
BKE_reportf(reports, RPT_ERROR,
|
||||
"wmOwnerID '%s' not in workspace '%s'",
|
||||
owner_id->name, workspace->id.name + 2);
|
||||
return;
|
||||
}
|
||||
|
||||
MEM_freeN(owner_id);
|
||||
RNA_POINTER_INVALIDATE(wstag_ptr);
|
||||
|
||||
WM_main_add_notifier(NC_WINDOW, NULL);
|
||||
}
|
||||
|
||||
static void rna_WorkSpace_owner_ids_clear(
|
||||
WorkSpace *workspace)
|
||||
{
|
||||
BLI_freelistN(&workspace->owner_ids);
|
||||
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, workspace);
|
||||
}
|
||||
|
||||
#else /* RNA_RUNTIME */
|
||||
|
||||
static void rna_def_workspace_owner(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "wmOwnerID", NULL);
|
||||
RNA_def_struct_sdna(srna, "wmOwnerID");
|
||||
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
|
||||
RNA_def_struct_ui_text(srna, "Work Space UI Tag", "");
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Name", "");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
}
|
||||
|
||||
static void rna_def_workspace_owner_ids(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
RNA_def_property_srna(cprop, "wmOwnerIDs");
|
||||
srna = RNA_def_struct(brna, "wmOwnerIDs", NULL);
|
||||
RNA_def_struct_sdna(srna, "WorkSpace");
|
||||
RNA_def_struct_ui_text(srna, "WorkSpace UI Tags", "");
|
||||
|
||||
/* add owner_id */
|
||||
func = RNA_def_function(srna, "new", "rna_WorkSpace_owner_ids_new");
|
||||
RNA_def_function_ui_description(func, "Add ui tag");
|
||||
parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the tag");
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
/* return type */
|
||||
parm = RNA_def_pointer(func, "owner_id", "wmOwnerID", "", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
/* remove owner_id */
|
||||
func = RNA_def_function(srna, "remove", "rna_WorkSpace_owner_ids_remove");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_ui_description(func, "Remove ui tag");
|
||||
/* owner_id to remove */
|
||||
parm = RNA_def_pointer(func, "owner_id", "wmOwnerID", "", "Tag to remove");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
|
||||
|
||||
/* clear all modifiers */
|
||||
func = RNA_def_function(srna, "clear", "rna_WorkSpace_owner_ids_clear");
|
||||
RNA_def_function_ui_description(func, "Remove all tags");
|
||||
}
|
||||
|
||||
static void rna_def_workspace(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@ -121,6 +211,11 @@ static void rna_def_workspace(BlenderRNA *brna)
|
||||
"rna_workspace_transform_orientations_item_get", NULL, NULL, NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Transform Orientations", "");
|
||||
|
||||
prop = RNA_def_property(srna, "owner_ids", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "wmOwnerID");
|
||||
RNA_def_property_ui_text(prop, "UI Tags", "");
|
||||
rna_def_workspace_owner_ids(brna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "object_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_enum_object_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Object interaction mode used in this window");
|
||||
@ -138,6 +233,13 @@ static void rna_def_workspace(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Scene Settings",
|
||||
"Use scene settings instead of workspace settings");
|
||||
RNA_def_property_update(prop, NC_SCREEN | ND_LAYER, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_filter_by_owner", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", WORKSPACE_USE_FILTER_BY_ORIGIN);
|
||||
RNA_def_property_ui_text(prop, "Use UI Tags",
|
||||
"Filter the UI by tags");
|
||||
RNA_def_property_update(prop, 0, "rna_window_update_all");
|
||||
}
|
||||
|
||||
static void rna_def_transform_orientation(BlenderRNA *brna)
|
||||
@ -160,6 +262,7 @@ static void rna_def_transform_orientation(BlenderRNA *brna)
|
||||
|
||||
void RNA_def_workspace(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_workspace_owner(brna);
|
||||
rna_def_workspace(brna);
|
||||
rna_def_transform_orientation(brna);
|
||||
}
|
||||
|
@ -376,6 +376,9 @@ void BPy_init_modules(void)
|
||||
PyModule_AddObject(mod, meth_bpy_register_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL));
|
||||
PyModule_AddObject(mod, meth_bpy_unregister_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL));
|
||||
|
||||
PyModule_AddObject(mod, meth_bpy_owner_id_get.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_get, NULL));
|
||||
PyModule_AddObject(mod, meth_bpy_owner_id_set.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_set, NULL));
|
||||
|
||||
/* add our own modules dir, this is a python package */
|
||||
bpy_package_py = bpy_import_test("bpy");
|
||||
}
|
||||
|
@ -8257,6 +8257,43 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
/* Access to 'owner_id' internal global. */
|
||||
|
||||
static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self))
|
||||
{
|
||||
const char *name = RNA_struct_state_owner_get();
|
||||
if (name) {
|
||||
return PyUnicode_FromString(name);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *pyrna_bl_owner_id_set(PyObject *UNUSED(self), PyObject *value)
|
||||
{
|
||||
const char *name;
|
||||
if (value == Py_None) {
|
||||
name = NULL;
|
||||
}
|
||||
else if (PyUnicode_Check(value)) {
|
||||
name = _PyUnicode_AsString(value);
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"owner_set(...): "
|
||||
"expected None or a string, not '%.200s'", Py_TYPE(value)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
RNA_struct_state_owner_set(name);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyMethodDef meth_bpy_owner_id_get = {
|
||||
"_bl_owner_id_get", (PyCFunction)pyrna_bl_owner_id_get, METH_NOARGS, NULL,
|
||||
};
|
||||
PyMethodDef meth_bpy_owner_id_set = {
|
||||
"_bl_owner_id_set", (PyCFunction)pyrna_bl_owner_id_set, METH_O, NULL,
|
||||
};
|
||||
|
||||
/* currently this is fairly limited, we would need to make some way to split up
|
||||
* pyrna_callback_classmethod_... if we want more than one callback per type */
|
||||
typedef struct BPyRNA_CallBack {
|
||||
|
@ -225,4 +225,8 @@ int pyrna_prop_validity_check(BPy_PropertyRNA *self);
|
||||
extern PyMethodDef meth_bpy_register_class;
|
||||
extern PyMethodDef meth_bpy_unregister_class;
|
||||
|
||||
/* bpy.utils._bl_owner_(get/set) */
|
||||
extern PyMethodDef meth_bpy_owner_id_set;
|
||||
extern PyMethodDef meth_bpy_owner_id_get;
|
||||
|
||||
#endif
|
||||
|
@ -341,6 +341,14 @@ void WM_menutype_free(void)
|
||||
|
||||
bool WM_menutype_poll(bContext *C, MenuType *mt)
|
||||
{
|
||||
/* If we're tagged, only use compatible. */
|
||||
if (mt->owner_id[0] != '\0') {
|
||||
const WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
if (BKE_workspace_owner_id_check(workspace, mt->owner_id) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mt->poll != NULL) {
|
||||
return mt->poll(C, mt);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
@ -49,6 +50,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
@ -341,6 +343,12 @@ static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid)
|
||||
km->spaceid = spaceid;
|
||||
km->regionid = regionid;
|
||||
|
||||
{
|
||||
const char *owner_id = RNA_struct_state_owner_get();
|
||||
if (owner_id) {
|
||||
BLI_strncpy(km->owner_id, owner_id, sizeof(km->owner_id));
|
||||
}
|
||||
}
|
||||
return km;
|
||||
}
|
||||
|
||||
@ -401,6 +409,14 @@ bool WM_keymap_remove(wmKeyConfig *keyconf, wmKeyMap *keymap)
|
||||
|
||||
bool WM_keymap_poll(bContext *C, wmKeyMap *keymap)
|
||||
{
|
||||
/* If we're tagged, only use compatible. */
|
||||
if (keymap->owner_id[0] != '\0') {
|
||||
const WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
if (BKE_workspace_owner_id_check(workspace, keymap->owner_id) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (keymap->poll != NULL) {
|
||||
return keymap->poll(C);
|
||||
}
|
||||
|
@ -341,6 +341,7 @@ typedef struct wmManipulatorGroupTypeRef {
|
||||
typedef struct wmManipulatorGroupType {
|
||||
const char *idname; /* MAX_NAME */
|
||||
const char *name; /* manipulator-group name - displayed in UI (keymap editor) */
|
||||
char owner_id[64]; /* MAX_NAME */
|
||||
|
||||
/* poll if manipulator-map should be visible */
|
||||
wmManipulatorGroupFnPoll poll;
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
@ -203,6 +204,13 @@ void wm_manipulatorgroup_ensure_initialized(wmManipulatorGroup *mgroup, const bC
|
||||
|
||||
bool WM_manipulator_group_type_poll(const bContext *C, const struct wmManipulatorGroupType *wgt)
|
||||
{
|
||||
/* If we're tagged, only use compatible. */
|
||||
if (wgt->owner_id[0] != '\0') {
|
||||
const WorkSpace *workspace = CTX_wm_workspace(C);
|
||||
if (BKE_workspace_owner_id_check(workspace, wgt->owner_id) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* Check for poll function, if manipulator-group belongs to an operator, also check if the operator is running. */
|
||||
return (!wgt->poll || wgt->poll(C, (wmManipulatorGroupType *)wgt));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user