Files
blender-addons/render_povray/nodes_gui.py
Campbell Barton e8da6131fd License headers: use SPDX-FileCopyrightText for all addons
Move copyright text to SPDX-FileCopyrightText or set to the
Blender Foundation so "make check_licenses" now runs without warnings.
2023-06-15 16:54:05 +10:00

280 lines
8.3 KiB
Python

# SPDX-FileCopyrightText: 2022 Blender Foundation
#
# 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)