Skip to content

Commit

Permalink
Merge pull request #414 from Hoikas/phony_pfm_reorg
Browse files Browse the repository at this point in the history
Reorganize PFM Stub Storage and Add the SDL Show/Hide Modifier.
  • Loading branch information
Hoikas authored Jul 6, 2024
2 parents 9dc7f68 + 0f0d6e1 commit 7363930
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 158 deletions.
12 changes: 10 additions & 2 deletions korman/exporter/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,12 @@ def _(temporary, parent):

@handle_temporary.register(bpy.types.NodeTree)
def _(temporary, parent):
self.exit_stack.enter_context(TemporaryObject(temporary, bpy.data.node_groups.remove))
log_msg(f"'{parent.name}' generated NodeTree '{temporary.name}'")
# NodeTrees are reuseable, so make sure we haven't already encountered it.
if not temporary.name in self.want_node_trees:
self.exit_stack.enter_context(TemporaryObject(temporary, bpy.data.node_groups.remove))
log_msg(f"'{parent.name}' generated NodeTree '{temporary.name}'")
else:
log_msg(f"'{parent.name}' reused NodeTree '{temporary.name}'")
if temporary.bl_idname == "PlasmaNodeTree":
parent_so = self.mgr.find_create_object(plSceneObject, bl=parent)
self.want_node_trees[temporary.name].add((parent, parent_so))
Expand Down Expand Up @@ -594,6 +598,10 @@ def age_name(self):
else:
return bpy.context.scene.world.plasma_age.age_name

@property
def age_sdl(self) -> bool:
return bpy.context.scene.world.plasma_age.age_sdl

@property
def dat_only(self):
return self._op.dat_only
Expand Down
8 changes: 7 additions & 1 deletion korman/operators/op_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,17 @@ class CollectionRemoveOperator(UIOperator, bpy.types.Operator):
index_prop = StringProperty(name="Index Property",
description="Name of the active element index property",
options=set())
manual_index = IntProperty(name="Manual Index",
description="Manual integer index to remove",
options=set())

def execute(self, context):
props = getattr(context, self.context).path_resolve(self.group_path)
collection = getattr(props, self.collection_prop)
index = getattr(props, self.index_prop)
if self.index_prop:
index = getattr(props, self.index_prop)
else:
index = self.manual_index
if len(collection) > index:
collection.remove(index)
setattr(props, self.index_prop, index - 1)
Expand Down
134 changes: 134 additions & 0 deletions korman/plasma_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# 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 <http://www.gnu.org/licenses/>.

python_files = {
"xAgeSDLBoolShowHide.py": (
{ "id": 1, "type": "ptAttribString", "name": "sdlName" },
{ "id": 2, "type": "ptAttribBoolean", "name": "showOnTrue" },
# --- CWE Only Below ---
{ "id": 3, "type": "ptAttribBoolean", "name": "defaultValue" },
{ "id": 4, "type": "ptAttribBoolean", "name": "evalOnFirstUpdate "},
),

"xAgeSDLIntShowHide.py": (
{ "id": 1, "type": "ptAttribString", "name": "stringVarName" },
{ "id": 2, "type": "ptAttribString", "name": "stringShowStates" },
# --- CWE Only Below ---
{ "id": 3, "type": "ptAttribInt", "name": "intDefault" },
{ "id": 4, "type": "ptAttribBoolean", "name": "boolFirstUpdate "},
),

# 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" },
)
}
12 changes: 1 addition & 11 deletions korman/properties/modifiers/avatar.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,6 @@ def requires_actor(self):
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"),
Expand Down Expand Up @@ -140,7 +130,7 @@ def logicwiz(self, bo, tree):
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
Expand Down
33 changes: 21 additions & 12 deletions korman/properties/modifiers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from ...nodes.node_python import *

from ... import helpers
from ... import plasma_api

class PlasmaModifierProperties(bpy.types.PropertyGroup):
@property
Expand Down Expand Up @@ -180,20 +181,24 @@ def requires_actor(self):

class PlasmaModifierLogicWiz:
def convert_logic(self, bo, **kwargs):
"""Creates, converts, and returns an unmanaged NodeTree for this logic wizard. If the wizard
fails during conversion, the temporary tree is deleted for you. However, on success, you
are responsible for removing the tree from Blender, if applicable."""
"""Attempts to look up an already existing logic tree matching the name provided and returns
it, if found. If not, creates, converts, and returns an unmanaged NodeTree for this wizard.
If the wizard fails during conversion, the temporary tree is deleted for you. However, on
success, you are responsible for removing the tree from Blender, if applicable."""
name = kwargs.pop("name", self.key_name)
assert not "tree" in kwargs
tree = bpy.data.node_groups.new(name, "PlasmaNodeTree")
kwargs["tree"] = tree
try:
self.logicwiz(bo, **kwargs)
except:
bpy.data.node_groups.remove(tree)
raise
else:
return tree

node_groups = bpy.data.node_groups
tree = node_groups.get(name)
if tree is None:
tree = node_groups.new(name, "PlasmaNodeTree")
kwargs["tree"] = tree
try:
self.logicwiz(bo, **kwargs)
except:
bpy.data.node_groups.remove(tree)
raise
return tree

def _create_python_file_node(self, tree, filename: str, attributes: Dict[str, Any]) -> bpy.types.Node:
pfm_node = tree.nodes.new("PlasmaPythonFileNode")
Expand All @@ -207,6 +212,10 @@ def _create_python_file_node(self, tree, filename: str, attributes: Dict[str, An
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
Expand Down
87 changes: 5 additions & 82 deletions korman/properties/modifiers/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,33 +35,6 @@
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),
Expand Down Expand Up @@ -246,11 +219,11 @@ def pre_export(self, exporter, bo):

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):
Expand Down Expand Up @@ -324,43 +297,6 @@ def translations(self):
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"

Expand Down Expand Up @@ -495,12 +431,11 @@ def harvest_actors(self):
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):
Expand Down Expand Up @@ -667,14 +602,6 @@ def sanity_check(self, exporter):
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"

Expand Down Expand Up @@ -755,11 +682,7 @@ def logicwiz(self, bo, tree):
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
Expand Down
Loading

0 comments on commit 7363930

Please sign in to comment.