Images: move save modified images operator from Python to C
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 16 May 2019 14:01:11 +0000 (16:01 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 16 May 2019 14:57:38 +0000 (16:57 +0200)
We will use this for saving images along with the .blend file.

Ref D4861

release/scripts/startup/bl_operators/image.py
release/scripts/startup/bl_ui/space_image.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/editors/include/ED_image.h
source/blender/editors/space_image/image_intern.h
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c

index 4f0b574..18446a6 100644 (file)
@@ -115,39 +115,6 @@ class EditExternally(Operator):
         return {'FINISHED'}
 
 
-class SaveDirty(Operator):
-    """Save all modified textures"""
-    bl_idname = "image.save_dirty"
-    bl_label = "Save Dirty"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    def execute(self, _context):
-        unique_paths = set()
-        for image in bpy.data.images:
-            if image.is_dirty:
-                if image.packed_file:
-                    if image.library:
-                        self.report({'WARNING'},
-                                    "Packed library image: %r from library %r"
-                                    " can't be re-packed" %
-                                    (image.name, image.library.filepath))
-                    else:
-                        image.pack()
-                else:
-                    filepath = bpy.path.abspath(image.filepath,
-                                                library=image.library)
-                    if "\\" not in filepath and "/" not in filepath:
-                        self.report({'WARNING'}, "Invalid path: " + filepath)
-                    elif filepath in unique_paths:
-                        self.report({'WARNING'},
-                                    "Path used by more than one image: %r" %
-                                    filepath)
-                    else:
-                        unique_paths.add(filepath)
-                        image.save()
-        return {'FINISHED'}
-
-
 class ProjectEdit(Operator):
     """Edit a snapshot of the view-port in an external image editor"""
     bl_idname = "image.project_edit"
@@ -248,5 +215,4 @@ classes = (
     EditExternally,
     ProjectApply,
     ProjectEdit,
-    SaveDirty,
 )
index a3e8ae8..8060609 100644 (file)
@@ -230,7 +230,7 @@ class IMAGE_MT_image(Menu):
         if ima and ima.source == 'SEQUENCE':
             layout.operator("image.save_sequence")
 
-        layout.operator("image.save_dirty", text="Save All Images")
+        layout.operator("image.save_all_modified", text="Save All Images")
 
         if ima:
             layout.separator()
index 26d480a..76a0cbb 100644 (file)
@@ -645,7 +645,7 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
             split.operator("paint.add_simple_uvs", icon='ADD', text="Add Simple UVs")
         elif have_image:
             layout.separator()
-            layout.operator("image.save_dirty", text="Save All Images", icon='FILE_TICK')
+            layout.operator("image.save_all_modified", text="Save All Images", icon='FILE_TICK')
 
 # TODO, move to space_view3d.py
 
index 5bd806b..a9be959 100644 (file)
@@ -28,6 +28,7 @@ struct ARegion;
 struct ImBuf;
 struct Image;
 struct ImageUser;
+struct ReportList;
 struct Scene;
 struct SpaceImage;
 struct ToolSettings;
@@ -110,4 +111,7 @@ void ED_image_draw_info(struct Scene *scene,
 
 bool ED_space_image_show_cache(struct SpaceImage *sima);
 
+int ED_image_save_all_modified_count(const struct bContext *C);
+bool ED_image_save_all_modified(const struct bContext *C, struct ReportList *reports);
+
 #endif /* __ED_IMAGE_H__ */
index a851684..2c723f4 100644 (file)
@@ -66,6 +66,7 @@ void IMAGE_OT_reload(struct wmOperatorType *ot);
 void IMAGE_OT_save(struct wmOperatorType *ot);
 void IMAGE_OT_save_as(struct wmOperatorType *ot);
 void IMAGE_OT_save_sequence(struct wmOperatorType *ot);
+void IMAGE_OT_save_all_modified(struct wmOperatorType *ot);
 void IMAGE_OT_pack(struct wmOperatorType *ot);
 void IMAGE_OT_unpack(struct wmOperatorType *ot);
 
index c317cb2..3dd7dd2 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_math.h"
 #include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
 #include "BLI_utildefines.h"
 
 #include "BLT_translation.h"
@@ -2157,6 +2159,122 @@ void IMAGE_OT_save_sequence(wmOperatorType *ot)
   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/********************** save all operator **********************/
+
+int ED_image_save_all_modified_count(const bContext *C)
+{
+  Main *bmain = CTX_data_main(C);
+  int num_files = 0;
+
+  for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
+    if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
+      continue;
+    }
+    else if (BKE_image_is_dirty(ima)) {
+      if (ima->source == IMA_SRC_FILE && !BKE_image_has_packedfile(ima)) {
+        num_files++;
+      }
+    }
+  }
+
+  return num_files;
+}
+
+bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
+{
+  Main *bmain = CTX_data_main(C);
+  Scene *scene = CTX_data_scene(C);
+  GSet *unique_paths = BLI_gset_str_new(__func__);
+  bool ok = true;
+
+  for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
+    if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
+      /* Don't save render results automatically. */
+    }
+    else if (BKE_image_is_dirty(ima) && (ima->source == IMA_SRC_FILE)) {
+      if (BKE_image_has_packedfile(ima)) {
+        if (ima->id.lib == NULL) {
+          /* Re-pack. */
+          BKE_image_memorypack(ima);
+        }
+        else {
+          /* Can't pack to library data. */
+          BKE_reportf(reports,
+                      RPT_ERROR,
+                      "Packed library image: %s from library %s can't be saved",
+                      ima->id.name,
+                      ima->id.lib->name);
+        }
+      }
+      else {
+        /* Save to file. */
+        const bool valid_path = strchr(ima->name, '\\') || strchr(ima->name, '/');
+
+        if (valid_path) {
+          ImageSaveOptions opts;
+
+          BKE_image_save_options_init(&opts, bmain, scene);
+
+          if (image_save_options_init(bmain, &opts, ima, NULL, false, false)) {
+            if (!BLI_gset_haskey(unique_paths, opts.filepath)) {
+              const bool save_ok = BKE_image_save(reports, bmain, ima, NULL, &opts);
+
+              if (save_ok) {
+                BLI_gset_insert(unique_paths, BLI_strdup(opts.filepath));
+              }
+
+              ok = ok && save_ok;
+            }
+            else {
+              BKE_reportf(reports,
+                          RPT_WARNING,
+                          "File path used by more than one saved image: %s",
+                          opts.filepath);
+            }
+          }
+        }
+        else {
+          BKE_reportf(reports,
+                      RPT_ERROR,
+                      "Image %s can't be saved, no valid file path: %s",
+                      ima->id.name,
+                      ima->name);
+        }
+      }
+    }
+  }
+
+  BLI_gset_free(unique_paths, MEM_freeN);
+
+  return ok;
+}
+
+static int image_save_all_modified_exec(bContext *C, wmOperator *op)
+{
+  ED_image_save_all_modified(C, op->reports);
+  return OPERATOR_FINISHED;
+}
+
+static bool image_save_all_modified_poll(bContext *C)
+{
+  return (ED_image_save_all_modified_count(C) > 0);
+}
+
+void IMAGE_OT_save_all_modified(wmOperatorType *ot)
+{
+  /* identifiers */
+  ot->name = "Save All Modified";
+  ot->idname = "IMAGE_OT_save_all_modified";
+  ot->description = "Save all modified images";
+
+  /* api callbacks */
+  ot->exec = image_save_all_modified_exec;
+  ot->poll = image_save_all_modified_poll;
+
+  /* flags */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
 /******************** reload image operator ********************/
 
 static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
index cbe655f..a8be93a 100644 (file)
@@ -224,6 +224,7 @@ static void image_operatortypes(void)
   WM_operatortype_append(IMAGE_OT_save);
   WM_operatortype_append(IMAGE_OT_save_as);
   WM_operatortype_append(IMAGE_OT_save_sequence);
+  WM_operatortype_append(IMAGE_OT_save_all_modified);
   WM_operatortype_append(IMAGE_OT_pack);
   WM_operatortype_append(IMAGE_OT_unpack);