From 620e9b28291f1dabd55d5b66b874516cee1734bf Mon Sep 17 00:00:00 2001
From: Bastien Montagne <montagne29@wanadoo.fr>
Date: Mon, 7 Nov 2016 14:20:29 +0100
Subject: [PATCH] blend2json.py: add option to only include some data fields
 (based on their names).

Typical usecase: --filter-data="name" to only get DNA structs' name
field value, much helpful to indentify datablocks in JSon result!
---
 utils/blend2json.py | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/utils/blend2json.py b/utils/blend2json.py
index 23ff94b..ba08d65 100755
--- a/utils/blend2json.py
+++ b/utils/blend2json.py
@@ -32,20 +32,24 @@ WARNING! This is still WIP tool!
 
 Example usage:
 
-   ./blend2json.py -i foo.blend
+   ./blend2json.py foo.blend
+
+To output also all 'name' fields from data:
+
+   ./blend2json.py --filter-data="name" foo.blend
 
 To output complete DNA struct info:
 
-   ./blend2json.py --full-dna -i foo.blend
+   ./blend2json.py --full-dna foo.blend
 
 To avoid getting all 'uid' old addresses (those will change really often even when data itself does not change,
 making diff pretty noisy):
 
-   ./blend2json.py --no-old-addresses -i foo.blend
+   ./blend2json.py --no-old-addresses foo.blend
 
 To check a .blend file instead of outputting its JSon version (use explicit -o option to do both at the same time):
 
-   ./blend2json.py -c -i foo.blend
+   ./blend2json.py -c foo.blend
 
 """
 
@@ -231,6 +235,7 @@ def do_bblock_filter(filters, blend, block, meta_keyval, data_keyval):
 def bblocks_to_json(args, fw, blend, address_map, indent, indent_step):
     no_address = args.no_address
     full_data = args.full_data
+    filter_data = args.filter_data
 
     def gen_meta_keyval(blend, block):
         keyval = [
@@ -245,9 +250,12 @@ def bblocks_to_json(args, fw, blend, address_map, indent, indent_step):
         ]
         return keyval
 
-    def gen_data_keyval(blend, block):
+    def gen_data_keyval(blend, block, key_filter=None):
         def _is_pointer(k):
             return blend.structs[block.sdna_index].field_from_path(blend.header, blend.handle, k).dna_name.is_pointer
+        if key_filter is not None:
+            return [(json_dumps(k)[1:-1], json_dumps(address_map.get(v, v) if _is_pointer(k) else v))
+                    for k, v in block.items_recursive_iter() if k in key_filter]
         return [(json_dumps(k)[1:-1], json_dumps(address_map.get(v, v) if _is_pointer(k) else v))
                 for k, v in block.items_recursive_iter()]
 
@@ -267,6 +275,9 @@ def bblocks_to_json(args, fw, blend, address_map, indent, indent_step):
             if full_data:
                 meta_keyval.append(("data", keyval_to_json(gen_data_keyval(blend, block),
                                                            indent + indent_step, indent_step, args.compact_output)))
+            elif filter_data:
+                meta_keyval.append(("data", keyval_to_json(gen_data_keyval(blend, block, filter_data),
+                                                           indent + indent_step, indent_step, args.compact_output)))
             keyval = keyval_to_json(meta_keyval, indent, indent_step, args.compact_output)
             fw('%s%s%s' % ('' if is_first else ',\n', indent, keyval))
             is_first = False
@@ -376,7 +387,12 @@ def argparse_create():
         "--full-data", dest="full_data",
         default=False, action='store_true', required=False,
         help=("Also put in JSon file data itself "
-                              "(WARNING! will generate *huge* verbose files - and is far from complete yet)"))
+              "(WARNING! will generate *huge* verbose files - and is far from complete yet)"))
+    parser.add_argument(
+        "--filter-data", dest="filter_data",
+        default=None, required=False,
+        help=("Only put in JSon file data fields which names match given comma-separated list "
+              "(ignored if --full-data is set)"))
     parser.add_argument(
         "--full-dna", dest="full_dna", default=False, action='store_true', required=False,
         help=("Also put in JSon file dna properties description (ignored when --compact-output is used)"))
@@ -407,6 +423,12 @@ def main():
                                re.compile(f), re.compile(d))
                               for m, f, d in args.block_filters]
 
+    if args.filter_data:
+        if args.full_data:
+            args.filter_data = None
+        else:
+            args.filter_data = {n.encode() for n in args.filter_data.split(',')}
+
     for infile, outfile in zip(args.input, args.output):
         with blendfile.open_blend(infile) as blend:
             address_map = gen_fake_addresses(args, blend)
-- 
GitLab