Skip to content

Commit

Permalink
standardize flag eval
Browse files Browse the repository at this point in the history
  • Loading branch information
Lilaa3 committed Sep 22, 2024
1 parent 8d6d4bc commit 7c96981
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 30 deletions.
24 changes: 21 additions & 3 deletions fast64_internal/sm64/animation/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

from bpy.types import Action

from ...utility import PluginError, encodeSegmentedAddr, intToHex
from ...f3d.f3d_parser import math_eval

from ...utility import PluginError, cast_integer, encodeSegmentedAddr, intToHex
from ..sm64_constants import MAX_U16, SegmentData
from ..sm64_classes import RomReader, DMATable, DMATableElement, IntArray

Expand Down Expand Up @@ -194,6 +196,22 @@ def names(self) -> list[str]:
names.append("unknown bits")
return names

@classmethod
def evaluate(cls, value: str | int):
if isinstance(value, cls):
return value
elif isinstance(value, str):
try:
value = cls(math_eval(value, cls))
except Exception as exc:
print(f"Failed to evaluate flags {value}: {exc}")
if isinstance(value, int): # the value was fully evaluated
if isinstance(value, SM64_AnimFlags):
value = value.value
return SM64_AnimFlags(cast_integer(value, 16, signed=False)) # cast to u16 for simplicity
else:
return value


@dataclasses.dataclass
class SM64_AnimHeader:
Expand Down Expand Up @@ -322,7 +340,7 @@ def read_binary(
read_headers[str(reader.start_address)] = header
header.reference = reader.start_address

header.flags = SM64_AnimFlags(reader.read_int(2, True)) # /*0x00*/ s16 flags;
header.flags = SM64_AnimFlags.evaluate(reader.read_int(2, True)) # /*0x00*/ s16 flags;
header.trans_divisor = reader.read_int(2, True) # /*0x02*/ s16 animYTransDivisor;
header.start_frame = reader.read_int(2, True) # /*0x04*/ s16 startFrame;
header.loop_start = reader.read_int(2, True) # /*0x06*/ s16 loopStart;
Expand Down Expand Up @@ -412,7 +430,7 @@ def read_c(
designated[var_defs[i]] = value

# Read from the dict
header.flags = designated["flags"]
header.flags = SM64_AnimFlags.evaluate(designated["flags"])
header.trans_divisor = int(designated["animYTransDivisor"], 0)
header.start_frame = int(designated["startFrame"], 0)
header.loop_start = int(designated["loopStart"], 0)
Expand Down
39 changes: 12 additions & 27 deletions fast64_internal/sm64/animation/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def draw_list_ops(layout: UILayout, op_cls: type, index: int, **op_args):
draw_list_op(layout, op_cls, op_name, index, **op_args)


def set_if_different(owner, prop: str, value: str):
def set_if_different(owner, prop: str, value):
if getattr(owner, prop) != value:
setattr(owner, prop, value)

Expand Down Expand Up @@ -184,20 +184,12 @@ class SM64_AnimHeaderProperties(PropertyGroup):
# Binary
table_index: IntProperty(name="Table Index", min=0)

def get_flags(self, allow_str: bool):
def get_flags(self, allow_str: bool) -> SM64_AnimFlags | str:
if self.use_custom_flags:
try:
try:
result = math_eval(self.custom_flags, SM64_AnimFlags)
except Exception as exc:
raise ValueError(f"Failed to evaluate custom flags {exc}") from exc
if isinstance(result, str):
raise ValueError("Failed to evaluate custom flags")
return SM64_AnimFlags(cast_integer(result, 16, signed=False))
except Exception as exc:
if allow_str:
return self.custom_flags
raise exc
result = SM64_AnimFlags.evaluate(self.custom_flags)
if not allow_str and isinstance(result, str):
raise ValueError("Failed to evaluate custom flags")
return result
value = SM64_AnimFlags(0)
for prop, flag in SM64_AnimFlags.props_to_flags().items():
if getattr(self, prop, False):
Expand All @@ -208,27 +200,20 @@ def get_flags(self, allow_str: bool):
def int_flags(self):
return self.get_flags(allow_str=False)

def set_flags(self, value: int | str, set_custom=True):
try:
value = math_eval(value, SM64_AnimFlags) # try to evaluate in case of string
except Exception as exc:
print(f"Failed to evaluate flags {value}: {exc}")
if isinstance(value, SM64_AnimFlags): # get int value from enum
value = value.value
if isinstance(value, int): # the value was fully evaluated
value = cast_integer(value, 16, signed=False) # cast to u16 for simplicity and readability
def set_flags(self, value: SM64_AnimFlags | str, set_custom=True):
if isinstance(value, SM64_AnimFlags): # the value was fully evaluated
for prop, flag in SM64_AnimFlags.props_to_flags().items(): # set prop flags
set_if_different(self, prop, bool(value & flag.value))
set_if_different(self, prop, flag in value)
if set_custom:
if value & ~SM64_AnimFlags.all_flags_with_prop(): # if a flag does not have a prop
if value not in SM64_AnimFlags.all_flags_with_prop(): # if a flag does not have a prop
set_if_different(self, "use_custom_flags", True)
set_if_different(self, "custom_flags", intToHex(value, 2))
elif isinstance(value, str):
if set_custom:
set_if_different(self, "custom_flags", value)
set_if_different(self, "use_custom_flags", True)
else: # invalid
raise ValueError(f"Invalid value: {value}")
raise ValueError(f"Invalid type: {value}")

@property
def manual_loop_range(self) -> tuple[int, int, int]:
Expand Down Expand Up @@ -912,7 +897,7 @@ def upgrade_old_props(self, scene: Scene):
action_props: SM64_ActionAnimProperty = get_action_props(action)
action_props.header: SM64_AnimHeaderProperties
if loop is not None:
action_props.header.set_flags(0x00 if loop else 0x01)
action_props.header.set_flags(SM64_AnimFlags(0) if loop else SM64_AnimFlags.ANIM_FLAG_NOLOOP)
if start_address is not None:
action_props.start_address = intToHex(int(start_address, 16))
if end_address is not None:
Expand Down

0 comments on commit 7c96981

Please sign in to comment.