[Bf-blender-cvs] [de7b142] experimental-build: Squashed commit of asset-engine branch.

Bastien Montagne noreply at git.blender.org
Fri Sep 16 16:15:58 CEST 2016


Commit: de7b1425c9fb08651833dd61b49f1af2a66f7a83
Author: Bastien Montagne
Date:   Fri Sep 16 16:15:17 2016 +0200
Branches: experimental-build
https://developer.blender.org/rBde7b1425c9fb08651833dd61b49f1af2a66f7a83

Squashed commit of asset-engine branch.

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

M	release/scripts/modules/bpy_types.py
M	release/scripts/startup/bl_operators/__init__.py
A	release/scripts/startup/bl_operators/amber.py
A	release/scripts/startup/bl_operators/amber_asyncio.py
A	release/scripts/startup/bl_operators/claude/__init__.py
A	release/scripts/startup/bl_operators/claude/appdirs.py
A	release/scripts/startup/bl_operators/claude/cache.py
A	release/scripts/startup/bl_operators/claude/pillar.py
A	release/scripts/startup/bl_operators/claude/texture_browser.py
A	release/scripts/startup/bl_operators/claude/wheels/CacheControl-0.11.6-py3-none-any.whl
A	release/scripts/startup/bl_operators/claude/wheels/__init__.py
A	release/scripts/startup/bl_operators/claude/wheels/lockfile-0.12.2-py2.py3-none-any.whl
A	release/scripts/startup/bl_operators/claude/wheels/pillarsdk-1.2.0-py2.py3-none-any.whl
A	release/scripts/startup/bl_operators/claude/wheels/pillarsdk-1.4.0-py2.py3-none-any.whl
M	release/scripts/startup/bl_ui/space_filebrowser.py
M	release/scripts/startup/bl_ui/space_info.py
A	source/blender/blenkernel/BKE_asset_engine.h
M	source/blender/blenkernel/BKE_global.h
M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/armature_update.c
A	source/blender/blenkernel/intern/asset_engine.c
M	source/blender/blenkernel/intern/blender.c
M	source/blender/blenkernel/intern/bpath.c
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenkernel/intern/constraint.c
M	source/blender/blenkernel/intern/library.c
A	source/blender/blenkernel/intern/library_asset.c
M	source/blender/blenkernel/intern/library_query.c
M	source/blender/blenkernel/intern/library_remap.c
M	source/blender/blenkernel/intern/modifier.c
M	source/blender/blenkernel/intern/node.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/object_update.c
M	source/blender/blenkernel/intern/packedFile.c
M	source/blender/blenloader/BLO_readfile.h
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/editors/include/ED_fileselect.h
M	source/blender/editors/interface/interface_regions.c
M	source/blender/editors/space_file/file_draw.c
M	source/blender/editors/space_file/file_intern.h
M	source/blender/editors/space_file/file_ops.c
M	source/blender/editors/space_file/filelist.c
M	source/blender/editors/space_file/filelist.h
M	source/blender/editors/space_file/filesel.c
M	source/blender/editors/space_file/space_file.c
M	source/blender/editors/space_outliner/outliner_draw.c
M	source/blender/editors/space_outliner/outliner_tools.c
M	source/blender/editors/space_script/script_edit.c
M	source/blender/editors/space_script/script_intern.h
M	source/blender/editors/space_script/script_ops.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesdna/DNA_object_types.h
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesdna/DNA_space_types.h
M	source/blender/makesdna/DNA_text_types.h
M	source/blender/makesrna/RNA_access.h
M	source/blender/makesrna/intern/CMakeLists.txt
M	source/blender/makesrna/intern/makesrna.c
M	source/blender/makesrna/intern/rna_ID.c
A	source/blender/makesrna/intern/rna_asset.c
M	source/blender/makesrna/intern/rna_internal.h
M	source/blender/makesrna/intern/rna_space.c
M	source/blender/makesrna/intern/rna_wm.c
M	source/blender/python/intern/bpy_app.c
M	source/blender/python/intern/bpy_rna.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_files.c
M	source/blender/windowmanager/intern/wm_files_link.c
M	source/blender/windowmanager/intern/wm_init_exit.c
M	source/blender/windowmanager/intern/wm_operator_props.c
M	source/blender/windowmanager/intern/wm_operators.c
M	source/blender/windowmanager/wm_files.h
M	source/blenderplayer/bad_level_call_stubs/stubs.c
M	source/creator/creator.c

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

diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index d64acd2..615e30b 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -645,6 +645,10 @@ class RenderEngine(StructRNA, metaclass=RNAMeta):
     __slots__ = ()
 
 
+class AssetEngine(StructRNA, metaclass=RNAMeta):
+    __slots__ = ()
+
+
 class KeyingSetInfo(StructRNA, metaclass=RNAMeta):
     __slots__ = ()
 
diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
index a696410..0b13200 100644
--- a/release/scripts/startup/bl_operators/__init__.py
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -51,6 +51,10 @@ _modules = [
     "wm",
     ]
 
+_modules.append("amber")
+_modules.append("amber_asyncio")
+_modules.append("claude")
+
 import bpy
 
 if bpy.app.build_options.freestyle:
diff --git a/release/scripts/startup/bl_operators/amber.py b/release/scripts/startup/bl_operators/amber.py
new file mode 100644
index 0000000..36c83ea
--- /dev/null
+++ b/release/scripts/startup/bl_operators/amber.py
@@ -0,0 +1,793 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# Note: This will be a simple addon later, but until it gets to master, it's simpler to have it
+#       as a startup module!
+
+import bpy
+from bpy.types import (
+        AssetEngine,
+        Panel,
+        PropertyGroup,
+        UIList,
+        )
+from bpy.props import (
+        StringProperty,
+        BoolProperty,
+        IntProperty,
+        FloatProperty,
+        EnumProperty,
+        CollectionProperty,
+        )
+
+import binascii
+import concurrent.futures as futures
+import hashlib
+import json
+import os
+import stat
+import struct
+import time
+import random
+
+
+AMBER_DB_NAME = "__amber_db.json"
+AMBER_DBK_VERSION = "version"
+
+
+##########
+# Helpers.
+
+# Notes about UUIDs:
+#    * UUID of an asset/variant/revision is computed once at its creation! Later changes to data do not affect it.
+#    * Collision, for unlikely it is, may happen across different repositories...
+#      Doubt this will be practical issue though.
+#    * We keep eight first bytes of 'clear' identifier, to (try to) keep some readable uuid.
+
+def _uuid_gen_single(used_uuids, uuid_root, h, str_arg):
+    h.update(str_arg.encode())
+    uuid = uuid_root + h.digest()
+    uuid = uuid[:23].replace(b'\0', b'\1')  # No null chars, RNA 'bytes' use them as in regular strings... :/
+    if uuid not in used_uuids:  # *Very* likely, but...
+        used_uuids.add(uuid)
+        return uuid
+    return None
+
+
+def _uuid_gen(used_uuids, uuid_root, bytes_seed, *str_args):
+    h = hashlib.md5(bytes_seed)
+    for arg in str_args:
+        uuid = _uuid_gen_single(used_uuids, uuid_root, h, arg)
+        if uuid is not None:
+            return uuid
+    # This is a fallback in case we'd get a collision... Should never be needed in real life!
+    for i in range(100000):
+        uuid = _uuid_gen_single(used_uuids, uuid_root, h, i.to_bytes(4, 'little'))
+        if uuid is not None:
+            return uuid
+    return None  # If this happens...
+
+
+def uuid_asset_gen(used_uuids, path_db, name, tags):
+    uuid_root = name.encode()[:8] + b'|'
+    return _uuid_gen_single(used_uuids, uuid_root, path_db.encode(), name, *tags)
+
+
+def uuid_variant_gen(used_uuids, asset_uuid, name):
+    uuid_root = name.encode()[:8] + b'|'
+    return _uuid_gen_single(used_uuids, uuid_root, asset_uuid, name)
+
+
+def uuid_revision_gen(used_uuids, variant_uuid, number, size, time):
+    uuid_root = str(number).encode() + b'|'
+    return _uuid_gen_single(used_uuids, uuid_root, variant_uuid, str(number), str(size), str(timestamp))
+
+
+def uuid_unpack_bytes(uuid_bytes):
+    return struct.unpack("!iiii", uuid_bytes.ljust(16, b'\0'))
+
+
+def uuid_unpack(uuid_hexstr):
+    return uuid_unpack_bytes(binascii.unhexlify(uuid_hexstr))
+
+
+def uuid_unpack_asset(uuid_repo_hexstr, uuid_asset_hexstr):
+    return uuid_unpack_bytes(binascii.unhexlify(uuid_repo_hexstr).ljust(8, b'\0') +
+                             binascii.unhexlify(uuid_asset_hexstr).ljust(8, b'\0'))
+
+
+def uuid_pack(uuid_iv4):
+    print(uuid_iv4)
+    return binascii.hexlify(struct.pack("!iiii", *uuid_iv4))
+
+
+# XXX Hack, once this becomes a real addon we'll just use addons' config system, for now store that in some own config.
+amber_repos_path = os.path.join(bpy.utils.user_resource('CONFIG', create=True), "amber_repos.json")
+amber_repos = None
+if not os.path.exists(amber_repos_path):
+    with open(amber_repos_path, 'w') as ar_f:
+        json.dump({}, ar_f)
+with open(amber_repos_path, 'r') as ar_f:
+    amber_repos = {uuid_unpack(uuid): path for uuid, path in json.load(ar_f).items()}
+assert(amber_repos != None)
+
+
+def save_amber_repos():
+    ar = {uuid_pack(uuid).decode(): path for uuid, path in amber_repos.items()}
+    with open(amber_repos_path, 'w') as ar_f:
+        json.dump(ar, ar_f)
+
+
+#############
+# Amber Jobs.
+class AmberJob:
+    def __init__(self, executor, job_id):
+        self.executor = executor
+        self.job_id = job_id
+        self.status = {'VALID'}
+        self.progress = 0.0
+
+
+class AmberJobList(AmberJob):
+    @staticmethod
+    def ls_repo(db_path):
+        repo = None
+        with open(db_path, 'r') as db_f:
+            repo = json.load(db_f)
+        if isinstance(repo, dict):
+            repo_ver = repo.get(AMBER_DBK_VERSION, "")
+            if repo_ver != "1.0.1":
+                # Unsupported...
+                print("WARNING: unsupported Amber repository version '%s'." % repo_ver)
+                repo = None
+        else:
+            repo = None
+        if repo is not None:
+            # Convert hexa string to array of four uint32...
+            # XXX will have to check endianess mess here, for now always use same one ('network' one).
+            repo_uuid = repo["uuid"]
+            repo["uuid"] = uuid_unpack(repo_uuid)
+            new_entries = {}
+            for euuid, e in repo["entries"].items():
+                new_variants = {}
+                for vuuid, v in e["variants"].items():
+                    new_revisions = {}
+                    for ruuid, r in v["revisions"].items():
+                        new_revisions[uuid_unpack(ruuid)] = r
+                    new_variants[uuid_unpack(vuuid)] = v
+                    v["revisions"] = new_revisions
+                    ruuid = v["revision_default"]
+                    v["revision_default"] = uuid_unpack(ruuid)
+                new_entries[uuid_unpack_asset(repo_uuid, euuid)] = e
+                e["variants"] = new_variants
+                vuuid = e["variant_default"]
+                e["variant_default"] = uuid_unpack(vuuid)
+            repo["entries"] = new_entries
+        #~ print(repo)
+        return repo
+
+    @staticmethod
+    def ls(path):
+        repo = None
+        ret = [".."]
+        tmp = os.listdir(path)
+        if AMBER_DB_NAME in tmp:
+            # That dir is an Amber repo, we only list content define by our amber 'db'.
+            repo = AmberJobList.ls_repo(os.path.join(path, AMBER_DB_NAME))
+        if repo is None:
+            ret += tmp
+        #~ time.sleep(0.1)  # 100% Artificial Lag (c)
+        return ret, repo
+
+    @staticmethod
+    def stat(root, path):
+        st = os.lstat(root + path)
+        #~ time.sleep(0.1)  # 100% Artificial Lag (c)
+        return path, (stat.S_ISDIR(st.st_mode), st.st_size, st.st_mtime)
+
+    def start(self):
+        self.nbr = 0
+        self.tot = 0
+        self.ls_task = self.executor.submit(self.ls, self.root)
+        self.status = {'VALID', 'RUNNING'}
+
+    def update(self, repository, dirs):
+        self.status = {'VALID', 'RUNNING'}
+        if self.ls_task is not None:
+            if not self.ls_task.done():
+                return
+            paths, repo = self.ls_task.result()
+            self.ls_task = None
+            self.tot = len(paths)
+            repository.clear()
+            dirs.clear()
+            if repo is not None:
+                repository.update(repo)
+            for p in paths:
+                self.stat_tasks.add(self.executor.submit(self.stat, self.root, p))
+
+        done = set()
+        for tsk in self.stat_tasks:
+            if tsk.done():
+                path, (is_dir, size, timestamp) = tsk.result()
+                self.nbr += 1
+                if is_dir:
+                    # We only list dirs from real file system.
+                    uuid = uuid_unpack_bytes((path.encode()[:8] + b"|" + self.nbr.to_bytes(4, 'little')))
+                    dirs.append((path, size, timestamp, uuid))
+                done.add(tsk)
+        self.stat_tasks -= done
+
+        self.progress = self.nbr / self.tot
+        if not self.stat_tasks and self.ls_task is None:
+            self.status = {'VALID'}
+
+    def __init__(self, executor, job_id, root):
+        super().__init__(executor, job_id)
+        self.root = root
+
+        self.ls_task = None
+        self.stat_tasks = set()
+
+        self.start()
+
+    def __del__(self):
+        # Avoid useless work!
+        if self.ls_task is not None:
+            self.ls_task.cancel()
+        for tsk in self.stat_tasks:
+            tsk.cancel()
+
+
+class AmberJobPreviews(AmberJob):
+    @staticmethod
+    def preview(uuid):
+        time.sleep(0.1)  # 100% Artificial Lag (c)
+        w = random

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list