Skip to content

Commit

Permalink
Add the SDL Show/Hide Modifier.
Browse files Browse the repository at this point in the history
This adds a modifier for the very common PythonFileMods
xAgeSDLBoolShowHude and xAgeSDLIntShowHide. Right now, Korman doesn't
try to parse SDL files, so the variable name and type have to be
specified manually. The benefit to this, however, is the ability to
easily wire up global SDL visibility type features.
  • Loading branch information
Hoikas committed Jun 30, 2024
1 parent 1cf33ba commit 0f0d6e1
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 3 deletions.
4 changes: 4 additions & 0 deletions korman/exporter/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,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
16 changes: 16 additions & 0 deletions korman/plasma_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@
# 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" },
Expand Down
86 changes: 84 additions & 2 deletions korman/properties/modifiers/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@

from __future__ import annotations

import bmesh
import bpy
from bpy.props import *
import mathutils
from PyHSPlasma import *
from typing import *

Expand All @@ -28,6 +26,11 @@
from ...nodes.node_messages import *
from ...nodes.node_responder import *

from typing import *

if TYPE_CHECKING:
from ...exporter import Exporter

from ...addon_prefs import game_versions
from .base import PlasmaModifierProperties, PlasmaModifierLogicWiz
from ...exporter import ExportError, utils
Expand Down Expand Up @@ -191,6 +194,85 @@ def requires_actor(self):
return True


class PlasmaSDLIntState(bpy.types.PropertyGroup):
value: int = IntProperty(
name="State Value",
description="The object is shown when the SDL variable is set to this value",
min=0,
soft_max=255,
options=set()
)


class PlasmaSDLShowHide(PlasmaModifierProperties, PlasmaModifierLogicWiz):
pl_id = "sdl_showhide"

bl_category = "Logic"
bl_label = "SDL Show/Hide"
bl_description = "Show/Hide an object based on an SDL Variable"
bl_object_types = {"MESH", "FONT"}
bl_icon = "VISIBLE_IPO_OFF"

sdl_variable: str = StringProperty(
name="SDL Variable",
description="Name of the SDL variable that controls visibility",
options=set()
)
variable_type: str = EnumProperty(
name="Type",
description="Data type of the SDL variable",
items=[
("bool", "Boolean", "A boolean, used to represent simple on/off for a single state"),
("int", "Integer", "An integer, used to represent multiple state combinations"),
],
options=set()
)

int_states = CollectionProperty(type=PlasmaSDLIntState)
bool_state: bool = BoolProperty(
name="Show When True",
description="If checked, show this object when the SDL Variable is TRUE. If not, hide it when TRUE.",
default=True,
options=set()
)

def created(self):
# Ensure at least one SDL int state is precreated for ease of use.
# REMEMBER: Blender's "sequences" don't do truthiness correctly...
if len(self.int_states) == 0:
self.int_states.add()

def sanity_check(self, exporter: Exporter):
if not exporter.age_sdl:
raise ExportError(f"'{self.id_data.name}': Age Global SDL is required for the SDL Show/Hide modifier!")
if not self.sdl_variable.strip():
raise ExportError(f"'{self.id_data.name}': A valid SDL variable is required for the SDL Show/Hide modifier!")

def logicwiz(self, bo, tree):
if self.variable_type == "bool":
pfm_node = self._create_standard_python_file_node(tree, "xAgeSDLBoolShowHide.py")
self._create_python_attribute(pfm_node, "sdlName", value=self.sdl_variable)
self._create_python_attribute(pfm_node, "showOnTrue", value=self.bool_state)
elif self.variable_type == "int":
pfm_node = self._create_standard_python_file_node(tree, "xAgeSDLIntShowHide.py")
self._create_python_attribute(pfm_node, "stringVarName", value=self.sdl_variable)
self._create_python_attribute(pfm_node, "stringShowStates", value=",".join(self._states))
else:
raise RuntimeError()

@property
def key_name(self):
if self.variable_type == "bool":
return f"cPythBoolShowHide_{self.sdl_variable}_{self.bool_state:d}"
elif self.variable_type == "int":
return f"cPythIntShowHide_{self.sdl_variable}_{'-'.join(self._states)}"

@property
def _states(self) -> Iterable[str]:
"""Returns a sorted, deduplicated iterable of the integer (converted to strings) states we should be visible in."""
return (str(i) for i in sorted(frozenset((i.value for i in self.int_states))))


class PlasmaTelescope(PlasmaModifierProperties, PlasmaModifierLogicWiz):
pl_id="telescope"

Expand Down
37 changes: 37 additions & 0 deletions korman/ui/modifiers/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,43 @@ def maintainersmarker(modifier, layout, context):
layout.label(text="Positive Y is North, positive Z is up.")
layout.prop(modifier, "calibration")

def sdl_showhide(modifier: PlasmaSDLShowHide, layout, context):
if not context.scene.world.plasma_age.age_sdl:
layout.label("This modifier requires Age Global SDL!", icon="ERROR")
return

valid_variable = modifier.sdl_variable.strip()
layout.alert = not valid_variable
layout.prop(modifier, "sdl_variable")
if not valid_variable:
layout.label("A valid SDL variable is required!", icon="ERROR")
layout.alert = False
layout.prop(modifier, "variable_type")
layout.separator()

def setup_collection_operator(op):
op.context = "object"
op.group_path = modifier.path_from_id()
op.collection_prop = "int_states"
op.index_prop = ""

if modifier.variable_type == "bool":
layout.prop(modifier, "bool_state")
elif modifier.variable_type == "int":
layout.label("Show when SDL variable is:")
sub = layout.column_flow()
for i, state in enumerate(modifier.int_states):
row = sub.row(align=True)
row.prop(state, "value", text="Value")
op = row.operator("ui.plasma_collection_remove", icon="ZOOMOUT", text="")
setup_collection_operator(op)
op.manual_index = i

op = layout.operator("ui.plasma_collection_add", icon="ZOOMIN", text="Add State Value")
setup_collection_operator(op)
else:
raise RuntimeError()

def telescope(modifier, layout, context):
layout.prop(modifier, "clickable_region")
layout.prop(modifier, "seek_target_object", icon="EMPTY_DATA")
Expand Down

0 comments on commit 0f0d6e1

Please sign in to comment.