[Bf-blender-cvs] [b3c8ffcb3e5] blender2.8: Workbench: UI for custom studio lights/matcaps

Jeroen Bakker noreply at git.blender.org
Fri Jun 8 10:41:58 CEST 2018


Commit: b3c8ffcb3e5312356065824f5481a906907feb80
Author: Jeroen Bakker
Date:   Thu Jun 7 16:01:57 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBb3c8ffcb3e5312356065824f5481a906907feb80

Workbench: UI for custom studio lights/matcaps

- all known image types are supported
- BpyAPI for studiolights added
- added open user pref operator in shading menu
- possible to add multiple files in a single run

For now refreshing studio lights will free all studiolights and reinit
the whole mechanism. This can be improved by only freeing deleted, reset
updated and add new custom studiolights.

details to show currently only shows the path we perhaps want to add
other information also

===================================================================

M	release/scripts/startup/bl_operators/wm.py
M	release/scripts/startup/bl_ui/space_userpref.py
M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/BKE_studiolight.h
M	source/blender/blenkernel/intern/studiolight.c
M	source/blender/makesdna/DNA_userdef_types.h
M	source/blender/makesrna/intern/rna_userdef.c

===================================================================

diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index e62a1f071a9..b0a5e19d269 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -19,13 +19,17 @@
 # <pep8 compliant>
 
 import bpy
-from bpy.types import Operator
+from bpy.types import (
+    Operator,
+    OperatorFileListElement
+)
 from bpy.props import (
     BoolProperty,
     EnumProperty,
     FloatProperty,
     IntProperty,
     StringProperty,
+    CollectionProperty,
 )
 
 from bpy.app.translations import pgettext_tip as tip_
@@ -2400,6 +2404,120 @@ class WM_OT_toolbar(Operator):
         return {'FINISHED'}
 
 
+# Studio Light operations
+class WM_OT_studiolight_install(Operator):
+    """Install a user defined studio light"""
+    bl_idname = "wm.studiolight_install"
+    bl_label = "Install Custom Studio Light"
+
+    files = CollectionProperty(
+            name="File Path",
+            type=OperatorFileListElement,
+            )
+    directory = StringProperty(
+            subtype='DIR_PATH',
+            )
+    filter_folder = BoolProperty(
+            name="Filter folders",
+            default=True,
+            options={'HIDDEN'},
+            )
+    filter_glob = StringProperty(
+            default="*.png;*.jpg;*.hdr;*.exr",
+            options={'HIDDEN'},
+            )
+    orientation = EnumProperty(
+        items=(
+            ("MATCAP", "MatCap", ""),
+            ("WORLD", "World", ""),
+            ("CAMERA", "Camera", ""),
+        )
+    )
+
+    def execute(self, context):
+        import traceback
+        import shutil
+        import pathlib
+        userpref = context.user_preferences
+
+        filepaths = [pathlib.Path(self.directory, e.name) for e in self.files]
+        path_studiolights = bpy.utils.user_resource('DATAFILES')
+
+        if not path_studiolights:
+            self.report({'ERROR'}, "Failed to get Studio Light path")
+            return {'CANCELLED'}
+
+        path_studiolights = pathlib.Path(path_studiolights, "studiolights", self.orientation.lower())
+        if not path_studiolights.exists():
+            try:
+                path_studiolights.mkdir(parents=True, exist_ok=True)
+            except:
+                traceback.print_exc()
+
+        for filepath in filepaths:
+            shutil.copy(str(filepath), str(path_studiolights))
+        userpref.studio_lights_refresh()
+
+        # print message
+        msg = (
+            tip_("StudioLight Installed %r into %r") %
+            (", ".join(str(x.name) for x in self.files), str(path_studiolights))
+        )
+        print(msg)
+        self.report({'INFO'}, msg)
+        return {'FINISHED'}
+
+    def invoke(self, context, event):
+        wm = context.window_manager
+        wm.fileselect_add(self)
+        return {'RUNNING_MODAL'}
+
+
+class WM_OT_studiolight_uninstall(Operator):
+    bl_idname = 'wm.studiolight_uninstall'
+    bl_label = "Uninstall Studio Light"
+    index = bpy.props.IntProperty()
+
+    def execute(self, context):
+        import pathlib
+        userpref = context.user_preferences
+        for studio_light in userpref.studio_lights:
+            if studio_light.index == self.index:
+                path = pathlib.Path(studio_light.path)
+                if path.exists():
+                    path.unlink()
+                    userpref.studio_lights_refresh()
+                    return {'FINISHED'}
+        return {'CANCELLED'}
+
+
+class WM_OT_studiolight_expand(Operator):
+    bl_idname = "wm.studiolight_expand"
+    bl_label = "Expand Studio Light"
+    index = bpy.props.IntProperty()
+
+    def execute(self, context):
+        userpref = context.user_preferences
+        for studio_light in userpref.studio_lights:
+            if studio_light.index == self.index:
+                studio_light.show_expanded = not studio_light.show_expanded
+                break
+
+        return {'FINISHED'}
+
+
+class WM_OT_studiolight_userpref_show(Operator):
+    """Show light user preferences"""
+    bl_idname = "wm.studiolight_userpref_show"
+    bl_label = ""
+    bl_options = {'INTERNAL'}
+
+    def execute(self, context):
+        context.user_preferences.active_section = 'LIGHTS'
+        bpy.ops.screen.userpref_show('INVOKE_DEFAULT')
+        return {'FINISHED'}
+
+
 classes = (
     BRUSH_OT_active_index_set,
     WM_OT_addon_disable,
@@ -2454,6 +2572,10 @@ classes = (
     WM_OT_owner_disable,
     WM_OT_owner_enable,
     WM_OT_url_open,
+    WM_OT_studiolight_expand,
+    WM_OT_studiolight_install,
+    WM_OT_studiolight_uninstall,
+    WM_OT_studiolight_userpref_show,
     WM_OT_tool_set_by_name,
     WM_OT_toolbar,
 )
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index d9cbc6416a3..7db91449049 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -22,6 +22,7 @@ from bpy.types import (
     Header,
     Menu,
     Panel,
+    Operator,
 )
 from bpy.app.translations import pgettext_iface as iface_
 from bpy.app.translations import contexts as i18n_contexts
@@ -1570,6 +1571,50 @@ class USERPREF_PT_addons(Panel):
                 row.label(text=module_name, translate=False)
 
 
+class USERPREF_PT_studiolight(Panel):
+    bl_space_type = 'USER_PREFERENCES'
+    bl_label = "Lights"
+    bl_region_type = 'WINDOW'
+    bl_options = {'HIDE_HEADER'}
+
+    @classmethod
+    def poll(cls, context):
+        userpref = context.user_preferences
+        return (userpref.active_section == 'LIGHTS')
+
+    def draw_studio_light(self, layout, studio_light):
+        box = layout.box()
+        row = box.row()
+
+        op = row.operator('wm.studiolight_expand', emboss=False, text="", icon='TRIA_DOWN' if studio_light.show_expanded else 'TRIA_RIGHT')
+        op.index = studio_light.index
+
+        row.label(text=studio_light.name, icon_value=studio_light.radiance_icon_id)
+        op = row.operator('wm.studiolight_uninstall', text="", icon='ZOOMOUT')
+        op.index = studio_light.index
+
+        if studio_light.show_expanded:
+            box.label(studio_light.path)
+
+
+    def draw(self, context):
+        layout = self.layout
+        userpref = context.user_preferences
+        lights = [light for light in userpref.studio_lights if light.is_user_defined]
+        layout.label("MatCaps")
+        for studio_light in filter(lambda x: x.orientation=='MATCAP', lights):
+            self.draw_studio_light(layout, studio_light)
+        layout.operator('wm.studiolight_install', text="Install Custom MatCap").orientation='MATCAP'
+        layout.label("World HDRI")
+        for studio_light in filter(lambda x: x.orientation=='WORLD', lights):
+            self.draw_studio_light(layout, studio_light)
+        layout.operator('wm.studiolight_install', text="Install Custom HDRI").orientation='WORLD'
+        layout.label("Camera HDRI")
+        for studio_light in filter(lambda x: x.orientation=='CAMERA', lights):
+            self.draw_studio_light(layout, studio_light)
+        layout.operator('wm.studiolight_install', text="Install Custom Camera HDRI").orientation='CAMERA'
+
+
 classes = (
     USERPREF_HT_header,
     USERPREF_PT_tabs,
@@ -1590,6 +1635,7 @@ classes = (
     USERPREF_PT_input,
     USERPREF_MT_addons_online_resources,
     USERPREF_PT_addons,
+    USERPREF_PT_studiolight,
 )
 
 if __name__ == "__main__":  # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index a401328df68..6c16b14886a 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3518,12 +3518,16 @@ class VIEW3D_PT_shading(Panel):
         if shading.type in ('SOLID', 'TEXTURED'):
             col.row().prop(shading, "light", expand=True)
             if shading.light == 'STUDIO':
-                col.row().template_icon_view(shading, "studio_light")
+                row = col.row()
+                row.template_icon_view(shading, "studio_light")
+                op = row.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='ZOOMIN')
                 if shading.studio_light_orientation == 'WORLD':
                     col.row().prop(shading, "studiolight_rot_z")
 
             elif shading.light == 'MATCAP':
-                col.row().template_icon_view(shading, "matcap")
+                row = col.row()
+                row.template_icon_view(shading, "matcap")
+                op = row.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='ZOOMIN')
 
         if shading.type == 'SOLID':
             col.separator()
@@ -3571,7 +3575,9 @@ class VIEW3D_PT_shading(Panel):
                 col.prop(view, "show_world")
 
         elif shading.type in ('MATERIAL'):
-            col.row().template_icon_view(shading, "studio_light")
+            row = col.row()
+            row.template_icon_view(shading, "studio_light")
+            op = row.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='ZOOMIN')
             if shading.studio_light_orientation == 'WORLD':
                 col.row().prop(shading, "studiolight_rot_z")
                 col.row().prop(shading, "studiolight_background")
diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index 9bf9f0ea904..7883f89f33a 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -61,6 +61,7 @@ enum StudioLightFlag {
 	STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED                  = (1 << 1),
 	STUDIOLIGHT_INTERNAL                                    = (1 << 2),
 	STUDIOLIGHT_EXTERNAL_FILE                               = (1 << 3),
+	STUDIOLIGHT_USER_DEFINED                                = (1 << 12),
 	STUDIOLIGHT_ORIENTATION_CAMERA                          = (1 << 4),
 	STUDIOLIGHT_ORIENTATION_WORLD                           = (1 << 5),
 	STUDIOLIGHT_ORIENTATION_VIEWNORMAL                      = (1 << 6),
@@ -69,6 +70,7 @@ enum StudioLightFlag {
 	STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE         = (1 << 9),
 	STUDIOLIGHT_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list