[Bf-blender-cvs] [12642bdeabe] blender-v3.2-release: Fix T96984: Create new image.browse operator for uiTemplateImage layouts

Jesse Yurkovich noreply at git.blender.org
Wed Jun 1 06:08:52 CEST 2022


Commit: 12642bdeabeb35802ee196868c9dbd23c153f622
Author: Jesse Yurkovich
Date:   Tue May 31 20:57:33 2022 -0700
Branches: blender-v3.2-release
https://developer.blender.org/rB12642bdeabeb35802ee196868c9dbd23c153f622

Fix T96984: Create new image.browse operator for uiTemplateImage layouts

The existing BUTTONS_OT_file_browse operator that's used for
uiTemplateImage layouts fails to work correctly with UDIM textures.

This is mainly due to it not realizing that it must tokenize the
filepath before signaling that an update has been made. It also doesn't
work correctly when executing its SHIFT-click behavior to open the image
in an external application. Lastly, it doesn't set the filters to Images
and Movies which is suboptimal for the user.

The new operator takes the unique features of BUTTONS_OT_file_browse
and creates a customized variant better suited for images.

Differential Revision: https://developer.blender.org/D14824

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

M	source/blender/editors/space_image/image_buttons.c
M	source/blender/editors/space_image/image_intern.h
M	source/blender/editors/space_image/image_ops.c
M	source/blender/editors/space_image/space_image.c

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

diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 208928afc1f..d0c21f85472 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -845,7 +845,10 @@ void uiTemplateImage(uiLayout *layout,
 
     row = uiLayoutRow(row, true);
     uiLayoutSetEnabled(row, is_packed == false);
-    uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+
+    prop = RNA_struct_find_property(&imaptr, "filepath");
+    uiDefAutoButR(block, &imaptr, prop, -1, "", ICON_NONE, 0, 0, 200, UI_UNIT_Y);
+    uiItemO(row, "", ICON_FILEBROWSER, "image.file_browse");
     uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
   }
 
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 2322420069e..364bec1377d 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -49,6 +49,7 @@ void IMAGE_OT_new(struct wmOperatorType *ot);
  * Called by other space types too.
  */
 void IMAGE_OT_open(struct wmOperatorType *ot);
+void IMAGE_OT_file_browse(struct wmOperatorType *ot);
 /**
  * Called by other space types too.
  */
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 68d342e2143..b01eec53e73 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1534,6 +1534,120 @@ void IMAGE_OT_open(wmOperatorType *ot)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Browse Image Operator
+ * \{ */
+
+static int image_file_browse_exec(bContext *C, wmOperator *op)
+{
+  Image *ima = op->customdata;
+  if (ima == NULL) {
+    return OPERATOR_CANCELLED;
+  }
+
+  char filepath[FILE_MAX];
+  RNA_string_get(op->ptr, "filepath", filepath);
+
+  /* If loading into a tiled texture, ensure that the filename is tokenized. */
+  if (ima->source == IMA_SRC_TILED) {
+    char *filename = (char *)BLI_path_basename(filepath);
+    BKE_image_ensure_tile_token(filename);
+  }
+
+  PointerRNA imaptr;
+  PropertyRNA *imaprop;
+  RNA_id_pointer_create(&ima->id, &imaptr);
+  imaprop = RNA_struct_find_property(&imaptr, "filepath");
+
+  RNA_property_string_set(&imaptr, imaprop, filepath);
+  RNA_property_update(C, &imaptr, imaprop);
+
+  return OPERATOR_FINISHED;
+}
+
+static int image_file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+  Image *ima = image_from_context(C);
+  if (!ima) {
+    return OPERATOR_CANCELLED;
+  }
+
+  char filepath[FILE_MAX];
+  BLI_strncpy(filepath, ima->filepath, sizeof(filepath));
+
+  /* Shift+Click to open the file, Alt+Click to browse a folder in the OS's browser. */
+  if (event->modifier & (KM_SHIFT | KM_ALT)) {
+    wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
+    PointerRNA props_ptr;
+
+    if (event->modifier & KM_ALT) {
+      char *lslash = (char *)BLI_path_slash_rfind(filepath);
+      if (lslash) {
+        *lslash = '\0';
+      }
+    }
+    else if (ima->source == IMA_SRC_TILED) {
+      ImageUser iuser;
+      BKE_imageuser_default(&iuser);
+
+      /* Use the file associated with the active tile. Otherwise use the first tile. */
+      const ImageTile *active = (ImageTile *)BLI_findlink(&ima->tiles, ima->active_tile_index);
+      iuser.tile = active ? active->tile_number : ((ImageTile *)ima->tiles.first)->tile_number;
+      BKE_image_user_file_path(&iuser, ima, filepath);
+    }
+
+    WM_operator_properties_create_ptr(&props_ptr, ot);
+    RNA_string_set(&props_ptr, "filepath", filepath);
+    WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr, NULL);
+    WM_operator_properties_free(&props_ptr);
+
+    return OPERATOR_CANCELLED;
+  }
+
+  /* The image is typically passed to the operator via layout/button context (e.g.
+   * #uiLayoutSetContextPointer()). The File Browser doesn't support restoring this context
+   * when calling `exec()` though, so we have to pass it the image via custom data. */
+  op->customdata = ima;
+
+  image_filesel(C, op, filepath);
+
+  return OPERATOR_RUNNING_MODAL;
+}
+
+static bool image_file_browse_poll(bContext *C)
+{
+  return image_from_context(C) != NULL;
+}
+
+void IMAGE_OT_file_browse(wmOperatorType *ot)
+{
+  /* identifiers */
+  ot->name = "Browse Image";
+  ot->description =
+      "Open an image file browser, hold Shift to open the file, Alt to browse containing "
+      "directory";
+  ot->idname = "IMAGE_OT_file_browse";
+
+  /* api callbacks */
+  ot->exec = image_file_browse_exec;
+  ot->invoke = image_file_browse_invoke;
+  ot->poll = image_file_browse_poll;
+
+  /* flags */
+  ot->flag = OPTYPE_UNDO;
+
+  /* properties */
+  WM_operator_properties_filesel(ot,
+                                 FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+                                 FILE_SPECIAL,
+                                 FILE_OPENFILE,
+                                 WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+                                 FILE_DEFAULTDISPLAY,
+                                 FILE_SORT_DEFAULT);
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Match Movie Length Operator
  * \{ */
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 568bd064e3e..2f3c7c74ae7 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -199,6 +199,7 @@ static void image_operatortypes(void)
 
   WM_operatortype_append(IMAGE_OT_new);
   WM_operatortype_append(IMAGE_OT_open);
+  WM_operatortype_append(IMAGE_OT_file_browse);
   WM_operatortype_append(IMAGE_OT_match_movie_length);
   WM_operatortype_append(IMAGE_OT_replace);
   WM_operatortype_append(IMAGE_OT_reload);



More information about the Bf-blender-cvs mailing list