Set material and color properties of Blob objects.
[blender-addons-contrib.git] / node_presets.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; version 2
6 #  of the License.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 bl_info = {
20     "name": "Node Presets",
21     "description": "Useful and time-saving tools for rendering workflow",
22     "author": "Campbell Barton",
23     "version": (1, 1),
24     "blender": (2, 69),
25     "location": "Node > Add Template",
26     "description": "Adds node presets",
27     "warning": "",
28     "wiki_url": "",
29     "tracker_url": "",
30     "category": "Render"}
31
32
33 import os
34 import bpy
35 from bpy.types import Operator, Menu, AddonPreferences
36 from bpy.props import StringProperty
37
38
39 # -----------------------------------------------------------------------------
40 # Node Adding Operator
41
42
43 def node_center(context):
44     from mathutils import Vector
45     loc = Vector((0.0, 0.0))
46     node_selected = context.selected_nodes
47     if node_selected:
48         for node in node_selected:
49             loc += node.location
50         loc /= len(node_selected)
51     return loc
52
53
54 def node_template_add(context, filepath, node_group, ungroup, report):
55     """ Main function
56     """
57
58     space = context.space_data
59     node_tree = space.node_tree
60     node_active = context.active_node
61     node_selected = context.selected_nodes
62
63     if node_tree is None:
64         report({'ERROR'}, "No node tree available")
65         return
66
67     with bpy.data.libraries.load(filepath, link=False) as (data_from, data_to):
68         assert(node_group in data_from.node_groups)
69         data_to.node_groups = [node_group]
70     node_group = data_to.node_groups[0]
71
72     # add node!
73     center = node_center(context)
74
75     for node in node_tree.nodes:
76         node.select = False
77
78     node_type_string = {
79         "ShaderNodeTree": "ShaderNodeGroup",
80         "CompositorNodeTree": "CompositorNodeGroup",
81         "TextureNodeTree": "TextureNodeGroup",
82         }[type(node_tree).__name__]
83
84     node = node_tree.nodes.new(type=node_type_string)
85     node.node_tree = node_group
86
87     is_fail = (node.node_tree is None)
88     if is_fail:
89         report({'WARNING'}, "Incompatible node type")
90
91     node.select = True
92     node_tree.nodes.active = node
93     node.location = center
94
95     if is_fail:
96         node_tree.nodes.remove(node)
97     else:
98         if ungroup:
99             bpy.ops.node.group_ungroup()
100
101     #node_group.user_clear()
102     #bpy.data.node_groups.remove(node_group)
103
104
105 # -----------------------------------------------------------------------------
106 # Node Template Prefs
107
108 def node_search_path(context):
109     user_preferences = context.user_preferences
110     addon_prefs = user_preferences.addons[__name__].preferences
111     dirpath = addon_prefs.search_path
112     return dirpath
113
114
115 class NodeTemplatePrefs(AddonPreferences):
116     bl_idname = __name__
117
118     search_path = StringProperty(
119             name="Directory of blend files with node-groups",
120             subtype='DIR_PATH',
121             )
122
123     def draw(self, context):
124         layout = self.layout
125         layout.prop(self, "search_path")
126
127
128 class NODE_OT_template_add(Operator):
129     """Add a node template"""
130     bl_idname = "node.template_add"
131     bl_label = "Add node group template"
132     bl_description = "Add node group template"
133     bl_options = {'REGISTER', 'UNDO'}
134
135     filepath = StringProperty(
136             subtype='FILE_PATH',
137             )
138     group_name = StringProperty(
139             )
140
141     def execute(self, context):
142         node_template_add(context, self.filepath, self.group_name, True, self.report)
143
144         return {'FINISHED'}
145
146     def invoke(self, context, event):
147         node_template_add(context, self.filepath, self.group_name, event.shift, self.report)
148
149         return {'FINISHED'}
150
151 # -----------------------------------------------------------------------------
152 # node menu list
153
154 def node_template_cache(context, reload=False):
155     node_cache = node_template_cache._node_cache
156     if reload:
157         node_cache[:] = []
158     if node_cache:
159         return node_cache
160
161     dirpath = node_search_path(context)
162     for fn in os.listdir(dirpath):
163         if fn.endswith(".blend"):
164             filepath = os.path.join(dirpath, fn)
165             with bpy.data.libraries.load(filepath) as (data_from, data_to):
166                 for group_name in data_from.node_groups:
167                     if not group_name.startswith('_'):
168                         node_cache.append((filepath, group_name))
169
170     return node_cache
171 node_template_cache._node_cache = []
172
173
174 class NODE_MT_template_add(Menu):
175     bl_label = "Node Template"
176
177     def draw(self, context):
178         layout = self.layout
179
180         dirpath = node_search_path(context)
181         if dirpath == "":
182             layout.label("Set search dir in the addon-prefs")
183             return
184
185         for filepath, group_name in node_template_cache(context):
186             props = layout.operator(NODE_OT_template_add.bl_idname,
187                                     text=group_name)
188             props.filepath = filepath
189             props.group_name = group_name
190
191
192 def add_node_button(self, context):
193     self.layout.menu(
194         NODE_MT_template_add.__name__,
195         text="Template",
196         icon="PLUGIN")
197
198
199 classes = (
200     NODE_OT_template_add,
201     NODE_MT_template_add,
202     NodeTemplatePrefs
203     )
204
205
206 def register():
207     for cls in classes:
208         bpy.utils.register_class(cls)
209
210     bpy.types.NODE_MT_add.append(add_node_button)
211
212
213 def unregister():
214     for cls in classes:
215         bpy.utils.unregister_class(cls)
216
217     bpy.types.NODE_MT_add.remove(add_node_button)
218
219 if __name__ == "__main__":
220     register()