This script adds an app handler triggered on scene update. That runs my watch_materials
function.
First the watch_materials
function checks to be sure you are using cycles. Then if there is another material it goes to the active object's active material and changes the node.
import bpy
from bpy.app.handlers import persistent
mat_count = len(bpy.data.materials)
@persistent
def watch_materials(something):
global mat_count
if bpy.context.scene.render.engine == 'CYCLES':
if len(bpy.data.materials) > mat_count:
mat_count = len(bpy.data.materials)
#get active object's active material
node_tree = bpy.context.active_object.active_material.node_tree
#save the location of the diffuse node
location = node_tree.nodes['Diffuse BSDF'].location.copy()
#delete that node
node_tree.nodes.remove(node_tree.nodes['Diffuse BSDF'])
#add new Principled node
principled = node_tree.nodes.new('ShaderNodeBsdfPrincipled')
# move it to where the diffuse node used to be
principled.location = location
#make the connection
node_tree.links.new(principled.outputs['BSDF'], node_tree.nodes['Material Output'].inputs['Surface'])
bpy.app.handlers.scene_update_post.append(watch_materials)
Just copy that script into blender's text editor and press the "Run Script" button. After that any new materials you add will look like this.
Granted, there are still things that could be done to this script. For example if you added a new material without the default nodes (can only be done through python) my script will break.
I have to mention Jerryno, his comment pointed me towards the app handler. I had made a version of this using a timer driven modal, it was nice, but far more complex (it works too).