# SPDX-License-Identifier: GPL-2.0-or-later """"Nodes based User interface for shaders exported to POV textures.""" import bpy from bpy.utils import register_class, unregister_class from bpy.types import Menu, Operator from bpy.props import ( StringProperty, ) # def find_node_input(node, name): # for input in node.inputs: # if input.name == name: # return input # def panel_node_draw(layout, id_data, output_type, input_name): # if not id_data.use_nodes: # #layout.operator("pov.material_use_nodes", icon='SOUND')#'NODETREE') # #layout.operator("pov.use_shading_nodes", icon='NODETREE') # layout.operator("WM_OT_context_toggle", icon='NODETREE').data_path = \ # "material.pov.material_use_nodes" # return False # ntree = id_data.node_tree # node = find_node(id_data, output_type) # if not node: # layout.label(text="No output node") # else: # input = find_node_input(node, input_name) # layout.template_node_view(ntree, node, input) # return True class NODE_MT_POV_map_create(Menu): """Create maps""" bl_idname = "POVRAY_MT_node_map_create" bl_label = "Create map" def draw(self, context): layout = self.layout layout.operator("node.map_create") def menu_func_nodes(self, context): ob = context.object if hasattr(ob, "active_material"): mat = context.object.active_material if mat and context.space_data.tree_type == "ObjectNodeTree": self.layout.prop(mat.pov, "material_use_nodes") self.layout.menu(NODE_MT_POV_map_create.bl_idname) self.layout.operator("wm.updatepreviewkey") if hasattr(mat, "active_texture") and context.scene.render.engine == "POVRAY_RENDER": tex = mat.active_texture if tex and context.space_data.tree_type == "TextureNodeTree": self.layout.prop(tex.pov, "texture_use_nodes") # ------------------------------------------------------------------------------ # # --------------------------------- Operators ---------------------------------- # # ------------------------------------------------------------------------------ # class NODE_OT_iso_add(Operator): bl_idname = "pov.nodeisoadd" bl_label = "Create iso props" def execute(self, context): ob = bpy.context.object if not bpy.context.scene.use_nodes: bpy.context.scene.use_nodes = True tree = bpy.context.scene.node_tree for node in tree.nodes: if node.bl_idname == "IsoPropsNode" and node.label == ob.name: tree.nodes.remove(node) isonode = tree.nodes.new("IsoPropsNode") isonode.location = (0, 0) isonode.label = ob.name return {"FINISHED"} class NODE_OT_map_create(Operator): bl_idname = "node.map_create" bl_label = "Create map" def execute(self, context): x = y = 0 space = context.space_data tree = space.edit_tree for node in tree.nodes: if node.select: x, y = node.location node.select = False tmap = tree.nodes.new("ShaderTextureMapNode") tmap.location = (x - 200, y) return {"FINISHED"} def invoke(self, context, event): wm = context.window_manager return wm.invoke_props_dialog(self) def draw(self, context): layout = self.layout mat = context.object.active_material layout.prop(mat.pov, "inputs_number") class NODE_OT_povray_node_texture_map_add(Operator): bl_idname = "pov.nodetexmapadd" bl_label = "Texture map" def execute(self, context): tree = bpy.context.object.active_material.node_tree tmap = tree.nodes.active mtl = context.object.active_material mtl.node_tree.nodes.active = tmap el = tmap.color_ramp.elements.new(0.5) for el in tmap.color_ramp.elements: el.color = (0, 0, 0, 1) for inp in tmap.inputs: tmap.inputs.remove(inp) for outp in tmap.outputs: tmap.outputs.remove(outp) pattern = tmap.inputs.new("NodeSocketVector", "Pattern") pattern.hide_value = True for i in range(3): tmap.inputs.new("NodeSocketColor", "Shader") tmap.outputs.new("NodeSocketShader", "BSDF") tmap.label = "Texture Map" return {"FINISHED"} class NODE_OT_povray_node_output_add(Operator): bl_idname = "pov.nodeoutputadd" bl_label = "Output" def execute(self, context): tree = bpy.context.object.active_material.node_tree tmap = tree.nodes.new("ShaderNodeOutputMaterial") mtl = context.object.active_material mtl.node_tree.nodes.active = tmap for inp in tmap.inputs: tmap.inputs.remove(inp) tmap.inputs.new("NodeSocketShader", "Surface") tmap.label = "Output" return {"FINISHED"} class NODE_OT_povray_node_layered_add(Operator): bl_idname = "pov.nodelayeredadd" bl_label = "Layered material" def execute(self, context): tree = bpy.context.object.active_material.node_tree tmap = tree.nodes.new("ShaderNodeAddShader") mtl = context.object.active_material mtl.node_tree.nodes.active = tmap tmap.label = "Layered material" return {"FINISHED"} class NODE_OT_povray_input_add(Operator): bl_idname = "pov.nodeinputadd" bl_label = "Add entry" def execute(self, context): mtl = context.object.active_material node = mtl.node_tree.nodes.active if node.type == "VALTORGB": number = 1 for inp in node.inputs: if inp.type == "SHADER": number += 1 node.inputs.new("NodeSocketShader", "%s" % number) els = node.color_ramp.elements pos1 = els[len(els) - 1].position pos2 = els[len(els) - 2].position pos = (pos1 - pos2) / 2 + pos2 el = els.new(pos) if node.bl_idname == "PovraySlopeNode": number = len(node.inputs) node.inputs.new("PovraySocketSlope", "%s" % number) return {"FINISHED"} class NODE_OT_povray_input_remove(Operator): bl_idname = "pov.nodeinputremove" bl_label = "Remove input" def execute(self, context): mtl = context.object.active_material node = mtl.node_tree.nodes.active if node.type in {"VALTORGB", "ADD_SHADER"}: number = len(node.inputs) - 1 if number > 5: inp = node.inputs[number] node.inputs.remove(inp) if node.type == "VALTORGB": els = node.color_ramp.elements number = len(els) - 2 el = els[number] els.remove(el) return {"FINISHED"} class NODE_OT_povray_image_open(Operator): bl_idname = "pov.imageopen" bl_label = "Open" filepath: StringProperty( name="File Path", description="Open image", maxlen=1024, subtype="FILE_PATH" ) def invoke(self, context, event): context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} def execute(self, context): im = bpy.data.images.load(self.filepath) mtl = context.object.active_material node = mtl.node_tree.nodes.active node.image = im.name return {"FINISHED"} # class TEXTURE_OT_povray_open_image(Operator): # bl_idname = "pov.openimage" # bl_label = "Open Image" # filepath = StringProperty( # name="File Path", # description="Open image", # maxlen=1024, # subtype='FILE_PATH', # ) # def invoke(self, context, event): # context.window_manager.fileselect_add(self) # return {'RUNNING_MODAL'} # def execute(self, context): # im=bpy.data.images.load(self.filepath) # tex = context.texture # tex.pov.image = im.name # view_layer = context.view_layer # view_layer.update() # return {'FINISHED'} classes = ( NODE_MT_POV_map_create, NODE_OT_iso_add, NODE_OT_map_create, NODE_OT_povray_node_texture_map_add, NODE_OT_povray_node_output_add, NODE_OT_povray_node_layered_add, NODE_OT_povray_input_add, NODE_OT_povray_input_remove, NODE_OT_povray_image_open, ) def register(): bpy.types.NODE_HT_header.append(menu_func_nodes) for cls in classes: register_class(cls) def unregister(): for cls in reversed(classes): unregister_class(cls) bpy.types.NODE_HT_header.remove(menu_func_nodes)