Skip to content

Commit

Permalink
upgrade table importing function
Browse files Browse the repository at this point in the history
  • Loading branch information
Lilaa3 committed Sep 30, 2024
1 parent f05ba21 commit f3570e5
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 66 deletions.
16 changes: 13 additions & 3 deletions fast64_internal/sm64/animation/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

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

from .constants import HEADER_STRUCT, HEADER_SIZE, TABLE_ELEMENT_PATTERN
Expand Down Expand Up @@ -871,12 +872,18 @@ def read_dma_binary(
def read_c(
self,
c_data: str,
start: int,
end: int,
comment_map: list[CommentMatch],
read_headers: dict[str, SM64_AnimHeader],
header_decls: list[CArrayDeclaration],
values_decls: list[CArrayDeclaration],
indices_decls: list[CArrayDeclaration],
):
for i, element_match in enumerate(re.finditer(TABLE_ELEMENT_PATTERN, c_data)):
table_start, table_end = adjust_start_end(start, end, comment_map)
self.start, self.end = table_start, table_end

for i, element_match in enumerate(re.finditer(TABLE_ELEMENT_PATTERN, c_data[start:end])):
enum, element, null = (
element_match.group("enum"),
element_match.group("element"),
Expand All @@ -895,12 +902,15 @@ def read_c(
read_headers,
i,
)
element_start, element_end = adjust_start_end(
table_start + element_match.start(), table_start + element_match.end(), comment_map
)
self.elements.append(
SM64_AnimTableElement(
element,
enum_name=enum,
reference_start=element_match.start(),
reference_end=element_match.end(),
reference_start=element_start - table_start,
reference_end=element_end - table_start,
header=header,
)
)
Expand Down
26 changes: 7 additions & 19 deletions fast64_internal/sm64/animation/constants.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,50 @@
import struct
import re

from ...utility import intToHex, COMMENT_PATTERN
from ...utility import intToHex
from ..sm64_constants import ACTOR_PRESET_INFO, ActorPresetInfo

HEADER_STRUCT = struct.Struct(">h h h h h h I I I")
HEADER_SIZE = HEADER_STRUCT.size

TABLE_ELEMENT_PATTERN = re.compile( # strict but only in the sense that it requires valid c code
r"""
(?:COMMENT_PATTERN)|
(?:\[\s*(?P<enum>\w+)\s*\]\s*=\s*)? # Don´t capture brackets or equal, works with nums
(?:(?:&\s*(?P<element>\w+))|(?P<null>NULL)) # Capture element or null, element requires &
(?:\s*,|) # allow no comma, techinically not correct but no other method works
""".replace(
"COMMENT_PATTERN", COMMENT_PATTERN.pattern
),
""",
re.DOTALL | re.VERBOSE | re.MULTILINE,
)


TABLE_PATTERN = re.compile(
r"""
(?:COMMENT_PATTERN)|
const\s+struct\s*Animation\s*\*const\s*(?P<name>\w+)\s*
(?:\[.*?\])? # Optional size, don´t capture
\s*=\s*\{
(?P<content>(?:COMMENT_PATTERN|[\s\S])*) # Capture any character including new lines
(?P<content>[\s\S]*) # Capture any character including new lines
(?=\}\s*;) # Look ahead for the end
""".replace(
"COMMENT_PATTERN", COMMENT_PATTERN.pattern
),
""",
re.DOTALL | re.VERBOSE | re.MULTILINE,
)


TABLE_ENUM_PATTERN = re.compile( # strict but only in the sense that it requires valid c code
r"""
(?:COMMENT_PATTERN)|
(?P<name>\w+)\s*
(?:\s*=\s*(?P<num>\w+)\s*)?
(?=,|) # lookahead, allow no comma, techinically not correct but no other method works
""".replace(
"COMMENT_PATTERN", COMMENT_PATTERN.pattern
),
""",
re.DOTALL | re.VERBOSE | re.MULTILINE,
)


TABLE_ENUM_LIST_PATTERN = re.compile(
r"""
(?:COMMENT_PATTERN)|
enum\s*(?P<name>\w+)\s*\{
(?P<content>(?:COMMENT_PATTERN|[\s\S])*) # Capture any character including new lines, lazy
(?P<content>[\s\S]*) # Capture any character including new lines, lazy
(?=\}\s*;)
""".replace(
"COMMENT_PATTERN", COMMENT_PATTERN.pattern
),
""",
re.DOTALL | re.VERBOSE | re.MULTILINE,
)

Expand Down
25 changes: 15 additions & 10 deletions fast64_internal/sm64/animation/exporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
from ..sm64_constants import BEHAVIOR_COMMANDS, BEHAVIOR_EXITS, defaultExtendSegment4, level_pointers
from ..sm64_utility import (
ModifyFoundDescriptor,
find_descriptors,
find_descriptor_in_text,
get_comment_map,
to_include_descriptor,
write_includes,
update_actor_includes,
Expand Down Expand Up @@ -467,11 +468,10 @@ def update_anim_header(path: Path, table_name: str, gen_enums: bool, override_fi


def update_enum_file(path: Path, override_files: bool, table: SM64_AnimTable):
text, comment_map = "", []
existing_file = path.exists() and not override_files
if existing_file:
text = path.read_text()
else:
text = ""
text, comment_map = get_comment_map(path.read_text())

if table.enum_list_start == -1 and table.enum_list_end == -1: # create new enum list
if text and text[-1] not in {"\n", "\r"}:
Expand Down Expand Up @@ -515,26 +515,31 @@ def update_table_file(
designated: bool,
enum_list_path: Path,
):
text, enum_text = "", ""
assert isinstance(table.reference, str) and table.reference, "Invalid table reference"

text, comment_less, enum_text, comment_map = "", "", "", []
existing_file = table_path.exists() and not override_files
if existing_file:
text = table_path.read_text()
comment_less, comment_map = get_comment_map(text)

# add include if not already there
descriptor = to_include_descriptor(Path("table_enum.h"))
if gen_enums and descriptor not in find_descriptors(text, [descriptor])[0]:
if gen_enums and len(find_descriptor_in_text(descriptor, comment_less, comment_map)) == 0:
text = '#include "table_enum.h"\n' + text

# First, find existing tables
tables = import_tables(text, table_path, table.reference)
tables = import_tables(comment_less, table_path, comment_map, table.reference)
enum_tables = []
if gen_enums:
assert isinstance(table.enum_list_reference, str) and table.enum_list_reference
enum_text, enum_comment_less, enum_comment_map = "", "", []
if enum_list_path.exists() and not override_files:
enum_text = enum_list_path.read_text()
enum_tables = import_enums(enum_text, enum_list_path, table.enum_list_reference)
enum_comment_less, enum_comment_map = get_comment_map(enum_text)
enum_tables = import_enums(enum_comment_less, enum_list_path, enum_comment_map, table.enum_list_reference)
if len(enum_tables) > 1:
raise PluginError(f'Duplicate enum list "{table.enum_list_reference}"')
else:
enum_tables = []

if len(tables) > 1:
raise PluginError(f'Duplicate animation table "{table.reference}"')
Expand Down
61 changes: 43 additions & 18 deletions fast64_internal/sm64/animation/importing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
from mathutils import Quaternion

from ...f3d.f3d_parser import math_eval
from ...utility import PluginError, decodeSegmentedAddr, filepath_checks, path_checks, intToHex, removeComments
from ...utility import PluginError, decodeSegmentedAddr, filepath_checks, path_checks, intToHex
from ...utility_anim import create_basic_action

from ..sm64_constants import AnimInfo, level_pointers
from ..sm64_level_parser import parseLevelAtPointer
from ..sm64_utility import import_rom_checks
from ..sm64_utility import CommentMatch, get_comment_map, adjust_start_end, import_rom_checks
from ..sm64_classes import RomReader

from .utility import (
Expand All @@ -27,6 +27,7 @@
get_scene_anim_props,
get_anim_actor_name,
anim_name_to_enum_name,
table_name_to_enum,
)
from .classes import (
SM64_Anim,
Expand Down Expand Up @@ -353,7 +354,7 @@ def from_anim_table_class(
anim_props.write_data_seperately = True
anim_props.data_address = intToHex(min(start_addresses))
anim_props.data_end_address = intToHex(max(end_addresses))
elif isinstance(table.reference, str): # C
elif isinstance(table.reference, str) and table.reference: # C
if use_custom_name:
anim_props.custom_table_name = table.reference
if anim_props.get_table_name(actor_name) != anim_props.custom_table_name:
Expand Down Expand Up @@ -416,15 +417,15 @@ def update_table_with_table_enum(table: SM64_AnimTable, enum_table: SM64_AnimTab
table.enum_list_end = enum_table.enum_list_end


def import_enums(c_data: str, path: Path, specific_name=""):
def import_enums(c_data: str, path: Path, comment_map: list[CommentMatch], specific_name=""):
tables = []
for list_match in re.finditer(TABLE_ENUM_LIST_PATTERN, c_data):
name, content = list_match.group("name"), list_match.group("content")
if name is None and content is None: # comment
continue
if specific_name and name != specific_name:
continue
list_start, list_end = c_data.find(content, list_match.start()), list_match.end()
list_start, list_end = adjust_start_end(c_data.find(content, list_match.start()), list_match.end(), comment_map)
content = c_data[list_start:list_end]
table = SM64_AnimTable(
file_name=path.name,
Expand All @@ -436,9 +437,12 @@ def import_enums(c_data: str, path: Path, specific_name=""):
name, num = (element_match.group("name"), element_match.group("num"))
if name is None and num is None: # comment
continue
enum_start, enum_end = adjust_start_end(
list_start + element_match.start(), list_start + element_match.end(), comment_map
)
table.elements.append(
SM64_AnimTableElement(
enum_name=name, enum_val=num, enum_start=element_match.start(), enum_end=element_match.end()
enum_name=name, enum_val=num, enum_start=enum_start - list_start, enum_end=enum_end - list_start
)
)
tables.append(table)
Expand All @@ -448,10 +452,11 @@ def import_enums(c_data: str, path: Path, specific_name=""):
def import_tables(
c_data: str,
path: Path,
comment_map: list[CommentMatch],
specific_name="",
header_decls: list[CArrayDeclaration] = None,
values_decls: list[CArrayDeclaration] = None,
indices_decls: list[CArrayDeclaration] = None,
header_decls: Optional[list[CArrayDeclaration]] = None,
values_decls: Optional[list[CArrayDeclaration]] = None,
indices_decls: Optional[list[CArrayDeclaration]] = None,
):
read_headers = {}
header_decls, values_decls, indices_decls = (
Expand All @@ -468,16 +473,24 @@ def import_tables(
if specific_name and name != specific_name:
continue

table_start, table_end = c_data.find(content, table_match.start()), table_match.end()
table = SM64_AnimTable(name, file_name=path.name, elements=table_elements, start=table_start, end=table_end)
table.read_c(c_data[table_start:table_end], read_headers, header_decls, values_decls, indices_decls)
table = SM64_AnimTable(name, file_name=path.name, elements=table_elements)
table.read_c(
c_data,
c_data.find(content, table_match.start()),
table_match.end(),
comment_map,
read_headers,
header_decls,
values_decls,
indices_decls,
)
tables.append(table)
return tables


DECL_PATTERN = re.compile(
r"(static\s+const\s+struct\s+Animation|static\s+const\s+u16|static\s+const\s+s16)\s+"
r"(\w+)\s*?(?:\[.*?\])?\s*?=\s*?\{(.*?)\};",
r"(\w+)\s*?(?:\[.*?\])?\s*?=\s*?\{(.*?)\s*?\};",
re.DOTALL,
)
VALUE_SPLIT_PATTERN = re.compile(r"\s*(?:(?:\.(?P<var>\w+)|\[\s*(?P<designator>.*?)\s*\])\s*=\s*)?(?P<val>.+?)(?:,|\Z)")
Expand Down Expand Up @@ -527,7 +540,7 @@ def import_c_animations(path: Path) -> tuple[SM64_AnimTable | None, dict[str, SM
raise PluginError("Path is neither a file or a folder but it exists, somehow.")

print("Reading from:\n" + "\n".join([f.name for f in file_paths]))
c_files = {file_path: removeComments(file_path.read_text()) for file_path in file_paths}
c_files = {file_path: get_comment_map(file_path.read_text()) for file_path in file_paths}

decl_lists = {"static const struct Animation": [], "static const u16": [], "static const s16": []}
header_decls, indices_decls, value_decls = (
Expand All @@ -536,15 +549,27 @@ def import_c_animations(path: Path) -> tuple[SM64_AnimTable | None, dict[str, SM
decl_lists["static const s16"],
)
tables: list[SM64_AnimTable] = []
for file_path, c_data in c_files.items():
find_decls(c_data, file_path, decl_lists)
for file_path, c_data in c_files.items():
tables.extend(import_tables(c_data, file_path, "", header_decls, value_decls, indices_decls))
enum_lists: list[SM64_AnimTable] = []
for file_path, (comment_less, _comment_map) in c_files.items():
find_decls(comment_less, file_path, decl_lists)
for file_path, (comment_less, comment_map) in c_files.items():
tables.extend(import_tables(comment_less, file_path, comment_map, "", header_decls, value_decls, indices_decls))
enum_lists.extend(import_enums(comment_less, file_path, comment_map))

if len(tables) > 1:
raise ValueError("More than 1 table declaration")
elif len(tables) == 1:
table: SM64_AnimTable = tables[0]
if enum_lists:
enum_table = next( # find enum with the same name or use the first
(
enum_table
for enum_table in enum_lists
if enum_table.reference == table_name_to_enum(table.reference)
),
enum_lists[0],
)
update_table_with_table_enum(table, enum_table)
read_headers = {header.reference: header for header in table.header_set}
return table, read_headers
else:
Expand Down
5 changes: 2 additions & 3 deletions fast64_internal/sm64/animation/properties.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from pathlib import Path
import os

import bpy
Expand Down Expand Up @@ -53,6 +52,7 @@
anim_name_to_enum_name,
action_name_to_enum_name,
duplicate_name,
table_name_to_enum,
)
from .importing import get_enum_from_import_preset, update_table_preset

Expand Down Expand Up @@ -1005,8 +1005,7 @@ def get_table_name(self, actor_name: str) -> str:
return f"{actor_name}_anims"

def get_enum_name(self, actor_name: str):
table_name = self.get_table_name(actor_name)
return table_name.title().replace("_", "")
return table_name_to_enum(self.get_table_name(actor_name))

def get_enum_end(self, actor_name: str):
table_name = self.get_table_name(actor_name)
Expand Down
4 changes: 4 additions & 0 deletions fast64_internal/sm64/animation/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ def duplicate_name(name: str, existing_names: dict[str, int]) -> str:
return name


def table_name_to_enum(name: str):
return name.title().replace("_", "")


def get_action_props(action: Action) -> "SM64_ActionAnimProperty":
return action.fast64.sm64.animation

Expand Down
Loading

0 comments on commit f3570e5

Please sign in to comment.