Material Preview into Node-editor window: it almost works!

Hi, I’ve tried with copy paste from Ui.py to space-node.py but had no luck.
I don’t know python, that’s why.
Can anyone point me how to do this?
Screenshot to make it clearer:

Attachments


Just copying won’t work as the context in the node editor doesn’t contain a reference to the active material…

this, for example works:

class NODE_PT_active_material_preview(Panel):
    bl_space_type = 'NODE_EDITOR'
    bl_region_type = 'UI'
    bl_label = "Preview"
    bl_options = {'DEFAULT_CLOSED'}
    
    @classmethod
    def poll(cls, context):
        ntree = context.space_data.node_tree
        return ntree is not None and ntree.type=='SHADER'
        
    def draw(self, context):
        self.layout.template_preview(context.active_object.active_material)

Just place somewhere in the space_node.py, and in by the end in the classes list, just add NODE_PT_active_material_preview (or whatever name you choose for the panel above :slight_smile: ).

classes = (
    NODE_HT_header,
    NODE_MT_editor_menus,
    NODE_MT_add,
    NODE_MT_view,
    NODE_MT_select,
    NODE_MT_node,
    NODE_MT_node_color_presets,
    NODE_MT_node_color_specials,
    NODE_PT_active_node_generic,
    NODE_PT_active_node_color,
    NODE_PT_active_node_properties,
    NODE_PT_backdrop,
    NODE_PT_quality,
    NODE_UL_interface_sockets,
    NODE_PT_grease_pencil,
    NODE_PT_grease_pencil_palettecolor,
    NODE_PT_grease_pencil_tools,
    NODE_PT_tools_grease_pencil_draw,
    NODE_PT_tools_grease_pencil_edit,
    NODE_PT_tools_grease_pencil_sculpt,
    NODE_PT_tools_grease_pencil_brush,
    NODE_PT_tools_grease_pencil_brushcurves,
    NODE_PT_active_material_preview,
)
1 Like

Wow! Thank you A LOT Secrop, it worked!
I applied it to a buildbot build, but I had to fight a few errors in the original space-node.py file:

when I load it up in a text editor and press the “Run Script” button Blender returns an error (in the console window) in line 24:

24    <b>from .properties_grease_pencil_common import (</b>
25    GreasePencilDrawingToolsPanel,
26    GreasePencilStrokeEditPanel,
27    GreasePencilStrokeSculptPanel,
28    GreasePencilBrushPanel,
29    GreasePencilBrushCurvesPanel,
30    GreasePencilDataPanel,
31    GreasePencilPaletteColorPanel,
32    GreasePencilToolsPanel
33)

Even without pasting anything! As if the error is already present in the file… what?!

Anyway, I #commented out# every GreasePencil related line in the file and the Preview panel popped up, wow!
Strange thing is that also the Grease Pencil’s panels are there. So what did my commenting out actually do?

Now, any suggestion on how to make the panel auto-update?

Ohhh i didn’t notice it wasn’t updating… Must investigate further. I’ll tell you something as soon i figure that out.

Ok… after some inspection, the template_preview can only be updated by recreating it (resizing either the template_preview or the toolshelf)… Changing this behaviour might be a bit difficult from the pyhton api.

The good news is that there’s also the template_id_preview, that updates after changes in the Id_datablock. :slight_smile:

Here’s a fix in the form of an addon (you can place it in your user addons folder and enable it in the preferences)
It’s not exactly the same as the template_preview, but it does the job.

bl_info = {
    "name": "NodeEditor Material Preview",
    "author": "",
    "version": (1, 0),
    "blender": (2, 79, 0),
    "location": "NodeEditor &gt; ToolShelf",
    "description": "Displays a material preview in the toolshelf",
    "warning": "",
    "wiki_url": "",
    "category": "Node",
    }



import bpy

class NODE_PT_material_preview(bpy.types.Panel):
    bl_space_type = 'NODE_EDITOR'
    bl_region_type = 'UI'
    bl_label = "Preview"
    bl_options = {'DEFAULT_CLOSED'}
    
    @classmethod
    def poll(cls, context):
        ntree = context.space_data.node_tree
        return ntree is not None and ntree.type=='SHADER'
        
    def draw(self, context):
        ob = context.active_object
        self.layout.template_ID_preview(ob, "active_material")

def register():
    bpy.utils.register_class(NODE_PT_material_preview)

def unregister():
    bpy.utils.unregister_class(NODE_PT_material_preview)

and you can also revert the space_node.py to the original. :wink:

1 Like

Its kind of lame that we can update the preview. I even tried simple solution like copy diffuse color and paste it back, this forces an update. Even this doesnt update the preview. yet when the mat preview in the material tab does update when you do this, super weird.

These kinds of things should be gone in 2.8, with the new depsgraph… (hoping)

Have not looked into 2.8 yet seems all is different. Sorry of zhitry cause that means I need to do tons of work on add-ons I made

Change this line for :
layout.template_preview(context.active_object.active_material, show_buttons=False)

Perhaps a bit of topic. But i got a big preview render option. It quite nice and i can set the size i want to it

I made it for an external render engine i used. Hacked together some code i found on the web and added some minor options. The window is just a regular WM window

Render Big Preview

PS why not convert this to an addon. Then you wont need to hack it each time with an update. Also you can make other people happy with this

3 Likes

@rombout Could you share the code for it, please?
I’m looking for something like this in vray for blender.

Sure here it is, you will need to adjust it to your engine. Also first time it opens its small and you need to drag it down to enlarge it. Thats is one downside to this. Also ive added the panelwith as a setting so this can be adjusted. But this doesnt work for the height

PS i also used a global var so the main preview panel is hidden once this one is open. Otherwise it would get messy. Also you need to force an update by resizing it and close/ reopen it. It doesnt work flawless…

class VIEW3D_MT_BigPreview(Operator):
	bl_idname = "thea.big_preview"
	bl_label = "Big Preview"
	bl_context = "material"
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'PREVIEW'

	def draw_header(self, context):
		layout = self.layout
		layout.label("Big Preview")

	def modal(self, context, event):
		if event.type in {'RIGHTMOUSE', 'ESC', 'LEFTMOUSE'}:
			self.tag_redraw()
			return {'CANCELLED'}
		return {"RUNNING_MODAL"}

	def execute(self, context):
		thea_globals.panelMatPreview = True
		return {'FINISHED'}

	def cancel(self, context):
		self.execute(context)

	def invoke(self, context, event):
		print("Invoke big preview")
		thea_globals.panelMatPreview = False
		wm = context.window_manager
		return wm.invoke_popup(self, width=bpy.context.scene.thea_PanelWidth, height=800)

		return {"RUNNING_MODAL"}

	def draw(self, context):
		layout = self.layout
		mat = bpy.context.object.active_material
		layout.label("Big Preview")
		layout.template_preview(mat, show_buttons=False, preview_id = "thea.big_preview")
		layout.label("Resize window to forces update")

Also i added a button above the preview panel so you can force it to open. I added this because i also have a shortcut connected to this.

class TheaMaterialPreview(MaterialButtonsPanel, bpy.types.Panel):
	bl_idname = "MATERIAL_PT_MatPreview"
	bl_space_type = 'PROPERTIES'
	bl_region_type = 'WINDOW'
	bl_context = "material"
	bl_label = "Preview"
	bl_options = {"DEFAULT_CLOSED"}

	COMPAT_ENGINES = set(['THEA_RENDER'])
	panelMatPreview = True

	@classmethod
	def poll(cls, context):
		engine = context.scene.render.engine
		return (
			   engine in cls.COMPAT_ENGINES) and context.object is not None and context.object.active_material is not None and (
			   thea_globals.panelMatPreview is True)

	def draw(self, context):
		layout = self.layout
		scene = context.scene
		row = layout.row()
		split = row.split(percentage=0.9)
		colL = split.column()
		colL.operator("thea.big_preview")
		colR = split.column()
		colR.label("")
		layout.template_preview(context.material, show_buttons=True, preview_id="MATERIAL_PT_MatPreview")

See attached image

I think there are a couple items which can be left out. I havent cleaned real proper yet

PS in blender 2.78c i could add a def check function. But in 2,79 this causes a crash. With this i was able to drag the window and it would update immediately

PS perhaps i can ask you something, im looking for the anwser how the icons in the material ui list are generated and where they come from.

The only thing i can catch is an id number. It updates the icon instantly and also adjusts the look of it when changing mat specs like diffuse, spec, and many more.

I cant see to tackle how this is done.
I did see that povray still is able to preview this icon. However the addon i use doesnt show anthing

This is what i mean
Cycles engine

My addon engine

@cyberlecs,

I was wondering if you implemented the code i gave? Didnt get a response back

hi @rombout
Thanks for sharing the code! :wink:
Not yet. I’m a bit overloaded at work so I did not have much time to look deeper at this yet.

Ah okay, yes i know that feeling :wink:

PS i also got the small material icons working now. Though im not sure ill like, because in our cause an a sort server app is launced each time we do renders. For the icons this is launched quite a lot.

So a made an settings option for this a user can decide now to use it or not. Leaving it off is faster, setting it on makes makes material picking perhaps easier.

The only method i got this working is by showing the same preview as the preview scene. So it does look a bit different than normal

02

Wanted this preview in the N panel forever and am surprised it still has to be sorta wonky. I attempted to find a way to get it auto-update, but it looks like the only way is inside a modal with a timer loop, which is unfortunate. (yes, I know there’s a way with a hack on a loop, but that’s a process blocking method and it’s a bad idea)

Top one auto-updates after a few seconds, the second has to be resized to refresh. Considering making a button to redraw, but I really did want something more elegant. Works in both Eevee and Cycles. Enjoy it.

image

Updated the basic version for 2.8 (comment out the top or bottom whichever one you bothers you):

bl_info = {
    "name": "NodeEditor Material Preview",
    "author": "",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "Node Editor Toolbar",
    "description": "Displays a material preview in the toolshelf",
    "warning": "",
    "wiki_url": "",
    "category": "Node",
    }



import bpy

class NODE_PT_material_preview(bpy.types.Panel):
    bl_space_type = 'NODE_EDITOR'
    bl_region_type = 'UI'
    bl_label = "Preview"
    bl_category = "Node"
    bl_options = {'DEFAULT_CLOSED'}

    @classmethod
    def poll(cls, context):
        ntree = context.space_data.node_tree
        return ntree is not None and ntree.type=='SHADER'

    # Comment self.layout line for preview you don't want with a #
    def draw(self, context):
        ob = context.active_object
        self.layout.template_ID_preview(ob, "active_material") # top one, button to switch materials and mat name
        self.layout.template_preview(context.active_object.active_material, show_buttons=False) # preview scene duplicate

def register():
    bpy.utils.register_class(NODE_PT_material_preview)

def unregister():
    bpy.utils.unregister_class(NODE_PT_material_preview)

I edited the thread title “almost” because, although the preview shows up, Blender got prone to sudden crashes. So I ended removing the addon. How much is your script stable?