Merge branch 'master' into blender2.8
[blender.git] / release / scripts / startup / bl_ui / space_node.py
index e14708e651d22e8fb80a418b41869d9883e0cbe7..750c01d28e5814a3570eeda9f0fa9475d256279d 100644 (file)
@@ -21,15 +21,15 @@ import bpy
 import nodeitems_utils
 from bpy.types import Header, Menu, Panel
 from bpy.app.translations import pgettext_iface as iface_
+from bl_operators.presets import PresetMenu
 from .properties_grease_pencil_common import (
-    GreasePencilDrawingToolsPanel,
-    GreasePencilStrokeEditPanel,
-    GreasePencilStrokeSculptPanel,
-    GreasePencilBrushPanel,
-    GreasePencilBrushCurvesPanel,
-    GreasePencilDataPanel,
-    GreasePencilPaletteColorPanel,
-    GreasePencilToolsPanel
+    AnnotationDrawingToolsPanel,
+    AnnotationDataPanel,
+    GreasePencilToolsPanel,
+)
+from .properties_material import (
+    EEVEE_MATERIAL_PT_settings,
+    MATERIAL_PT_viewport
 )
 
 
@@ -48,78 +48,110 @@ class NODE_HT_header(Header):
         row = layout.row(align=True)
         row.template_header()
 
-        NODE_MT_editor_menus.draw_collapsible(context, layout)
-
-        layout.prop(snode, "tree_type", text="", expand=True)
+        # Now expanded via the 'ui_type'
+        # layout.prop(snode, "tree_type", text="")
 
         if snode.tree_type == 'ShaderNodeTree':
-            if scene.render.use_shading_nodes:
-                layout.prop(snode, "shader_type", text="", expand=True)
+            layout.prop(snode, "shader_type", text="")
 
             ob = context.object
-            if (not scene.render.use_shading_nodes or snode.shader_type == 'OBJECT') and ob:
+            if snode.shader_type == 'OBJECT' and ob:
+
+                NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+                # No shader nodes for Eevee lamps
+                if snode_id and not (context.engine == 'BLENDER_EEVEE' and ob.type == 'LIGHT'):
+                    row = layout.row()
+                    row.prop(snode_id, "use_nodes")
+
+                layout.separator_spacer()
+
                 row = layout.row()
+                types_that_support_material = {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'GPENCIL'}
                 # disable material slot buttons when pinned, cannot find correct slot within id_from (#36589)
-                row.enabled = not snode.pin
+                # disable also when the selected object does not support materials
+                row.enabled = not snode.pin and ob.type in types_that_support_material
                 # Show material.new when no active ID/slot exists
-                if not id_from and ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'METABALL'}:
+                if not id_from and ob.type in types_that_support_material:
                     row.template_ID(ob, "active_material", new="material.new")
-                # Material ID, but not for Lamps
-                if id_from and ob.type != 'LAMP':
+                # Material ID, but not for Lights
+                if id_from and ob.type != 'LIGHT':
                     row.template_ID(id_from, "active_material", new="material.new")
 
-                # Don't show "Use Nodes" Button when Engine is BI for Lamps
-                if snode_id and not (scene.render.use_shading_nodes == 0 and ob.type == 'LAMP'):
-                    layout.prop(snode_id, "use_nodes")
+            if snode.shader_type == 'WORLD':
+                NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+                if snode_id:
+                    row = layout.row()
+                    row.prop(snode_id, "use_nodes")
+
+                layout.separator_spacer()
 
-            if scene.render.use_shading_nodes and snode.shader_type == 'WORLD':
                 row = layout.row()
                 row.enabled = not snode.pin
                 row.template_ID(scene, "world", new="world.new")
-                if snode_id:
-                    row.prop(snode_id, "use_nodes")
 
-            if scene.render.use_shading_nodes and snode.shader_type == 'LINESTYLE':
-                rl = context.scene.render.layers.active
-                lineset = rl.freestyle_settings.linesets.active
+            if snode.shader_type == 'LINESTYLE':
+                view_layer = context.view_layer
+                lineset = view_layer.freestyle_settings.linesets.active
+
                 if lineset is not None:
+                    NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+                    if snode_id:
+                        row = layout.row()
+                        row.prop(snode_id, "use_nodes")
+
+                    layout.separator_spacer()
+
                     row = layout.row()
                     row.enabled = not snode.pin
                     row.template_ID(lineset, "linestyle", new="scene.freestyle_linestyle_new")
-                    if snode_id:
-                        row.prop(snode_id, "use_nodes")
 
         elif snode.tree_type == 'TextureNodeTree':
-            layout.prop(snode, "texture_type", text="", expand=True)
+            layout.prop(snode, "texture_type", text="")
+
+            NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+            if snode_id:
+                layout.prop(snode_id, "use_nodes")
+
+            layout.separator_spacer()
 
             if id_from:
                 if snode.texture_type == 'BRUSH':
                     layout.template_ID(id_from, "texture", new="texture.new")
                 else:
                     layout.template_ID(id_from, "active_texture", new="texture.new")
-            if snode_id:
-                layout.prop(snode_id, "use_nodes")
 
         elif snode.tree_type == 'CompositorNodeTree':
+
+            NODE_MT_editor_menus.draw_collapsible(context, layout)
+
             if snode_id:
                 layout.prop(snode_id, "use_nodes")
+
+            layout.prop(snode, "use_auto_render")
             layout.prop(snode, "show_backdrop")
             if snode.show_backdrop:
                 row = layout.row(align=True)
                 row.prop(snode, "backdrop_channels", text="", expand=True)
-            layout.prop(snode, "use_auto_render")
 
         else:
             # Custom node tree is edited as independent ID block
+            NODE_MT_editor_menus.draw_collapsible(context, layout)
+
+            layout.separator_spacer()
+
             layout.template_ID(snode, "node_tree", new="node.new_node_tree")
 
+
         layout.prop(snode, "pin", text="")
-        layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
+        layout.separator_spacer()
 
-        layout.separator()
+        layout.template_running_jobs()
 
-        # Auto-offset nodes (called "insert_offset" in code)
-        layout.prop(snode, "use_insert_offset", text="")
+        layout.operator("node.tree_path_parent", text="", icon='FILE_PARENT')
 
         # Snap
         row = layout.row(align=True)
@@ -128,12 +160,6 @@ class NODE_HT_header(Header):
         if tool_settings.snap_node_element != 'GRID':
             row.prop(tool_settings, "snap_target", text="")
 
-        row = layout.row(align=True)
-        row.operator("node.clipboard_copy", text="", icon='COPYDOWN')
-        row.operator("node.clipboard_paste", text="", icon='PASTEDOWN')
-
-        layout.template_running_jobs()
-
 
 class NODE_MT_editor_menus(Menu):
     bl_idname = "NODE_MT_editor_menus"
@@ -158,9 +184,11 @@ class NODE_MT_add(bpy.types.Menu):
         layout = self.layout
 
         layout.operator_context = 'INVOKE_DEFAULT'
-        props = layout.operator("node.add_search", text="Search ...")
+        props = layout.operator("node.add_search", text="Search...", icon='VIEWZOOM')
         props.use_transform = True
 
+        layout.separator()
+
         # actual node submenus are defined by draw functions from node categories
         nodeitems_utils.draw_node_categories_menu(self, context)
 
@@ -171,11 +199,18 @@ class NODE_MT_view(Menu):
     def draw(self, context):
         layout = self.layout
 
+        snode = context.space_data
+
         layout.operator("node.properties", icon='MENU_PANEL')
         layout.operator("node.toolbar", icon='MENU_PANEL')
 
         layout.separator()
 
+        # Auto-offset nodes (called "insert_offset" in code)
+        layout.prop(snode, "use_insert_offset")
+
+        layout.separator()
+
         layout.operator("view2d.zoom_in")
         layout.operator("view2d.zoom_out")
 
@@ -189,14 +224,12 @@ class NODE_MT_view(Menu):
 
             layout.operator("node.backimage_move", text="Backdrop Move")
             layout.operator("node.backimage_zoom", text="Backdrop Zoom In").factor = 1.2
-            layout.operator("node.backimage_zoom", text="Backdrop Zoom Out").factor = 0.83333
+            layout.operator("node.backimage_zoom", text="Backdrop Zoom Out").factor = 1.0 / 1.2
             layout.operator("node.backimage_fit", text="Fit Backdrop to Available Space")
 
         layout.separator()
 
-        layout.operator("screen.area_dupli")
-        layout.operator("screen.screen_full_area")
-        layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+        layout.menu("INFO_MT_area")
 
 
 class NODE_MT_select(Menu):
@@ -205,7 +238,7 @@ class NODE_MT_select(Menu):
     def draw(self, context):
         layout = self.layout
 
-        layout.operator("node.select_border").tweak = False
+        layout.operator("node.select_box").tweak = False
         layout.operator("node.select_circle")
 
         layout.separator()
@@ -236,7 +269,8 @@ class NODE_MT_node(Menu):
         layout.operator("transform.resize")
 
         layout.separator()
-
+        layout.operator("node.clipboard_copy", text="Copy")
+        layout.operator("node.clipboard_paste", text="Paste")
         layout.operator("node.duplicate_move")
         layout.operator("node.delete")
         layout.operator("node.delete_reconnect")
@@ -271,16 +305,15 @@ class NODE_MT_node(Menu):
 
         layout.separator()
 
-        layout.operator("node.read_renderlayers")
-        layout.operator("node.read_fullsamplelayers")
+        layout.operator("node.read_viewlayers")
 
 
-class NODE_MT_node_color_presets(Menu):
+class NODE_PT_node_color_presets(PresetMenu):
     """Predefined node color"""
     bl_label = "Color Presets"
     preset_subdir = "node_color"
     preset_operator = "script.execute_preset"
-    draw = Menu.draw_preset
+    preset_add_operator = "node.node_color_preset_add"
 
 
 class NODE_MT_node_color_specials(Menu):
@@ -292,11 +325,46 @@ class NODE_MT_node_color_specials(Menu):
         layout.operator("node.node_copy_color", icon='COPY_ID')
 
 
+class NODE_MT_specials(Menu):
+    bl_label = "Node Context Menu"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator_context = 'INVOKE_DEFAULT'
+        layout.operator("node.duplicate_move")
+        layout.operator("node.delete")
+        layout.operator_context = 'EXEC_DEFAULT'
+
+        layout.operator("node.delete_reconnect")
+
+        layout.separator()
+
+        layout.operator("node.link_make").replace = False
+        layout.operator("node.link_make", text="Make and Replace Links").replace = True
+        layout.operator("node.links_detach")
+
+        layout.separator()
+
+        layout.operator("node.group_make", text="Group")
+        layout.operator("node.group_ungroup", text="Ungroup")
+        layout.operator("node.group_edit").exit = False
+
+        layout.separator()
+
+        layout.operator("node.hide_toggle")
+        layout.operator("node.mute_toggle")
+        layout.operator("node.preview_toggle")
+        layout.operator("node.hide_socket_toggle")
+        layout.operator("node.options_toggle")
+        layout.operator("node.collapse_hide_unused_toggle")
+
+
 class NODE_PT_active_node_generic(Panel):
     bl_space_type = 'NODE_EDITOR'
     bl_region_type = 'UI'
+    bl_category = "Node"
     bl_label = "Node"
-#    bl_options = {'HIDE_HEADER'}
 
     @classmethod
     def poll(cls, context):
@@ -313,8 +381,10 @@ class NODE_PT_active_node_generic(Panel):
 class NODE_PT_active_node_color(Panel):
     bl_space_type = 'NODE_EDITOR'
     bl_region_type = 'UI'
+    bl_category = "Node"
     bl_label = "Color"
     bl_options = {'DEFAULT_CLOSED'}
+    bl_parent_id = 'NODE_PT_active_node_generic'
 
     @classmethod
     def poll(cls, context):
@@ -324,6 +394,9 @@ class NODE_PT_active_node_color(Panel):
         node = context.active_node
         self.layout.prop(node, "use_custom_color", text="")
 
+    def draw_header_preset(self, context):
+        NODE_PT_node_color_presets.draw_panel_header(self.layout)
+
     def draw(self, context):
         layout = self.layout
         node = context.active_node
@@ -331,19 +404,17 @@ class NODE_PT_active_node_color(Panel):
         layout.enabled = node.use_custom_color
 
         row = layout.row()
-        col = row.column()
-        col.menu("NODE_MT_node_color_presets")
-        col.prop(node, "color", text="")
-        col = row.column(align=True)
-        col.operator("node.node_color_preset_add", text="", icon='ZOOMIN').remove_active = False
-        col.operator("node.node_color_preset_add", text="", icon='ZOOMOUT').remove_active = True
-        col.menu("NODE_MT_node_color_specials", text="", icon='DOWNARROW_HLT')
+        row.prop(node, "color", text="")
+        row.menu("NODE_MT_node_color_specials", text="", icon='DOWNARROW_HLT')
 
 
 class NODE_PT_active_node_properties(Panel):
     bl_space_type = 'NODE_EDITOR'
     bl_region_type = 'UI'
+    bl_category = "Node"
     bl_label = "Properties"
+    bl_options = {'DEFAULT_CLOSED'}
+    bl_parent_id = 'NODE_PT_active_node_generic'
 
     @classmethod
     def poll(cls, context):
@@ -364,7 +435,7 @@ class NODE_PT_active_node_properties(Panel):
         value_inputs = [socket for socket in node.inputs if socket.enabled and not socket.is_linked]
         if value_inputs:
             layout.separator()
-            layout.label("Inputs:")
+            layout.label(text="Inputs:")
             for socket in value_inputs:
                 row = layout.row()
                 socket.draw(context, row, node, iface_(socket.name, socket.bl_rna.translation_context))
@@ -374,6 +445,7 @@ class NODE_PT_active_node_properties(Panel):
 class NODE_PT_backdrop(Panel):
     bl_space_type = 'NODE_EDITOR'
     bl_region_type = 'UI'
+    bl_category = "Node"
     bl_label = "Backdrop"
 
     @classmethod
@@ -387,24 +459,28 @@ class NODE_PT_backdrop(Panel):
 
     def draw(self, context):
         layout = self.layout
+        layout.use_property_split = True
 
         snode = context.space_data
         layout.active = snode.show_backdrop
-        layout.prop(snode, "backdrop_channels", text="")
-        layout.prop(snode, "backdrop_zoom", text="Zoom")
 
-        col = layout.column(align=True)
-        col.label(text="Offset:")
-        col.prop(snode, "backdrop_x", text="X")
-        col.prop(snode, "backdrop_y", text="Y")
-        col.operator("node.backimage_move", text="Move")
+        col = layout.column()
+
+        col.prop(snode, "backdrop_channels", text="Channels")
+        col.prop(snode, "backdrop_zoom", text="Zoom")
 
-        layout.operator("node.backimage_fit", text="Fit")
+        col.prop(snode, "backdrop_offset", text="Offset")
+
+        col.separator()
+
+        col.operator("node.backimage_move", text="Move")
+        col.operator("node.backimage_fit", text="Fit")
 
 
 class NODE_PT_quality(bpy.types.Panel):
     bl_space_type = 'NODE_EDITOR'
     bl_region_type = 'UI'
+    bl_category = "Node"
     bl_label = "Performance"
 
     @classmethod
@@ -414,6 +490,7 @@ class NODE_PT_quality(bpy.types.Panel):
 
     def draw(self, context):
         layout = self.layout
+        layout.use_property_split = True
 
         snode = context.space_data
         tree = snode.node_tree
@@ -440,36 +517,25 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
 
             # inputs get icon on the left
             if not socket.is_output:
-                row.template_node_socket(color)
+                row.template_node_socket(color=color)
 
             row.prop(socket, "name", text="", emboss=False, icon_value=icon)
 
             # outputs get icon on the right
             if socket.is_output:
-                row.template_node_socket(color)
+                row.template_node_socket(color=color)
 
         elif self.layout_type == 'GRID':
             layout.alignment = 'CENTER'
-            layout.template_node_socket(color)
+            layout.template_node_socket(color=color)
 
 
 # Grease Pencil properties
-class NODE_PT_grease_pencil(GreasePencilDataPanel, Panel):
-    bl_space_type = 'NODE_EDITOR'
-    bl_region_type = 'UI'
-
-    # NOTE: this is just a wrapper around the generic GP Panel
-
-    @classmethod
-    def poll(cls, context):
-        snode = context.space_data
-        return snode is not None and snode.node_tree is not None
-
-
-# Grease Pencil palette colors
-class NODE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
+class NODE_PT_grease_pencil(AnnotationDataPanel, Panel):
     bl_space_type = 'NODE_EDITOR'
     bl_region_type = 'UI'
+    bl_category = "Node"
+    bl_options = {'DEFAULT_CLOSED'}
 
     # NOTE: this is just a wrapper around the generic GP Panel
 
@@ -482,6 +548,7 @@ class NODE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
 class NODE_PT_grease_pencil_tools(GreasePencilToolsPanel, Panel):
     bl_space_type = 'NODE_EDITOR'
     bl_region_type = 'UI'
+    bl_category = "Node"
     bl_options = {'DEFAULT_CLOSED'}
 
     # NOTE: this is just a wrapper around the generic GP tools panel
@@ -489,41 +556,41 @@ class NODE_PT_grease_pencil_tools(GreasePencilToolsPanel, Panel):
     # toolbar, but which may not necessarily be open
 
 
-# Tool Shelf ------------------
-
-
-# Grease Pencil drawing tools
-class NODE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
-    bl_space_type = 'NODE_EDITOR'
-    bl_region_type = 'TOOLS'
-
-
-# Grease Pencil stroke editing tools
-class NODE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
+class EEVEE_NODE_PT_material_settings(Panel):
     bl_space_type = 'NODE_EDITOR'
-    bl_region_type = 'TOOLS'
-
+    bl_region_type = 'UI'
+    bl_category = "Node"
+    bl_label = "Settings"
+    COMPAT_ENGINES = {'BLENDER_EEVEE'}
 
-# Grease Pencil stroke sculpting tools
-class NODE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
-    bl_space_type = 'NODE_EDITOR'
-    bl_region_type = 'TOOLS'
+    @classmethod
+    def poll(cls, context):
+        snode = context.space_data
+        return (context.engine in cls.COMPAT_ENGINES) and \
+               snode.tree_type == 'ShaderNodeTree' and snode.id and \
+               snode.id.bl_rna.identifier == 'Material'
 
-# Grease Pencil drawing brushes
+    def draw(self, context):
+        material = context.space_data.id
+        EEVEE_MATERIAL_PT_settings.draw_shared(self, material)
 
 
-class NODE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
+class NODE_PT_material_viewport(Panel):
     bl_space_type = 'NODE_EDITOR'
-    bl_region_type = 'TOOLS'
-
-# Grease Pencil drawing curves
-
+    bl_region_type = 'UI'
+    bl_category = "Node"
+    bl_label = "Viewport Display"
+    bl_options = {'DEFAULT_CLOSED'}
 
-class NODE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
-    bl_space_type = 'NODE_EDITOR'
-    bl_region_type = 'TOOLS'
+    @classmethod
+    def poll(cls, context):
+        snode = context.space_data
+        return snode.tree_type == 'ShaderNodeTree' and snode.id and \
+               snode.id.bl_rna.identifier == 'Material'
 
-# -----------------------------
+    def draw(self, context):
+        material = context.space_data.id
+        MATERIAL_PT_viewport.draw_shared(self, material)
 
 
 def node_draw_tree_view(layout, context):
@@ -537,8 +604,9 @@ classes = (
     NODE_MT_view,
     NODE_MT_select,
     NODE_MT_node,
-    NODE_MT_node_color_presets,
+    NODE_PT_node_color_presets,
     NODE_MT_node_color_specials,
+    NODE_MT_specials,
     NODE_PT_active_node_generic,
     NODE_PT_active_node_color,
     NODE_PT_active_node_properties,
@@ -546,13 +614,9 @@ classes = (
     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,
+    EEVEE_NODE_PT_material_settings,
+    NODE_PT_material_viewport,
 )