[Bf-blender-cvs] [0eda3bae649] asset-uuid: Add 'asset uuid' to IDs.

Bastien Montagne noreply at git.blender.org
Mon Nov 25 17:54:31 CET 2019


Commit: 0eda3bae64913fa858a2a9eef80acd15f3ebd85a
Author: Bastien Montagne
Date:   Mon Nov 25 17:07:34 2019 +0100
Branches: asset-uuid
https://developer.blender.org/rB0eda3bae64913fa858a2a9eef80acd15f3ebd85a

Add 'asset uuid' to IDs.

This commit is a subset of the asset-engine branch, only adding the uuid
struct to data-blocks, with a basic minimal RNA/Python API to use it.

it does not contain anything regarding asset engines and asset
management itself.

Besides being a first step towards full integration of asset engine work
into master, it is also the 'minimal requirement' from the studio here
for next Cosmos production pipeline (regarding own in-house management
tools).

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

A	release/scripts/modules/amber/__init__.py
A	release/scripts/modules/amber/engine.py
A	release/scripts/modules/amber/operators.py
A	release/scripts/modules/amber/repository.py
A	release/scripts/modules/amber/ui.py
A	release/scripts/modules/amber/utils.py
M	release/scripts/modules/bpy_types.py
A	source/blender/blenkernel/BKE_asset_engine.h
M	source/blender/blenkernel/CMakeLists.txt
A	source/blender/blenkernel/intern/asset_engine.c
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/library_remap.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/space_outliner/outliner_draw.c
M	source/blender/editors/space_outliner/outliner_tools.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesdna/DNA_space_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/python/intern/bpy_rna_id_collection.c

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

diff --git a/release/scripts/modules/amber/__init__.py b/release/scripts/modules/amber/__init__.py
new file mode 100644
index 00000000000..98273c4d016
--- /dev/null
+++ b/release/scripts/modules/amber/__init__.py
@@ -0,0 +1,71 @@
+# ##### 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>
+
+bl_info = {
+    "name": "Amber Asset Engine",
+    "author": "Bastien Montagne",
+    "version": (0, 0, 1),
+    "blender": (2, 80, 2),
+    "location": "File browser...",
+    "description": "Create and use asset repositories on local file system.",
+    "category": "Workflow",
+    "support": 'OFFICIAL',
+}
+
+if "bpy" in locals():
+    import importlib
+    importlib.reload(repository)
+    importlib.reload(engine)
+    importlib.reload(operators)
+    importlib.reload(ui)
+else:
+    from . import (
+        repository,
+        engine,
+        operators,
+        ui
+        )
+
+
+import bpy
+from bpy.props import (
+        BoolProperty,
+        )
+
+
+classes = repository.classes + engine.classes + operators.classes + ui.classes
+
+
+def register():
+    bpy.types.WindowManager.amber_enable_editing = BoolProperty(
+                                name="Enable Amber Editing",
+                                description="Enable editing of items in Amber asset engine repositories")
+    for cls in classes:
+        bpy.utils.register_class(cls)
+
+
+def unregister():
+    for cls in classes:
+        bpy.utils.unregister_class(cls)
+    del bpy.types.WindowManager.amber_enable_editing
+
+
+if __name__ == "__main__":
+    register()
diff --git a/release/scripts/modules/amber/engine.py b/release/scripts/modules/amber/engine.py
new file mode 100644
index 00000000000..8615eabf707
--- /dev/null
+++ b/release/scripts/modules/amber/engine.py
@@ -0,0 +1,633 @@
+# ##### 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>
+
+import bpy
+from bpy.types import (
+        AssetEngine,
+        PropertyGroup,
+        )
+from bpy.props import (
+        StringProperty,
+        BoolProperty,
+        IntProperty,
+        CollectionProperty,
+        PointerProperty,
+        )
+
+import concurrent.futures as futures
+import os
+import stat
+import time
+import random
+
+from . import (repository, utils)
+
+from .repository import (
+        AmberDataRepository,
+        AmberDataRepositoryPG,
+
+        AmberDataRepositoryList,
+        AmberDataRepositoryListPG,
+        )
+
+
+#############
+# 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(path):
+        repo = None
+        ret = [".."]
+        tmp = os.listdir(path)
+        if utils.AMBER_DB_NAME in tmp:
+            # That dir is an Amber repo, we only list content define by our amber 'db'.
+            repo = AmberDataRepository.ls_repo(os.path.join(path, utils.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 = utils.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):
+        repo_uuid = uuid[0]
+        repo_path = AmberDataRepositoryList().repositories.get(repo_uuid, (None, None))[1]
+        if repo_path is None:
+            return [0, 0, []]
+
+        repo = AmberDataRepository()
+        repo.from_dict(repo.ls_repo(os.path.join(repo_path, utils.AMBER_DB_NAME)), repo_path)
+
+        preview_path = os.path.join(repo_path, repo.assets[uuid[1]].preview_path)
+
+        if preview_path and preview_path.endswith(".dat"):
+            w, h, pixels = utils.preview_read_dat(preview_path)
+            return [w, h, list(pixels)]
+
+        #~ time.sleep(0.1)  # 100% Artificial Lag (c)
+        w = random.randint(8, 32)
+        h = random.randint(8, 32)
+        return [w, h, [random.randint(-2147483647, 2147483647) for i in range(w * h)]]
+
+    def start(self, uuids):
+        self.nbr = 0
+        self.preview_tasks = {uuid.uuid_asset[:]: self.executor.submit(self.preview, (uuid.uuid_repository[:], uuid.uuid_asset[:])) for uuid in uuids.uuids}
+        self.tot = len(self.preview_tasks)
+        self.status = {'VALID', 'RUNNING'}
+
+    def update(self, uuids):
+        self.status = {'VALID', 'RUNNING'}
+
+        uuids = {uuid.uuid_asset[:]: uuid for uuid in uuids.uuids}
+
+        new_uuids = set(uuids)
+        old_uuids = set(self.preview_tasks)
+        del_uuids = old_uuids - new_uuids
+        new_uuids -= old_uuids
+
+        for uuid_asset in del_uuids:
+            self.preview_tasks[uuid_asset].cancel()
+            del self.preview_tasks[uuid_asset]
+
+        for uuid_asset in new_uuids:
+            uuid = uuids[uuid_asset]
+            self.preview_tasks[uuid_asset] = self.executor.submit(self.preview, (uuid.uuid_repository[:], uuid_asset))
+
+        self.tot = len(self.preview_tasks)
+        self.nbr = 0
+
+        done_uuids = set()
+        for uuid_asset, tsk in self.preview_tasks.items():
+            if tsk.done():
+                w, h, pixels = tsk.result()
+                uuids[uuid_asset].preview_size = (w, h)
+                uuids[uuid_asset].preview_pixels = pixels
+                self.nbr += 1
+                done_uuids.add(uuid_asset)
+
+        for uuid_asset in done_uuids:
+            del self.preview_tasks[uuid_asset]
+
+        self.progress = self.nbr / self.tot
+        if not self.preview_tasks:
+            self.status = {'VALID'}
+
+    def __init__(self, executor, job_id, uuids):
+        super().__init__(executor, job_id)
+        self.preview_tasks = {}
+
+        self.start(uuids)
+
+    def __del__(self):
+        # Avoid useless work!
+        for tsk in self.preview_tasks.values():
+            tsk.cancel()
+
+
+###########################
+# Main Asset Engine class.
+class AssetEngineAmber(AssetEngine):
+    bl_label = "Amber"
+    bl_version = (0 << 16) + (0 << 8) + 4  # Usual maj.min.rev version scheme...
+
+    repository_pg: PointerProperty(name="Repository", type=AmberDataRepositoryPG, description="Current Amber repository")
+    repositories_pg: PointerProperty(name="Repositories", type=AmberDataRepositoryListPG, description="Known Amber repositories")
+
+    def __init__(self):
+        self.executor = futures.ThreadPoolExecutor(8)  # Using threads for now, if issues arise we'll switch to process.
+        self.jobs = {}
+        self.repos = {}
+        self.repository = AmberDataRepository()
+
+        self.repositories = AmberDataRepositoryList()
+        self.repositories.to_pg(self.repositories_pg)
+
+        self.reset()
+
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list