1 # SPDX-License-Identifier: GPL-2.0-or-later
3 """"Nodes based User interface for shaders exported to POV textures."""
6 from bpy
.utils
import register_class
, unregister_class
7 from bpy
.types
import Menu
, Operator
8 from bpy
.props
import (
12 # def find_node_input(node, name):
13 # for input in node.inputs:
14 # if input.name == name:
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"
25 # ntree = id_data.node_tree
27 # node = find_node(id_data, output_type)
29 # layout.label(text="No output node")
31 # input = find_node_input(node, input_name)
32 # layout.template_node_view(ntree, node, input)
37 class NODE_MT_POV_map_create(Menu
):
40 bl_idname
= "POVRAY_MT_node_map_create"
41 bl_label
= "Create map"
43 def draw(self
, context
):
45 layout
.operator("node.map_create")
48 def menu_func_nodes(self
, context
):
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
85 class NODE_OT_map_create(Operator
):
86 bl_idname
= "node.map_create"
87 bl_label
= "Create map"
89 def execute(self
, context
):
91 space
= context
.space_data
92 tree
= space
.edit_tree
93 for node
in tree
.nodes
:
97 tmap
= tree
.nodes
.new("ShaderTextureMapNode")
98 tmap
.location
= (x
- 200, y
)
101 def invoke(self
, context
, event
):
102 wm
= context
.window_manager
103 return wm
.invoke_props_dialog(self
)
105 def draw(self
, context
):
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
130 tmap
.inputs
.new("NodeSocketColor", "Shader")
131 tmap
.outputs
.new("NodeSocketShader", "BSDF")
132 tmap
.label
= "Texture Map"
136 class NODE_OT_povray_node_output_add(Operator
):
137 bl_idname
= "pov.nodeoutputadd"
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"
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"
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":
174 for inp
in node
.inputs
:
175 if inp
.type == "SHADER":
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
184 if node
.bl_idname
== "PovraySlopeNode":
185 number
= len(node
.inputs
)
186 node
.inputs
.new("PovraySocketSlope", "%s" % number
)
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
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
211 class NODE_OT_povray_image_open(Operator
):
212 bl_idname
= "pov.imageopen"
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
231 # class TEXTURE_OT_povray_open_image(Operator):
232 # bl_idname = "pov.openimage"
233 # bl_label = "Open Image"
235 # filepath = StringProperty(
237 # description="Open image",
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'}
256 NODE_MT_POV_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
,
269 bpy
.types
.NODE_HT_header
.append(menu_func_nodes
)
275 for cls
in reversed(classes
):
276 unregister_class(cls
)
277 bpy
.types
.NODE_HT_header
.remove(menu_func_nodes
)