From 778caadf1132fa9b7d8c8481b4292006492dbec5 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 23 Jun 2024 15:35:15 -0400 Subject: [PATCH] Centralize the definitions for standard Plasma APIs. This helps make Korman more maintainable by reducing potential duplication of Python attribute definitions. Further, it simplifies the code to create a Python File Node for a standard API file. --- korman/plasma_api.py | 118 ++++++++++++++++++++++++++ korman/properties/modifiers/avatar.py | 12 +-- korman/properties/modifiers/base.py | 5 ++ korman/properties/modifiers/gui.py | 87 ++----------------- korman/properties/modifiers/logic.py | 28 +----- korman/properties/modifiers/render.py | 26 +----- 6 files changed, 132 insertions(+), 144 deletions(-) create mode 100644 korman/plasma_api.py diff --git a/korman/plasma_api.py b/korman/plasma_api.py new file mode 100644 index 0000000..98a6182 --- /dev/null +++ b/korman/plasma_api.py @@ -0,0 +1,118 @@ +# This file is part of Korman. +# +# Korman is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Korman is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Korman. If not, see . + +python_files = { + # Provided by all variants of Uru and Myst V + "xDialogToggle.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "Activate" }, + { "id": 4, "type": "ptAttribString", "name": "Vignette" }, + ), + + # Provided by CWE or OfflineKI + "xDynTextLoc.py": ( + { "id": 1, "type": "ptAttribDynamicMap", "name": "dynTextMap", }, + { "id": 2, "type": "ptAttribString", "name": "locPath" }, + { "id": 3, "type": "ptAttribString", "name": "fontFace" }, + { "id": 4, "type": "ptAttribInt", "name": "fontSize" }, + { "id": 5, "type": "ptAttribFloat", "name": "fontColorR" }, + { "id": 6, "type": "ptAttribFloat", "name": "fontColorG" }, + { "id": 7, "type": "ptAttribFloat", "name": "fontColorB" }, + { "id": 8, "type": "ptAttribFloat", "name": "fontColorA" }, + { "id": 9, "type": "ptAttribInt", "name": "marginTop" }, + { "id": 10, "type": "ptAttribInt", "name": "marginLeft" }, + { "id": 11, "type": "ptAttribInt", "name": "marginBottom" }, + { "id": 12, "type": "ptAttribInt", "name": "marginRight" }, + { "id": 13, "type": "ptAttribInt", "name": "lineSpacing" }, + # Yes, it"s really a ptAttribDropDownList, but those are only for use in + # artist generated node trees. + { "id": 14, "type": "ptAttribString", "name": "justify" }, + { "id": 15, "type": "ptAttribFloat", "name": "clearColorR" }, + { "id": 16, "type": "ptAttribFloat", "name": "clearColorG" }, + { "id": 17, "type": "ptAttribFloat", "name": "clearColorB" }, + { "id": 18, "type": "ptAttribFloat", "name": "clearColorA" }, + { "id": 19, "type": "ptAttribBoolean", "name": "blockRGB" }, + ), + + # Provided by CWE and OfflineKI + "xEntryCam.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "actRegionSensor" }, + { "id": 2, "type": "ptAttribSceneobject", "name": "camera" }, + { "id": 3, "type": "ptAttribBoolean", "name": "undoFirstPerson" }, + ), + + # Provided by CWE + "xJournalBookGUIPopup.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "actClickableBook" }, + { "id": 10, "type": "ptAttribBoolean", "name": "StartOpen" }, + { "id": 11, "type": "ptAttribFloat", "name": "BookWidth" }, + { "id": 12, "type": "ptAttribFloat", "name": "BookHeight" }, + { "id": 13, "type": "ptAttribString", "name": "LocPath" }, + { "id": 14, "type": "ptAttribString", "name": "GUIType" }, + ), + + # Provided by all variants of Uru and Myst V + "xLinkingBookGUIPopup.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "actClickableBook" }, + { "id": 2, "type": "ptAttribBehavior", "name": "SeekBehavior" }, + { "id": 3, "type": "ptAttribResponder", "name": "respLinkResponder" }, + { "id": 4, "type": "ptAttribString", "name": "TargetAge" }, + { "id": 5, "type": "ptAttribActivator", "name": "actBookshelf" }, + { "id": 6, "type": "ptAttribActivator", "name": "shareRegion" }, + { "id": 7, "type": "ptAttribBehavior", "name": "shareBookSeek" }, + { "id": 10, "type": "ptAttribBoolean", "name": "IsDRCStamped" }, + { "id": 11, "type": "ptAttribBoolean", "name": "ForceThirdPerson" }, + ), + + # Supplied by the OfflineKI script: + # https://gitlab.com/diafero/offline-ki/blob/master/offlineki/xSimpleJournal.py + "xSimpleJournal.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "bookClickable" }, + { "id": 2, "type": "ptAttribString", "name": "journalFileName" }, + { "id": 3, "type": "ptAttribBoolean", "name": "isNotebook" }, + { "id": 4, "type": "ptAttribFloat", "name": "BookWidth" }, + { "id": 5, "type": "ptAttribFloat", "name": "BookHeight" }, + ), + + # Supplied by the OfflineKI script: + # https://gitlab.com/diafero/offline-ki/blob/master/offlineki/xSimpleLinkingBook.py + "xSimpleLinkingBook.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "bookClickable" }, + { "id": 2, "type": "ptAttribString", "name": "destinationAge" }, + { "id": 3, "type": "ptAttribString", "name": "spawnPoint" }, + { "id": 4, "type": "ptAttribString", "name": "linkPanel" }, + { "id": 5, "type": "ptAttribString", "name": "bookCover" }, + { "id": 6, "type": "ptAttribString", "name": "stampTexture" }, + { "id": 7, "type": "ptAttribFloat", "name": "stampX" }, + { "id": 8, "type": "ptAttribFloat", "name": "stampY" }, + { "id": 9, "type": "ptAttribFloat", "name": "bookWidth" }, + { "id": 10, "type": "ptAttribFloat", "name": "BookHeight" }, + { "id": 11, "type": "ptAttribBehavior", "name": "msbSeekBeforeUI" }, + { "id": 12, "type": "ptAttribResponder", "name": "respOneShot" }, + ), + + # Provided by CWE or OfflineKI + "xSitCam.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "sitAct" }, + { "id": 2, "type": "ptAttribSceneobject", "name": "sitCam" }, + ), + + # Provided by all variants of Uru and Myst V + "xTelescope.py": ( + { "id": 1, "type": "ptAttribActivator", "name": "Activate" }, + { "id": 2, "type": "ptAttribSceneobject", "name": "Camera" }, + { "id": 3, "type": "ptAttribBehavior", "name": "Behavior" }, + { "id": 4, "type": "ptAttribString", "name": "Vignette" }, + ) +} diff --git a/korman/properties/modifiers/avatar.py b/korman/properties/modifiers/avatar.py index c6397f5..bbd0bc9 100644 --- a/korman/properties/modifiers/avatar.py +++ b/korman/properties/modifiers/avatar.py @@ -78,16 +78,6 @@ class PlasmaLadderModifier(PlasmaModifierProperties): return True -# Use xSitCam.py for when we want a camera to pop up -sitting_pfm = { - "filename": "xSitCam.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", 'name': "sitAct" }, - { 'id': 2, 'type': "ptAttribSceneobject", 'name': "sitCam" }, - ) -} - - sitting_approach_flags = [("kApproachFront", "Front", "Approach from the font"), ("kApproachLeft", "Left", "Approach from the left"), ("kApproachRight", "Right", "Approach from the right"), @@ -140,7 +130,7 @@ class PlasmaSittingBehavior(idprops.IDPropObjectMixin, PlasmaModifierProperties, sittingmod.name = "SittingBeh" # xSitCam.py PythonFileMod if self.sitting_camera is not None: - sittingpynode = self._create_python_file_node(tree, sitting_pfm["filename"], sitting_pfm["attribs"]) + sittingpynode = self._create_python_standard_file_node(tree, "xSitCam.py") sittingmod.link_output(sittingpynode, "satisfies", "sitAct") # Camera Object diff --git a/korman/properties/modifiers/base.py b/korman/properties/modifiers/base.py index 2a984a2..1495c86 100644 --- a/korman/properties/modifiers/base.py +++ b/korman/properties/modifiers/base.py @@ -26,6 +26,7 @@ if TYPE_CHECKING: from ...nodes.node_python import * from ... import helpers +from ... import plasma_api class PlasmaModifierProperties(bpy.types.PropertyGroup): @property @@ -207,6 +208,10 @@ class PlasmaModifierLogicWiz: pfm_node.update() return pfm_node + def _create_standard_python_file_node(self, tree, filename: str) -> bpy.types.Node: + """Create a Python File Node for a standard Plasma Python API file (e.g. xAgeSDLBoolShowHide.py)""" + return self._create_python_file_node(tree, filename, plasma_api.python_files[filename]) + def _create_python_attribute(self, pfm_node: PlasmaPythonFileNode, attribute_name: str, **kwargs): """Creates and links a Python Attribute Node to the Python File Node given by `pfm_node`. For attribute nodes that require multiple values, the `value` may be set to None and diff --git a/korman/properties/modifiers/gui.py b/korman/properties/modifiers/gui.py index 5b06df2..0016e4d 100644 --- a/korman/properties/modifiers/gui.py +++ b/korman/properties/modifiers/gui.py @@ -35,33 +35,6 @@ if TYPE_CHECKING: from ...exporter import Exporter from .game_gui import PlasmaGameGuiDialogModifier - -journal_pfms = { - pvPots : { - # Supplied by the OfflineKI script: - # https://gitlab.com/diafero/offline-ki/blob/master/offlineki/xSimpleJournal.py - "filename": "xSimpleJournal.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", "name": "bookClickable" }, - { 'id': 2, 'type': "ptAttribString", "name": "journalFileName" }, - { 'id': 3, 'type': "ptAttribBoolean", "name": "isNotebook" }, - { 'id': 4, 'type': "ptAttribFloat", "name": "BookWidth" }, - { 'id': 5, 'type': "ptAttribFloat", "name": "BookHeight" }, - ) - }, - pvMoul : { - "filename": "xJournalBookGUIPopup.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", 'name': "actClickableBook" }, - { 'id': 10, 'type': "ptAttribBoolean", 'name': "StartOpen" }, - { 'id': 11, 'type': "ptAttribFloat", 'name': "BookWidth" }, - { 'id': 12, 'type': "ptAttribFloat", 'name': "BookHeight" }, - { 'id': 13, 'type': "ptAttribString", 'name': "LocPath" }, - { 'id': 14, 'type': "ptAttribString", 'name': "GUIType" }, - ) - }, -} - # Do not change the numeric IDs. They allow the list to be rearranged. _languages = [("Dutch", "Nederlands", "Dutch", 0), ("English", "English", "", 1), @@ -246,11 +219,11 @@ class PlasmaJournalBookModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz def logicwiz(self, bo, tree, age_name, version): # Assign journal script based on target version - journal_pfm = journal_pfms[version] - journalnode = self._create_python_file_node(tree, journal_pfm["filename"], journal_pfm["attribs"]) if version <= pvPots: + journalnode = self._create_standard_python_file_node(tree, "xSimpleJournal.py") self._create_pots_nodes(bo, tree.nodes, journalnode, age_name) else: + journalnode = self._create_standard_python_file_node(tree, "xJournalBookGUIPopup.py") self._create_moul_nodes(bo, tree.nodes, journalnode, age_name) def _create_pots_nodes(self, clickable_object, nodes, journalnode, age_name): @@ -324,43 +297,6 @@ class PlasmaJournalBookModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz return self.journal_translations -linking_pfms = { - pvPots : { - # Supplied by the OfflineKI script: - # https://gitlab.com/diafero/offline-ki/blob/master/offlineki/xSimpleLinkingBook.py - "filename": "xSimpleLinkingBook.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", "name": "bookClickable" }, - { 'id': 2, 'type': "ptAttribString", "name": "destinationAge" }, - { 'id': 3, 'type': "ptAttribString", "name": "spawnPoint" }, - { 'id': 4, 'type': "ptAttribString", "name": "linkPanel" }, - { 'id': 5, 'type': "ptAttribString", "name": "bookCover" }, - { 'id': 6, 'type': "ptAttribString", "name": "stampTexture" }, - { 'id': 7, 'type': "ptAttribFloat", "name": "stampX" }, - { 'id': 8, 'type': "ptAttribFloat", "name": "stampY" }, - { 'id': 9, 'type': "ptAttribFloat", "name": "bookWidth" }, - { 'id': 10, 'type': "ptAttribFloat", "name": "BookHeight" }, - { 'id': 11, 'type': "ptAttribBehavior", "name": "msbSeekBeforeUI" }, - { 'id': 12, 'type': "ptAttribResponder", "name": "respOneShot" }, - ) - }, - pvMoul : { - "filename": "xLinkingBookGUIPopup.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", 'name': "actClickableBook" }, - { 'id': 2, 'type': "ptAttribBehavior", 'name': "SeekBehavior" }, - { 'id': 3, 'type': "ptAttribResponder", 'name': "respLinkResponder" }, - { 'id': 4, 'type': "ptAttribString", 'name': "TargetAge" }, - { 'id': 5, 'type': "ptAttribActivator", 'name': "actBookshelf" }, - { 'id': 6, 'type': "ptAttribActivator", 'name': "shareRegion" }, - { 'id': 7, 'type': "ptAttribBehavior", 'name': "shareBookSeek" }, - { 'id': 10, 'type': "ptAttribBoolean", 'name': "IsDRCStamped" }, - { 'id': 11, 'type': "ptAttribBoolean", 'name': "ForceThirdPerson" }, - ) - }, -} - - class PlasmaLinkingBookModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz): pl_id = "linkingbookmod" @@ -495,12 +431,11 @@ class PlasmaLinkingBookModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz yield self.seek_point.name def logicwiz(self, bo, tree, age_name, version): - # Assign linking book script based on target version - linking_pfm = linking_pfms[version] - linkingnode = self._create_python_file_node(tree, linking_pfm["filename"], linking_pfm["attribs"]) if version <= pvPots: + linkingnode = self._create_standard_python_file_node(tree, "xSimpleLinkingBook.py") self._create_pots_nodes(bo, tree.nodes, linkingnode, age_name) else: + linkingnode = self._create_standard_python_file_node(tree, "xLinkingBookGUIPopup.py") self._create_moul_nodes(bo, tree.nodes, linkingnode, age_name) def _create_pots_nodes(self, clickable_object, nodes, linkingnode, age_name): @@ -667,14 +602,6 @@ class PlasmaLinkingBookModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz raise ExportError("{}: Linking Book modifier requires a seek point!", self.id_data.name) -dialog_toggle = { - "filename": "xDialogToggle.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", 'name': "Activate" }, - { 'id': 4, 'type': "ptAttribString", 'name': "Vignette" }, - ) -} - class PlasmaNotePopupModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz): pl_id = "note_popup" @@ -755,11 +682,7 @@ class PlasmaNotePopupModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz): nodes = tree.nodes # xDialogToggle.py PythonFile Node - dialog_node = self._create_python_file_node( - tree, - dialog_toggle["filename"], - dialog_toggle["attribs"] - ) + dialog_node = self._create_standard_python_file_node(tree, "xDialogToggle.py") self._create_python_attribute(dialog_node, "Vignette", value=self.gui_page) # Clickable diff --git a/korman/properties/modifiers/logic.py b/korman/properties/modifiers/logic.py index 4cb4fd9..80a266b 100644 --- a/korman/properties/modifiers/logic.py +++ b/korman/properties/modifiers/logic.py @@ -34,15 +34,6 @@ from ...exporter import ExportError, utils from ... import idprops from .physics import bounds_type_index, bounds_type_str, bounds_types -entry_cam_pfm = { - "filename": "xEntryCam.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", 'name': "actRegionSensor" }, - { 'id': 2, 'type': "ptAttribSceneobject", 'name': "camera" }, - { 'id': 3, 'type': "ptAttribBoolean", 'name': "undoFirstPerson" }, - ) -} - class PlasmaVersionedNodeTree(idprops.IDPropMixin, bpy.types.PropertyGroup): version = EnumProperty(name="Version", description="Plasma versions this node tree exports under", @@ -148,11 +139,7 @@ class PlasmaSpawnPoint(PlasmaModifierProperties, PlasmaModifierLogicWiz): yield self.convert_logic(bo) def logicwiz(self, bo, tree): - pfm_node = self._create_python_file_node( - tree, - entry_cam_pfm["filename"], - entry_cam_pfm["attribs"] - ) + pfm_node = self._create_standard_python_file_node(tree, "xEntryCam.py") volume_sensor: PlasmaVolumeSensorNode = tree.nodes.new("PlasmaVolumeSensorNode") volume_sensor.find_input_socket("enter").allow = True @@ -204,17 +191,6 @@ class PlasmaMaintainersMarker(PlasmaModifierProperties): return True -telescope_pfm = { - "filename": "xTelescope.py", - "attribs": ( - { 'id': 1, 'type': "ptAttribActivator", 'name': "Activate" }, - { 'id': 2, 'type': "ptAttribSceneobject", 'name': "Camera" }, - { 'id': 3, 'type': "ptAttribBehavior", 'name': "Behavior" }, - { 'id': 4, 'type': "ptAttribString", 'name': "Vignette" }, - ) -} - - class PlasmaTelescope(PlasmaModifierProperties, PlasmaModifierLogicWiz): pl_id="telescope" @@ -255,7 +231,7 @@ class PlasmaTelescope(PlasmaModifierProperties, PlasmaModifierLogicWiz): nodes = tree.nodes # Create Python Node - telescopepynode = self._create_python_file_node(tree, telescope_pfm["filename"], telescope_pfm["attribs"]) + telescopepynode = self._create_standard_python_file_node(tree, "xTelescope.py") # Clickable telescopeclick = nodes.new("PlasmaClickableNode") diff --git a/korman/properties/modifiers/render.py b/korman/properties/modifiers/render.py index ec0645e..3488bfa 100644 --- a/korman/properties/modifiers/render.py +++ b/korman/properties/modifiers/render.py @@ -624,30 +624,6 @@ class PlasmaLightingMod(PlasmaModifierProperties): return False -_LOCALIZED_TEXT_PFM = ( - { 'id': 1, 'type': "ptAttribDynamicMap", 'name': "dynTextMap", }, - { 'id': 2, 'type': "ptAttribString", 'name': "locPath" }, - { 'id': 3, 'type': "ptAttribString", 'name': "fontFace" }, - { 'id': 4, 'type': "ptAttribInt", 'name': "fontSize" }, - { 'id': 5, 'type': "ptAttribFloat", 'name': "fontColorR" }, - { 'id': 6, 'type': "ptAttribFloat", 'name': "fontColorG" }, - { 'id': 7, 'type': "ptAttribFloat", 'name': "fontColorB" }, - { 'id': 8, 'type': "ptAttribFloat", 'name': "fontColorA" }, - { 'id': 9, 'type': "ptAttribInt", 'name': "marginTop" }, - { 'id': 10, 'type': "ptAttribInt", 'name': "marginLeft" }, - { 'id': 11, 'type': "ptAttribInt", 'name': "marginBottom" }, - { 'id': 12, 'type': "ptAttribInt", 'name': "marginRight" }, - { 'id': 13, 'type': "ptAttribInt", 'name': "lineSpacing" }, - # Yes, it's really a ptAttribDropDownList, but those are only for use in - # artist generated node trees. - { 'id': 14, 'type': "ptAttribString", 'name': "justify" }, - { 'id': 15, 'type': "ptAttribFloat", 'name': "clearColorR" }, - { 'id': 16, 'type': "ptAttribFloat", 'name': "clearColorG" }, - { 'id': 17, 'type': "ptAttribFloat", 'name': "clearColorB" }, - { 'id': 18, 'type': "ptAttribFloat", 'name': "clearColorA" }, - { 'id': 19, 'type': "ptAttribBoolean", 'name': "blockRGB" }, -) - class PlasmaLocalizedTextModifier(PlasmaModifierProperties, PlasmaModifierLogicWiz, TranslationMixin): pl_id = "dynatext" pl_page_types = {"gui", "room"} @@ -738,7 +714,7 @@ class PlasmaLocalizedTextModifier(PlasmaModifierProperties, PlasmaModifierLogicW self._create_nodes(bo, tree, age_name=age_name, version=version) def _create_nodes(self, bo, tree, *, age_name, version, material=None, clear_color=None): - pfm_node = self._create_python_file_node(tree, "xDynTextLoc.py", _LOCALIZED_TEXT_PFM) + pfm_node = self._create_standard_python_file_node(tree, "xDynTextLoc.py") loc_path = self.key_name if version <= pvPots else "{}.{}.{}".format(age_name, self.localization_set, self.key_name) self._create_python_attribute(pfm_node, "dynTextMap", "ptAttribDynamicMap",