I am trying to build a python script that will apply textures to my object and place it into a specific object hierarchy. It was working fine until I started getting two errors that said:
rna_uiItemO: operator missing srna ‘build.material’
and
rna_uiItemO: operator missing srna ‘build.hierarchy’
Does anyone know what is causing this? Here is the script:
bl_info = {
"name": "MassiveLoop Heiarchy Builder V4",
"blender": (2, 80, 0),
"category": "Object",
}
#Before running this script make sure you have selected the colliders cubes
import bpy
from bpy.types import (
Operator,
Panel,
PropertyGroup,
)
class BuildHeiarchy(bpy.types.Operator):
"""Build the heiarchy for exporting models""" # Use this as a tooltip for menu items and buttons.
bl_idname = "build.heiarchy" # Unique identifier for buttons and menu items to reference.
bl_label = "Build MassiveLoop Heiarchy V4" # Display name in the interface.
bl_options = {'REGISTER', 'UNDO'} # Enable undo for the operator.
projectname: bpy.props.StringProperty(name="Object Name", description="named bob", default="Bob")
def execute(self, context): # execute() is called when running the operator.
# -------------------------------------------
colliders = bpy.context.selected_objects #Adds the selected objects to the colliders group
objName = self.projectname #"Bob" #Name of the object that has been modeled
if bpy.data.objects.get(objName) is not None:
mainOBJ = bpy.data.objects[objName] #Finds the main object
mainOBJ.name = "GEO_" + mainOBJ.name #Renames the main object
for i in range(len(colliders)):
colliders[i].name = objName + "_Collider_" + str(i + 1) #Renames the collider objects
bpy.ops.object.empty_add(radius=0.1,location=(0,0,0)) #Creates the parent object
parentOBJ = bpy.context.active_object
parentOBJ.name = objName
bpy.ops.object.empty_add(radius=0.1,location=(0,0,0)) #Creates the Collider Group
collidersGRP = bpy.context.active_object
collidersGRP.name = "GRP_Colliders"
#The area below sets the object heiarchy
collidersGRP.parent = parentOBJ
for i in range(len(colliders)):
colliders[i].parent = collidersGRP
mainOBJ.parent = parentOBJ
self.report({'INFO'}, "Heiarchy Created")
if bpy.data.objects.get(objName) is None:
self.report({'WARNING'}, "No Object Exists with that name!!!!!")
#---------------------------------------------
return {'FINISHED'} # Lets Blender know the operator finished successfully.
class BuildMaterial(bpy.types.Operator):
"""Build the material for exporting models""" # Use this as a tooltip for menu items and buttons.
bl_idname = "build.material" # Unique identifier for buttons and menu items to reference.
bl_label = "Build MassiveLoop Material V4" # Display name in the interface.
bl_options = {'REGISTER', 'UNDO'} # Enable undo for the operator.
projectname: bpy.props.StringProperty(name="Object Name", description="named bob", default="Bob")
texSize: bpy.props.StringProperty(name="Size of Textures", description="The size of the texture files to be imported when using Create Material", default="4k")
def execute(self, context): # execute() is called when running the operator.
# -------------------------------------------
objName = self.projectname #Name of the object that has been modeled
selectedObjects = [bpy.context.selected_objects]
if bpy.data.objects.get(objName) is not None:
mat = bpy.data.materials.get(objName)
if mat is None:
# create material
mat = bpy.data.materials.new(name=objName)
for obj in bpy.context.selected_objects:
if obj.data.materials:
# assign to 1st material slot
obj.data.materials[0] = mat
self.report({'INFO'}, "Material Created")
print("Material Created")
else:
# no slots
obj.data.materials.append(mat)
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
texImageAT = mat.node_tree.nodes.new('ShaderNodeTexImage')
texImageAT.image = bpy.data.images.load("C:\\Users\\Laire\\Desktop\\" + objName + "_Stuff\\" + objName + "\\LowPoly\\Textures\\" + objName + "_" + self.texSize + "_AlbedoTransparency.tif")
mat.node_tree.links.new(bsdf.inputs['Base Color'], texImageAT.outputs['Color'])
texImageAT = mat.node_tree.nodes.new('ShaderNodeTexImage')
texImageAT.image = bpy.data.images.load("C:\\Users\\Laire\\Desktop\\" + objName + "_Stuff\\" + objName + "\\LowPoly\\Textures\\" + objName + "_" + self.texSize + "_MetallicSmoothness.tif")
mat.node_tree.links.new(bsdf.inputs['Metallic'], texImageAT.outputs['Color'])
texImageAT = mat.node_tree.nodes.new('ShaderNodeTexImage')
texImageAT.image = bpy.data.images.load("C:\\Users\\Laire\\Desktop\\" + objName + "_Stuff\\" + objName + "\\LowPoly\\Textures\\" + objName + "_" + self.texSize + "_Normal.tif")
mat.node_tree.links.new(bsdf.inputs['Normal'], texImageAT.outputs['Color'])
self.report({'INFO'}, "Material Created")
#---------------------------------------------
return {'FINISHED'} # Lets Blender know the operator finished successfully.
class OBJECT_PT_Builder(Panel):
bl_label = "MassiveLoop Builders"
bl_idname = "OBJECT_PT_MassiveLoopPanel"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Create"
bl_context = "objectmode"
bl_options = {"DEFAULT_CLOSED"}
def draw(self, context):
layout = self.layout
wm = context.window_manager
col = layout.column(align=True)
prop_new = col.operator("build.heiarchy", text="Heiarchy Builder", icon="SHADERFX")
prop_new = col.operator("build.material", text="Material Builder", icon="SHADERFX")
def menu_func(self, context):
self.layout.operator(BuildHeiarchy.bl_idname)
def register():
bpy.utils.register_class(OBJECT_PT_Builder)
bpy.types.VIEW3D_MT_object.append(menu_func)
def unregister():
bpy.utils.unregister_class(OBJECT_PT_Builder)
# This allows you to run the script directly from Blender's Text editor
# to test the add-on without having to install it.
if __name__ == "__main__":
register()