101 lines
4.1 KiB
Python
101 lines
4.1 KiB
Python
![]() |
# ##### BEGIN GPL LICENSE BLOCK #####
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or
|
||
|
# modify it under the terms of the GNU General Public License
|
||
|
# as published by the Free Software Foundation; either version 2
|
||
|
# of the License, or (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program; if not, write to the Free Software Foundation,
|
||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
#
|
||
|
# ##### END GPL LICENSE BLOCK #####
|
||
|
|
||
|
# <pep8-80 compliant>
|
||
|
|
||
|
import bpy
|
||
|
from bpy.types import Operator
|
||
|
from bpy.props import (EnumProperty,
|
||
|
FloatVectorProperty,
|
||
|
StringProperty,
|
||
|
CollectionProperty
|
||
|
)
|
||
|
|
||
|
# XXX These node item lists should actually be generated by a callback at operator execution time (see node_type_items below),
|
||
|
# using the active node tree from the context. Due to a difficult bug in bpy this is not possible (item list memory gets freed too early),
|
||
|
# so for now just copy the static item lists to these global variables.
|
||
|
#
|
||
|
# In the custom_nodes branch, the static per-tree-type node items are replaced by a single independent type list anyway (with a poll function
|
||
|
# to limit node types to the respective trees). So this workaround is only temporary.
|
||
|
|
||
|
node_type_items_dict = {}
|
||
|
node_type_items_dict['SHADER'] = [(item.identifier, item.name, item.description, item.value) for item in bpy.types.ShaderNode.bl_rna.properties['type'].enum_items]
|
||
|
node_type_items_dict['COMPOSITING'] = [(item.identifier, item.name, item.description, item.value) for item in bpy.types.CompositorNode.bl_rna.properties['type'].enum_items]
|
||
|
node_type_items_dict['TEXTURE'] = [(item.identifier, item.name, item.description, item.value) for item in bpy.types.TextureNode.bl_rna.properties['type'].enum_items]
|
||
|
|
||
|
# Returns the enum item list for the edited tree in the context
|
||
|
def node_type_items(self, context):
|
||
|
snode = context.space_data
|
||
|
if not snode:
|
||
|
return []
|
||
|
tree = snode.edit_tree
|
||
|
if not tree:
|
||
|
return []
|
||
|
|
||
|
# XXX Does not work correctly, see comment above
|
||
|
#return [(item.identifier, item.name, item.description, item.value) for item in tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items]
|
||
|
|
||
|
if tree.type in node_type_items_dict:
|
||
|
return node_type_items_dict[tree.type]
|
||
|
else:
|
||
|
return []
|
||
|
|
||
|
class NODE_OT_add_search(bpy.types.Operator):
|
||
|
'''Add a node to the active tree'''
|
||
|
bl_idname = "node.add_search"
|
||
|
bl_label = "Search and Add Node"
|
||
|
bl_options = {'REGISTER', 'UNDO'}
|
||
|
|
||
|
# XXX this should be called 'node_type' but the operator search property is hardcoded to 'type' by a hack in bpy_operator_wrap.c ...
|
||
|
type = EnumProperty(items=node_type_items, name="Node Type", description="Node type")
|
||
|
|
||
|
def create_node(self, context):
|
||
|
space = context.space_data
|
||
|
tree = space.edit_tree
|
||
|
|
||
|
node = tree.nodes.new(type=self.type)
|
||
|
for n in tree.nodes:
|
||
|
if n==node:
|
||
|
node.select = True
|
||
|
tree.nodes.active = node
|
||
|
else:
|
||
|
node.select = False
|
||
|
node.location = space.cursor_location
|
||
|
return node
|
||
|
|
||
|
@classmethod
|
||
|
def poll(cls, context):
|
||
|
space = context.space_data
|
||
|
# needs active node editor and a tree to add nodes to
|
||
|
return space.type == 'NODE_EDITOR' and space.edit_tree
|
||
|
|
||
|
def execute(self, context):
|
||
|
self.create_node(context)
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
def invoke(self, context, event):
|
||
|
space = context.space_data
|
||
|
v2d = context.region.view2d
|
||
|
|
||
|
# convert mouse position to the View2D for later node placement
|
||
|
space.cursor_location = v2d.region_to_view(event.mouse_region_x, event.mouse_region_y)
|
||
|
|
||
|
context.window_manager.invoke_search_popup(self)
|
||
|
return {'CANCELLED'}
|
||
|
|