diff options
author | Lukas Toenne <lukas.toenne@googlemail.com> | 2013-05-09 15:43:48 +0400 |
---|---|---|
committer | Lukas Toenne <lukas.toenne@googlemail.com> | 2013-05-09 15:43:48 +0400 |
commit | 56485b6562ee349513e5de4ac450150f569a230d (patch) | |
tree | 61e8a666fda5c5e13ce301b731d3687d062ec87c /release/scripts | |
parent | 2e0f741d0190d60243d8ace131ffcd7f3b620f63 (diff) |
Upgrade for the add_search node operator. This now uses the same basic system as the regular add_node operator, with enum items generated from the common node categories system (nodeitems_utils module). This means that any node listed in the regular node Add menu can now also be added via searching, including node groups and the like. The search operator also uses the subsequent transform to make insertion a bit more streamlined.
Diffstat (limited to 'release/scripts')
-rw-r--r-- | release/scripts/modules/nodeitems_utils.py | 13 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/node.py | 107 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_node.py | 1 |
3 files changed, 55 insertions, 66 deletions
diff --git a/release/scripts/modules/nodeitems_utils.py b/release/scripts/modules/nodeitems_utils.py index 3fbafc3ae9b..b58207d7c65 100644 --- a/release/scripts/modules/nodeitems_utils.py +++ b/release/scripts/modules/nodeitems_utils.py @@ -114,6 +114,19 @@ def register_node_categories(identifier, cat_list): _node_categories[identifier] = (cat_list, draw_add_menu, menu_types, panel_types) +def node_categories_iter(context): + for cat_type in _node_categories.values(): + for cat in cat_type[0]: + if cat.poll and cat.poll(context): + yield cat + + +def node_items_iter(context): + for cat in node_categories_iter(context): + for item in cat.items(context): + yield item + + def unregister_node_cat_types(cats): bpy.types.NODE_MT_add.remove(cats[1]) for mt in cats[2]: diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py index 39d701a8f25..c7081b6b5c1 100644 --- a/release/scripts/startup/bl_operators/node.py +++ b/release/scripts/startup/bl_operators/node.py @@ -18,7 +18,7 @@ # <pep8-80 compliant> -import bpy +import bpy, nodeitems_utils from bpy.types import Operator, PropertyGroup from bpy.props import BoolProperty, CollectionProperty, EnumProperty, IntProperty, StringProperty @@ -62,15 +62,20 @@ class NodeAddOperator(): else: space.cursor_location = tree.view_center - def create_node(self, context): + # XXX explicit node_type argument is usually not necessary, but required to make search operator work: + # add_search has to override the 'type' property since it's hardcoded in bpy_operator_wrap.c ... + def create_node(self, context, node_type=None): space = context.space_data tree = space.edit_tree + if node_type is None: + node_type = self.type + # select only the new node for n in tree.nodes: n.select = False - node = tree.nodes.new(type=self.type) + node = tree.nodes.new(type=node_type) for setting in self.settings: # XXX catch exceptions here? @@ -151,83 +156,53 @@ class NODE_OT_add_and_link_node(NodeAddOperator, Operator): return {'FINISHED'} -def node_classes_iter(base=bpy.types.Node): - """ - Yields all true node classes by checking for the is_registered_node_type classmethod. - Node types can use specialized subtypes of bpy.types.Node, which are not usable - nodes themselves (e.g. CompositorNode). - """ - if base.is_registered_node_type(): - yield base - for subclass in base.__subclasses__(): - for node_class in node_classes_iter(subclass): - yield node_class - - -def node_class_items_iter(node_class, context): - identifier = node_class.bl_rna.identifier - # XXX Checking for explicit group node types is stupid. - # This should be replaced by a generic system of generating - # node items via callback. - # Group node_tree pointer should also use a poll function to filter the library list, - # but cannot do that without a node instance here. A node callback could just use the internal poll function. - if identifier in {'ShaderNodeGroup', 'CompositorNodeGroup', 'TextureNodeGroup'}: - tree_idname = context.space_data.edit_tree.bl_idname - for group in bpy.data.node_groups: - if group.bl_idname == tree_idname: - # XXX empty string should be replaced by description from tree - yield (group.name, "", {"node_tree": group}) - else: - yield (node_class.bl_rna.name, node_class.bl_rna.description, {}) - - -def node_items_iter(context): - snode = context.space_data - if not snode: - return - tree = snode.edit_tree - if not tree: - return - - for node_class in node_classes_iter(): - if node_class.poll(tree): - for item in node_class_items_iter(node_class, context): - yield (node_class,) + item - - -# Create an enum list from node class items -def node_type_items_cb(self, context): - # XXX Python has to keep a ref to those strings, else they may be freed :( - NODE_OT_add_search._enum_str_store = [(str(index), item[1], item[2]) - for index, item in enumerate(node_items_iter(context))] - return NODE_OT_add_search._enum_str_store - - class NODE_OT_add_search(NodeAddOperator, Operator): '''Add a node to the active tree''' bl_idname = "node.add_search" bl_label = "Search and Add Node" bl_options = {'REGISTER', 'UNDO'} - # XXX Python has to keep a ref to the data (strings) generated by enum's callback, else they may be freed :( - _enum_str_store = [] + # Create an enum list from node items + def node_enum_items(self, context): + enum_items = [] + for index, item in enumerate(nodeitems_utils.node_items_iter(context)): + nodetype = getattr(bpy.types, item.nodetype, None) + if nodetype: + enum_items.append((str(index), item.label, nodetype.bl_rna.description, index)) + return enum_items + + # Look up the item based on index + def find_node_item(self, context): + for index, item in enumerate(nodeitems_utils.node_items_iter(context)): + if str(index) == self.type: + return item + return None - # XXX this should be called 'node_type' but the operator search + # XXX this should be called 'node_item' but the operator search # property is hardcoded to 'type' by a hack in bpy_operator_wrap.c ... type = EnumProperty( name="Node Type", description="Node type", - items=node_type_items_cb, + items=node_enum_items, ) def execute(self, context): - for index, item in enumerate(node_items_iter(context)): - if str(index) == self.type: - node = self.create_node(context, item[0].bl_rna.identifier) - for prop, value in item[3].items(): - setattr(node, prop, value) - break - return {'FINISHED'} + item = self.find_node_item(context) + if item: + # apply settings from the node item + for setting in item.settings.items(): + ops = self.settings.add() + ops.name = setting[0] + ops.value = setting[1] + + self.create_node(context, item.nodetype) + + if self.use_transform: + bpy.ops.transform.translate('INVOKE_DEFAULT') + + return {'FINISHED'} + else: + return {'CANCELLED'} def invoke(self, context, event): self.store_mouse_cursor(context, event) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index f58679e836d..86d53648cc1 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -117,6 +117,7 @@ class NODE_MT_add(bpy.types.Menu): layout.operator_context = 'INVOKE_DEFAULT' op = layout.operator("node.add_search", text="Search ...") + op.use_transform = True # actual node submenus are added by draw functions from node categories |