WIP: MaterialX addon #104594
@ -46,14 +46,14 @@ def register():
|
|||||||
|
|
||||||
register_classes()
|
register_classes()
|
||||||
nodes.register()
|
nodes.register()
|
||||||
matlib.register()
|
|
||||||
material.register()
|
material.register()
|
||||||
|
matlib.register()
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
log("unregister")
|
log("unregister")
|
||||||
|
|
||||||
material.unregister()
|
|
||||||
matlib.unregister()
|
matlib.unregister()
|
||||||
|
material.unregister()
|
||||||
nodes.unregister()
|
nodes.unregister()
|
||||||
unregister_classes()
|
unregister_classes()
|
||||||
|
@ -1,87 +1,38 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Copyright 2022, AMD
|
# Copyright 2022, AMD
|
||||||
|
|
||||||
from nodeitems_utils import (
|
from .. import logging
|
||||||
NodeCategory,
|
log = logging.Log("bl_nodes")
|
||||||
NodeItem,
|
|
||||||
register_node_categories,
|
|
||||||
unregister_node_categories,
|
from . import (
|
||||||
|
color,
|
||||||
|
converter,
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
shader,
|
||||||
|
texture,
|
||||||
|
vector,
|
||||||
)
|
)
|
||||||
from nodeitems_builtins import (
|
node_parser_classes = (
|
||||||
ShaderNodeCategory,
|
output.ShaderNodeOutputMaterial,
|
||||||
|
|
||||||
|
color.ShaderNodeInvert,
|
||||||
|
color.ShaderNodeMixRGB,
|
||||||
|
|
||||||
|
converter.ShaderNodeMath,
|
||||||
|
|
||||||
|
input.ShaderNodeValue,
|
||||||
|
input.ShaderNodeRGB,
|
||||||
|
|
||||||
|
shader.ShaderNodeAddShader,
|
||||||
|
shader.ShaderNodeMixShader,
|
||||||
|
shader.ShaderNodeEmission,
|
||||||
|
shader.ShaderNodeBsdfGlass,
|
||||||
|
shader.ShaderNodeBsdfDiffuse,
|
||||||
|
shader.ShaderNodeBsdfPrincipled,
|
||||||
|
|
||||||
|
texture.ShaderNodeTexImage,
|
||||||
|
|
||||||
|
vector.ShaderNodeNormalMap,
|
||||||
)
|
)
|
||||||
from .. import utils
|
|
||||||
|
|
||||||
|
|
||||||
class CompatibleShaderNodeCategory(NodeCategory):
|
|
||||||
""" Appear with an active USD plugin in Material shader editor only """
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return context.space_data.tree_type == 'ShaderNodeTree'
|
|
||||||
|
|
||||||
|
|
||||||
# add nodes here once they are supported
|
|
||||||
node_categories = [
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_INPUT", '_', True), "Input", items=[
|
|
||||||
NodeItem('ShaderNodeRGB'),
|
|
||||||
NodeItem('ShaderNodeValue'),
|
|
||||||
], ),
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_OUTPUT", '_', True), "Output", items=[
|
|
||||||
NodeItem('ShaderNodeOutputMaterial'),
|
|
||||||
], ),
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_SHADERS", '_', True), "Shader", items=[
|
|
||||||
NodeItem('ShaderNodeBsdfDiffuse'),
|
|
||||||
NodeItem('ShaderNodeBsdfGlass'),
|
|
||||||
NodeItem('ShaderNodeEmission'),
|
|
||||||
NodeItem('ShaderNodeBsdfPrincipled'),
|
|
||||||
]),
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_TEXTURE", '_', True), "Texture", items=[
|
|
||||||
NodeItem('ShaderNodeTexImage'),
|
|
||||||
], ),
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_COLOR", '_', True), "Color", items=[
|
|
||||||
NodeItem('ShaderNodeInvert'),
|
|
||||||
NodeItem('ShaderNodeMixRGB'),
|
|
||||||
], ),
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_CONVERTER", '_', True), "Converter", items=[
|
|
||||||
NodeItem('ShaderNodeMath'),
|
|
||||||
], ),
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_VECTOR", '_', True), "Vector", items=[
|
|
||||||
NodeItem('ShaderNodeNormalMap'),
|
|
||||||
], ),
|
|
||||||
CompatibleShaderNodeCategory(utils.with_prefix("SHADER_NODE_CATEGORY_LAYOUT", '_', True), "Layout", items=[
|
|
||||||
NodeItem('NodeFrame'),
|
|
||||||
NodeItem('NodeReroute'),
|
|
||||||
], ),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# some nodes are hidden from plugins by Cycles itself(like Material Output), some we could not support.
|
|
||||||
# thus we'll hide 'em all to show only selected set of supported Blender nodes
|
|
||||||
# custom HdUSD_CompatibleShaderNodeCategory will be used instead
|
|
||||||
# def hide_cycles_and_eevee_poll(method):
|
|
||||||
# @classmethod
|
|
||||||
# def func(cls, context):
|
|
||||||
# return not context.scene.render.engine == 'HdUSD' and method(context)
|
|
||||||
# return func
|
|
||||||
|
|
||||||
|
|
||||||
old_shader_node_category_poll = None
|
|
||||||
|
|
||||||
|
|
||||||
def register():
|
|
||||||
# hide Cycles/Eevee menu
|
|
||||||
# global old_shader_node_category_poll
|
|
||||||
# old_shader_node_category_poll = ShaderNodeCategory.poll
|
|
||||||
# ShaderNodeCategory.poll = hide_cycles_and_eevee_poll(ShaderNodeCategory.poll)
|
|
||||||
|
|
||||||
# use custom menu
|
|
||||||
register_node_categories(utils.with_prefix("NODES", '_', True), node_categories)
|
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
|
||||||
# restore Cycles/Eevee menu
|
|
||||||
# if old_shader_node_category_poll and ShaderNodeCategory.poll is not old_shader_node_category_poll:
|
|
||||||
# ShaderNodeCategory.poll = old_shader_node_category_poll
|
|
||||||
|
|
||||||
# remove custom menu
|
|
||||||
unregister_node_categories(utils.with_prefix("NODES", '_', True))
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Copyright 2022, AMD
|
# Copyright 2022, AMD
|
||||||
|
|
||||||
from ..node_parser import NodeParser
|
from .node_parser import NodeParser
|
||||||
|
from . import log
|
||||||
from ... import logging
|
|
||||||
log = logging.Log("bl_nodes.nodes.color")
|
|
||||||
|
|
||||||
|
|
||||||
class ShaderNodeInvert(NodeParser):
|
class ShaderNodeInvert(NodeParser):
|
@ -1,10 +1,8 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Copyright 2022, AMD
|
# Copyright 2022, AMD
|
||||||
|
|
||||||
from ..node_parser import NodeParser
|
from .node_parser import NodeParser
|
||||||
|
from . import log
|
||||||
from ... import logging
|
|
||||||
log = logging.Log("bl_nodes.nodes.converter")
|
|
||||||
|
|
||||||
|
|
||||||
class ShaderNodeMath(NodeParser):
|
class ShaderNodeMath(NodeParser):
|
@ -1,7 +1,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Copyright 2022, AMD
|
# Copyright 2022, AMD
|
||||||
|
|
||||||
from ..node_parser import NodeParser
|
from .node_parser import NodeParser
|
||||||
|
|
||||||
|
|
||||||
class ShaderNodeValue(NodeParser):
|
class ShaderNodeValue(NodeParser):
|
@ -9,6 +9,7 @@ import MaterialX as mx
|
|||||||
from .. import utils
|
from .. import utils
|
||||||
from ..utils import pass_node_reroute
|
from ..utils import pass_node_reroute
|
||||||
from ..nodes import get_mx_node_cls
|
from ..nodes import get_mx_node_cls
|
||||||
|
|
||||||
from .. import logging
|
from .. import logging
|
||||||
log = logging.Log("bl_nodes.node_parser")
|
log = logging.Log("bl_nodes.node_parser")
|
||||||
|
|
||||||
@ -265,8 +266,8 @@ class NodeParser:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def get_node_parser_cls(bl_idname):
|
def get_node_parser_cls(bl_idname):
|
||||||
""" Returns NodeParser class for node_idname or None if not found """
|
""" Returns NodeParser class for node_idname or None if not found """
|
||||||
from . import nodes
|
from . import node_parser_classes
|
||||||
return getattr(nodes, bl_idname, None)
|
return next((cls for cls in node_parser_classes if cls.__name__ == bl_idname), None)
|
||||||
|
|
||||||
# INTERNAL FUNCTIONS
|
# INTERNAL FUNCTIONS
|
||||||
def _export_node(self, node, out_key, to_socket, group_node=None):
|
def _export_node(self, node, out_key, to_socket, group_node=None):
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
# Copyright 2022, AMD
|
|
||||||
|
|
||||||
from .input import *
|
|
||||||
from .output import *
|
|
||||||
from .shader import *
|
|
||||||
from .texture import *
|
|
||||||
from .color import *
|
|
||||||
from .converter import *
|
|
||||||
from .vector import *
|
|
@ -1,7 +1,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Copyright 2022, AMD
|
# Copyright 2022, AMD
|
||||||
|
|
||||||
from ..node_parser import NodeParser, Id
|
from .node_parser import NodeParser, Id
|
||||||
|
|
||||||
|
|
||||||
class ShaderNodeOutputMaterial(NodeParser):
|
class ShaderNodeOutputMaterial(NodeParser):
|
@ -3,10 +3,8 @@
|
|||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from ..node_parser import NodeParser
|
from .node_parser import NodeParser
|
||||||
|
from . import log
|
||||||
from ... import logging
|
|
||||||
log = logging.Log("bl_nodes.nodes.shader")
|
|
||||||
|
|
||||||
|
|
||||||
SSS_MIN_RADIUS = 0.0001
|
SSS_MIN_RADIUS = 0.0001
|
@ -1,8 +1,8 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Copyright 2022, AMD
|
# Copyright 2022, AMD
|
||||||
|
|
||||||
from ..node_parser import NodeParser
|
from .node_parser import NodeParser
|
||||||
from ...utils import cache_image_file
|
from ..utils import cache_image_file
|
||||||
|
|
||||||
|
|
||||||
TEXTURE_ERROR_COLOR = (1.0, 0.0, 1.0) # following Cycles color for wrong Texture nodes
|
TEXTURE_ERROR_COLOR = (1.0, 0.0, 1.0) # following Cycles color for wrong Texture nodes
|
@ -1,10 +1,9 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
# Copyright 2022, AMD
|
# Copyright 2022, AMD
|
||||||
|
|
||||||
from ..node_parser import NodeParser
|
from .node_parser import NodeParser
|
||||||
|
from . import log
|
||||||
|
|
||||||
from ... import logging
|
|
||||||
log = logging.Log("bl_nodes.nodes.vector")
|
|
||||||
|
|
||||||
DEFAULT_SPACE = 'OBJECT'
|
DEFAULT_SPACE = 'OBJECT'
|
||||||
|
|
@ -11,7 +11,7 @@ FORMAT_STR = "%(asctime)s %(levelname)s %(name)s [%(thread)d]: %(message)s"
|
|||||||
|
|
||||||
# root logger for the addon
|
# root logger for the addon
|
||||||
logger = logging.getLogger(ADDON_ALIAS)
|
logger = logging.getLogger(ADDON_ALIAS)
|
||||||
logger.setLevel('DEBUG')
|
logger.setLevel('INFO')
|
||||||
|
|
||||||
# file_handler = logging.handlers.RotatingFileHandler(PLUGIN_ROOT_DIR / 'usdhydra.log',
|
# file_handler = logging.handlers.RotatingFileHandler(PLUGIN_ROOT_DIR / 'usdhydra.log',
|
||||||
# mode='w', encoding='utf-8', delay=True,
|
# mode='w', encoding='utf-8', delay=True,
|
||||||
|
@ -3,27 +3,12 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
|
|
||||||
class MATERIALX_Panel(bpy.types.Panel):
|
|
||||||
bl_space_type = 'PROPERTIES'
|
|
||||||
bl_region_type = 'WINDOW'
|
|
||||||
bl_context = 'render'
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIALX_ChildPanel(bpy.types.Panel):
|
|
||||||
bl_space_type = 'PROPERTIES'
|
|
||||||
bl_region_type = 'WINDOW'
|
|
||||||
bl_parent_id = ''
|
|
||||||
|
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
ui,
|
ui,
|
||||||
properties
|
properties
|
||||||
)
|
)
|
||||||
|
|
||||||
register_classes, unregister_classes = bpy.utils.register_classes_factory([
|
register_classes, unregister_classes = bpy.utils.register_classes_factory([
|
||||||
ui.MATERIAL_PT_context,
|
|
||||||
ui.MATERIAL_PT_preview,
|
|
||||||
ui.MATERIAL_OP_new_mx_node_tree,
|
ui.MATERIAL_OP_new_mx_node_tree,
|
||||||
ui.MATERIAL_OP_duplicate_mx_node_tree,
|
ui.MATERIAL_OP_duplicate_mx_node_tree,
|
||||||
ui.MATERIAL_OP_convert_shader_to_mx,
|
ui.MATERIAL_OP_convert_shader_to_mx,
|
||||||
@ -31,17 +16,14 @@ register_classes, unregister_classes = bpy.utils.register_classes_factory([
|
|||||||
ui.MATERIAL_OP_link_mx_node_tree,
|
ui.MATERIAL_OP_link_mx_node_tree,
|
||||||
ui.MATERIAL_OP_unlink_mx_node_tree,
|
ui.MATERIAL_OP_unlink_mx_node_tree,
|
||||||
ui.MATERIAL_MT_mx_node_tree,
|
ui.MATERIAL_MT_mx_node_tree,
|
||||||
ui.MATERIAL_PT_material,
|
ui.MATERIAL_PT_materialx,
|
||||||
ui.MATERIAL_PT_material_settings_surface,
|
ui.MATERIAL_PT_materialx_surfaceshader,
|
||||||
|
ui.MATERIAL_PT_materialx_displacementshader,
|
||||||
ui.MATERIAL_OP_link_mx_node,
|
ui.MATERIAL_OP_link_mx_node,
|
||||||
ui.MATERIAL_OP_invoke_popup_input_nodes,
|
ui.MATERIAL_OP_invoke_popup_input_nodes,
|
||||||
ui.MATERIAL_OP_invoke_popup_shader_nodes,
|
ui.MATERIAL_OP_invoke_popup_shader_nodes,
|
||||||
ui.MATERIAL_OP_remove_node,
|
ui.MATERIAL_OP_remove_node,
|
||||||
ui.MATERIAL_OP_disconnect_node,
|
ui.MATERIAL_OP_disconnect_node,
|
||||||
ui.MATERIAL_PT_material_settings_displacement,
|
|
||||||
ui.MATERIAL_PT_output_surface,
|
|
||||||
ui.MATERIAL_PT_output_displacement,
|
|
||||||
ui.MATERIAL_PT_output_volume,
|
|
||||||
ui.MATERIAL_OP_export_mx_file,
|
ui.MATERIAL_OP_export_mx_file,
|
||||||
ui.MATERIAL_OP_export_mx_console,
|
ui.MATERIAL_OP_export_mx_console,
|
||||||
ui.MATERIAL_PT_tools,
|
ui.MATERIAL_PT_tools,
|
||||||
|
@ -7,7 +7,7 @@ import bpy
|
|||||||
import MaterialX as mx
|
import MaterialX as mx
|
||||||
|
|
||||||
from ..node_tree import MxNodeTree
|
from ..node_tree import MxNodeTree
|
||||||
from ..bl_nodes.nodes import ShaderNodeOutputMaterial
|
from ..bl_nodes.output import ShaderNodeOutputMaterial
|
||||||
from ..utils import MX_LIBS_DIR
|
from ..utils import MX_LIBS_DIR
|
||||||
|
|
||||||
from ..utils import logging, get_temp_file, MaterialXProperties
|
from ..utils import logging, get_temp_file, MaterialXProperties
|
||||||
@ -30,8 +30,7 @@ class MaterialProperties(MaterialXProperties):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
return next((node for node in material.node_tree.nodes if
|
return next((node for node in material.node_tree.nodes if
|
||||||
# TODO add implementation
|
node.bl_idname == ShaderNodeOutputMaterial.__name__ and
|
||||||
# node.bl_idname == ShaderNodeOutputMaterial.__name__ and
|
|
||||||
node.is_active_output), None)
|
node.is_active_output), None)
|
||||||
|
|
||||||
def export(self, obj: bpy.types.Object) -> [mx.Document, None]:
|
def export(self, obj: bpy.types.Object) -> [mx.Document, None]:
|
||||||
|
@ -8,97 +8,19 @@ import MaterialX as mx
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy_extras.io_utils import ExportHelper
|
from bpy_extras.io_utils import ExportHelper
|
||||||
|
|
||||||
from . import MATERIALX_Panel, MATERIALX_ChildPanel
|
|
||||||
from ..node_tree import MxNodeTree, NODE_LAYER_SEPARATION_WIDTH
|
from ..node_tree import MxNodeTree, NODE_LAYER_SEPARATION_WIDTH
|
||||||
from ..nodes.node import is_mx_node_valid
|
from ..nodes.node import is_mx_node_valid
|
||||||
from .. import utils
|
from .. import utils
|
||||||
from ..preferences import addon_preferences
|
|
||||||
from ..utils import pass_node_reroute, title_str, mx_properties
|
from ..utils import pass_node_reroute, title_str, mx_properties
|
||||||
|
from ..preferences import addon_preferences
|
||||||
|
|
||||||
from ..utils import logging
|
from ..utils import logging
|
||||||
log = logging.Log(tag='material.ui')
|
log = logging.Log(tag='material.ui')
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_context(MATERIALX_Panel):
|
|
||||||
bl_label = ""
|
|
||||||
bl_context = "material"
|
|
||||||
bl_options = {'HIDE_HEADER'}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
if context.active_object and context.active_object.type == 'GPENCIL':
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return context.material or context.object
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
|
|
||||||
material = context.material
|
|
||||||
object = context.object
|
|
||||||
slot = context.material_slot
|
|
||||||
space = context.space_data
|
|
||||||
|
|
||||||
if object:
|
|
||||||
is_sortable = len(object.material_slots) > 1
|
|
||||||
rows = 1
|
|
||||||
if is_sortable:
|
|
||||||
rows = 4
|
|
||||||
|
|
||||||
row = layout.row()
|
|
||||||
|
|
||||||
row.template_list("MATERIAL_UL_matslots", "", object, "material_slots", object,
|
|
||||||
"active_material_index", rows=rows)
|
|
||||||
|
|
||||||
col = row.column(align=True)
|
|
||||||
col.operator("object.material_slot_add", icon='ADD', text="")
|
|
||||||
col.operator("object.material_slot_remove", icon='REMOVE', text="")
|
|
||||||
|
|
||||||
col.menu("MATERIAL_MT_context_menu", icon='DOWNARROW_HLT', text="")
|
|
||||||
|
|
||||||
if is_sortable:
|
|
||||||
col.separator()
|
|
||||||
|
|
||||||
col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
|
|
||||||
col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
|
||||||
|
|
||||||
if object.mode == 'EDIT':
|
|
||||||
row = layout.row(align=True)
|
|
||||||
row.operator("object.material_slot_assign", text="Assign")
|
|
||||||
row.operator("object.material_slot_select", text="Select")
|
|
||||||
row.operator("object.material_slot_deselect", text="Deselect")
|
|
||||||
|
|
||||||
split = layout.split(factor=0.65)
|
|
||||||
|
|
||||||
if object:
|
|
||||||
split.template_ID(object, "active_material", new=utils.with_prefix("material_duplicate_mat_mx_node_tree"))
|
|
||||||
row = split.row()
|
|
||||||
|
|
||||||
if slot:
|
|
||||||
row.prop(slot, "link", text="")
|
|
||||||
else:
|
|
||||||
row.label()
|
|
||||||
elif material:
|
|
||||||
split.template_ID(space, "pin_id")
|
|
||||||
split.separator()
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_preview(MATERIALX_Panel):
|
|
||||||
bl_label = "Preview"
|
|
||||||
bl_context = "material"
|
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return context.material
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
self.layout.template_preview(context.material)
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_OP_new_mx_node_tree(bpy.types.Operator):
|
class MATERIAL_OP_new_mx_node_tree(bpy.types.Operator):
|
||||||
"""Create new MaterialX node tree for selected material"""
|
"""Create new MaterialX node tree for selected material"""
|
||||||
bl_idname = utils.with_prefix("material_new_mx_node_tree")
|
bl_idname = utils.with_prefix('material_new_mx_node_tree')
|
||||||
bl_label = "New"
|
bl_label = "New"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -112,7 +34,7 @@ class MATERIAL_OP_new_mx_node_tree(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_duplicate_mat_mx_node_tree(bpy.types.Operator):
|
class MATERIAL_OP_duplicate_mat_mx_node_tree(bpy.types.Operator):
|
||||||
"""Create duplicates of Material and MaterialX node tree for selected material"""
|
"""Create duplicates of Material and MaterialX node tree for selected material"""
|
||||||
bl_idname = utils.with_prefix("material_duplicate_mat_mx_node_tree")
|
bl_idname = utils.with_prefix('material_duplicate_mat_mx_node_tree')
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -123,7 +45,7 @@ class MATERIAL_OP_duplicate_mat_mx_node_tree(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_duplicate_mx_node_tree(bpy.types.Operator):
|
class MATERIAL_OP_duplicate_mx_node_tree(bpy.types.Operator):
|
||||||
"""Create duplicate of MaterialX node tree for selected material"""
|
"""Create duplicate of MaterialX node tree for selected material"""
|
||||||
bl_idname = utils.with_prefix("material_duplicate_mx_node_tree")
|
bl_idname = utils.with_prefix('material_duplicate_mx_node_tree')
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -138,7 +60,7 @@ class MATERIAL_OP_duplicate_mx_node_tree(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_convert_shader_to_mx(bpy.types.Operator):
|
class MATERIAL_OP_convert_shader_to_mx(bpy.types.Operator):
|
||||||
"""Converts standard shader node tree to MaterialX node tree for selected material"""
|
"""Converts standard shader node tree to MaterialX node tree for selected material"""
|
||||||
bl_idname = utils.with_prefix("material_convert_shader_to_mx")
|
bl_idname = utils.with_prefix('material_convert_shader_to_mx')
|
||||||
bl_label = "Convert to MaterialX"
|
bl_label = "Convert to MaterialX"
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -150,7 +72,7 @@ class MATERIAL_OP_convert_shader_to_mx(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_link_mx_node_tree(bpy.types.Operator):
|
class MATERIAL_OP_link_mx_node_tree(bpy.types.Operator):
|
||||||
"""Link MaterialX node tree to selected material"""
|
"""Link MaterialX node tree to selected material"""
|
||||||
bl_idname = utils.with_prefix("material_link_mx_node_tree")
|
bl_idname = utils.with_prefix('material_link_mx_node_tree')
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
mx_node_tree_name: bpy.props.StringProperty(default="")
|
mx_node_tree_name: bpy.props.StringProperty(default="")
|
||||||
@ -162,7 +84,7 @@ class MATERIAL_OP_link_mx_node_tree(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_unlink_mx_node_tree(bpy.types.Operator):
|
class MATERIAL_OP_unlink_mx_node_tree(bpy.types.Operator):
|
||||||
"""Unlink MaterialX node tree from selected material"""
|
"""Unlink MaterialX node tree from selected material"""
|
||||||
bl_idname = utils.with_prefix("material_unlink_mx_node_tree")
|
bl_idname = utils.with_prefix('material_unlink_mx_node_tree')
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -171,7 +93,7 @@ class MATERIAL_OP_unlink_mx_node_tree(bpy.types.Operator):
|
|||||||
|
|
||||||
|
|
||||||
class MATERIAL_MT_mx_node_tree(bpy.types.Menu):
|
class MATERIAL_MT_mx_node_tree(bpy.types.Menu):
|
||||||
bl_idname = "MATERIAL_MT_mx_node_tree"
|
bl_idname = utils.with_prefix('MATERIAL_MT_mx_node_tree', '_', True)
|
||||||
bl_label = "MX Nodetree"
|
bl_label = "MX Nodetree"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
@ -189,8 +111,11 @@ class MATERIAL_MT_mx_node_tree(bpy.types.Menu):
|
|||||||
op.mx_node_tree_name = ng.name
|
op.mx_node_tree_name = ng.name
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_material(MATERIALX_Panel):
|
class MATERIAL_PT_materialx(bpy.types.Panel):
|
||||||
bl_label = ""
|
bl_idname = utils.with_prefix("MATERIAL_PT_materialx", '_', True)
|
||||||
|
bl_label = "MaterialX"
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
bl_context = "material"
|
bl_context = "material"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -201,12 +126,7 @@ class MATERIAL_PT_material(MATERIALX_Panel):
|
|||||||
mat_materialx = mx_properties(context.material)
|
mat_materialx = mx_properties(context.material)
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
split = layout.row(align=True).split(factor=0.4)
|
row = layout.row(align=True)
|
||||||
row = split.column()
|
|
||||||
row.alignment = 'RIGHT'
|
|
||||||
row.label(text="MaterialX")
|
|
||||||
row = split.row()
|
|
||||||
row = row.row(align=True)
|
|
||||||
row.menu(MATERIAL_MT_mx_node_tree.bl_idname, text="", icon='MATERIAL')
|
row.menu(MATERIAL_MT_mx_node_tree.bl_idname, text="", icon='MATERIAL')
|
||||||
|
|
||||||
if mat_materialx.mx_node_tree:
|
if mat_materialx.mx_node_tree:
|
||||||
@ -219,14 +139,10 @@ class MATERIAL_PT_material(MATERIALX_Panel):
|
|||||||
row.operator(MATERIAL_OP_convert_shader_to_mx.bl_idname, icon='FILE_TICK', text="Convert")
|
row.operator(MATERIAL_OP_convert_shader_to_mx.bl_idname, icon='FILE_TICK', text="Convert")
|
||||||
row.operator(MATERIAL_OP_new_mx_node_tree.bl_idname, icon='ADD', text="")
|
row.operator(MATERIAL_OP_new_mx_node_tree.bl_idname, icon='ADD', text="")
|
||||||
|
|
||||||
def draw_header(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
layout.label(text=f"Material: {context.material.name}")
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_OP_link_mx_node(bpy.types.Operator):
|
class MATERIAL_OP_link_mx_node(bpy.types.Operator):
|
||||||
"""Link MaterialX node"""
|
"""Link MaterialX node"""
|
||||||
bl_idname = utils.with_prefix("material_link_mx_node")
|
bl_idname = utils.with_prefix('material_link_mx_node')
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
new_node_name: bpy.props.StringProperty()
|
new_node_name: bpy.props.StringProperty()
|
||||||
@ -259,7 +175,7 @@ class MATERIAL_OP_link_mx_node(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_invoke_popup_input_nodes(bpy.types.Operator):
|
class MATERIAL_OP_invoke_popup_input_nodes(bpy.types.Operator):
|
||||||
"""Open panel with nodes to link"""
|
"""Open panel with nodes to link"""
|
||||||
bl_idname = utils.with_prefix("material_invoke_popup_input_nodes")
|
bl_idname = utils.with_prefix('material_invoke_popup_input_nodes')
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
input_num: bpy.props.IntProperty()
|
input_num: bpy.props.IntProperty()
|
||||||
@ -324,7 +240,7 @@ class MATERIAL_OP_invoke_popup_input_nodes(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_invoke_popup_shader_nodes(bpy.types.Operator):
|
class MATERIAL_OP_invoke_popup_shader_nodes(bpy.types.Operator):
|
||||||
"""Open panel with shader nodes to link"""
|
"""Open panel with shader nodes to link"""
|
||||||
bl_idname = utils.with_prefix("material_invoke_popup_shader_nodes")
|
bl_idname = utils.with_prefix('material_invoke_popup_shader_nodes')
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
|
||||||
input_num: bpy.props.IntProperty()
|
input_num: bpy.props.IntProperty()
|
||||||
@ -378,7 +294,7 @@ class MATERIAL_OP_invoke_popup_shader_nodes(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_remove_node(bpy.types.Operator):
|
class MATERIAL_OP_remove_node(bpy.types.Operator):
|
||||||
"""Remove linked node"""
|
"""Remove linked node"""
|
||||||
bl_idname = utils.with_prefix("material_remove_node")
|
bl_idname = utils.with_prefix('material_remove_node')
|
||||||
bl_label = "Remove"
|
bl_label = "Remove"
|
||||||
|
|
||||||
input_node_name: bpy.props.StringProperty()
|
input_node_name: bpy.props.StringProperty()
|
||||||
@ -402,7 +318,7 @@ class MATERIAL_OP_remove_node(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATERIAL_OP_disconnect_node(bpy.types.Operator):
|
class MATERIAL_OP_disconnect_node(bpy.types.Operator):
|
||||||
"""Disconnect linked node"""
|
"""Disconnect linked node"""
|
||||||
bl_idname = utils.with_prefix("material_disconnect_node")
|
bl_idname = utils.with_prefix('material_disconnect_node')
|
||||||
bl_label = "Disconnect"
|
bl_label = "Disconnect"
|
||||||
|
|
||||||
output_node_name: bpy.props.StringProperty()
|
output_node_name: bpy.props.StringProperty()
|
||||||
@ -420,9 +336,13 @@ class MATERIAL_OP_disconnect_node(bpy.types.Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_material_settings_surface(MATERIALX_ChildPanel):
|
class MATERIAL_PT_materialx_output(bpy.types.Panel):
|
||||||
bl_label = "surfaceshader"
|
bl_label = ""
|
||||||
bl_parent_id = 'MATERIAL_PT_material'
|
bl_parent_id = MATERIAL_PT_materialx.bl_idname
|
||||||
|
bl_space_type = 'PROPERTIES'
|
||||||
|
bl_region_type = 'WINDOW'
|
||||||
|
|
||||||
|
out_key = ""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
@ -437,7 +357,7 @@ class MATERIAL_PT_material_settings_surface(MATERIALX_ChildPanel):
|
|||||||
layout.label(text="No output node")
|
layout.label(text="No output node")
|
||||||
return
|
return
|
||||||
|
|
||||||
input = output_node.inputs[self.bl_label]
|
input = output_node.inputs[self.out_key]
|
||||||
link = next((link for link in input.links if link.is_valid), None)
|
link = next((link for link in input.links if link.is_valid), None)
|
||||||
|
|
||||||
split = layout.split(factor=0.4)
|
split = layout.split(factor=0.4)
|
||||||
@ -450,7 +370,7 @@ class MATERIAL_PT_material_settings_surface(MATERIALX_ChildPanel):
|
|||||||
box.scale_x = 0.7
|
box.scale_x = 0.7
|
||||||
box.scale_y = 0.5
|
box.scale_y = 0.5
|
||||||
op = box.operator(MATERIAL_OP_invoke_popup_shader_nodes.bl_idname, icon='HANDLETYPE_AUTO_CLAMP_VEC')
|
op = box.operator(MATERIAL_OP_invoke_popup_shader_nodes.bl_idname, icon='HANDLETYPE_AUTO_CLAMP_VEC')
|
||||||
op.input_num = output_node.inputs.find(self.bl_label)
|
op.input_num = output_node.inputs.find(self.out_key)
|
||||||
|
|
||||||
if link and is_mx_node_valid(link.from_node):
|
if link and is_mx_node_valid(link.from_node):
|
||||||
row.prop(link.from_node, 'name', text="")
|
row.prop(link.from_node, 'name', text="")
|
||||||
@ -462,7 +382,6 @@ class MATERIAL_PT_material_settings_surface(MATERIALX_ChildPanel):
|
|||||||
row.label(icon='BLANK1')
|
row.label(icon='BLANK1')
|
||||||
|
|
||||||
if not link:
|
if not link:
|
||||||
layout.label(text="No input node")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if not is_mx_node_valid(link.from_node):
|
if not is_mx_node_valid(link.from_node):
|
||||||
@ -477,102 +396,23 @@ class MATERIAL_PT_material_settings_surface(MATERIALX_ChildPanel):
|
|||||||
link.from_node.draw_node_view(context, layout)
|
link.from_node.draw_node_view(context, layout)
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_material_settings_displacement(MATERIALX_ChildPanel):
|
class MATERIAL_PT_materialx_surfaceshader(MATERIAL_PT_materialx_output):
|
||||||
bl_label = "displacementshader"
|
bl_idname = utils.with_prefix('MATERIAL_PT_materialx_surfaceshader', '_', True)
|
||||||
bl_parent_id = 'MATERIAL_PT_material'
|
bl_label = "Surface Shader"
|
||||||
|
|
||||||
@classmethod
|
out_key = 'surfaceshader'
|
||||||
def poll(cls, context):
|
|
||||||
return bool(mx_properties(context.material).mx_node_tree)
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
|
|
||||||
node_tree = mx_properties(context.material).mx_node_tree
|
|
||||||
output_node = node_tree.output_node
|
|
||||||
if not output_node:
|
|
||||||
layout.label(text="No output node")
|
|
||||||
return
|
|
||||||
|
|
||||||
input = output_node.inputs[self.bl_label]
|
|
||||||
link = next((link for link in input.links if link.is_valid), None)
|
|
||||||
|
|
||||||
split = layout.split(factor=0.4)
|
|
||||||
row = split.row(align=True)
|
|
||||||
row.alignment = 'RIGHT'
|
|
||||||
row.label(text='Displacement')
|
|
||||||
|
|
||||||
row = split.row(align=True)
|
|
||||||
box = row.box()
|
|
||||||
box.scale_x = 0.7
|
|
||||||
box.scale_y = 0.5
|
|
||||||
op = box.operator(MATERIAL_OP_invoke_popup_shader_nodes.bl_idname, icon='HANDLETYPE_AUTO_CLAMP_VEC')
|
|
||||||
op.input_num = output_node.inputs.find(self.bl_label)
|
|
||||||
|
|
||||||
if link and is_mx_node_valid(link.from_node):
|
|
||||||
row.prop(link.from_node, 'name', text="")
|
|
||||||
else:
|
|
||||||
box = row.box()
|
|
||||||
box.scale_y = 0.5
|
|
||||||
box.label(text='None')
|
|
||||||
|
|
||||||
row.label(icon='BLANK1')
|
|
||||||
|
|
||||||
if not link:
|
|
||||||
layout.label(text="No input node")
|
|
||||||
return
|
|
||||||
|
|
||||||
if not is_mx_node_valid(link.from_node):
|
|
||||||
layout.label(text="Unsupported node")
|
|
||||||
return
|
|
||||||
|
|
||||||
link = pass_node_reroute(link)
|
|
||||||
if not link:
|
|
||||||
return
|
|
||||||
|
|
||||||
layout.separator()
|
|
||||||
|
|
||||||
link.from_node.draw_node_view(context, layout)
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_output_node(MATERIALX_ChildPanel):
|
class MATERIAL_PT_materialx_displacementshader(MATERIAL_PT_materialx_output):
|
||||||
bl_label = ""
|
bl_idname = utils.with_prefix('MATERIAL_PT_materialx_sdisplacementshader', '_', True)
|
||||||
bl_parent_id = 'MATERIAL_PT_material'
|
bl_label = "Displacement Shader"
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return not bool(mx_properties(context.material).mx_node_tree)
|
|
||||||
|
|
||||||
def draw(self, context):
|
|
||||||
layout = self.layout
|
|
||||||
|
|
||||||
node_tree = context.material.node_tree
|
|
||||||
|
|
||||||
output_node = mx_properties(context.material).output_node
|
|
||||||
if not output_node:
|
|
||||||
layout.label(text="No output node")
|
|
||||||
return
|
|
||||||
|
|
||||||
input = output_node.inputs[self.bl_label]
|
|
||||||
layout.template_node_view(node_tree, output_node, input)
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_output_surface(MATERIAL_PT_output_node):
|
|
||||||
bl_label = "Surface"
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_output_displacement(MATERIAL_PT_output_node):
|
|
||||||
bl_label = "Displacement"
|
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
out_key = 'displacementshader'
|
||||||
class MATERIAL_PT_output_volume(MATERIAL_PT_output_node):
|
|
||||||
bl_label = "Volume"
|
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_OP_export_mx_file(bpy.types.Operator, ExportHelper):
|
class MATERIAL_OP_export_mx_file(bpy.types.Operator, ExportHelper):
|
||||||
bl_idname = utils.with_prefix("material_export_mx_file")
|
bl_idname = utils.with_prefix('material_export_mx_file')
|
||||||
bl_label = "Export MaterialX"
|
bl_label = "Export MaterialX"
|
||||||
bl_description = "Export material as MaterialX node tree to .mtlx file"
|
bl_description = "Export material as MaterialX node tree to .mtlx file"
|
||||||
|
|
||||||
@ -659,7 +499,7 @@ class MATERIAL_OP_export_mx_file(bpy.types.Operator, ExportHelper):
|
|||||||
|
|
||||||
|
|
||||||
class MATERIAL_OP_export_mx_console(bpy.types.Operator):
|
class MATERIAL_OP_export_mx_console(bpy.types.Operator):
|
||||||
bl_idname = utils.with_prefix("material_export_mx_console")
|
bl_idname = utils.with_prefix('material_export_mx_console')
|
||||||
bl_label = "Export MaterialX to Console"
|
bl_label = "Export MaterialX to Console"
|
||||||
bl_description = "Export material as MaterialX node tree to console"
|
bl_description = "Export material as MaterialX node tree to console"
|
||||||
|
|
||||||
@ -672,7 +512,8 @@ class MATERIAL_OP_export_mx_console(bpy.types.Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_tools(MATERIALX_Panel):
|
class MATERIAL_PT_tools(bpy.types.Panel):
|
||||||
|
bl_idname = utils.with_prefix('MATERIAL_PT_tools', '_', True)
|
||||||
bl_label = "MaterialX Tools"
|
bl_label = "MaterialX Tools"
|
||||||
bl_space_type = "NODE_EDITOR"
|
bl_space_type = "NODE_EDITOR"
|
||||||
bl_region_type = "UI"
|
bl_region_type = "UI"
|
||||||
@ -691,50 +532,18 @@ class MATERIAL_PT_tools(MATERIALX_Panel):
|
|||||||
layout.operator(MATERIAL_OP_export_mx_file.bl_idname, text="Export MaterialX to file", icon='EXPORT')
|
layout.operator(MATERIAL_OP_export_mx_file.bl_idname, text="Export MaterialX to file", icon='EXPORT')
|
||||||
|
|
||||||
|
|
||||||
class MATERIAL_PT_dev(MATERIALX_ChildPanel):
|
class MATERIAL_PT_dev(bpy.types.Panel):
|
||||||
|
bl_idname = utils.with_prefix('MATERIAL_PT_dev', '_', True)
|
||||||
bl_label = "Dev"
|
bl_label = "Dev"
|
||||||
bl_parent_id = 'MATERIAL_PT_tools'
|
bl_parent_id = MATERIAL_PT_tools.bl_idname
|
||||||
bl_space_type = "NODE_EDITOR"
|
bl_space_type = "NODE_EDITOR"
|
||||||
bl_region_type = "UI"
|
bl_region_type = "UI"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return addon_preferences().dev_tools
|
preferences = addon_preferences()
|
||||||
|
return preferences.dev_tools if preferences else True
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
layout.operator(MATERIAL_OP_export_mx_console.bl_idname)
|
layout.operator(MATERIAL_OP_export_mx_console.bl_idname)
|
||||||
|
|
||||||
|
|
||||||
def depsgraph_update(depsgraph):
|
|
||||||
context = bpy.context
|
|
||||||
mx_node_tree = None
|
|
||||||
if hasattr(context, 'object') and context.object and context.object.active_material:
|
|
||||||
mx_node_tree = mx_properties(context.object.active_material).mx_node_tree
|
|
||||||
|
|
||||||
# trying to show MaterialX area with node tree or Shader area
|
|
||||||
screen = context.screen
|
|
||||||
if not hasattr(screen, 'areas'):
|
|
||||||
return
|
|
||||||
|
|
||||||
for window in context.window_manager.windows:
|
|
||||||
for area in window.screen.areas:
|
|
||||||
if not mx_node_tree:
|
|
||||||
if area.ui_type != utils.with_prefix('MxNodeTree'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
area.ui_type = 'ShaderNodeTree'
|
|
||||||
continue
|
|
||||||
|
|
||||||
if area.ui_type not in (utils.with_prefix('MxNodeTree'), 'ShaderNodeTree'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
space = next(s for s in area.spaces if s.type == 'NODE_EDITOR')
|
|
||||||
if space.pin or space.shader_type != 'OBJECT':
|
|
||||||
continue
|
|
||||||
|
|
||||||
area.ui_type = utils.with_prefix('MxNodeTree')
|
|
||||||
space.node_tree = mx_node_tree
|
|
||||||
|
|
||||||
mx_node_tree.update_links()
|
|
||||||
|
@ -84,12 +84,16 @@ class MATLIB_OP_load_package(bpy.types.Operator):
|
|||||||
|
|
||||||
class MATLIB_PT_matlib(bpy.types.Panel):
|
class MATLIB_PT_matlib(bpy.types.Panel):
|
||||||
bl_idname = utils.with_prefix("MATLIB_PT_matlib", '_', True)
|
bl_idname = utils.with_prefix("MATLIB_PT_matlib", '_', True)
|
||||||
bl_label = "Material Library"
|
bl_label = "MaterialX Library"
|
||||||
bl_context = "material"
|
bl_context = "material"
|
||||||
bl_region_type = 'WINDOW'
|
bl_region_type = 'WINDOW'
|
||||||
bl_space_type = 'PROPERTIES'
|
bl_space_type = 'PROPERTIES'
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return context.material
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
matlib_prop = utils.mx_properties(context.window_manager).matlib
|
matlib_prop = utils.mx_properties(context.window_manager).matlib
|
||||||
|
@ -253,10 +253,10 @@ class MxNodeTree(bpy.types.ShaderNodeTree):
|
|||||||
def update_(self):
|
def update_(self):
|
||||||
self.update_links()
|
self.update_links()
|
||||||
|
|
||||||
# TODO: Uncomment
|
for material in bpy.data.materials:
|
||||||
# for material in bpy.data.materials:
|
if utils.mx_properties(material).mx_node_tree and \
|
||||||
# if material.hdusd.mx_node_tree and material.hdusd.mx_node_tree.name == self.name:
|
utils.mx_properties(material).mx_node_tree.name == self.name:
|
||||||
# material.hdusd.update()
|
utils.mx_properties(material).update()
|
||||||
|
|
||||||
for window in bpy.context.window_manager.windows:
|
for window in bpy.context.window_manager.windows:
|
||||||
for area in window.screen.areas:
|
for area in window.screen.areas:
|
||||||
|
@ -195,7 +195,8 @@ class NODES_PT_dev(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return addon_preferences().dev_tools
|
preferences = addon_preferences()
|
||||||
|
return preferences.dev_tools if preferences else True
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
@ -37,4 +37,8 @@ class AddonPreferences(bpy.types.AddonPreferences):
|
|||||||
|
|
||||||
|
|
||||||
def addon_preferences():
|
def addon_preferences():
|
||||||
|
if ADDON_ALIAS not in bpy.context.preferences.addons:
|
||||||
|
return None
|
||||||
|
|
||||||
return bpy.context.preferences.addons[ADDON_ALIAS].preferences
|
return bpy.context.preferences.addons[ADDON_ALIAS].preferences
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ MATLIB_FOLDER = "matlib"
|
|||||||
MATLIB_DIR = ADDON_DATA_DIR / MATLIB_FOLDER
|
MATLIB_DIR = ADDON_DATA_DIR / MATLIB_FOLDER
|
||||||
MATLIB_URL = "https://api.matlib.gpuopen.com/api"
|
MATLIB_URL = "https://api.matlib.gpuopen.com/api"
|
||||||
|
|
||||||
|
TEMP_FOLDER = "bl-materialx"
|
||||||
|
|
||||||
SUPPORTED_FORMATS = {".png", ".jpeg", ".jpg", ".hdr", ".tga", ".bmp"}
|
SUPPORTED_FORMATS = {".png", ".jpeg", ".jpg", ".hdr", ".tga", ".bmp"}
|
||||||
DEFAULT_FORMAT = ".hdr"
|
DEFAULT_FORMAT = ".hdr"
|
||||||
BLENDER_DEFAULT_FORMAT = "HDR"
|
BLENDER_DEFAULT_FORMAT = "HDR"
|
||||||
@ -331,7 +333,7 @@ def export_mx_to_file(doc, filepath, *, mx_node_tree=None, is_export_deps=False,
|
|||||||
|
|
||||||
|
|
||||||
def temp_dir():
|
def temp_dir():
|
||||||
d = Path(tempfile.gettempdir()) / "blender-mx"
|
d = Path(tempfile.gettempdir()) / TEMP_FOLDER
|
||||||
if not d.is_dir():
|
if not d.is_dir():
|
||||||
log("Creating temp dir", d)
|
log("Creating temp dir", d)
|
||||||
d.mkdir()
|
d.mkdir()
|
||||||
|
Loading…
Reference in New Issue
Block a user