The project dropdown rendered garbled labels. EnumProperty does not copy the strings a callback returns — Python has to keep a reference or Blender reads freed memory, which shows as mojibake rather than as a crash. The callback built fresh tuples on every redraw, so each set was collected the moment it returned. The items are now built once when the project list changes and held at module level; the callback returns that list and allocates nothing, which also makes a per-redraw callback free rather than merely correct. Add-on 1.0.2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "VFXReview — Submit Render",
|
"name": "VFXReview — Submit Render",
|
||||||
"author": "Two Tales",
|
"author": "Two Tales",
|
||||||
"version": (1, 0, 1),
|
"version": (1, 0, 2),
|
||||||
"blender": (3, 6, 0),
|
"blender": (3, 6, 0),
|
||||||
"location": "Properties > Output > VFXReview",
|
"location": "Properties > Output > VFXReview",
|
||||||
"description": "Queue this .blend on the studio render farm instead of rendering locally",
|
"description": "Queue this .blend on the studio render farm instead of rendering locally",
|
||||||
@@ -101,12 +101,28 @@ def api_request(path, payload=None, method="GET"):
|
|||||||
|
|
||||||
_project_cache = []
|
_project_cache = []
|
||||||
|
|
||||||
|
# Blender does not copy the strings an EnumProperty callback returns — Python
|
||||||
|
# must keep a reference to them or the UI renders freed memory, which shows up
|
||||||
|
# as garbled labels rather than as a crash. So the items are built once when the
|
||||||
|
# project list changes and held here; the callback only ever returns this list.
|
||||||
|
_enum_items = [("", "Refresh projects...", "")]
|
||||||
|
|
||||||
|
|
||||||
|
def rebuild_enum_items():
|
||||||
|
global _enum_items
|
||||||
|
if _project_cache:
|
||||||
|
_enum_items = [
|
||||||
|
(p["code"], "%s - %s" % (p["code"], p["name"]), "")
|
||||||
|
for p in _project_cache
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
_enum_items = [("", "Refresh projects...", "")]
|
||||||
|
return _enum_items
|
||||||
|
|
||||||
|
|
||||||
def project_items(self, context):
|
def project_items(self, context):
|
||||||
"""Project dropdown. Cached because Blender calls this on every redraw."""
|
"""Called on every redraw, so it does no work and allocates nothing."""
|
||||||
if not _project_cache:
|
return _enum_items
|
||||||
return [("", "Refresh projects…", "")]
|
|
||||||
return [(p["code"], "%s — %s" % (p["code"], p["name"]), "") for p in _project_cache]
|
|
||||||
|
|
||||||
|
|
||||||
# ── Scene → job ───────────────────────────────────────────────────────────────
|
# ── Scene → job ───────────────────────────────────────────────────────────────
|
||||||
@@ -142,6 +158,7 @@ class VFXR_OT_refresh_projects(Operator):
|
|||||||
return {"CANCELLED"}
|
return {"CANCELLED"}
|
||||||
|
|
||||||
_project_cache = data.get("projects", [])
|
_project_cache = data.get("projects", [])
|
||||||
|
rebuild_enum_items()
|
||||||
self.report({"INFO"}, "%d project(s) loaded" % len(_project_cache))
|
self.report({"INFO"}, "%d project(s) loaded" % len(_project_cache))
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user