Commit: f9adc7fbac6a8263730acd084db3efa302201b59 Author: Bastien Montagne Date: Fri Mar 13 16:17:00 2015 +0100 Branches: asset-engine https://developer.blender.org/rBf9adc7fbac6a8263730acd084db3efa302201b59
Start to make Amber a bit more serious! Still useless - behaves more or less like a very basic, broken filebrowser. But basics are here, and listing process seems to be working pretty well. =================================================================== M release/scripts/startup/bl_operators/amber.py =================================================================== diff --git a/release/scripts/startup/bl_operators/amber.py b/release/scripts/startup/bl_operators/amber.py index c42c01d..2a564b7 100644 --- a/release/scripts/startup/bl_operators/amber.py +++ b/release/scripts/startup/bl_operators/amber.py @@ -32,41 +32,140 @@ from bpy.props import ( CollectionProperty, ) +import concurrent.futures as futures +import os +import stat +import time + +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): + ret = [".."] + os.listdir(path) + time.sleep(0.1) # 100% Artificial Lag (c) + return ret + + @staticmethod + def stat(path): + st = os.lstat(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, entries, uuids): + if self.ls_task is not None: + if not self.ls_task.done(): + return + paths = self.ls_task.result() + self.ls_task = None + self.tot = len(paths) + for p in paths: + self.stat_tasks.add(self.executor.submit(self.stat, self.root + p)) + else: + done = set() + for tsk in self.stat_tasks: + if tsk.done(): + path, (is_dir, size, timestamp) = tsk.result() + self.nbr += 1 + + entry = entries.entries.add() + entry.type = {'DIR'} if is_dir else {'BLENDER'} # TODO stupid! + entry.relpath = path + entry.uuid = entry.relpath.encode()[:8] + b"|" + bytes(self.nbr) + uuids[entry.uuid] = self.root + path + variant = entry.variants.add() + entry.variants.active = variant + rev = variant.revisions.add() + rev.size = size + rev.timestamp = timestamp + variant.revisions.active = rev + + 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.entries = {} + 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 AssetEngineAmber(AssetEngine): bl_label = "Amber" def __init__(self): + self.executor = futures.ThreadPoolExecutor(8) # Using threads for now, if issues arise we'll switch to process. self.jobs = {} self.uuids = {} + self.job_uuid = 1 + + def __del__(self): + self.executor.shutdown(wait=False) + def status(self, job_id): if job_id: job = self.jobs.get(job_id, None) - #~ if job is not None: - #~ return {'VALID'} - return set() - else: - return {'VALID'} + return job.status if job is not None else set() + return {'VALID'} def progress(self, job_id): - return 0.5 + if job_id: + job = self.jobs.get(job_id, None) + return job.progress if job is not None else 0.0 + progress = 0.0 + nbr_jobs = 0 + for job in self.jobs.values(): + if 'RUNNING' in job.status: + nbr_jobs += 1 + progress += job.progress + return progress / nbr_jobs if nbr_jobs else 0.0 def kill(self, job_id): - pass + if job_id: + self.jobs.pop(job_id, None) + return + for job in self.jobs.values(): + job.kill() def list_dir(self, job_id, entries): - if len(entries.entries) == 0: - entry = entries.entries.add() - entry.type = {'BLENDER'} - entry.relpath = "foobar.blend" - entry.name = "MyLittleTest" - entry.uuid = entry.relpath.encode()[:8] + b"|0000000001" - self.uuids[entry.uuid] = "/home/i74700deb64/Téléchargements/wall_UE_D_01.blend" - variant = entry.variants.add() - entry.variants.active = variant - rev = variant.revisions.add() - variant.revisions.active = rev - return 1 + job = self.jobs.get(job_id, None) + if job is not None and isinstance(job, AmberJobList): + print(job.root, entries.root_path) + if job.root != entries.root_path: + self.jobs[job_id] = AmberJobList(self.executor, job_id, entries.root_path) + else: + job.update(entries, self.uuids) + else: + self.job_uuid += 1 + job_id = self.job_uuid + self.jobs[job_id] = AmberJobList(self.executor, job_id, entries.root_path) + return job_id def load_pre(self, uuids, entries): # Not quite sure this engine will need it in the end, but for sake of testing... _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs