diff --git a/addons/io_hubs_addon/components/definitions/audio.py b/addons/io_hubs_addon/components/definitions/audio.py index 1269b054..0e8ab0c1 100644 --- a/addons/io_hubs_addon/components/definitions/audio.py +++ b/addons/io_hubs_addon/components/definitions/audio.py @@ -32,7 +32,7 @@ class Audio(HubsComponent): description="Loop", default=True) - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/audio_params.py b/addons/io_hubs_addon/components/definitions/audio_params.py index 5fc734a0..2a3a0ed0 100644 --- a/addons/io_hubs_addon/components/definitions/audio_params.py +++ b/addons/io_hubs_addon/components/definitions/audio_params.py @@ -2,7 +2,7 @@ from bpy.props import BoolProperty, FloatProperty, EnumProperty from ..hubs_component import HubsComponent from ..types import PanelType, NodeType, MigrationType -from ..utils import is_linked +from ..utils import is_linked, get_host_reference_message from ..consts import DISTACE_MODELS, MAX_ANGLE from math import degrees, radians @@ -105,7 +105,7 @@ def gather(self, export_settings, object): 'coneOuterGain': self.coneOuterGain } - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True @@ -115,13 +115,9 @@ def migrate(self, migration_type, instance_version, host, migration_report, ob=N self.coneOuterAngle) if migration_type != MigrationType.GLOBAL or is_linked(ob): - host_type = "bone" if hasattr(host, "tail") else "object" - if host_type == "bone": - host_reference = f"\"{host.name}\" in \"{host.id_data.name_full}\"" - else: - host_reference = f"\"{host.name_full}\"" + host_reference = get_host_reference_message(panel_type, host, ob=ob) migration_report.append( - f"Warning: The Media Cone angles may not have migrated correctly for the Audio Params component on the {host_type} {host_reference}") + f"Warning: The Media Cone angles may not have migrated correctly for the Audio Params component on the {panel_type.value} {host_reference}") return migration_occurred diff --git a/addons/io_hubs_addon/components/definitions/audio_settings.py b/addons/io_hubs_addon/components/definitions/audio_settings.py index d3e20b0a..5b4d873c 100644 --- a/addons/io_hubs_addon/components/definitions/audio_settings.py +++ b/addons/io_hubs_addon/components/definitions/audio_settings.py @@ -114,7 +114,7 @@ def gather(self, export_settings, object): 'mediaConeOuterGain': self.mediaConeOuterGain, } - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/audio_zone.py b/addons/io_hubs_addon/components/definitions/audio_zone.py index cb5180e4..ed009e3d 100644 --- a/addons/io_hubs_addon/components/definitions/audio_zone.py +++ b/addons/io_hubs_addon/components/definitions/audio_zone.py @@ -56,7 +56,7 @@ def create_gizmo(cls, ob, gizmo_group): return gizmo - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/image.py b/addons/io_hubs_addon/components/definitions/image.py index 00b11e03..50af84f6 100644 --- a/addons/io_hubs_addon/components/definitions/image.py +++ b/addons/io_hubs_addon/components/definitions/image.py @@ -37,7 +37,7 @@ class Image(HubsComponent): items=PROJECTION_MODE, default="flat") - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/link.py b/addons/io_hubs_addon/components/definitions/link.py index 1c0899d8..53cc5bde 100644 --- a/addons/io_hubs_addon/components/definitions/link.py +++ b/addons/io_hubs_addon/components/definitions/link.py @@ -19,7 +19,7 @@ class Link(HubsComponent): href: StringProperty(name="Link URL", description="Link URL", default="https://mozilla.org") - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/loop_animation.py b/addons/io_hubs_addon/components/definitions/loop_animation.py index a9115f01..d1b280e7 100644 --- a/addons/io_hubs_addon/components/definitions/loop_animation.py +++ b/addons/io_hubs_addon/components/definitions/loop_animation.py @@ -4,7 +4,7 @@ from bpy.types import PropertyGroup, Menu, Operator from ..hubs_component import HubsComponent from ..types import Category, PanelType, NodeType -from ..utils import redraw_component_ui +from ..utils import redraw_component_ui, get_host_reference_message msgbus_owners = [] @@ -683,7 +683,7 @@ def unregister(): unregister_msgbus() - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True @@ -714,13 +714,9 @@ def migrate(self, migration_type, instance_version, host, migration_report, ob=N track.track_type = track_type if migration_warning: - host_type = "bone" if hasattr(host, "tail") else "object" - if host_type == "bone": - host_reference = f"\"{host.name}\" in \"{host.id_data.name_full}\"" - else: - host_reference = f"\"{host.name_full}\"" + host_reference = get_host_reference_message(panel_type, host, ob=ob) migration_report.append( - f"Warning: The Loop Animation component on the {host_type} {host_reference} may not have migrated correctly") + f"Warning: The Loop Animation component on the {panel_type.value} {host_reference} may not have migrated correctly") return migration_occurred diff --git a/addons/io_hubs_addon/components/definitions/media_frame.py b/addons/io_hubs_addon/components/definitions/media_frame.py index a6fba057..096d431a 100644 --- a/addons/io_hubs_addon/components/definitions/media_frame.py +++ b/addons/io_hubs_addon/components/definitions/media_frame.py @@ -5,7 +5,7 @@ from ..models import box from ..hubs_component import HubsComponent from ..types import Category, PanelType, NodeType, MigrationType -from ..utils import V_S1, is_linked +from ..utils import V_S1, is_linked, get_host_reference_message from .networked import migrate_networked from mathutils import Matrix, Vector @@ -118,7 +118,7 @@ def create_gizmo(cls, ob, gizmo_group): return gizmo - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True @@ -128,13 +128,9 @@ def migrate(self, migration_type, instance_version, host, migration_report, ob=N self.bounds = bounds if migration_type != MigrationType.GLOBAL or is_linked(ob): - host_type = "bone" if hasattr(host, "tail") else "object" - if host_type == "bone": - host_reference = f"\"{host.name}\" in \"{host.id_data.name_full}\"" - else: - host_reference = f"\"{host.name_full}\"" + host_reference = get_host_reference_message(panel_type, host, ob=ob) migration_report.append( - f"Warning: The Media Frame component's Y and Z bounds on the {host_type} {host_reference} may not have migrated correctly") + f"Warning: The Media Frame component's Y and Z bounds on the {panel_type.value} {host_reference} may not have migrated correctly") return migration_occurred diff --git a/addons/io_hubs_addon/components/definitions/model.py b/addons/io_hubs_addon/components/definitions/model.py index 535971fd..f2072cbf 100644 --- a/addons/io_hubs_addon/components/definitions/model.py +++ b/addons/io_hubs_addon/components/definitions/model.py @@ -19,7 +19,7 @@ class Model(HubsComponent): src: StringProperty(name="Model URL", description="Model URL", default="https://mozilla.org") - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/morph_audio_feedback.py b/addons/io_hubs_addon/components/definitions/morph_audio_feedback.py index 958a954d..6360d1ff 100644 --- a/addons/io_hubs_addon/components/definitions/morph_audio_feedback.py +++ b/addons/io_hubs_addon/components/definitions/morph_audio_feedback.py @@ -92,10 +92,10 @@ class MorphAudioFeedback(HubsComponent): default=1.0) @classmethod - def poll(cls, context, panel_type): - return context.object.type == 'MESH' + def poll(cls, panel_type, host, ob=None): + return host.type == 'MESH' - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/nav_mesh.py b/addons/io_hubs_addon/components/definitions/nav_mesh.py index c6b7f9bc..8d344ee8 100644 --- a/addons/io_hubs_addon/components/definitions/nav_mesh.py +++ b/addons/io_hubs_addon/components/definitions/nav_mesh.py @@ -14,5 +14,5 @@ class NavMesh(HubsComponent): } @classmethod - def poll(cls, context, panel_type): - return context.object.type == 'MESH' + def poll(cls, panel_type, host, ob=None): + return host.type == 'MESH' diff --git a/addons/io_hubs_addon/components/definitions/reflection_probe.py b/addons/io_hubs_addon/components/definitions/reflection_probe.py index e2be0189..43d132cd 100644 --- a/addons/io_hubs_addon/components/definitions/reflection_probe.py +++ b/addons/io_hubs_addon/components/definitions/reflection_probe.py @@ -882,8 +882,8 @@ def draw_global(cls, context, layout, panel): icon='ERROR') @ classmethod - def poll(cls, context, panel_type): - return context.object.type == 'LIGHT_PROBE' + def poll(cls, panel_type, host, ob=None): + return host.type == 'LIGHT_PROBE' @ staticmethod def register(): diff --git a/addons/io_hubs_addon/components/definitions/spawner.py b/addons/io_hubs_addon/components/definitions/spawner.py index 68b67758..e8bff25d 100644 --- a/addons/io_hubs_addon/components/definitions/spawner.py +++ b/addons/io_hubs_addon/components/definitions/spawner.py @@ -30,7 +30,7 @@ def gather(self, export_settings, object): } } - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/video.py b/addons/io_hubs_addon/components/definitions/video.py index b766a98f..db0babdb 100644 --- a/addons/io_hubs_addon/components/definitions/video.py +++ b/addons/io_hubs_addon/components/definitions/video.py @@ -39,7 +39,7 @@ class Video(HubsComponent): description="Loop", default=True) - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/definitions/video_texture_source.py b/addons/io_hubs_addon/components/definitions/video_texture_source.py index e1a6394d..653524ce 100644 --- a/addons/io_hubs_addon/components/definitions/video_texture_source.py +++ b/addons/io_hubs_addon/components/definitions/video_texture_source.py @@ -24,21 +24,26 @@ class VideoTextureSource(HubsComponent): name="FPS", description="FPS", default=15) @classmethod - def poll(cls, context, panel_type): - ob = context.object + def poll(cls, panel_type, host, ob=None): if panel_type == PanelType.OBJECT: return hasattr( - ob, 'type') and ( - ob.type == 'CAMERA' or [x for x in children_recursive(ob) if x.type == "CAMERA" and not x.parent_bone]) + host, 'type') and ( + host.type == 'CAMERA' or + [x for x in children_recursive(host) if x.type == "CAMERA" and not x.parent_bone]) elif panel_type == PanelType.BONE: - bone = context.active_bone - return [x for x in children_recursive(ob) if x.type == "CAMERA" and x.parent_bone == bone.name] + return [x for x in children_recursive(ob) if x.type == "CAMERA" and x.parent_bone == host.name] return False - def draw(self, context, layout, panel): - super().draw(context, layout, panel) - if not VideoTextureSource.poll(context, PanelType(panel.bl_context)): - col = layout.column() - col.alert = True - col.label(text='No camera found in the object hierarchy', - icon='ERROR') + @classmethod + def get_unsupported_host_message(cls, panel_type, host, ob=None): + if panel_type == PanelType.BONE: + host_reference = f"\"{host.name}\" in \"{ob.name_full}\"" + object_message = "" + else: + host_reference = f"\"{host.name_full}\"" + object_message = " aren't cameras themselves and" + + host_type = panel_type.value + message = f"Warning: Unsupported component on {host_type} {host_reference}, {host_type}s that{object_message} don't have a camera somewhere in their child hierarchy don't support {cls.get_display_name()} components" + + return message diff --git a/addons/io_hubs_addon/components/definitions/waypoint.py b/addons/io_hubs_addon/components/definitions/waypoint.py index c6ee0e18..fdf431db 100644 --- a/addons/io_hubs_addon/components/definitions/waypoint.py +++ b/addons/io_hubs_addon/components/definitions/waypoint.py @@ -81,7 +81,7 @@ def create_gizmo(cls, ob, gizmo_group): return gizmo - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): migration_occurred = False if instance_version < (1, 0, 0): migration_occurred = True diff --git a/addons/io_hubs_addon/components/handlers.py b/addons/io_hubs_addon/components/handlers.py index a7b19202..aaba6426 100644 --- a/addons/io_hubs_addon/components/handlers.py +++ b/addons/io_hubs_addon/components/handlers.py @@ -3,7 +3,7 @@ from .components_registry import get_components_registry from .utils import redirect_c_stdout, get_host_components, is_linked from .gizmos import update_gizmos -from .types import MigrationType +from .types import MigrationType, PanelType import io import sys import traceback @@ -14,14 +14,14 @@ file_loading = False -def migrate(component, migration_type, host, migration_report, ob=None): +def migrate(component, migration_type, panel_type, host, migration_report, ob=None): instance_version = tuple(component.instance_version) definition_version = component.__class__.get_definition_version() was_migrated = False if instance_version < definition_version: was_migrated = component.migrate( - migration_type, instance_version, host, migration_report, ob=ob) + migration_type, panel_type, instance_version, host, migration_report, ob=ob) if type(was_migrated) != bool: print(f"Warning: the {component.get_display_name()} component didn't return whether a migration occurred.") @@ -30,6 +30,10 @@ def migrate(component, migration_type, host, migration_report, ob=None): component.instance_version = definition_version + if panel_type not in component.__class__.get_panel_type() or not component.__class__.poll(panel_type, host, ob=ob): + message = component.__class__.get_unsupported_host_message(panel_type, host, ob=ob) + migration_report.append(message) + return was_migrated @@ -48,7 +52,7 @@ def migrate_components( for component in get_host_components(scene): try: was_migrated = migrate( - component, migration_type, scene, migration_report) + component, migration_type, PanelType.SCENE, scene, migration_report) except Exception as e: was_migrated = True error = f"Error: Migration failed for component {component.get_display_name()} on scene \"{scene.name_full}\"" @@ -66,7 +70,7 @@ def migrate_components( for component in get_host_components(ob): try: was_migrated = migrate( - component, migration_type, ob, migration_report, ob=ob) + component, migration_type, PanelType.OBJECT, ob, migration_report, ob=ob) except Exception as e: was_migrated = True error = f"Error: Migration failed for component {component.get_display_name()} on object \"{ob.name_full}\"" @@ -85,7 +89,7 @@ def migrate_components( for component in get_host_components(bone): try: was_migrated = migrate( - component, migration_type, bone, migration_report, ob=ob) + component, migration_type, PanelType.BONE, bone, migration_report, ob=ob) except Exception as e: was_migrated = True error = f"Error: Migration failed for component {component.get_display_name()} on bone \"{bone.name}\" in \"{ob.name_full}\"" @@ -103,7 +107,7 @@ def migrate_components( for component in get_host_components(material): try: was_migrated = migrate( - component, migration_type, material, migration_report) + component, migration_type, PanelType.MATERIAL, material, migration_report) except Exception as e: was_migrated = True error = f"Error: Migration failed for component {component.get_display_name()} on material \"{material.name_full}\"" diff --git a/addons/io_hubs_addon/components/hubs_component.py b/addons/io_hubs_addon/components/hubs_component.py index 73c58fd1..c1504cab 100644 --- a/addons/io_hubs_addon/components/hubs_component.py +++ b/addons/io_hubs_addon/components/hubs_component.py @@ -122,9 +122,10 @@ def post_export(self, export_settings, host, ob=None): '''This is called by the exporter after the export process has finished''' pass - def migrate(self, migration_type, instance_version, host, migration_report, ob=None): + def migrate(self, migration_type, panel_type, instance_version, host, migration_report, ob=None): '''This is called when an object component needs to migrate the data from previous add-on versions. The migration_type argument is the type of migration, GLOBAL represents file loads, and LOCAL represents things like append/link. + The panel_type argument is used to determine what data-block the component is on. The instance_version argument represents the version of the component that will be migrated from, as a tuple. The host argument is what the component is attached to, object/bone. The migration_report argument is a list that you can append messages to and they will be displayed to the user after the migration has finished. @@ -147,11 +148,23 @@ def get_properties(cls): return {} @classmethod - def poll(cls, context, panel_type): + def poll(cls, panel_type, host, ob=None): '''This method will return true if this component's shown be shown or run. - This is currently called when checking if the component should be added to the components pop-up and when the components properties panel is drawn''' + This is currently called when checking if the component should be added to the components pop-up, when the components properties panel is drawn, and during migrations to warn about unsupported hosts. + The ob argument is guaranteed to be present only for objects/bones.''' return True + @classmethod + def get_unsupported_host_message(cls, panel_type, host, ob=None): + '''This method will return the message to use if this component isn't supported on this host. + This is currently called during migrations.''' + from .utils import get_host_reference_message + host_reference = get_host_reference_message(panel_type, host, ob=ob) + host_type = panel_type.value + message = f"Warning: Unsupported component on {host_type} {host_reference}, {host_type}s don't support {cls.get_display_name()} components" + + return message + @staticmethod def register(): '''This is called by the Blender runtime when the component is registered. diff --git a/addons/io_hubs_addon/components/operators.py b/addons/io_hubs_addon/components/operators.py index 8af7ec58..8880d5aa 100644 --- a/addons/io_hubs_addon/components/operators.py +++ b/addons/io_hubs_addon/components/operators.py @@ -38,7 +38,8 @@ def invoke(self, context, event): # Filter components that are not targeted to this object type or their poll method call returns False def filter_source_type(cmp): (_, component_class) = cmp - return not component_class.is_dep_only() and PanelType(panel_type) in component_class.get_panel_type() and component_class.poll(context, PanelType(panel_type)) + host = get_object_source(context, panel_type) + return not component_class.is_dep_only() and PanelType(panel_type) in component_class.get_panel_type() and component_class.poll(PanelType(panel_type), host, ob=context.object) components_registry = get_components_registry() components_icons = get_components_icons() diff --git a/addons/io_hubs_addon/components/types.py b/addons/io_hubs_addon/components/types.py index 38fa5f4e..c28acc6c 100644 --- a/addons/io_hubs_addon/components/types.py +++ b/addons/io_hubs_addon/components/types.py @@ -5,7 +5,6 @@ class PanelType(Enum): OBJECT = 'object' SCENE = 'scene' MATERIAL = 'material' - OBJECT_DATA = 'data' BONE = 'bone' diff --git a/addons/io_hubs_addon/components/ui.py b/addons/io_hubs_addon/components/ui.py index 0989f5e0..ab8d8c1b 100644 --- a/addons/io_hubs_addon/components/ui.py +++ b/addons/io_hubs_addon/components/ui.py @@ -17,7 +17,18 @@ def draw_component(panel, context, obj, row, component_item): component_class = get_component_by_name(component_name) if component_class: panel_type = PanelType(panel.bl_context) - if panel_type not in component_class.get_panel_type(): + if panel_type not in component_class.get_panel_type() or not component_class.poll(panel_type, obj, ob=context.object): + col = row.box().column() + top_row = col.row() + top_row.label( + text=f"Unsupported host for component '{component_class.get_display_name()}'", icon="ERROR") + remove_component_operator = top_row.operator( + "wm.remove_hubs_component", + text="", + icon="X" + ) + remove_component_operator.component_name = component_name + remove_component_operator.panel_type = panel.bl_context return component_id = component_class.get_id() diff --git a/addons/io_hubs_addon/components/utils.py b/addons/io_hubs_addon/components/utils.py index 6921bd8a..28e2d66b 100644 --- a/addons/io_hubs_addon/components/utils.py +++ b/addons/io_hubs_addon/components/utils.py @@ -1,6 +1,7 @@ import bpy from .components_registry import get_component_by_name from .gizmos import update_gizmos +from .types import PanelType from mathutils import Vector from contextlib import contextmanager import os @@ -275,3 +276,12 @@ def display_wrapped_text(layout, wrapped_text, *, heading_icon='NONE'): text_column.label(text=line, icon=heading_icon) else: text_column.label(text=line, icon=padding_icon) + + +def get_host_reference_message(panel_type, host, ob=None): + if panel_type == PanelType.BONE: + host_reference = f"\"{host.name}\" in \"{ob.name_full}\"" + else: + host_reference = f"\"{host.name_full}\"" + + return host_reference