Scene Manager: request publishes missing on this site
- Request (globe) on casting rows and loaded assets whose latest publish is not on this site, and Request Missing for all of them, through the new wtdcmds command wtd_request_revisions. Requested publishes show "requested, waiting for the download". - The version picker requests a version that is not on this site. - A 404 explains that the session is gone or wtdcmds is too old. - Fake server: car (vehicles) with a publish not on this site, wtd_request_revisions and /_test/download; 45 checks. - Tested live: car_paul modeling.blend v001 -> Requested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ee7710479
commit
9fe38ce58a
8 files changed
+197
-19
No files matched your search
+104
-3
@@ -120,9 +120,36 @@ def version_status(library):
|
||||
return "LATEST", "latest"
|
||||
if available is not None and available["name"] != current:
|
||||
return "UPDATE", f"{available['name']} available"
|
||||
if latest.get("sync_status") == "Requested":
|
||||
return "PENDING", f"{latest['name']} requested, waiting for the download"
|
||||
return "PENDING", f"{latest['name']} published, not available on this site yet"
|
||||
|
||||
|
||||
def file_data(file_oid, default=None):
|
||||
"""Latest known revisions of a file (refreshed by requests and version checks)."""
|
||||
return STATE.files.get(file_oid) or default
|
||||
|
||||
|
||||
def to_request(file):
|
||||
"""The latest revision of a file when it is not on this site and not requested yet, else None."""
|
||||
latest = (file or {}).get("latest")
|
||||
if latest and latest.get("oid") and not latest.get("available") and latest.get("sync_status") != "Requested":
|
||||
return latest
|
||||
return None
|
||||
|
||||
|
||||
def missing_files(scene):
|
||||
"""File oids of the cast and loaded assets whose latest publish can be requested."""
|
||||
casting = STATE.casting.get(context_oid(scene)) or {"assets": []}
|
||||
file_oids = [a["file"]["file_oid"] for a in casting["assets"] if a.get("file")]
|
||||
file_oids += [library["wtd_file_oid"] for library in lib.managed_libraries()]
|
||||
return [oid for oid in dict.fromkeys(file_oids) if to_request(file_data(oid))]
|
||||
|
||||
|
||||
def _asset_of(file_oid):
|
||||
return file_oid.split("/assets/", 1)[-1].split("/", 1)[0]
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Background requests
|
||||
# --------------------------------------------------------------------------- #
|
||||
@@ -225,6 +252,41 @@ def refresh_versions(quiet=False):
|
||||
)
|
||||
|
||||
|
||||
def request_revisions(revisions):
|
||||
"""Ask Libreflow to download revisions on this site ({revision oid: file oid})."""
|
||||
uid = session_uid()
|
||||
|
||||
def done(result):
|
||||
requested, messages = [], []
|
||||
for oid, data in result.items():
|
||||
file_oid = revisions.get(oid, "")
|
||||
what = f"{_asset_of(file_oid)} {data.get('name') or oid.rsplit('/', 1)[-1]}"
|
||||
if data.get("error"):
|
||||
messages.append(f"{what}: {data['error']}")
|
||||
continue
|
||||
file = STATE.files.get(file_oid)
|
||||
if file is not None and (file.get("latest") or {}).get("oid") == oid:
|
||||
file["latest"] = data
|
||||
if data.get("available"):
|
||||
file["latest_available"] = data
|
||||
for revision in STATE.revisions.get(file_oid, []):
|
||||
if revision.get("oid") == oid:
|
||||
revision.update(data)
|
||||
if data.get("available"):
|
||||
messages.append(f"{what} is already on this site: refresh")
|
||||
else:
|
||||
requested.append(what)
|
||||
text = f"Requested {', '.join(requested)}" if requested else "Nothing requested"
|
||||
report(text + ("; " + "; ".join(messages) if messages else ""), "WARNING" if messages else "INFO")
|
||||
|
||||
ipc.run(
|
||||
"Requesting",
|
||||
lambda: ipc.call("wtd_request_revisions", uid, revision_oids=list(revisions)),
|
||||
done,
|
||||
_on_error("Request"),
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Settings
|
||||
# --------------------------------------------------------------------------- #
|
||||
@@ -486,6 +548,34 @@ class WTD_OT_scene_update(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class WTD_OT_scene_request(bpy.types.Operator):
|
||||
bl_idname = "wtd_scene.request"
|
||||
bl_label = "Request"
|
||||
bl_description = (
|
||||
"Ask Libreflow to download the latest publish on this site (from the exchange site, "
|
||||
"or from the site that published it). Refresh once it is downloaded"
|
||||
)
|
||||
|
||||
file_oid: StringProperty(description="Only the latest publish of this file", options={"SKIP_SAVE"})
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return connected()
|
||||
|
||||
def execute(self, context):
|
||||
file_oids = [self.file_oid] if self.file_oid else missing_files(context.scene)
|
||||
revisions = {}
|
||||
for file_oid in file_oids:
|
||||
revision = to_request(file_data(file_oid))
|
||||
if revision is not None:
|
||||
revisions[revision["oid"]] = file_oid
|
||||
if not revisions:
|
||||
self.report({"INFO"}, "Nothing to request")
|
||||
return {"CANCELLED"}
|
||||
request_revisions(revisions)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
def _revision_items(self, context):
|
||||
return _REVISION_ITEMS
|
||||
|
||||
@@ -524,7 +614,12 @@ class WTD_OT_scene_pick_revision(bpy.types.Operator):
|
||||
(
|
||||
r["name"],
|
||||
f"{r['name']} {time.strftime('%Y-%m-%d', time.localtime(r['date'])) if r.get('date') else ''}"
|
||||
f" {r.get('user') or ''}" + ("" if r.get("available") else " (not on this site)"),
|
||||
f" {r.get('user') or ''}"
|
||||
+ (
|
||||
""
|
||||
if r.get("available")
|
||||
else " (requested)" if r.get("sync_status") == "Requested" else " (not on this site: request)"
|
||||
),
|
||||
r.get("comment") or "",
|
||||
"CHECKMARK" if r["name"] == current else "NONE",
|
||||
index,
|
||||
@@ -542,9 +637,14 @@ class WTD_OT_scene_pick_revision(bpy.types.Operator):
|
||||
library = bpy.data.libraries.get(self.library)
|
||||
if library is None:
|
||||
return {"CANCELLED"}
|
||||
revision = next(r for r in STATE.revisions[library["wtd_file_oid"]] if r["name"] == self.revision)
|
||||
file_oid = library["wtd_file_oid"]
|
||||
revision = next(r for r in STATE.revisions[file_oid] if r["name"] == self.revision)
|
||||
if not revision.get("available"):
|
||||
self.report({"WARNING"}, f"{revision['name']} is not available on this site")
|
||||
if revision.get("sync_status") == "Requested":
|
||||
self.report({"WARNING"}, f"{revision['name']} is requested, waiting for the download")
|
||||
else:
|
||||
request_revisions({revision["oid"]: file_oid})
|
||||
self.report({"INFO"}, f"{revision['name']} is not on this site: requested, pick it again once downloaded")
|
||||
return {"CANCELLED"}
|
||||
updated, messages = _update_libraries([self.library], target=revision)
|
||||
if messages:
|
||||
@@ -844,6 +944,7 @@ classes = (
|
||||
WTD_OT_scene_refresh,
|
||||
WTD_OT_scene_load,
|
||||
WTD_OT_scene_update,
|
||||
WTD_OT_scene_request,
|
||||
WTD_OT_scene_pick_revision,
|
||||
WTD_OT_scene_remove,
|
||||
WTD_OT_scene_select_instance,
|
||||
|
||||
Reference in new issue
Block a user