UI: Attemps to improve FH drag-n-drop support #116724

Open
Guillermo Venegas wants to merge 13 commits from guishe/blender:test-dnd-fh into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
Contributor

#116047 Adds support to drag-n-drop to file handlers, however current implementation
depends a lot in how imports operators are implemented, for example alembic just imports
one file per call and current implementation will only support drag-n-drop one file at
the time. Also the implementation only supports to call one file handler for drag-n-drop

This pr contains 2 attempts to improve current workflow

  1. The first allows user to select a file handler and select what files to use with
    the active file handler and allows to set the import settings, this just imports the files selected
    with the active file handler

  2. The second allows user to chose a file handler for each extension type and allow
    to set the import settings for each extension type, this allows to run a call to all imports
    operator in a single click.

Current workflow Proposal 1 Proposal 2

Few concerns:

  1. How this can affect to files handlers that depends a lot in context?
  2. What about import operators that can run as background job?
#116047 Adds support to drag-n-drop to file handlers, however current implementation depends a lot in how imports operators are implemented, for example alembic just imports one file per call and current implementation will only support drag-n-drop one file at the time. Also the implementation only supports to call one file handler for drag-n-drop This pr contains 2 attempts to improve current workflow 1. ~~The first allows user to select a file handler and select what files to use with the active file handler and allows to set the import settings, this just imports the files selected with the active file handler~~ 2. The second allows user to chose a file handler for each extension type and allow to set the import settings for each extension type, this allows to run a call to all imports operator in a single click. |Current workflow|Proposal 1|Proposal 2| |---|---|---| |<video src="/attachments/c57397fb-cd6c-4487-8ec8-804465c7ab0f" title="2023-12-31 10-02-32.mp4" controls></video>|<video src="/attachments/e9faaab9-7e58-4456-b2bd-c015dab7dc14" title="2023-12-31 10-19-40.mp4" controls></video>|<video src="/attachments/f3faa9e0-b85e-4b29-9143-d9c655b52ed4" title="2024-01-02 15-08-38.mp4" controls></video>| Few concerns: 1. How this can affect to files handlers that depends a lot in context? 2. What about import operators that can run as background job?
Iliya Katushenock added this to the User Interface project 2024-01-02 22:31:30 +01:00

I think proposal 2 is good with some tweaks.

  • The "Import Alembic" choice can be hidden when there is only one matching importer.
  • I was expecting the enums labels to be the name of the importer, not the file extension?
  • Maybe it could show a text below saying something like ".abc files, 4/7".
  • And the button at the bottom could say "Import 7 Files".
  • I don't think the (files with) unknown extensions need to be shown.
I think proposal 2 is good with some tweaks. * The "Import Alembic" choice can be hidden when there is only one matching importer. * I was expecting the enums labels to be the name of the importer, not the file extension? * Maybe it could show a text below saying something like ".abc files, 4/7". * And the button at the bottom could say "Import 7 Files". * I don't think the (files with) unknown extensions need to be shown.
Brecht Van Lommel requested changes 2024-01-12 15:26:20 +01:00
Brecht Van Lommel left a comment
Owner

Marking as request changes.

Marking as request changes.
Guillermo Venegas force-pushed test-dnd-fh from a3d305ec60 to 4216461129 2024-01-13 00:09:15 +01:00 Compare
Author
Contributor

Everything done, but I don't know what label to put in case it's not a single fh (see .txt .py)
Edit: Best cases scenarios that would not be a problem (only one exporter for usd,ply...) , maybe thinking more about fh that supports images or videos

will do some cleanup

Everything done, but I don't know what label to put in case it's not a single fh (see `.txt .py`) Edit: Best cases scenarios that would not be a problem (only one exporter for usd,ply...) , maybe thinking more about fh that supports images or videos will do some cleanup <video src="/attachments/5448f1ad-ce24-4bdb-91e2-6333ee269152" title="2024-01-12 17-09-38.mp4" controls></video>
Guillermo Venegas added 3 commits 2024-01-14 02:41:54 +01:00
Guillermo Venegas added 1 commit 2024-01-14 02:47:10 +01:00
Guillermo Venegas added 1 commit 2024-01-15 03:52:06 +01:00
Author
Contributor

@Brecht Can you ping the bot for a package build?

I think it's almost finished, there are a couple of things that I have included just for testing that can be removed

@Brecht Can you ping the bot for a package build? I think it's almost finished, there are a couple of things that I have included just for testing that can be removed
Guillermo Venegas added 1 commit 2024-01-15 06:22:52 +01:00
buildbot/vexp-code-patch-lint Build done. Details
buildbot/vexp-code-patch-darwin-x86_64 Build done. Details
buildbot/vexp-code-patch-darwin-arm64 Build done. Details
buildbot/vexp-code-patch-linux-x86_64 Build done. Details
buildbot/vexp-code-patch-windows-amd64 Build done. Details
buildbot/vexp-code-patch-coordinator Build done. Details
73d2057fd9
remove defined struct

@blender-bot package

@blender-bot package
Member

Package build started. Download here when ready.

Package build started. [Download here](https://builder.blender.org/download/patch/PR116724) when ready.
Guillermo Venegas added 1 commit 2024-01-15 16:31:11 +01:00
Author
Contributor

Now only proposal 2 remains in the code.

Everything done, but I don't know what label to put in a tab where is not handled by a single fh.

Apart from that, I think it is ready for review

Now only proposal 2 remains in the code. >Everything done, but I don't know what label to put in a tab where is not handled by a single fh. Apart from that, I think it is ready for review

Everything done, but I don't know what label to put in a tab where is not handled by a single fh.

It's a good question, I don't have an obvious solution. To me the current state of falling back to the file extension seems reasonable.

> >Everything done, but I don't know what label to put in a tab where is not handled by a single fh. It's a good question, I don't have an obvious solution. To me the current state of falling back to the file extension seems reasonable.

Minor suggestion for the UI:

  • I don't think we need a box around the boxes operator presets + settings. Just one level of boxes is enough.
  • For the number of files display, I would simplify that by removing the box, the icon and having the text be e.g. "4 .abc files". Since the button with 12 is very close below it seems unnecessary to have that number duplicated there.

Maybe @Harley or @pablovazquez have an opinion on this UI as well.

Minor suggestion for the UI: * I don't think we need a box around the boxes operator presets + settings. Just one level of boxes is enough. * For the number of files display, I would simplify that by removing the box, the icon and having the text be e.g. "4 .abc files". Since the button with 12 is very close below it seems unnecessary to have that number duplicated there. Maybe @Harley or @pablovazquez have an opinion on this UI as well.
Member

I'm mostly with Brecht here....

If the outer border is removed, and also the border around the information line at the bottom then it is nicely separated from the rest.

However, I struggle with the informational text at the the bottom. The button indicates that you will import all 12 files. Therefore I think I'd want that text to show the totals, not just the amount on this page. If this were to remain only a count of the files of the type on this page I think I'd want that above the settings, not below.

So maybe something like this, although perhaps with some removal of redundant "files" text?

image

I'm mostly with Brecht here.... If the outer border is removed, and also the border around the information line at the bottom then it is nicely separated from the rest. However, I struggle with the informational text at the the bottom. The button indicates that you will import all 12 files. Therefore I think I'd want that text to show the totals, not just the amount on this page. If this were to remain only a count of the files of the type on this page I think I'd want that _above_ the settings, not below. So maybe something like this, although perhaps with some removal of redundant "files" text? ![image](/attachments/98b4e805-976c-4c6f-b871-c08c10d88d84)
121 KiB
Guillermo Venegas added 3 commits 2024-01-16 04:40:44 +01:00
Author
Contributor

Added also small change
image

Added also small change ![image](/attachments/91653696-a73e-4f5e-8d3c-5ab1c7c8af4e)
138 KiB
Guillermo Venegas added 1 commit 2024-01-19 15:57:10 +01:00
Guillermo Venegas added 1 commit 2024-01-19 15:59:07 +01:00
Author
Contributor

Removed changes that were just for testing and are in other pr (the confirm button will show ok by now, until !117143)

image

Additional diff with file handlers for test

diff --git a/scripts/startup/bl_operators/wm.py b/scripts/startup/bl_operators/wm.py
index d252efe1614..6ed6961a737 100644
--- a/scripts/startup/bl_operators/wm.py
+++ b/scripts/startup/bl_operators/wm.py
@@ -3525,6 +3525,200 @@ class WM_OT_drop_blend_file(Operator):
         col.operator("wm.append", text="Append...", icon='APPEND_BLEND').filepath = self.filepath
 
 
+class WM_FH_alembic(bpy.types.FileHandler):
+    bl_idname = "WM_FH_alembic"
+    bl_label = "Alembic"
+    bl_import_operator = "WM_OT_alembic_import"
+    bl_file_extensions = ".abc"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class WM_FH_collada(bpy.types.FileHandler):
+    bl_idname = "WM_FH_collada"
+    bl_label = "COLLADA"
+    bl_import_operator = "WM_OT_collada_import"
+    bl_file_extensions = ".dae"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class WM_FH_gpencil(bpy.types.FileHandler):
+    bl_idname = "WM_FH_gpencil"
+    bl_label = "gpencil"
+    bl_import_operator = "WM_OT_gpencil_import_svg"
+    bl_file_extensions = ".svg"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class WM_FH_obj(bpy.types.FileHandler):
+    bl_idname = "WM_FH_obj"
+    bl_label = "Wavefront OBJ"
+    bl_import_operator = "WM_OT_obj_import"
+    bl_file_extensions = ".obj;.mtl"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class WM_FH_ply(bpy.types.FileHandler):
+    bl_idname = "WM_FH_ply"
+    bl_label = "PLY"
+    bl_import_operator = "WM_OT_ply_import"
+    bl_file_extensions = ".ply"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class WM_FH_stl(bpy.types.FileHandler):
+    bl_idname = "WM_FH_stl"
+    bl_label = "STL (experimental)"
+    bl_import_operator = "WM_OT_stl_import"
+    bl_file_extensions = ".stl"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class WM_FH_import_mesh_stl(bpy.types.FileHandler):
+    bl_idname = "WM_FH_import_mesh_stl"
+    bl_label = "STL"
+    bl_import_operator = "import_mesh.stl"
+    bl_file_extensions = ".stl"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class WM_FH_usd(bpy.types.FileHandler):
+    bl_idname = "WM_FH_usd"
+    bl_label = "USD"
+    bl_import_operator = "WM_OT_usd_import"
+    bl_file_extensions = ".usd;.usda;.usdc;.usdz"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return context.area.type == "VIEW_3D"
+
+
+class CurveTextImport1(bpy.types.Operator):
+    """ Test importer that creates a text object from a .txt file """
+    bl_idname = "curve.text_import1"
+    bl_label = "Import a text file as text object 1"
+
+    """
+    This Operator supports import one .txt file at the time, we need the
+    following filepath property that the file handler will use to set file path data.
+    """
+    filepath: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'})
+
+    @classmethod
+    def poll(cls, context):
+        return (context.area and context.area.type == "VIEW_3D")
+
+    def execute(self, context):
+        """ Calls to this Operator can set unfiltered filepaths, ensure the file extension is .txt. """
+        if not self.filepath or not self.filepath.endswith(".txt"):
+            return {'CANCELLED'}
+
+        with open(self.filepath) as file:
+            text_curve = bpy.data.curves.new(type="FONT", name="Text")
+            text_curve.body = ''.join(file.readlines())
+            text_object = bpy.data.objects.new(name="Text", object_data=text_curve)
+            bpy.context.scene.collection.objects.link(text_object)
+        return {'FINISHED'}
+
+    """
+    By default the file handler invokes the operator with the filepath property set.
+    In this example if this property is set the operator is executed, if not the
+    file select window is invoked.
+    This depends on setting ``options={'SKIP_SAVE'}`` to the property options to avoid
+    to reuse filepath data between operator calls.
+    """
+
+    def invoke(self, context, event):
+        if self.filepath:
+            return self.execute(context)
+        context.window_manager.fileselect_add(self)
+        return {'RUNNING_MODAL'}
+
+
+class CURVE_FH_text_import1(bpy.types.FileHandler):
+    bl_idname = "CURVE_FH_text_import1"
+    bl_label = "Text file as curve object 1"
+    bl_import_operator = "curve.text_import1"
+    bl_file_extensions = ".txt;.py"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return (context.area and context.area.type == 'VIEW_3D')
+
+
+class CurveTextImport(bpy.types.Operator):
+    """ Test importer that creates a text object from a .txt file """
+    bl_idname = "curve.text_import"
+    bl_label = "Import a text file as text object"
+
+    """
+    This Operator supports import one .txt file at the time, we need the
+    following filepath property that the file handler will use to set file path data.
+    """
+    filepath: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'})
+
+    @classmethod
+    def poll(cls, context):
+        return (context.area and context.area.type == "VIEW_3D")
+
+    def execute(self, context):
+        """ Calls to this Operator can set unfiltered filepaths, ensure the file extension is .txt. """
+        if not self.filepath or not self.filepath.endswith(".txt"):
+            return {'CANCELLED'}
+
+        with open(self.filepath) as file:
+            text_curve = bpy.data.curves.new(type="FONT", name="Text")
+            text_curve.body = ''.join(file.readlines())
+            text_object = bpy.data.objects.new(name="Text", object_data=text_curve)
+            bpy.context.scene.collection.objects.link(text_object)
+        return {'FINISHED'}
+
+    """
+    By default the file handler invokes the operator with the filepath property set.
+    In this example if this property is set the operator is executed, if not the
+    file select window is invoked.
+    This depends on setting ``options={'SKIP_SAVE'}`` to the property options to avoid
+    to reuse filepath data between operator calls.
+    """
+
+    def invoke(self, context, event):
+        if self.filepath:
+            return self.execute(context)
+        context.window_manager.fileselect_add(self)
+        return {'RUNNING_MODAL'}
+
+
+class CURVE_FH_text_import(bpy.types.FileHandler):
+    bl_idname = "CURVE_FH_text_import"
+    bl_label = "Text file as curve object"
+    bl_import_operator = "curve.text_import"
+    bl_file_extensions = ".txt;.py"
+
+    @classmethod
+    def poll_drop(cls, context):
+        return (context.area and context.area.type == 'VIEW_3D')
+
+
 classes = (
     WM_OT_context_collection_boolean_set,
     WM_OT_context_cycle_array,
@@ -3570,5 +3764,19 @@ classes = (
     WM_MT_splash_quick_setup,
     WM_MT_splash,
     WM_MT_splash_about,
-    WM_MT_region_toggle_pie
+    WM_MT_region_toggle_pie,
+
+    WM_FH_alembic,
+    WM_FH_collada,
+    WM_FH_gpencil,
+    WM_FH_obj,
+    WM_FH_ply,
+    WM_FH_stl,
+    WM_FH_import_mesh_stl,
+    WM_FH_usd,
+
+    CURVE_FH_text_import,
+    CURVE_FH_text_import1,
+    CurveTextImport,
+    CurveTextImport1,
 )
Removed changes that were just for testing and are in other pr (the confirm button will show ok by now, until !117143) ![image](/attachments/e245d4a9-7f50-493d-abbe-0787c4b1a441) <details> <summary>Additional diff with file handlers for test</summary> ```diff diff --git a/scripts/startup/bl_operators/wm.py b/scripts/startup/bl_operators/wm.py index d252efe1614..6ed6961a737 100644 --- a/scripts/startup/bl_operators/wm.py +++ b/scripts/startup/bl_operators/wm.py @@ -3525,6 +3525,200 @@ class WM_OT_drop_blend_file(Operator): col.operator("wm.append", text="Append...", icon='APPEND_BLEND').filepath = self.filepath +class WM_FH_alembic(bpy.types.FileHandler): + bl_idname = "WM_FH_alembic" + bl_label = "Alembic" + bl_import_operator = "WM_OT_alembic_import" + bl_file_extensions = ".abc" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class WM_FH_collada(bpy.types.FileHandler): + bl_idname = "WM_FH_collada" + bl_label = "COLLADA" + bl_import_operator = "WM_OT_collada_import" + bl_file_extensions = ".dae" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class WM_FH_gpencil(bpy.types.FileHandler): + bl_idname = "WM_FH_gpencil" + bl_label = "gpencil" + bl_import_operator = "WM_OT_gpencil_import_svg" + bl_file_extensions = ".svg" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class WM_FH_obj(bpy.types.FileHandler): + bl_idname = "WM_FH_obj" + bl_label = "Wavefront OBJ" + bl_import_operator = "WM_OT_obj_import" + bl_file_extensions = ".obj;.mtl" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class WM_FH_ply(bpy.types.FileHandler): + bl_idname = "WM_FH_ply" + bl_label = "PLY" + bl_import_operator = "WM_OT_ply_import" + bl_file_extensions = ".ply" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class WM_FH_stl(bpy.types.FileHandler): + bl_idname = "WM_FH_stl" + bl_label = "STL (experimental)" + bl_import_operator = "WM_OT_stl_import" + bl_file_extensions = ".stl" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class WM_FH_import_mesh_stl(bpy.types.FileHandler): + bl_idname = "WM_FH_import_mesh_stl" + bl_label = "STL" + bl_import_operator = "import_mesh.stl" + bl_file_extensions = ".stl" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class WM_FH_usd(bpy.types.FileHandler): + bl_idname = "WM_FH_usd" + bl_label = "USD" + bl_import_operator = "WM_OT_usd_import" + bl_file_extensions = ".usd;.usda;.usdc;.usdz" + + @classmethod + def poll_drop(cls, context): + return context.area.type == "VIEW_3D" + + +class CurveTextImport1(bpy.types.Operator): + """ Test importer that creates a text object from a .txt file """ + bl_idname = "curve.text_import1" + bl_label = "Import a text file as text object 1" + + """ + This Operator supports import one .txt file at the time, we need the + following filepath property that the file handler will use to set file path data. + """ + filepath: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'}) + + @classmethod + def poll(cls, context): + return (context.area and context.area.type == "VIEW_3D") + + def execute(self, context): + """ Calls to this Operator can set unfiltered filepaths, ensure the file extension is .txt. """ + if not self.filepath or not self.filepath.endswith(".txt"): + return {'CANCELLED'} + + with open(self.filepath) as file: + text_curve = bpy.data.curves.new(type="FONT", name="Text") + text_curve.body = ''.join(file.readlines()) + text_object = bpy.data.objects.new(name="Text", object_data=text_curve) + bpy.context.scene.collection.objects.link(text_object) + return {'FINISHED'} + + """ + By default the file handler invokes the operator with the filepath property set. + In this example if this property is set the operator is executed, if not the + file select window is invoked. + This depends on setting ``options={'SKIP_SAVE'}`` to the property options to avoid + to reuse filepath data between operator calls. + """ + + def invoke(self, context, event): + if self.filepath: + return self.execute(context) + context.window_manager.fileselect_add(self) + return {'RUNNING_MODAL'} + + +class CURVE_FH_text_import1(bpy.types.FileHandler): + bl_idname = "CURVE_FH_text_import1" + bl_label = "Text file as curve object 1" + bl_import_operator = "curve.text_import1" + bl_file_extensions = ".txt;.py" + + @classmethod + def poll_drop(cls, context): + return (context.area and context.area.type == 'VIEW_3D') + + +class CurveTextImport(bpy.types.Operator): + """ Test importer that creates a text object from a .txt file """ + bl_idname = "curve.text_import" + bl_label = "Import a text file as text object" + + """ + This Operator supports import one .txt file at the time, we need the + following filepath property that the file handler will use to set file path data. + """ + filepath: bpy.props.StringProperty(subtype='FILE_PATH', options={'SKIP_SAVE'}) + + @classmethod + def poll(cls, context): + return (context.area and context.area.type == "VIEW_3D") + + def execute(self, context): + """ Calls to this Operator can set unfiltered filepaths, ensure the file extension is .txt. """ + if not self.filepath or not self.filepath.endswith(".txt"): + return {'CANCELLED'} + + with open(self.filepath) as file: + text_curve = bpy.data.curves.new(type="FONT", name="Text") + text_curve.body = ''.join(file.readlines()) + text_object = bpy.data.objects.new(name="Text", object_data=text_curve) + bpy.context.scene.collection.objects.link(text_object) + return {'FINISHED'} + + """ + By default the file handler invokes the operator with the filepath property set. + In this example if this property is set the operator is executed, if not the + file select window is invoked. + This depends on setting ``options={'SKIP_SAVE'}`` to the property options to avoid + to reuse filepath data between operator calls. + """ + + def invoke(self, context, event): + if self.filepath: + return self.execute(context) + context.window_manager.fileselect_add(self) + return {'RUNNING_MODAL'} + + +class CURVE_FH_text_import(bpy.types.FileHandler): + bl_idname = "CURVE_FH_text_import" + bl_label = "Text file as curve object" + bl_import_operator = "curve.text_import" + bl_file_extensions = ".txt;.py" + + @classmethod + def poll_drop(cls, context): + return (context.area and context.area.type == 'VIEW_3D') + + classes = ( WM_OT_context_collection_boolean_set, WM_OT_context_cycle_array, @@ -3570,5 +3764,19 @@ classes = ( WM_MT_splash_quick_setup, WM_MT_splash, WM_MT_splash_about, - WM_MT_region_toggle_pie + WM_MT_region_toggle_pie, + + WM_FH_alembic, + WM_FH_collada, + WM_FH_gpencil, + WM_FH_obj, + WM_FH_ply, + WM_FH_stl, + WM_FH_import_mesh_stl, + WM_FH_usd, + + CURVE_FH_text_import, + CURVE_FH_text_import1, + CurveTextImport, + CurveTextImport1, ) ``` </details>
Author
Contributor

Since we can now change the title, this can also be customized:

  1. Only one file handler
  2. Multiple tabs
  3. Only one tab with multiple fh

Since we can now change the title, this can also be customized: 1. Only one file handler 2. Multiple tabs 3. Only one tab with multiple fh <video src="/attachments/2d9d319a-0bbb-4721-817a-87fb8785feba" title="2024-01-26 20-35-58.mp4" controls></video>
This pull request has changes conflicting with the target branch.
  • source/blender/editors/io/io_drop_import_file.cc

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u test-dnd-fh:guishe-test-dnd-fh
git checkout guishe-test-dnd-fh
Sign in to join this conversation.
No reviewers
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#116724
No description provided.