From 71ddc6384a731276d56d32fcd80a6f0d7b7c560f Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 19 Aug 2024 18:10:25 +0500 Subject: [PATCH] bonsai bcf v3 - support adding/removing related topics #2790 Not entirely sure about TopicHandler.guid typing, just made it consistent with v2 for now. --- src/bcf/bcf/v3/topic.py | 4 +-- src/bonsai/bonsai/bim/module/bcf/operator.py | 32 +++++++++++--------- src/bonsai/bonsai/tool/bcf.py | 19 ++++++++++++ 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/bcf/bcf/v3/topic.py b/src/bcf/bcf/v3/topic.py index 34a9af35fa..42a4269ddb 100644 --- a/src/bcf/bcf/v3/topic.py +++ b/src/bcf/bcf/v3/topic.py @@ -49,11 +49,11 @@ class TopicHandler: return self.markup.topic @property - def guid(self) -> Optional[str]: + def guid(self) -> str: """Return the GUID of the topic.""" if self._markup: return self.topic.guid - return self._topic_dir.name if self._topic_dir else None + return self._topic_dir.name if self._topic_dir else "" @property def header(self) -> Optional[mdl.Header]: diff --git a/src/bonsai/bonsai/bim/module/bcf/operator.py b/src/bonsai/bonsai/bim/module/bcf/operator.py index 3a13127ed3..65283010cb 100644 --- a/src/bonsai/bonsai/bim/module/bcf/operator.py +++ b/src/bonsai/bonsai/bim/module/bcf/operator.py @@ -441,21 +441,25 @@ class AddBcfRelatedTopic(bpy.types.Operator): def execute(self, context): bcfxml = bcfstore.BcfStore.get_bcfxml() assert bcfxml - - if not (version := (bcfxml.version.version_id or "")).startswith("2"): - self.report({"INFO"}, f"BCF {version} is not yet supported: {self.bl_rna.bl_idname}.") - return {"FINISHED"} + bcf_v2 = (bcfxml.version.version_id or "").startswith("2") props = context.scene.BCFProperties blender_topic = props.active_topic topic = bcfxml.topics[blender_topic.name] - topic.topic.related_topic.append( - bcf.v2.model.TopicRelatedTopic( - guid=next((t for t in bcfxml.topics.values() if t.topic.title == props.related_topic)).guid - ) - ) + related_topics = tool.Bcf.get_topic_related_topics(topic) + related_topic_guid = props.related_topic + + if bcf_v2: + assert tool.Bcf.is_list_of(related_topics, bcf.v2.model.TopicRelatedTopic) + related_topic = bcf.v2.model.TopicRelatedTopic(guid=related_topic_guid) + related_topics.append(related_topic) + else: + assert tool.Bcf.is_list_of(related_topics, bcf.v3.model.TopicRelatedTopicsRelatedTopic) + related_topic = bcf.v3.model.TopicRelatedTopicsRelatedTopic(guid=related_topic_guid) + related_topics.append(related_topic) + + tool.Bcf.set_topic_related_topics(topic, related_topics) bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index) - props.related_topic = "" return {"FINISHED"} @@ -982,14 +986,12 @@ class RemoveBcfRelatedTopic(bpy.types.Operator): bcfxml = bcfstore.BcfStore.get_bcfxml() assert bcfxml - if not (version := (bcfxml.version.version_id or "")).startswith("2"): - self.report({"INFO"}, f"BCF {version} is not yet supported: {self.bl_rna.bl_idname}.") - return {"FINISHED"} - props = context.scene.BCFProperties blender_topic = props.active_topic topic = bcfxml.topics[blender_topic.name] - del topic.topic.related_topic[self.index] + related_topics = tool.Bcf.get_topic_related_topics(topic) + del related_topics[self.index] + tool.Bcf.set_topic_related_topics(topic, related_topics) bpy.ops.bim.load_bcf_topic(topic_guid=topic.guid, topic_index=props.active_topic_index) return {"FINISHED"} diff --git a/src/bonsai/bonsai/tool/bcf.py b/src/bonsai/bonsai/tool/bcf.py index 7753be96f0..106af04971 100644 --- a/src/bonsai/bonsai/tool/bcf.py +++ b/src/bonsai/bonsai/tool/bcf.py @@ -169,6 +169,25 @@ class Bcf(bonsai.core.tool.Bcf): related_topics = related_topics.related_topic if related_topics else [] return related_topics + @classmethod + def set_topic_related_topics( + cls, + topic: bcf.agnostic.topic.TopicHandler, + related_topics: Union[list[bcf.v2.model.TopicRelatedTopic], list[bcf.v3.model.TopicRelatedTopicsRelatedTopic]], + ) -> None: + topic_ = topic.topic + if isinstance(topic_, bcf.v2.model.Topic): + assert cls.is_list_of(related_topics, bcf.v2.model.TopicRelatedTopic) + topic_.related_topic = related_topics + else: + assert cls.is_list_of(related_topics, bcf.v3.model.TopicRelatedTopicsRelatedTopic) + topic_related_topics = topic_.related_topics + if topic_related_topics is None: + if not related_topics: + return + topic_.related_topics = (topic_related_topics := bcf.v3.model.TopicRelatedTopics()) + topic_related_topics.related_topic = related_topics + ## visinfo @classmethod def get_viewpoint_bitmaps(