Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Tue, 3 Apr 2018 14:13:13 +0000 (16:13 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Tue, 3 Apr 2018 14:13:13 +0000 (16:13 +0200)
release/scripts/startup/bl_operators/file.py
release/scripts/startup/bl_ui/space_info.py
source/blender/makesrna/intern/rna_rna.c

index 1b51906a0322af95c21ec575bcf9d19b28275feb..4ab8d59f263b0995355a87cddb38402e0a9f2b7e 100644 (file)
@@ -249,7 +249,61 @@ class WM_OT_previews_batch_clear(Operator):
         return {'FINISHED'}
 
 
+class WM_OT_blend_strings_utf8_validate(Operator):
+    """Check and fix all strings in current .blend file to be valid UTF-8 Unicode (needed for some old, 2.4x area files)"""
+    bl_idname = "wm.blend_strings_utf8_validate"
+    bl_label = "Validate .blend strings"
+    bl_options = {'REGISTER'}
+
+    def validate_strings(self, item, done_items):
+        if item is None:
+            return False
+
+        if item in done_items:
+            return False
+        done_items.add(item)
+
+        if getattr(item, 'library', None) is not None:
+            return False  # No point in checking library data, we cannot fix it anyway...
+
+        changed = False
+        for prop in item.bl_rna.properties:
+            if prop.identifier in {'bl_rna', 'rna_type'}:
+                continue  # Or we'd recurse 'till Hell freezes.
+            if prop.is_readonly:
+                continue
+            if prop.type == 'STRING':
+                val_bytes = item.path_resolve(prop.identifier, False).as_bytes()
+                val_utf8 = val_bytes.decode('utf-8', 'replace')
+                val_bytes_valid = val_utf8.encode('utf-8')
+                if val_bytes_valid != val_bytes:
+                    print("found bad utf8 encoded string %r, fixing to %r (%r)..."
+                          "" % (val_bytes, val_bytes_valid, val_utf8))
+                    setattr(item, prop.identifier, val_utf8)
+                    changed = True
+            elif prop.type == 'POINTER':
+                it = getattr(item, prop.identifier)
+                changed |= self.validate_strings(it, done_items)
+            elif prop.type == 'COLLECTION':
+                for it in getattr(item, prop.identifier):
+                    changed |= self.validate_strings(it, done_items)
+        return changed
+
+    def execute(self, context):
+        changed = False
+        done_items = set()
+        for prop in bpy.data.bl_rna.properties:
+            if prop.type == 'COLLECTION':
+                for it in getattr(bpy.data, prop.identifier):
+                    changed |= self.validate_strings(it, done_items)
+        if changed:
+            self.report({'WARNING'},
+                        "Some strings were fixed, don't forget to save the .blend file to keep those changes")
+        return {'FINISHED'}
+
+
 classes = (
     WM_OT_previews_batch_clear,
     WM_OT_previews_batch_generate,
+    WM_OT_blend_strings_utf8_validate,
 )
index 8c69e733a2d6bb7fb7be8a7cb4b19b13b579f99c..96e8f9420d9661206ea0b37d374a5fcade59f515 100644 (file)
@@ -168,6 +168,7 @@ class INFO_MT_file(Menu):
         layout.separator()
 
         layout.menu("INFO_MT_file_external_data", icon='EXTERNAL_DATA')
+        layout.operator("wm.blend_strings_utf8_validate", icon='FILE_BLEND')
 
         layout.separator()
 
index 0452c6440526e4743990cad0d4c0817c2efb17e6..a46c8e2f18f8ba3d40cbcf79504b824ae3076984 100644 (file)
@@ -638,7 +638,7 @@ static const EnumPropertyItem *rna_Property_tags_itemf(
        int totitem = 0;
 
        for (const EnumPropertyItem *struct_tags = RNA_struct_property_tag_defines(srna);
-            struct_tags->identifier;
+            struct_tags != NULL && struct_tags->identifier != NULL;
             struct_tags++)
        {
                memcpy(&tmp, struct_tags, sizeof(tmp));