Skip to content
This repository was archived by the owner on Jan 1, 2025. It is now read-only.

Commit f8bc5f7

Browse files
authored
Minor Options Revamp (#86)
* change the way options are displayed * make Options.Field abstract, make relevant options generics * add option reprs
1 parent 2c3cd47 commit f8bc5f7

File tree

2 files changed

+94
-40
lines changed

2 files changed

+94
-40
lines changed

Mods/ModMenu/OptionManager.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@
1414
_MOD_OPTIONS_EVENT_ID: int = 1417
1515
_MOD_OPTIONS_MENU_NAME: str = "MODS"
1616

17+
_INDENT: int = 2
18+
19+
20+
class _ModHeader(Options.Field):
21+
def __init__(self, Caption: str) -> None:
22+
self.Caption = Caption
23+
self.Description = ""
24+
self.IsHidden = False
25+
1726

1827
def _create_data_provider(name: str) -> unrealsdk.UObject:
1928
"""
@@ -149,15 +158,18 @@ def _DataProviderOptionsBasePopulate(caller: unrealsdk.UObject, function: unreal
149158
continue
150159
if not one_shown:
151160
one_shown = True
152-
all_options.append(Options.Field(mod.Name))
161+
all_options.append(_ModHeader(mod.Name))
153162
all_options.append(option)
154163

155164
_nested_options_stack.append(Options.Nested(_MOD_OPTIONS_MENU_NAME, "", all_options))
156165

166+
first_level = len(_nested_options_stack) == 1
157167
for idx, option in enumerate(_nested_options_stack[-1].Children):
158168
if option.IsHidden:
159169
continue
160170

171+
indent = " " * _INDENT if first_level and not isinstance(option, _ModHeader) else ""
172+
161173
if isinstance(option, Options.Spinner):
162174
spinner_idx: int
163175
if isinstance(option, Options.Boolean):
@@ -166,12 +178,12 @@ def _DataProviderOptionsBasePopulate(caller: unrealsdk.UObject, function: unreal
166178
spinner_idx = option.Choices.index(option.CurrentValue)
167179

168180
params.TheList.AddSpinnerListItem(
169-
idx, option.Caption, False, spinner_idx, option.Choices
181+
idx, indent + option.Caption, False, spinner_idx, option.Choices
170182
)
171183
elif isinstance(option, Options.Slider):
172184
params.TheList.AddSliderListItem(
173185
idx,
174-
option.Caption,
186+
indent + option.Caption,
175187
False,
176188
option.CurrentValue,
177189
option.MinValue,
@@ -180,11 +192,9 @@ def _DataProviderOptionsBasePopulate(caller: unrealsdk.UObject, function: unreal
180192
)
181193
elif isinstance(option, Options.Field):
182194
disabled = False
183-
new = False
184195
if isinstance(option, Options.Nested):
185196
disabled = not _is_anything_shown(option.Children)
186-
new = True
187-
params.TheList.AddListItem(idx, option.Caption, disabled, new)
197+
params.TheList.AddListItem(idx, indent + option.Caption, disabled, False)
188198

189199
caller.AddDescription(idx, option.Description)
190200

Mods/ModMenu/Options.py

+78-34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from abc import ABC, abstractmethod
2-
from typing import Any, Optional, Sequence, Tuple
2+
from reprlib import recursive_repr
3+
from typing import Any, Generic, Optional, Sequence, Tuple, TypeVar
34

45
from . import DeprecationHelper as dh
56

@@ -14,6 +15,8 @@
1415
"Value",
1516
)
1617

18+
T = TypeVar("T")
19+
1720

1821
class Base(ABC):
1922
"""
@@ -39,7 +42,7 @@ def __init__(
3942
raise NotImplementedError
4043

4144

42-
class Value(Base):
45+
class Value(Base, Generic[T]):
4346
"""
4447
The abstract base class for all options that store a value.
4548
@@ -52,22 +55,22 @@ class Value(Base):
5255
5356
IsHidden: If the option is hidden from the options menu.
5457
"""
55-
CurrentValue: Any
56-
StartingValue: Any
58+
CurrentValue: T
59+
StartingValue: T
5760

5861
@abstractmethod
5962
def __init__(
6063
self,
6164
Caption: str,
6265
Description: str,
63-
StartingValue: Any,
66+
StartingValue: T,
6467
*,
6568
IsHidden: bool = True
6669
) -> None:
6770
raise NotImplementedError
6871

6972

70-
class Hidden(Value):
73+
class Hidden(Value[T]):
7174
"""
7275
A hidden option that never displays in the menu but stores an arbitrary (json serializable)
7376
value to the settings file.
@@ -81,11 +84,12 @@ class Hidden(Value):
8184
StartingValue: The default value of the option.
8285
IsHidden: If the option is hidden from the options menu. This is forced to True.
8386
"""
87+
8488
def __init__(
8589
self,
8690
Caption: str,
8791
Description: str = "",
88-
StartingValue: Any = None,
92+
StartingValue: T = None, # type: ignore
8993
*,
9094
IsHidden: bool = True
9195
) -> None:
@@ -116,8 +120,18 @@ def IsHidden(self) -> bool: # type: ignore
116120
def IsHidden(self, val: bool) -> None:
117121
pass
118122

123+
@recursive_repr()
124+
def __repr__(self) -> str:
125+
return (
126+
f"Hidden("
127+
f"Caption={repr(self.Caption)},"
128+
f"Description={repr(self.Description)},"
129+
f"*,IsHidden={repr(self.IsHidden)}"
130+
f")"
131+
)
119132

120-
class Slider(Value):
133+
134+
class Slider(Value[int]):
121135
"""
122136
An option which allows users to select a value along a slider.
123137
@@ -176,8 +190,23 @@ def __init__(
176190
self.Increment = Increment
177191
self.IsHidden = IsHidden
178192

179-
180-
class Spinner(Value):
193+
@recursive_repr()
194+
def __repr__(self) -> str:
195+
return (
196+
f"Slider("
197+
f"Caption={repr(self.Caption)},"
198+
f"Description={repr(self.Description)},"
199+
f"CurrentValue={repr(self.CurrentValue)},"
200+
f"StartingValue={repr(self.StartingValue)},"
201+
f"MinValue={repr(self.MinValue)},"
202+
f"MaxValue={repr(self.MaxValue)},"
203+
f"Increment={repr(self.Increment)},"
204+
f"*,IsHidden={repr(self.IsHidden)}"
205+
f")"
206+
)
207+
208+
209+
class Spinner(Value[str]):
181210
"""
182211
An option which allows users to select one value from a sequence of strings.
183212
@@ -242,8 +271,21 @@ def __init__(
242271
f"Provided starting value '{self.StartingValue}' is not in the list of choices."
243272
)
244273

245-
246-
class Boolean(Spinner):
274+
@recursive_repr()
275+
def __repr__(self) -> str:
276+
return (
277+
f"Spinner("
278+
f"Caption={repr(self.Caption)},"
279+
f"Description={repr(self.Description)},"
280+
f"CurrentValue={repr(self.CurrentValue)},"
281+
f"StartingValue={repr(self.StartingValue)},"
282+
f"Choices={repr(self.Choices)},"
283+
f"*,IsHidden={repr(self.IsHidden)}"
284+
f")"
285+
)
286+
287+
288+
class Boolean(Spinner, Value[bool]):
247289
"""
248290
A special form of a spinner, with two options representing boolean values.
249291
@@ -309,6 +351,19 @@ def CurrentValue(self, val: Any) -> None:
309351
else:
310352
self._current_value = bool(val)
311353

354+
@recursive_repr()
355+
def __repr__(self) -> str:
356+
return (
357+
f"Boolean("
358+
f"Caption={repr(self.Caption)},"
359+
f"Description={repr(self.Description)},"
360+
f"CurrentValue={repr(self.CurrentValue)},"
361+
f"StartingValue={repr(self.StartingValue)},"
362+
f"Choices={repr(self.Choices)},"
363+
f"*,IsHidden={repr(self.IsHidden)}"
364+
f")"
365+
)
366+
312367

313368
class Field(Base):
314369
"""
@@ -320,33 +375,11 @@ class Field(Base):
320375
IsHidden: If the field is hidden from the options menu.
321376
"""
322377

323-
def __init__(
324-
self,
325-
Caption: str,
326-
Description: str = "",
327-
*,
328-
IsHidden: bool = False
329-
) -> None:
330-
"""
331-
Creates the option.
332-
333-
Args:
334-
Caption: The name of the option.
335-
Description: A short description of the option to show when hovering over it in the menu.
336-
IsHidden (keyword only): If the value is hidden from the options menu.
337-
"""
338-
self.Caption = Caption
339-
self.Description = Description
340-
self.IsHidden = IsHidden
341-
342378

343379
class Nested(Field):
344380
"""
345381
A field which when clicked opens up a nested menu with more options.
346382
347-
These are distinguished from normal fields by having the "new" exclaimation mark to the side of
348-
it, but you should probably still give it a meaningful description.
349-
350383
Note that these fields will be disabled if all child options are either hidden or other disabled
351384
nested fields.
352385
@@ -383,3 +416,14 @@ def __init__(
383416
self.Description = Description
384417
self.Children = Children
385418
self.IsHidden = IsHidden
419+
420+
@recursive_repr()
421+
def __repr__(self) -> str:
422+
return (
423+
f"Nested("
424+
f"Caption={repr(self.Caption)},"
425+
f"Description={repr(self.Description)},"
426+
f"Children={repr(self.Children)},"
427+
f"*,IsHidden={repr(self.IsHidden)}"
428+
f")"
429+
)

0 commit comments

Comments
 (0)