Bonsai: persist colour-by-property Pset selection across save/reload

SaveColourscheme only serialized colourscheme_query (the free text
custom-query field), never colourscheme_key (the dropdown that
actually drives colour-by-property when not in Custom Query mode).
LoadColourscheme was symmetrically blind to it too, so after saving a
colour scheme built from a Pset property and reopening the file, the
colours came back but the Pset selection was silently lost, exactly
as reported.

Save now records whichever of colourscheme_key/colourscheme_query was
actually driving the query, matching the logic already used by
ColourByProperty and SelectByProperty. Load restores colourscheme_key,
falling back to "QUERY" when the saved key is no longer a valid choice
for the current active object (its dynamic enum is scoped per-object),
so the saved query string still gets used instead of the selection
silently disappearing.

Fixes #6354.

Generated with the assistance of an AI coding tool.
This commit is contained in:
Petru Conduraru
2026-07-16 13:40:20 +03:00
parent 821cf7b671
commit bec61d6d2c
@@ -39,6 +39,7 @@ from natsort import natsorted
import bonsai.core.search as core import bonsai.core.search as core
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.search.data import ColourByPropertyData
from bonsai.bim.prop import StrProperty from bonsai.bim.prop import StrProperty
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -1186,7 +1187,8 @@ class SaveColourscheme(Operator, tool.Ifc.Operator):
return return
props = tool.Search.get_search_props() props = tool.Search.get_search_props()
query = props.colourscheme_query colourscheme_key = props.colourscheme_key
query = props.colourscheme_query if colourscheme_key == "QUERY" else colourscheme_key
group = [g for g in tool.Ifc.get().by_type("IfcGroup") if g.Name == self.name] group = [g for g in tool.Ifc.get().by_type("IfcGroup") if g.Name == self.name]
colourscheme = {cs.name: {"colour": cs.colour[0:3], "total": cs.total} for cs in props.colourscheme} colourscheme = {cs.name: {"colour": cs.colour[0:3], "total": cs.total} for cs in props.colourscheme}
@@ -1195,9 +1197,17 @@ class SaveColourscheme(Operator, tool.Ifc.Operator):
description = json.loads(group.Description) description = json.loads(group.Description)
description["colourscheme"] = colourscheme description["colourscheme"] = colourscheme
description["colourscheme_query"] = query description["colourscheme_query"] = query
description["colourscheme_key"] = colourscheme_key
group.Description = json.dumps(description) group.Description = json.dumps(description)
else: else:
description = json.dumps({"type": "BBIM_Search", "colourscheme": colourscheme, "colourscheme_query": query}) description = json.dumps(
{
"type": "BBIM_Search",
"colourscheme": colourscheme,
"colourscheme_query": query,
"colourscheme_key": colourscheme_key,
}
)
group = ifcopenshell.api.group.add_group(tool.Ifc.get(), name=self.name, description=description) group = ifcopenshell.api.group.add_group(tool.Ifc.get(), name=self.name, description=description)
def invoke(self, context, event): def invoke(self, context, event):
@@ -1215,6 +1225,20 @@ class LoadColourscheme(Operator, tool.Ifc.Operator):
group = tool.Ifc.get().by_id(int(props.saved_colourschemes)) group = tool.Ifc.get().by_id(int(props.saved_colourschemes))
description = json.loads(group.Description) description = json.loads(group.Description)
props.colourscheme_query = description.get("colourscheme_query") props.colourscheme_query = description.get("colourscheme_query")
# colourscheme_key is a dynamic enum scoped to the active object's Psets
# (see ColourByPropertyData.colourscheme_key), so a previously saved key
# is only a valid choice if the current active object still exposes it.
# Otherwise fall back to "QUERY" so the saved query string (restored
# above) is used as a custom query instead of silently dropping the
# colour-by-property selection.
colourscheme_key = description.get("colourscheme_key")
valid_keys = {item[0] for item in ColourByPropertyData.colourscheme_key() if item is not None}
if colourscheme_key and colourscheme_key in valid_keys:
props.colourscheme_key = colourscheme_key
else:
props.colourscheme_key = "QUERY"
props.colourscheme.clear() props.colourscheme.clear()
for name, data in description.get("colourscheme", {}).items(): for name, data in description.get("colourscheme", {}).items():
new = props.colourscheme.add() new = props.colourscheme.add()