Merge branch 'blender-v3.6-release'
[blender-addons.git] / render_povray / nodes_gui.py
blob0aa7d15192ee3be38d49289664041da2555488d6
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 """"Nodes based User interface for shaders exported to POV textures."""
4 import bpy
6 from bpy.utils import register_class, unregister_class
7 from bpy.types import Menu, Operator
8 from bpy.props import (
9 StringProperty,
12 # def find_node_input(node, name):
13 # for input in node.inputs:
14 # if input.name == name:
15 # return input
17 # def panel_node_draw(layout, id_data, output_type, input_name):
18 # if not id_data.use_nodes:
19 # #layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE')
20 # #layout.operator("pov.use_shading_nodes", icon='NODETREE')
21 # layout.operator("WM_OT_context_toggle", icon='NODETREE').data_path = \
22 # "material.pov.material_use_nodes"
23 # return False
25 # ntree = id_data.node_tree
27 # node = find_node(id_data, output_type)
28 # if not node:
29 # layout.label(text="No output node")
30 # else:
31 # input = find_node_input(node, input_name)
32 # layout.template_node_view(ntree, node, input)
34 # return True
37 class NODE_MT_POV_map_create(Menu):
38 """Create maps"""
40 bl_idname = "POVRAY_MT_node_map_create"
41 bl_label = "Create map"
43 def draw(self, context):
44 layout = self.layout
45 layout.operator("node.map_create")
48 def menu_func_nodes(self, context):
49 ob = context.object
50 if hasattr(ob, "active_material"):
51 mat = context.object.active_material
52 if mat and context.space_data.tree_type == "ObjectNodeTree":
53 self.layout.prop(mat.pov, "material_use_nodes")
54 self.layout.menu(NODE_MT_POV_map_create.bl_idname)
55 self.layout.operator("wm.updatepreviewkey")
56 if hasattr(mat, "active_texture") and context.scene.render.engine == "POVRAY_RENDER":
57 tex = mat.active_texture
58 if tex and context.space_data.tree_type == "TextureNodeTree":
59 self.layout.prop(tex.pov, "texture_use_nodes")
62 # ------------------------------------------------------------------------------ #
63 # --------------------------------- Operators ---------------------------------- #
64 # ------------------------------------------------------------------------------ #
67 class NODE_OT_iso_add(Operator):
68 bl_idname = "pov.nodeisoadd"
69 bl_label = "Create iso props"
71 def execute(self, context):
72 ob = bpy.context.object
73 if not bpy.context.scene.use_nodes:
74 bpy.context.scene.use_nodes = True
75 tree = bpy.context.scene.node_tree
76 for node in tree.nodes:
77 if node.bl_idname == "IsoPropsNode" and node.label == ob.name:
78 tree.nodes.remove(node)
79 isonode = tree.nodes.new("IsoPropsNode")
80 isonode.location = (0, 0)
81 isonode.label = ob.name
82 return {"FINISHED"}
85 class NODE_OT_map_create(Operator):
86 bl_idname = "node.map_create"
87 bl_label = "Create map"
89 def execute(self, context):
90 x = y = 0
91 space = context.space_data
92 tree = space.edit_tree
93 for node in tree.nodes:
94 if node.select:
95 x, y = node.location
96 node.select = False
97 tmap = tree.nodes.new("ShaderTextureMapNode")
98 tmap.location = (x - 200, y)
99 return {"FINISHED"}
101 def invoke(self, context, event):
102 wm = context.window_manager
103 return wm.invoke_props_dialog(self)
105 def draw(self, context):
106 layout = self.layout
107 mat = context.object.active_material
108 layout.prop(mat.pov, "inputs_number")
111 class NODE_OT_povray_node_texture_map_add(Operator):
112 bl_idname = "pov.nodetexmapadd"
113 bl_label = "Texture map"
115 def execute(self, context):
116 tree = bpy.context.object.active_material.node_tree
117 tmap = tree.nodes.active
118 mtl = context.object.active_material
119 mtl.node_tree.nodes.active = tmap
120 el = tmap.color_ramp.elements.new(0.5)
121 for el in tmap.color_ramp.elements:
122 el.color = (0, 0, 0, 1)
123 for inp in tmap.inputs:
124 tmap.inputs.remove(inp)
125 for outp in tmap.outputs:
126 tmap.outputs.remove(outp)
127 pattern = tmap.inputs.new("NodeSocketVector", "Pattern")
128 pattern.hide_value = True
129 for i in range(3):
130 tmap.inputs.new("NodeSocketColor", "Shader")
131 tmap.outputs.new("NodeSocketShader", "BSDF")
132 tmap.label = "Texture Map"
133 return {"FINISHED"}
136 class NODE_OT_povray_node_output_add(Operator):
137 bl_idname = "pov.nodeoutputadd"
138 bl_label = "Output"
140 def execute(self, context):
141 tree = bpy.context.object.active_material.node_tree
142 tmap = tree.nodes.new("ShaderNodeOutputMaterial")
143 mtl = context.object.active_material
144 mtl.node_tree.nodes.active = tmap
145 for inp in tmap.inputs:
146 tmap.inputs.remove(inp)
147 tmap.inputs.new("NodeSocketShader", "Surface")
148 tmap.label = "Output"
149 return {"FINISHED"}
152 class NODE_OT_povray_node_layered_add(Operator):
153 bl_idname = "pov.nodelayeredadd"
154 bl_label = "Layered material"
156 def execute(self, context):
157 tree = bpy.context.object.active_material.node_tree
158 tmap = tree.nodes.new("ShaderNodeAddShader")
159 mtl = context.object.active_material
160 mtl.node_tree.nodes.active = tmap
161 tmap.label = "Layered material"
162 return {"FINISHED"}
165 class NODE_OT_povray_input_add(Operator):
166 bl_idname = "pov.nodeinputadd"
167 bl_label = "Add entry"
169 def execute(self, context):
170 mtl = context.object.active_material
171 node = mtl.node_tree.nodes.active
172 if node.type == "VALTORGB":
173 number = 1
174 for inp in node.inputs:
175 if inp.type == "SHADER":
176 number += 1
177 node.inputs.new("NodeSocketShader", "%s" % number)
178 els = node.color_ramp.elements
179 pos1 = els[len(els) - 1].position
180 pos2 = els[len(els) - 2].position
181 pos = (pos1 - pos2) / 2 + pos2
182 el = els.new(pos)
184 if node.bl_idname == "PovraySlopeNode":
185 number = len(node.inputs)
186 node.inputs.new("PovraySocketSlope", "%s" % number)
188 return {"FINISHED"}
191 class NODE_OT_povray_input_remove(Operator):
192 bl_idname = "pov.nodeinputremove"
193 bl_label = "Remove input"
195 def execute(self, context):
196 mtl = context.object.active_material
197 node = mtl.node_tree.nodes.active
198 if node.type in {"VALTORGB", "ADD_SHADER"}:
199 number = len(node.inputs) - 1
200 if number > 5:
201 inp = node.inputs[number]
202 node.inputs.remove(inp)
203 if node.type == "VALTORGB":
204 els = node.color_ramp.elements
205 number = len(els) - 2
206 el = els[number]
207 els.remove(el)
208 return {"FINISHED"}
211 class NODE_OT_povray_image_open(Operator):
212 bl_idname = "pov.imageopen"
213 bl_label = "Open"
215 filepath: StringProperty(
216 name="File Path", description="Open image", maxlen=1024, subtype="FILE_PATH"
219 def invoke(self, context, event):
220 context.window_manager.fileselect_add(self)
221 return {"RUNNING_MODAL"}
223 def execute(self, context):
224 im = bpy.data.images.load(self.filepath)
225 mtl = context.object.active_material
226 node = mtl.node_tree.nodes.active
227 node.image = im.name
228 return {"FINISHED"}
231 # class TEXTURE_OT_povray_open_image(Operator):
232 # bl_idname = "pov.openimage"
233 # bl_label = "Open Image"
235 # filepath = StringProperty(
236 # name="File Path",
237 # description="Open image",
238 # maxlen=1024,
239 # subtype='FILE_PATH',
242 # def invoke(self, context, event):
243 # context.window_manager.fileselect_add(self)
244 # return {'RUNNING_MODAL'}
246 # def execute(self, context):
247 # im=bpy.data.images.load(self.filepath)
248 # tex = context.texture
249 # tex.pov.image = im.name
250 # view_layer = context.view_layer
251 # view_layer.update()
252 # return {'FINISHED'}
255 classes = (
256 NODE_MT_POV_map_create,
257 NODE_OT_iso_add,
258 NODE_OT_map_create,
259 NODE_OT_povray_node_texture_map_add,
260 NODE_OT_povray_node_output_add,
261 NODE_OT_povray_node_layered_add,
262 NODE_OT_povray_input_add,
263 NODE_OT_povray_input_remove,
264 NODE_OT_povray_image_open,
268 def register():
269 bpy.types.NODE_HT_header.append(menu_func_nodes)
270 for cls in classes:
271 register_class(cls)
274 def unregister():
275 for cls in reversed(classes):
276 unregister_class(cls)
277 bpy.types.NODE_HT_header.remove(menu_func_nodes)