Skip to content

Commit 0f0d6e1

Browse files
committed
Add the SDL Show/Hide Modifier.
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.
1 parent 1cf33ba commit 0f0d6e1

File tree

5 files changed

+148
-3
lines changed

5 files changed

+148
-3
lines changed

korman/exporter/convert.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,10 @@ def age_name(self):
598598
else:
599599
return bpy.context.scene.world.plasma_age.age_name
600600

601+
@property
602+
def age_sdl(self) -> bool:
603+
return bpy.context.scene.world.plasma_age.age_sdl
604+
601605
@property
602606
def dat_only(self):
603607
return self._op.dat_only

korman/operators/op_ui.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,17 @@ class CollectionRemoveOperator(UIOperator, bpy.types.Operator):
7777
index_prop = StringProperty(name="Index Property",
7878
description="Name of the active element index property",
7979
options=set())
80+
manual_index = IntProperty(name="Manual Index",
81+
description="Manual integer index to remove",
82+
options=set())
8083

8184
def execute(self, context):
8285
props = getattr(context, self.context).path_resolve(self.group_path)
8386
collection = getattr(props, self.collection_prop)
84-
index = getattr(props, self.index_prop)
87+
if self.index_prop:
88+
index = getattr(props, self.index_prop)
89+
else:
90+
index = self.manual_index
8591
if len(collection) > index:
8692
collection.remove(index)
8793
setattr(props, self.index_prop, index - 1)

korman/plasma_api.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@
1414
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
1515

1616
python_files = {
17+
"xAgeSDLBoolShowHide.py": (
18+
{ "id": 1, "type": "ptAttribString", "name": "sdlName" },
19+
{ "id": 2, "type": "ptAttribBoolean", "name": "showOnTrue" },
20+
# --- CWE Only Below ---
21+
{ "id": 3, "type": "ptAttribBoolean", "name": "defaultValue" },
22+
{ "id": 4, "type": "ptAttribBoolean", "name": "evalOnFirstUpdate "},
23+
),
24+
25+
"xAgeSDLIntShowHide.py": (
26+
{ "id": 1, "type": "ptAttribString", "name": "stringVarName" },
27+
{ "id": 2, "type": "ptAttribString", "name": "stringShowStates" },
28+
# --- CWE Only Below ---
29+
{ "id": 3, "type": "ptAttribInt", "name": "intDefault" },
30+
{ "id": 4, "type": "ptAttribBoolean", "name": "boolFirstUpdate "},
31+
),
32+
1733
# Provided by all variants of Uru and Myst V
1834
"xDialogToggle.py": (
1935
{ "id": 1, "type": "ptAttribActivator", "name": "Activate" },

korman/properties/modifiers/logic.py

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@
1515

1616
from __future__ import annotations
1717

18-
import bmesh
1918
import bpy
2019
from bpy.props import *
21-
import mathutils
2220
from PyHSPlasma import *
2321
from typing import *
2422

@@ -28,6 +26,11 @@
2826
from ...nodes.node_messages import *
2927
from ...nodes.node_responder import *
3028

29+
from typing import *
30+
31+
if TYPE_CHECKING:
32+
from ...exporter import Exporter
33+
3134
from ...addon_prefs import game_versions
3235
from .base import PlasmaModifierProperties, PlasmaModifierLogicWiz
3336
from ...exporter import ExportError, utils
@@ -191,6 +194,85 @@ def requires_actor(self):
191194
return True
192195

193196

197+
class PlasmaSDLIntState(bpy.types.PropertyGroup):
198+
value: int = IntProperty(
199+
name="State Value",
200+
description="The object is shown when the SDL variable is set to this value",
201+
min=0,
202+
soft_max=255,
203+
options=set()
204+
)
205+
206+
207+
class PlasmaSDLShowHide(PlasmaModifierProperties, PlasmaModifierLogicWiz):
208+
pl_id = "sdl_showhide"
209+
210+
bl_category = "Logic"
211+
bl_label = "SDL Show/Hide"
212+
bl_description = "Show/Hide an object based on an SDL Variable"
213+
bl_object_types = {"MESH", "FONT"}
214+
bl_icon = "VISIBLE_IPO_OFF"
215+
216+
sdl_variable: str = StringProperty(
217+
name="SDL Variable",
218+
description="Name of the SDL variable that controls visibility",
219+
options=set()
220+
)
221+
variable_type: str = EnumProperty(
222+
name="Type",
223+
description="Data type of the SDL variable",
224+
items=[
225+
("bool", "Boolean", "A boolean, used to represent simple on/off for a single state"),
226+
("int", "Integer", "An integer, used to represent multiple state combinations"),
227+
],
228+
options=set()
229+
)
230+
231+
int_states = CollectionProperty(type=PlasmaSDLIntState)
232+
bool_state: bool = BoolProperty(
233+
name="Show When True",
234+
description="If checked, show this object when the SDL Variable is TRUE. If not, hide it when TRUE.",
235+
default=True,
236+
options=set()
237+
)
238+
239+
def created(self):
240+
# Ensure at least one SDL int state is precreated for ease of use.
241+
# REMEMBER: Blender's "sequences" don't do truthiness correctly...
242+
if len(self.int_states) == 0:
243+
self.int_states.add()
244+
245+
def sanity_check(self, exporter: Exporter):
246+
if not exporter.age_sdl:
247+
raise ExportError(f"'{self.id_data.name}': Age Global SDL is required for the SDL Show/Hide modifier!")
248+
if not self.sdl_variable.strip():
249+
raise ExportError(f"'{self.id_data.name}': A valid SDL variable is required for the SDL Show/Hide modifier!")
250+
251+
def logicwiz(self, bo, tree):
252+
if self.variable_type == "bool":
253+
pfm_node = self._create_standard_python_file_node(tree, "xAgeSDLBoolShowHide.py")
254+
self._create_python_attribute(pfm_node, "sdlName", value=self.sdl_variable)
255+
self._create_python_attribute(pfm_node, "showOnTrue", value=self.bool_state)
256+
elif self.variable_type == "int":
257+
pfm_node = self._create_standard_python_file_node(tree, "xAgeSDLIntShowHide.py")
258+
self._create_python_attribute(pfm_node, "stringVarName", value=self.sdl_variable)
259+
self._create_python_attribute(pfm_node, "stringShowStates", value=",".join(self._states))
260+
else:
261+
raise RuntimeError()
262+
263+
@property
264+
def key_name(self):
265+
if self.variable_type == "bool":
266+
return f"cPythBoolShowHide_{self.sdl_variable}_{self.bool_state:d}"
267+
elif self.variable_type == "int":
268+
return f"cPythIntShowHide_{self.sdl_variable}_{'-'.join(self._states)}"
269+
270+
@property
271+
def _states(self) -> Iterable[str]:
272+
"""Returns a sorted, deduplicated iterable of the integer (converted to strings) states we should be visible in."""
273+
return (str(i) for i in sorted(frozenset((i.value for i in self.int_states))))
274+
275+
194276
class PlasmaTelescope(PlasmaModifierProperties, PlasmaModifierLogicWiz):
195277
pl_id="telescope"
196278

korman/ui/modifiers/logic.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,43 @@ def maintainersmarker(modifier, layout, context):
6060
layout.label(text="Positive Y is North, positive Z is up.")
6161
layout.prop(modifier, "calibration")
6262

63+
def sdl_showhide(modifier: PlasmaSDLShowHide, layout, context):
64+
if not context.scene.world.plasma_age.age_sdl:
65+
layout.label("This modifier requires Age Global SDL!", icon="ERROR")
66+
return
67+
68+
valid_variable = modifier.sdl_variable.strip()
69+
layout.alert = not valid_variable
70+
layout.prop(modifier, "sdl_variable")
71+
if not valid_variable:
72+
layout.label("A valid SDL variable is required!", icon="ERROR")
73+
layout.alert = False
74+
layout.prop(modifier, "variable_type")
75+
layout.separator()
76+
77+
def setup_collection_operator(op):
78+
op.context = "object"
79+
op.group_path = modifier.path_from_id()
80+
op.collection_prop = "int_states"
81+
op.index_prop = ""
82+
83+
if modifier.variable_type == "bool":
84+
layout.prop(modifier, "bool_state")
85+
elif modifier.variable_type == "int":
86+
layout.label("Show when SDL variable is:")
87+
sub = layout.column_flow()
88+
for i, state in enumerate(modifier.int_states):
89+
row = sub.row(align=True)
90+
row.prop(state, "value", text="Value")
91+
op = row.operator("ui.plasma_collection_remove", icon="ZOOMOUT", text="")
92+
setup_collection_operator(op)
93+
op.manual_index = i
94+
95+
op = layout.operator("ui.plasma_collection_add", icon="ZOOMIN", text="Add State Value")
96+
setup_collection_operator(op)
97+
else:
98+
raise RuntimeError()
99+
63100
def telescope(modifier, layout, context):
64101
layout.prop(modifier, "clickable_region")
65102
layout.prop(modifier, "seek_target_object", icon="EMPTY_DATA")

0 commit comments

Comments
 (0)