Browse Source

Ensure note popups don't clobber each other.

Fail fast if someone sets up multiple note popups with conflicting
settings. This will allow us to obey the principle of least surprise.
pull/406/head
Adam Johnson 2 months ago
parent
commit
20ccfa87f9
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 6
      korman/exporter/convert.py
  2. 8
      korman/exporter/gui.py
  3. 2
      korman/properties/modifiers/anim.py
  4. 2
      korman/properties/modifiers/avatar.py
  5. 2
      korman/properties/modifiers/game_gui.py
  6. 8
      korman/properties/modifiers/gui.py
  7. 2
      korman/properties/modifiers/logic.py
  8. 4
      korman/properties/modifiers/render.py
  9. 2
      korman/properties/modifiers/sound.py

6
korman/exporter/convert.py

@ -229,7 +229,7 @@ class Exporter:
for mod in bl_obj.plasma_modifiers.modifiers:
fn = getattr(mod, "sanity_check", None)
if fn is not None:
fn()
fn(self)
inc_progress()
self.report.msg("... Age is grinning and holding a spatula. Must be OK, then.")
@ -502,7 +502,9 @@ class Exporter:
# Wow, recursively generated objects. Aren't you special?
with indent():
for mod in temporary.plasma_modifiers.modifiers:
mod.sanity_check()
fn = getattr(mod, "sanity_check", None)
if fn is not None:
fn(self)
do_pre_export(temporary)
return temporary

8
korman/exporter/gui.py

@ -49,10 +49,12 @@ class GuiConverter:
if TYPE_CHECKING:
_parent: weakref.ref[Exporter] = ...
_pages: Dict[str, Any] = ...
_mods_exported: Set[str] = ...
def __init__(self, parent: Optional[Exporter] = None):
self._parent = weakref.ref(parent) if parent is not None else None
self._pages = {}
self._mods_exported = set()
# Go ahead and prepare the GUI transparent material for future use.
@ -206,6 +208,12 @@ class GuiConverter:
w2c[2, i] *= -1.0
return PostEffectModMatrices(c2w, w2c)
def check_pre_export(self, name: str, **kwargs):
previous = self._pages.setdefault(name, kwargs)
if previous != kwargs:
diff = set(previous.items()) - set(kwargs.items())
raise ExportError(f"GUI Page '{name}' has target modifiers with conflicting settings:\n{diff}")
def create_note_gui(self, gui_page: str, gui_camera: bpy.types.Object):
if not gui_page in self._mods_exported:
guidialog_object = utils.create_empty_object(f"{gui_page}_NoteDialog")

2
korman/properties/modifiers/anim.py

@ -42,7 +42,7 @@ class ActionModifier:
return None
raise ExportError("'{}': Object has an animation modifier but is not animated".format(bo.name))
def sanity_check(self) -> None:
def sanity_check(self, exporter) -> None:
if not self.id_data.plasma_object.has_animation_data:
raise ExportError("'{}': Has an animation modifier but no animation data.", self.id_data.name)

2
korman/properties/modifiers/avatar.py

@ -189,7 +189,7 @@ class PlasmaSittingBehavior(idprops.IDPropObjectMixin, PlasmaModifierProperties,
# This should be an empty, really...
return True
def sanity_check(self):
def sanity_check(self, exporter):
# The user absolutely MUST specify a clickable or this won't export worth crap.
if self.clickable_object is None:
raise ExportError("'{}': Sitting Behavior's clickable object is invalid".format(self.key_name))

2
korman/properties/modifiers/game_gui.py

@ -70,7 +70,7 @@ class _GameGuiMixin:
def requires_dyntext(self) -> bool:
return False
def sanity_check(self):
def sanity_check(self, exporter):
age: PlasmaAge = bpy.context.scene.world.plasma_age
# Game GUI modifiers must be attached to objects in a GUI page, ONLY

8
korman/properties/modifiers/gui.py

@ -660,7 +660,7 @@ class PlasmaLinkingBookModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz
share.link_input(share_anim_stage, "stage", "stage_refs")
share.link_output(linkingnode, "hosts", "shareBookSeek")
def sanity_check(self):
def sanity_check(self, exporter):
if self.clickable is None:
raise ExportError("{}: Linking Book modifier requires a clickable!", self.id_data.name)
if self.seek_point is None:
@ -724,11 +724,15 @@ class PlasmaNotePopupModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz):
if self.id_data.type == "MESH":
return self.id_data
def sanity_check(self):
def sanity_check(self, exporter: Exporter):
page_type = helpers.get_page_type(self.id_data.plasma_object.page)
if page_type != "room":
raise ExportError(f"Note Popup modifiers should be in a 'room' page, not a '{page_type}' page!")
# It's OK if multiple note popups point to the same GUI page,
# they just need to have the same camera.
exporter.gui.check_pre_export(self.gui_page, pl_id="note_popup", camera=self.gui_camera)
def pre_export(self, exporter: Exporter, bo: bpy.types.Object):
# The GUI converter will debounce duplicate GUI dialogs.
yield from exporter.gui.create_note_gui(self.gui_page, self.gui_camera)

2
korman/properties/modifiers/logic.py

@ -154,7 +154,7 @@ class PlasmaTelescope(PlasmaModifierProperties, PlasmaModifierLogicWiz):
type=bpy.types.Object,
poll=idprops.poll_camera_objects)
def sanity_check(self):
def sanity_check(self, exporter):
if self.camera_object is None:
raise ExportError(f"'{self.id_data.name}': Telescopes must specify a camera!")

4
korman/properties/modifiers/render.py

@ -120,7 +120,7 @@ class PlasmaBlendMod(PlasmaModifierProperties):
for i in (j.blend_onto for j in self.dependencies if j.blend_onto is not None and j.enabled):
yield i
def sanity_check(self):
def sanity_check(self, exporter):
if self.has_circular_dependency:
raise ExportError("'{}': Circular Render Dependency detected!".format(self.id_data.name))
@ -770,7 +770,7 @@ class PlasmaLocalizedTextModifier(PlasmaModifierProperties, PlasmaModifierLogicW
def localization_set(self):
return "DynaTexts"
def sanity_check(self):
def sanity_check(self, exporter):
if self.texture is None:
raise ExportError("'{}': Localized Text modifier requires a texture", self.id_data.name)

2
korman/properties/modifiers/sound.py

@ -533,7 +533,7 @@ class PlasmaSoundEmitter(PlasmaModifierProperties):
stereize_left = PointerProperty(type=bpy.types.Object, options={"HIDDEN", "SKIP_SAVE"})
stereize_right = PointerProperty(type=bpy.types.Object, options={"HIDDEN", "SKIP_SAVE"})
def sanity_check(self):
def sanity_check(self, exporter):
modifiers = self.id_data.plasma_modifiers
# Sound emitters can potentially export sounds to more than one emitter SceneObject. Currently,

Loading…
Cancel
Save