From dda75c5f3e6db944cd3dddffe0fe33b71d8122dc Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Tue, 10 Jan 2023 13:45:45 +0100 Subject: [PATCH 01/39] UI update & other changes --- fast64_internal/oot/cutscene/constants.py | 227 ++++++++++++++++-- .../oot/cutscene/exporter/functions.py | 16 -- fast64_internal/oot/cutscene/operators.py | 34 ++- fast64_internal/oot/cutscene/properties.py | 117 +++++---- fast64_internal/oot/oot_constants.py | 219 ++++++++--------- .../oot/scene/exporter/to_c/scene_cutscene.py | 28 --- fast64_internal/oot/scene/operators.py | 2 +- fast64_internal/oot/scene/properties.py | 7 +- 8 files changed, 421 insertions(+), 229 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 81a9c2412..b313bd1fa 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -1,20 +1,19 @@ ootEnumCSTextboxTypeEntryC = { - "Text": "CS_TEXT_DISPLAY_TEXTBOX", + "Text": "CS_TEXT", "None": "CS_TEXT_NONE", - "LearnSong": "CS_TEXT_LEARN_SONG", + "LearnSong": "CS_TEXT_OCARINA_ACTION", } ootEnumCSListTypeListC = { "Textbox": "CS_TEXT_LIST", - "FX": "CS_SCENE_TRANS_FX", - "Lighting": "CS_LIGHTING_LIST", + "FX": "CS_TRANSITION", + "Lighting": "CS_LIGHT_SETTING_LIST", "Time": "CS_TIME_LIST", - "PlayBGM": "CS_PLAY_BGM_LIST", - "StopBGM": "CS_STOP_BGM_LIST", - "FadeBGM": "CS_FADE_BGM_LIST", + "PlayBGM": "CS_START_SEQ_LIST", + "StopBGM": "CS_STOP_SEQ_LIST", + "FadeBGM": "CS_FADE_OUT_SEQ_LIST", "Misc": "CS_MISC_LIST", - "0x09": "CS_CMD_09_LIST", - "Unk": "CS_UNK_DATA_LIST", + "0x09": "CS_RUMBLE_CONTROLLER_LIST", } ootEnumCSListTypeEntryC = { @@ -22,12 +21,11 @@ "FX": None, # no list entries "Lighting": "CS_LIGHTING", "Time": "CS_TIME", - "PlayBGM": "CS_PLAY_BGM", - "StopBGM": "CS_STOP_BGM", - "FadeBGM": "CS_FADE_BGM", + "PlayBGM": "CS_START_SEQ", + "StopBGM": "CS_STOP_SEQ", + "FadeBGM": "CS_FADE_OUT_SEQ", "Misc": "CS_MISC", - "0x09": "CS_CMD_09", - "Unk": "CS_UNK_DATA", + "0x09": "CS_RUMBLE_CONTROLLER", } ootEnumCSWriteType = [ @@ -38,15 +36,14 @@ ootEnumCSListType = [ ("Textbox", "Textbox", "Textbox"), - ("FX", "Scene Trans FX", "Scene Trans FX"), + ("FX", "Transition", "Transition"), ("Lighting", "Lighting", "Lighting"), ("Time", "Time", "Time"), ("PlayBGM", "Play BGM", "Play BGM"), ("StopBGM", "Stop BGM", "Stop BGM"), ("FadeBGM", "Fade BGM", "Fade BGM"), ("Misc", "Misc", "Misc"), - ("0x09", "Cmd 09", "Cmd 09"), - ("Unk", "Unknown Data", "Unknown Data"), + ("0x09", "Rumble Controller", "Rumble Controller"), ] ootEnumCSListTypeIcons = [ @@ -58,8 +55,7 @@ "SNAP_FACE", "IPO_EASE_IN_OUT", "OPTIONS", - "EVENT_F9", - "QUESTION", + "OUTLINER_OB_FORCE_FIELD", ] ootEnumCSTextboxType = [("Text", "Text", "Text"), ("None", "None", "None"), ("LearnSong", "Learn Song", "Learn Song")] @@ -81,3 +77,196 @@ ("12", "To Dim Unk", "Fade gSaveContext.unk_1410 255>100, works with scene xn 11/17"), ("13", "From Dim", "Alpha 100>255"), ] + +ootEnumCSMiscType = [ + ("CS_MISC_SET_LOCKED_VIEWPOINT", "Set Locked Viewpoint", "Set Locked Viewpoint"), + ("CS_MISC_SHOW_TITLE_CARD", "Show Area Title Card", "Show Area Title Card"), + ("CS_MISC_RAIN", "Rain", "Rain"), + ("CS_MISC_SNOW", "Snow", "Snow"), + ("CS_MISC_LIGHTNING", "Lightning", "Lightning"), + ("CS_MISC_LIFT_FOG", "Lift Fog", "Lift Fog"), + ("CS_MISC_CLOUDY_SKY", "Cloudy Sky", "Cloudy Sky"), + ("CS_MISC_QUAKE_START", "Start Quake", "Start Quake"), + ("CS_MISC_QUAKE_STOP", "Stop Quake", "Stop Quake"), + ("CS_MISC_SANDSTORM_FILL", "Sandstorm Fill", "Sandstorm Fill"), + ("CS_MISC_SUNSSONG_START", "Start Sun's Song", "Start Sun's Song"), + ("CS_MISC_STOP_STORM_AND_ADVANCE_TO_DAY", "Stop Storm And Advance To Day", "Stop Storm And Advance To Day"), + ("CS_MISC_FREEZE_TIME", "Freeze Time", "Freeze Time"), + ("CS_MISC_TIME_ADVANCE_TO_NIGHT", "Advance Time to Night", "Advance Time to Night"), + ("CS_MISC_SET_TIME_BASED_LIGHT_SETTING", "Set Time Based on Light Settings", "Set Time Based on Light Settings"), + ("CS_MISC_FADE_KOKIRI_GRASS_ENV_ALPHA", "Grass fade in Kokiri Forest", "Grass fade in Kokiri Forest"), + ("CS_MISC_DEKU_TREE_DEATH", "Deku Tree Death", "Deku Tree Death"), + ("CS_MISC_TRIFORCE_FLASH", "Triforce Flash", "Triforce Flash"), + ("CS_MISC_HIDE_ROOM", "Hide Current Room", "Hide Current Room"), + ("CS_MISC_VISMONO_BLACK_AND_WHITE", "Set Screen to Black & White", "Set Screen to Black & White"), + ("CS_MISC_VISMONO_SEPIA", "Set Screen to Sepia", "Set Screen to Sepia"), + ("CS_MISC_HALT_ALL_ACTORS", "Halt All Actors", "Halt All Actors"), + ("CS_MISC_RESUME_ALL_ACTORS", "Resume All Actors", "Resume All Actors"), + ("CS_MISC_RED_PULSATING_LIGHTS", "Red Pulsating Lights", "Red Pulsating Lights"), + ("CS_MISC_LONG_SCARECROW_SONG", "Play Long Scarecrow Song", "Play Long Scarecrow Song"), + ("CS_MISC_SET_CSFLAG_0", "Set CS Flag 0", "Set CS Flag 0"), + ("CS_MISC_SET_CSFLAG_1", "Set CS Flag 1", "Set CS Flag 1"), + ("CS_MISC_SET_CSFLAG_3", "Set CS Flag 3", "Set CS Flag 3"), + ("CS_MISC_SET_CSFLAG_4", "Set CS Flag 4", "Set CS Flag 4"), + ("CS_MISC_SET_FLAG_FAST_WINDMILL", "Set Fast Windmill Flag", "Set Fast Windmill Flag"), + ("CS_MISC_SET_FLAG_WELL_DRAINED", "Set Well Drained Flag", "Set Well Drained Flag"), + ("CS_MISC_SET_FLAG_LAKE_HYLIA_RESTORED", "Set Lake Hylia Restored Flag", "Set Lake Hylia Restored Flag"), + ("CS_MISC_STOP_CUTSCENE", "Stop Cutscene", "Stop Cutscene"), +] + +ootEnumCSDestinationType = [ + ("CS_DEST_CUTSCENE_MAP_GANON_HORSE", "Cutscene Map Ganon Horse", "Cutscene Map Ganon Horse"), + ("CS_DEST_CUTSCENE_MAP_THREE_GODDESSES", "Cutscene Map Three Goddesses", "Cutscene Map Three Goddesses"), + ("CS_DEST_GERUDO_VALLEY_DIN_PART_1", "Gerudo Valley Din Part 1", "Gerudo Valley Din Part 1"), + ("CS_DEST_DEATH_MOUNTAIN_TRAIL_NAYRU", "Death Mountain Trail Nayru", "Death Mountain Trail Nayru"), + ("CS_DEST_KOKIRI_FOREST_FARORE", "Kokiri Forest Farore", "Kokiri Forest Farore"), + ("CS_DEST_CUTSCENE_MAP_TRIFORCE_CREATION", "Cutscene Map Triforce Creation", "Cutscene Map Triforce Creation"), + ("CS_DEST_KOKIRI_FOREST_RECEIVE_KOKIRI_EMERALD", "Kokiri Forest Receive Kokiri Emerald", "Kokiri Forest Receive Kokiri Emerald"), + ("CS_DEST_TEMPLE_OF_TIME_FROM_MASTER_SWORD", "Temple Of Time From Master Sword", "Temple Of Time From Master Sword"), + ("CS_DEST_GERUDO_VALLEY_DIN_PART_2", "Gerudo Valley Din Part 2", "Gerudo Valley Din Part 2"), + ("CS_DEST_LINKS_HOUSE_INTRO", "Links House Intro", "Links House Intro"), + ("CS_DEST_KOKIRI_FOREST_INTRO", "Kokiri Forest Intro", "Kokiri Forest Intro"), + ("CS_DEST_DEATH_MOUNTAIN_TRAIL_FROM_GORON_RUBY", "Death Mountain Trail From Goron Ruby", "Death Mountain Trail From Goron Ruby"), + ("CS_DEST_ZORAS_FOUNTAIN_FROM_ZORAS_SAPPHIRE", "Zoras Fountain From Zoras Sapphire", "Zoras Fountain From Zoras Sapphire"), + ("CS_DEST_KOKIRI_FOREST_FROM_KOKIRI_EMERALD", "Kokiri Forest From Kokiri Emerald", "Kokiri Forest From Kokiri Emerald"), + ("CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED", "Temple Of Time Kokiri Emerald Restored", "Temple Of Time Kokiri Emerald Restored"), + ("CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED", "Temple Of Time Goron Ruby Restored", "Temple Of Time Goron Ruby Restored"), + ("CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED", "Temple Of Time Zoras Sapphire Restored", "Temple Of Time Zoras Sapphire Restored"), + ("CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION", "Temple Of Time After Light Medallion", "Temple Of Time After Light Medallion"), + ("CS_DEST_DEATH_MOUNTAIN_TRAIL", "Death Mountain Trail", "Death Mountain Trail"), + ("CS_DEST_LAKE_HYLIA_WATER_RESTORED", "Lake Hylia Water Restored", "Lake Hylia Water Restored"), + ("CS_DEST_DESERT_COLOSSUS_REQUIEM", "Desert Colossus Requiem", "Desert Colossus Requiem"), + ("CS_DEST_CUTSCENE_MAP_GANONDORF_DEFEATED_CREDITS", "Cutscene Map Ganondorf Defeated Credits", "Cutscene Map Ganondorf Defeated Credits"), + ("CS_DEST_JABU_JABU", "Jabu Jabu", "Jabu Jabu"), + ("CS_DEST_CHAMBER_OF_SAGES_LIGHT_MEDALLION", "Chamber Of Sages Light Medallion", "Chamber Of Sages Light Medallion"), + ("CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED_2", "Temple Of Time Kokiri Emerald Restored 2", "Temple Of Time Kokiri Emerald Restored 2"), + ("CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED_2", "Temple Of Time Goron Ruby Restored 2", "Temple Of Time Goron Ruby Restored 2"), + ("CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED_2", "Temple Of Time Zoras Sapphire Restored 2", "Temple Of Time Zoras Sapphire Restored 2"), + ("CS_DEST_CHAMBER_OF_SAGES_FOREST_MEDALLION", "Chamber Of Sages Forest Medallion", "Chamber Of Sages Forest Medallion"), + ("CS_DEST_CHAMBER_OF_SAGES_FIRE_MEDALLION", "Chamber Of Sages Fire Medallion", "Chamber Of Sages Fire Medallion"), + ("CS_DEST_CHAMBER_OF_SAGES_WATER_MEDALLION", "Chamber Of Sages Water Medallion", "Chamber Of Sages Water Medallion"), + ("CS_DEST_HYRULE_FIELD_FLASHBACK", "Hyrule Field Flashback", "Hyrule Field Flashback"), + ("CS_DEST_HYRULE_FIELD_FROM_ZELDA_ESCAPE", "Hyrule Field From Zelda Escape", "Hyrule Field From Zelda Escape"), + ("CS_DEST_CUTSCENE_MAP_GANONDORF_FROM_MASTER_SWORD", "Cutscene Map Ganondorf From Master Sword", "Cutscene Map Ganondorf From Master Sword"), + ("CS_DEST_HYRULE_FIELD_INTRO_DREAM", "Hyrule Field Intro Dream", "Hyrule Field Intro Dream"), + ("CS_DEST_CUTSCENE_MAP_SHEIKAH_LEGEND", "Cutscene Map Sheikah Legend", "Cutscene Map Sheikah Legend"), + ("CS_DEST_TEMPLE_OF_TIME_ZELDA_REVEAL", "Temple Of Time Zelda Reveal", "Temple Of Time Zelda Reveal"), + ("CS_DEST_TEMPLE_OF_TIME_GET_LIGHT_ARROWS", "Temple Of Time Get Light Arrows", "Temple Of Time Get Light Arrows"), + ("CS_DEST_LAKE_HYLIA_FROM_LAKE_RESTORED", "Lake Hylia From Lake Restored", "Lake Hylia From Lake Restored"), + ("CS_DEST_KAKARIKO_VILLAGE_DRAIN_WELL", "Kakariko Village Drain Well", "Kakariko Village Drain Well"), + ("CS_DEST_WINDMILL_FROM_WELL_DRAINED", "Windmill From Well Drained", "Windmill From Well Drained"), + ("CS_DEST_TEMPLE_OF_TIME_FROM_ALL_STONES_RESTORED", "Temple Of Time From All Stones Restored", "Temple Of Time From All Stones Restored"), + ("CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION_ALT", "Temple Of Time After Light Medallion Alt", "Temple Of Time After Light Medallion Alt"), + ("CS_DEST_KAKARIKO_VILLAGE_NOCTURNE_PART_2", "Kakariko Village Nocturne Part 2", "Kakariko Village Nocturne Part 2"), + ("CS_DEST_DESERT_COLOSSUS_FROM_REQUIEM", "Desert Colossus From Requiem", "Desert Colossus From Requiem"), + ("CS_DEST_TEMPLE_OF_TIME_FROM_LIGHT_ARROWS", "Temple Of Time From Light Arrows", "Temple Of Time From Light Arrows"), + ("CS_DEST_KAKARIKO_VILLAGE_FROM_NOCTURNE", "Kakariko Village From Nocturne", "Kakariko Village From Nocturne"), + ("CS_DEST_HYRULE_FIELD_FROM_ZELDAS_COURTYARD", "Hyrule Field From Zeldas Courtyard", "Hyrule Field From Zeldas Courtyard"), + ("CS_DEST_TEMPLE_OF_TIME_SONG_OF_TIME", "Temple Of Time Song Of Time", "Temple Of Time Song Of Time"), + ("CS_DEST_HYRULE_FIELD_FROM_SONG_OF_TIME", "Hyrule Field From Song Of Time", "Hyrule Field From Song Of Time"), + ("CS_DEST_GERUDO_VALLEY_CREDITS", "Gerudo Valley Credits", "Gerudo Valley Credits"), + ("CS_DEST_GERUDO_FORTRESS_CREDITS", "Gerudo Fortress Credits", "Gerudo Fortress Credits"), + ("CS_DEST_KAKARIKO_VILLAGE_CREDITS", "Kakariko Village Credits", "Kakariko Village Credits"), + ("CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_1", "Death Mountain Trail Credits Part 1", "Death Mountain Trail Credits Part 1"), + ("CS_DEST_GORON_CITY_CREDITS", "Goron City Credits", "Goron City Credits"), + ("CS_DEST_LAKE_HYLIA_CREDITS", "Lake Hylia Credits", "Lake Hylia Credits"), + ("CS_DEST_ZORAS_FOUNTAIN_CREDITS", "Zoras Fountain Credits", "Zoras Fountain Credits"), + ("CS_DEST_ZORAS_DOMAIN_CREDITS", "Zoras Domain Credits", "Zoras Domain Credits"), + ("CS_DEST_KOKIRI_FOREST_CREDITS_PART_1", "Kokiri Forest Credits Part 1", "Kokiri Forest Credits Part 1"), + ("CS_DEST_KOKIRI_FOREST_CREDITS_PART_2", "Kokiri Forest Credits Part 2", "Kokiri Forest Credits Part 2"), + ("CS_DEST_HYRULE_FIELD_CREDITS", "Hyrule Field Credits", "Hyrule Field Credits"), + ("CS_DEST_LON_LON_RANCH_CREDITS_PART_1_ALT", "Lon Lon Ranch Credits Part 1 Alt", "Lon Lon Ranch Credits Part 1 Alt"), + ("CS_DEST_KAKARIKO_VILLAGE_FROM_TRAIL_OWL", "Kakariko Village From Trail Owl", "Kakariko Village From Trail Owl"), + ("CS_DEST_HYRULE_FIELD_FROM_LAKE_HYLIA_OWL", "Hyrule Field From Lake Hylia Owl", "Hyrule Field From Lake Hylia Owl"), + ("CS_DEST_CUTSCENE_MAP_DEKU_SPROUT_PART_2", "Cutscene Map Deku Sprout Part 2", "Cutscene Map Deku Sprout Part 2"), + ("CS_DEST_KOKIRI_FOREST_DEKU_SPROUT_PART_3", "Kokiri Forest Deku Sprout Part 3", "Kokiri Forest Deku Sprout Part 3"), + ("CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_2", "Death Mountain Trail Credits Part 2", "Death Mountain Trail Credits Part 2"), + ("CS_DEST_TEMPLE_OF_TIME_CREDITS", "Temple Of Time Credits", "Temple Of Time Credits"), + ("CS_DEST_ZELDAS_COURTYARD_CREDITS", "Zeldas Courtyard Credits", "Zeldas Courtyard Credits"), + ("CS_DEST_LON_LON_RANCH_CREDITS_PART_1", "Lon Lon Ranch Credits Part 1", "Lon Lon Ranch Credits Part 1"), + ("CS_DEST_LON_LON_RANCH_CREDITS_PART_2", "Lon Lon Ranch Credits Part 2", "Lon Lon Ranch Credits Part 2"), + ("CS_DEST_LON_LON_RANCH_CREDITS_PART_3", "Lon Lon Ranch Credits Part 3", "Lon Lon Ranch Credits Part 3"), + ("CS_DEST_LON_LON_RANCH_CREDITS_PART_4", "Lon Lon Ranch Credits Part 4", "Lon Lon Ranch Credits Part 4"), + ("CS_DEST_LON_LON_RANCH_CREDITS_PART_5", "Lon Lon Ranch Credits Part 5", "Lon Lon Ranch Credits Part 5"), + ("CS_DEST_LON_LON_RANCH_CREDITS_PART_6", "Lon Lon Ranch Credits Part 6", "Lon Lon Ranch Credits Part 6"), + ("CS_DEST_LON_LON_RANCH_1", "Lon Lon Ranch 1", "Lon Lon Ranch 1"), + ("CS_DEST_LON_LON_RANCH_2", "Lon Lon Ranch 2", "Lon Lon Ranch 2"), + ("CS_DEST_LON_LON_RANCH_3", "Lon Lon Ranch 3", "Lon Lon Ranch 3"), + ("CS_DEST_LON_LON_RANCH_4", "Lon Lon Ranch 4", "Lon Lon Ranch 4"), + ("CS_DEST_LON_LON_RANCH_5", "Lon Lon Ranch 5", "Lon Lon Ranch 5"), + ("CS_DEST_LON_LON_RANCH_6", "Lon Lon Ranch 6", "Lon Lon Ranch 6"), + ("CS_DEST_LON_LON_RANCH_7", "Lon Lon Ranch 7", "Lon Lon Ranch 7"), + ("CS_DEST_LON_LON_RANCH_8", "Lon Lon Ranch 8", "Lon Lon Ranch 8"), + ("CS_DEST_LON_LON_RANCH_9", "Lon Lon Ranch 9", "Lon Lon Ranch 9"), + ("CS_DEST_LON_LON_RANCH_10", "Lon Lon Ranch 10", "Lon Lon Ranch 10"), + ("CS_DEST_LON_LON_RANCH_11", "Lon Lon Ranch 11", "Lon Lon Ranch 11"), + ("CS_DEST_LON_LON_RANCH_12", "Lon Lon Ranch 12", "Lon Lon Ranch 12"), + ("CS_DEST_LON_LON_RANCH_13", "Lon Lon Ranch 13", "Lon Lon Ranch 13"), + ("CS_DEST_LON_LON_RANCH_14", "Lon Lon Ranch 14", "Lon Lon Ranch 14"), + ("CS_DEST_LON_LON_RANCH_15", "Lon Lon Ranch 15", "Lon Lon Ranch 15"), + ("CS_DEST_LON_LON_RANCH_FROM_EPONAS_SONG", "Lon Lon Ranch From Eponas Song", "Lon Lon Ranch From Eponas Song"), + ("CS_DEST_STONES_RESTORED_CONDITIONAL", "Stones Restored Conditional", "Stones Restored Conditional"), + ("CS_DEST_DESERT_COLOSSUS_FROM_CHAMBER_OF_SAGES", "Desert Colossus From Chamber Of Sages", "Desert Colossus From Chamber Of Sages"), + ("CS_DEST_GRAVEYARD_FROM_CHAMBER_OF_SAGES", "Graveyard From Chamber Of Sages", "Graveyard From Chamber Of Sages"), + ("CS_DEST_DEATH_MOUNTAIN_CRATER_FROM_CHAMBER_OF_SAGES", "Death Mountain Crater From Chamber Of Sages", "Death Mountain Crater From Chamber Of Sages"), + ("CS_DEST_SACRED_FOREST_MEADOW_WARP_PAD", "Sacred Forest Meadow Warp Pad", "Sacred Forest Meadow Warp Pad"), + ("CS_DEST_KOKIRI_FOREST_FROM_CHAMBER_OF_SAGES", "Kokiri Forest From Chamber Of Sages", "Kokiri Forest From Chamber Of Sages"), + ("CS_DEST_DESERT_COLOSSUS_FROM_NABOORU_CAPTURE", "Desert Colossus From Nabooru Capture", "Desert Colossus From Nabooru Capture"), + ("CS_DEST_TEMPLE_OF_TIME_FRONT_OF_PEDESTAL", "Temple Of Time Front Of Pedestal", "Temple Of Time Front Of Pedestal"), + ("CS_DEST_HYRULE_FIELD_TITLE_SCREEN", "Hyrule Field Title Screen", "Hyrule Field Title Screen"), + ("CS_DEST_TITLE_SCREEN_DEMO", "Title Screen Demo", "Title Screen Demo"), + ("CS_DEST_GRAVEYARD_SUNS_SONG_PART_2", "Graveyard Suns Song Part 2", "Graveyard Suns Song Part 2"), + ("CS_DEST_ROYAL_FAMILYS_TOMB_SUNS_SONG_PART_3", "Royal Familys Tomb Suns Song Part 3", "Royal Familys Tomb Suns Song Part 3"), + ("CS_DEST_GANONS_CASTLE_DISPEL_FOREST_BEAM", "Ganons Castle Dispel Forest Beam", "Ganons Castle Dispel Forest Beam"), + ("CS_DEST_GANONS_CASTLE_DISPEL_WATER_BEAM", "Ganons Castle Dispel Water Beam", "Ganons Castle Dispel Water Beam"), + ("CS_DEST_GANONS_CASTLE_DISPEL_SHADOW_BEAM", "Ganons Castle Dispel Shadow Beam", "Ganons Castle Dispel Shadow Beam"), + ("CS_DEST_GANONS_CASTLE_DISPEL_FIRE_BEAM", "Ganons Castle Dispel Fire Beam", "Ganons Castle Dispel Fire Beam"), + ("CS_DEST_GANONS_CASTLE_DISPEL_LIGHT_BEAM", "Ganons Castle Dispel Light Beam", "Ganons Castle Dispel Light Beam"), + ("CS_DEST_GANONS_CASTLE_DISPEL_SPIRIT_BEAM", "Ganons Castle Dispel Spirit Beam", "Ganons Castle Dispel Spirit Beam"), + ("CS_DEST_GANONS_CASTLE_DISPEL_BARRIER_CONDITONAL", "Ganons Castle Dispel Barrier Conditonal", "Ganons Castle Dispel Barrier Conditonal"), + ("CS_DEST_HYRULE_FIELD_FROM_FAIRY_OCARINA", "Hyrule Field From Fairy Ocarina", "Hyrule Field From Fairy Ocarina"), + ("CS_DEST_HYRULE_FIELD_FROM_IMPA_ESCORT", "Hyrule Field From Impa Escort", "Hyrule Field From Impa Escort"), + ("CS_DEST_FROM_RAURU_FINAL_MESSAGE_CONDITIONAL", "From Rauru Final Message Conditional", "From Rauru Final Message Conditional"), + ("CS_DEST_HYRULE_FIELD_CREDITS_SKY", "Hyrule Field Credits Sky", "Hyrule Field Credits Sky"), + ("CS_DEST_GANON_BATTLE_TOWER_COLLAPSE", "Ganon Battle Tower Collapse", "Ganon Battle Tower Collapse"), + ("CS_DEST_ZELDAS_COURTYARD_RECEIVE_LETTER", "Zeldas Courtyard Receive Letter", "Zeldas Courtyard Receive Letter"), +] + +ootEnumTextType = [ + ("CS_TEXT_NORMAL", "Normal Text", "Normal Text"), + ("CS_TEXT_CHOICE", "Choice", "Choice"), + ("CS_TEXT_OCARINA_ACTION", "Ocarina Action", "Ocarina Action"), + ("CS_TEXT_GORON_RUBY", "Goron Ruby (use alt text)", "Goron Ruby (use alt text)"), + ("CS_TEXT_ZORA_SAPPHIRE", "Zora Sapphire (use alt text)", "Zora Sapphire (use alt text)"), +] + +ootCSSubPropToName = { + "startFrame": "Start Frame", + "endFrame": "End Frame", + + # TextBox + "messageId": "Text ID", + "ocarinaSongAction": "Ocarina Action", + "csTextType": "Text Type", + "topOptionBranch": "Text ID for Top Option", + "bottomOptionBranch": "Text ID for Bottom Option", + "ocarinaMessageId": "Ocarina Message ID", + + # Lighting + "index": "Light Settings Index", + + # Time + "hour": "Hour", + "minute": "Minute", + + # BGM + "csSeqID": "BGM ID", + + # Misc + "csMiscType": "Misc Type", + + # Rumble + "unk2": "Source Strength", + "unk3": "Duration", + "unk4": "Decrease Rate", +} diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index 9ac6204f5..c51a8a9b3 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -72,22 +72,6 @@ def readCutsceneData(csParentOut, csParentIn): entryOut.unk3 = entryIn.unk3 entryOut.unk4 = entryIn.unk4 listOut.entries.append(entryOut) - elif listOut.listType == "Unk": - for entryIn in listIn.unk: - entryOut = OOTCSUnk() - entryOut.unk1 = entryIn.unk1 - entryOut.unk2 = entryIn.unk2 - entryOut.unk3 = entryIn.unk3 - entryOut.unk4 = entryIn.unk4 - entryOut.unk5 = entryIn.unk5 - entryOut.unk6 = entryIn.unk6 - entryOut.unk7 = entryIn.unk7 - entryOut.unk8 = entryIn.unk8 - entryOut.unk9 = entryIn.unk9 - entryOut.unk10 = entryIn.unk10 - entryOut.unk11 = entryIn.unk11 - entryOut.unk12 = entryIn.unk12 - listOut.entries.append(entryOut) csParentOut.csLists.append(listOut) diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index 530bd3251..c2648bd45 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -1,4 +1,4 @@ -import os +import os, bpy from bpy.path import abspath from bpy.ops import object from bpy.props import StringProperty, EnumProperty, IntProperty @@ -8,7 +8,7 @@ from ..oot_utility import getCollection from ..scene.exporter.to_c import ootCutsceneDataToC from .exporter import convertCutsceneObject -from .constants import ootEnumCSTextboxType, ootEnumCSListType, ootEnumCSListTypeIcons +from .constants import ootEnumCSTextboxType, ootEnumCSListType, ootEnumCSListTypeIcons, ootEnumCSDestinationType def checkGetFilePaths(context: Context): @@ -38,7 +38,7 @@ def ootCutsceneIncludes(headerfilename): return ret -def drawCSListAddOp(layout: UILayout, objName: str, collectionType): +def drawCSListAddOp(layout: UILayout, objName: str, collectionType: str): def addButton(row): nonlocal l op = row.operator(OOTCSListAdd.bl_idname, text=ootEnumCSListType[l][1], icon=ootEnumCSListTypeIcons[l]) @@ -47,11 +47,10 @@ def addButton(row): op.objName = objName l += 1 - box = layout.column(align=True) + box = layout.box() l = 0 row = box.row(align=True) - row.label(text="Add:") - addButton(row) + row.label(text="Cutscene Commands") for _ in range(3): row = box.row(align=True) for _ in range(3): @@ -153,11 +152,34 @@ def execute(self, context): return {"CANCELLED"} +class OOT_SearchCSDestinationEnumOperator(Operator): + bl_idname = "object.oot_search_cs_dest_enum_operator" + bl_label = "Choose Destination" + bl_property = "csDestination" + bl_options = {"REGISTER", "UNDO"} + + csDestination: EnumProperty(items=ootEnumCSDestinationType, default="CS_DEST_CUTSCENE_MAP_GANON_HORSE") + objName: StringProperty() + + def execute(self, context): + obj = bpy.data.objects[self.objName] + obj.ootCutsceneProperty.csDestination = self.csDestination + + context.region.tag_redraw() + self.report({"INFO"}, "Selected: " + self.csDestination) + return {"FINISHED"} + + def invoke(self, context, event): + context.window_manager.invoke_search_popup(self) + return {"RUNNING_MODAL"} + + oot_cutscene_classes = ( OOTCSTextboxAdd, OOTCSListAdd, OOT_ExportCutscene, OOT_ExportAllCutscenes, + OOT_SearchCSDestinationEnumOperator, ) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index a4537cc64..3b938fab3 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -2,9 +2,19 @@ from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty, CollectionProperty, PointerProperty from bpy.utils import register_class, unregister_class from ...utility import PluginError, prop_split -from ..oot_utility import OOTCollectionAdd, drawCollectionOps -from .operators import OOTCSTextboxAdd, drawCSListAddOp -from .constants import ootEnumCSTextboxType, ootEnumCSListType, ootEnumCSTransitionType, ootEnumCSTextboxTypeIcons +from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName +from ..oot_constants import ootEnumMusicSeq +from .operators import OOTCSTextboxAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp +from .constants import ( + ootEnumCSTextboxType, + ootEnumCSListType, + ootEnumCSTransitionType, + ootEnumCSTextboxTypeIcons, + ootEnumCSDestinationType, + ootEnumCSMiscType, + ootEnumTextType, + ootCSSubPropToName, +) # Perhaps this should have been called something like OOTCSParentPropertyType, @@ -27,8 +37,11 @@ def filterProp(self, name, listProp): def filterName(self, name, listProp): return name - def draw(self, layout, listProp, listIndex, cmdIndex, objName, collectionType): - layout.prop( + def draw(self, layout: UILayout, listProp: "OOTCSListProperty", listIndex: int, cmdIndex: int, objName: str, collectionType: str): + # Draws list elements + box = layout.box().column() + + box.prop( self, "expandTab", text=self.getName() + " " + str(cmdIndex), @@ -36,11 +49,12 @@ def draw(self, layout, listProp, listIndex, cmdIndex, objName, collectionType): ) if not self.expandTab: return - box = layout.box().column() + drawCollectionOps(box, cmdIndex, collectionType + "." + self.attrName, listIndex, objName) + for p in self.subprops: if self.filterProp(p, listProp): - prop_split(box, self, p, self.filterName(p, listProp)) + prop_split(box, self, p, ootCSSubPropToName[self.filterName(p, listProp)]) class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): @@ -51,7 +65,7 @@ class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): "ocarinaSongAction", "startFrame", "endFrame", - "type", + "csTextType", "topOptionBranch", "bottomOptionBranch", "ocarinaMessageId", @@ -64,6 +78,8 @@ class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): bottomOptionBranch: StringProperty(name="", default="0x0000") ocarinaMessageId: StringProperty(name="", default="0x0000") + csTextType: EnumProperty(name="Text Type", items=ootEnumTextType, default="CS_TEXT_NORMAL") + def getName(self): return self.textboxType @@ -96,8 +112,9 @@ class OOTCSTimeProperty(OOTCSProperty, PropertyGroup): class OOTCSBGMProperty(OOTCSProperty, PropertyGroup): propName = "BGM" attrName = "bgm" - subprops = ["value", "startFrame", "endFrame"] + subprops = ["csSeqID", "startFrame", "endFrame"] value: StringProperty(name="", default="0x0000") + csSeqID: EnumProperty(name="Seq ID", items=ootEnumMusicSeq, default="NA_BGM_GENERAL_SFX") def filterProp(self, name, listProp): return name != "endFrame" or listProp.listType == "FadeBGM" @@ -111,8 +128,9 @@ def filterName(self, name, listProp): class OOTCSMiscProperty(OOTCSProperty, PropertyGroup): propName = "Misc" attrName = "misc" - subprops = ["operation", "startFrame", "endFrame"] + subprops = ["csMiscType", "startFrame", "endFrame"] operation: IntProperty(name="", default=1, min=1, max=35) + csMiscType: EnumProperty(name="Type", items=ootEnumCSMiscType, default="CS_MISC_SET_LOCKED_VIEWPOINT") class OOTCS0x09Property(OOTCSProperty, PropertyGroup): @@ -124,24 +142,6 @@ class OOTCS0x09Property(OOTCSProperty, PropertyGroup): unk4: StringProperty(name="", default="0x00") -class OOTCSUnkProperty(OOTCSProperty, PropertyGroup): - propName = "Unk" - attrName = "unk" - subprops = ["unk1", "unk2", "unk3", "unk4", "unk5", "unk6", "unk7", "unk8", "unk9", "unk10", "unk11", "unk12"] - unk1: StringProperty(name="", default="0x00000000") - unk2: StringProperty(name="", default="0x00000000") - unk3: StringProperty(name="", default="0x00000000") - unk4: StringProperty(name="", default="0x00000000") - unk5: StringProperty(name="", default="0x00000000") - unk6: StringProperty(name="", default="0x00000000") - unk7: StringProperty(name="", default="0x00000000") - unk8: StringProperty(name="", default="0x00000000") - unk9: StringProperty(name="", default="0x00000000") - unk10: StringProperty(name="", default="0x00000000") - unk11: StringProperty(name="", default="0x00000000") - unk12: StringProperty(name="", default="0x00000000") - - class OOTCSListProperty(PropertyGroup): expandTab: BoolProperty(default=True) @@ -152,7 +152,6 @@ class OOTCSListProperty(PropertyGroup): bgm: CollectionProperty(type=OOTCSBGMProperty) misc: CollectionProperty(type=OOTCSMiscProperty) nine: CollectionProperty(type=OOTCS0x09Property) - unk: CollectionProperty(type=OOTCSUnkProperty) unkType: StringProperty(name="", default="0x0001") fxType: EnumProperty(items=ootEnumCSTransitionType) @@ -160,21 +159,26 @@ class OOTCSListProperty(PropertyGroup): fxEndFrame: IntProperty(name="", default=1, min=0) def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionType: str): - layout.prop( + box = layout.box().column() + + # Draw current command tab + box.prop( self, "expandTab", - text=self.listType + " List" if self.listType != "FX" else "Scene Trans FX", + text=self.listType + " List" if self.listType != "FX" else "Transition", icon="TRIA_DOWN" if self.expandTab else "TRIA_RIGHT", ) + if not self.expandTab: return - box = layout.box().column() + drawCollectionOps(box, listIndex, collectionType, None, objName, False) + # Draw current command content if self.listType == "Textbox": attrName = "textbox" elif self.listType == "FX": - prop_split(box, self, "fxType", "Transition") + prop_split(box, self, "fxType", "Transition Type") prop_split(box, self, "fxStartFrame", "Start Frame") prop_split(box, self, "fxEndFrame", "End Frame") return @@ -188,25 +192,23 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT attrName = "misc" elif self.listType == "0x09": attrName = "nine" - elif self.listType == "Unk": - prop_split(box, self, "unkType", "Unk List Type") - attrName = "unk" else: raise PluginError("Internal error: invalid listType " + self.listType) dat = getattr(self, attrName) - for i, p in enumerate(dat): - p.draw(box, self, listIndex, i, objName, collectionType) - if len(dat) == 0: - box.label(text="No items in " + self.listType + " List.") + if self.listType == "Textbox": - row = box.row(align=True) + subBox = box.box() + subBox.label(text="TextBox Commands") + row = subBox.row(align=True) + for l in range(3): addOp = row.operator( OOTCSTextboxAdd.bl_idname, text="Add " + ootEnumCSTextboxType[l][1], icon=ootEnumCSTextboxTypeIcons[l], ) + addOp.collectionType = collectionType + ".textbox" addOp.textboxType = ootEnumCSTextboxType[l][0] addOp.listIndex = listIndex @@ -218,28 +220,44 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT addOp.subIndex = listIndex addOp.objName = objName + for i, p in enumerate(dat): + p.draw(box, self, listIndex, i, objName, collectionType) + + if len(dat) == 0: + box.label(text="No items in " + self.listType + " List.") + class OOTCutsceneProperty(PropertyGroup): csEndFrame: IntProperty(name="End Frame", min=0, default=100) - csWriteTerminator: BoolProperty(name="Write Terminator (Code Execution)") + csWriteTerminator: BoolProperty(name="Cutscene Destination (Scene Change)") + csDestination: EnumProperty(name="Destination", items=ootEnumCSDestinationType) csTermIdx: IntProperty(name="Index", min=0) - csTermStart: IntProperty(name="Start Frm", min=0, default=99) - csTermEnd: IntProperty(name="End Frm", min=0, default=100) + csTermStart: IntProperty(name="Start Frame", min=0, default=99) + csTermEnd: IntProperty(name="End Frame", min=0, default=100) csLists: CollectionProperty(type=OOTCSListProperty, name="Cutscene Lists") def draw_props(self, layout: UILayout, obj: Object): layout.prop(self, "csEndFrame") - layout.prop(self, "csWriteTerminator") + + csDestLayout = layout.box() + csDestLayout.prop(self, "csWriteTerminator") if self.csWriteTerminator: - r = layout.row() - r.prop(self, "csTermIdx") + r = csDestLayout.row() + + searchBox = r.box().row() + searchOp = searchBox.operator(OOT_SearchCSDestinationEnumOperator.bl_idname, icon="VIEWZOOM", text="") + searchOp.objName = obj.name + searchBox.label(text=getEnumName(ootEnumCSDestinationType, self.csDestination)) + + r = csDestLayout.row() r.prop(self, "csTermStart") r.prop(self, "csTermEnd") - for i, p in enumerate(self.csLists): - p.draw_props(layout, p, i, obj.name, "Cutscene") drawCSListAddOp(layout, obj.name, "Cutscene") + for i, p in enumerate(self.csLists): + p.draw_props(layout, i, obj.name, "Cutscene") + classes = ( OOTCSTextboxProperty, @@ -248,7 +266,6 @@ def draw_props(self, layout: UILayout, obj: Object): OOTCSBGMProperty, OOTCSMiscProperty, OOTCS0x09Property, - OOTCSUnkProperty, OOTCSListProperty, OOTCutsceneProperty, ) diff --git a/fast64_internal/oot/oot_constants.py b/fast64_internal/oot/oot_constants.py index b456d59d0..a3d9cf169 100644 --- a/fast64_internal/oot/oot_constants.py +++ b/fast64_internal/oot/oot_constants.py @@ -190,113 +190,118 @@ ootEnumMusicSeq = [ ("Custom", "Custom", "Custom"), - ("0x02", "Hyrule Field", "Hyrule Field"), - ("0x03", "Hyrule Field (Initial Segment From Loading Area)", "Hyrule Field (Initial Segment From Loading Area)"), - ("0x04", "Hyrule Field (Moving Segment 1)", "Hyrule Field (Moving Segment 1)"), - ("0x05", "Hyrule Field (Moving Segment 2)", "Hyrule Field (Moving Segment 2)"), - ("0x06", "Hyrule Field (Moving Segment 3)", "Hyrule Field (Moving Segment 3)"), - ("0x07", "Hyrule Field (Moving Segment 4)", "Hyrule Field (Moving Segment 4)"), - ("0x08", "Hyrule Field (Moving Segment 5)", "Hyrule Field (Moving Segment 5)"), - ("0x09", "Hyrule Field (Moving Segment 6)", "Hyrule Field (Moving Segment 6)"), - ("0x0A", "Hyrule Field (Moving Segment 7)", "Hyrule Field (Moving Segment 7)"), - ("0x0B", "Hyrule Field (Moving Segment 8)", "Hyrule Field (Moving Segment 8)"), - ("0x0C", "Hyrule Field (Moving Segment 9)", "Hyrule Field (Moving Segment 9)"), - ("0x0D", "Hyrule Field (Moving Segment 10)", "Hyrule Field (Moving Segment 10)"), - ("0x0E", "Hyrule Field (Moving Segment 11)", "Hyrule Field (Moving Segment 11)"), - ("0x0F", "Hyrule Field (Enemy Approaches)", "Hyrule Field (Enemy Approaches)"), - ("0x10", "Hyrule Field (Enemy Near Segment 1)", "Hyrule Field (Enemy Near Segment 1)"), - ("0x11", "Hyrule Field (Enemy Near Segment 2)", "Hyrule Field (Enemy Near Segment 2)"), - ("0x12", "Hyrule Field (Enemy Near Segment 3)", "Hyrule Field (Enemy Near Segment 3)"), - ("0x13", "Hyrule Field (Enemy Near Segment 4)", "Hyrule Field (Enemy Near Segment 4)"), - ("0x14", "Hyrule Field (Standing Still Segment 1)", "Hyrule Field (Standing Still Segment 1)"), - ("0x15", "Hyrule Field (Standing Still Segment 2)", "Hyrule Field (Standing Still Segment 2)"), - ("0x16", "Hyrule Field (Standing Still Segment 3)", "Hyrule Field (Standing Still Segment 3)"), - ("0x17", "Hyrule Field (Standing Still Segment 4)", "Hyrule Field (Standing Still Segment 4)"), - ("0x18", "Dodongo's Cavern", "Dodongo's Cavern"), - ("0x19", "Kakariko Village (Adult)", "Kakariko Village (Adult)"), - ("0x1A", "Enemy Battle", "Enemy Battle"), - ("0x1B", "Boss Battle 00", "Boss Battle 00"), - ("0x1C", "Inside the Deku Tree", "Inside the Deku Tree"), - ("0x1D", "Market", "Market"), - ("0x1E", "Title Theme", "Title Theme"), - ("0x1F", "Link's House", "Link's House"), - ("0x20", "Game Over", "Game Over"), - ("0x21", "Boss Clear", "Boss Clear"), - ("0x22", "Item Get", "Item Get"), - ("0x23", "Opening Ganon", "Opening Ganon"), - ("0x24", "Heart Get", "Heart Get"), - ("0x25", "Prelude Of Light", "Prelude Of Light"), - ("0x26", "Inside Jabu-Jabu's Belly", "Inside Jabu-Jabu's Belly"), - ("0x27", "Kakariko Village (Child)", "Kakariko Village (Child)"), - ("0x28", "Great Fairy's Fountain", "Great Fairy's Fountain"), - ("0x29", "Zelda's Theme", "Zelda's Theme"), - ("0x2A", "Fire Temple", "Fire Temple"), - ("0x2B", "Open Treasure Chest", "Open Treasure Chest"), - ("0x2C", "Forest Temple", "Forest Temple"), - ("0x2D", "Hyrule Castle Courtyard", "Hyrule Castle Courtyard"), - ("0x2E", "Ganondorf's Theme", "Ganondorf's Theme"), - ("0x2F", "Lon Lon Ranch", "Lon Lon Ranch"), - ("0x30", "Goron City", "Goron City "), - ("0x31", "Hyrule Field Morning Theme", "Hyrule Field Morning Theme"), - ("0x32", "Spiritual Stone Get", "Spiritual Stone Get"), - ("0x33", "Bolero of Fire", "Bolero of Fire"), - ("0x34", "Minuet of Woods", "Minuet of Woods"), - ("0x35", "Serenade of Water", "Serenade of Water"), - ("0x36", "Requiem of Spirit", "Requiem of Spirit"), - ("0x37", "Nocturne of Shadow", "Nocturne of Shadow"), - ("0x38", "Mini-Boss Battle", "Mini-Boss Battle"), - ("0x39", "Obtain Small Item", "Obtain Small Item"), - ("0x3A", "Temple of Time", "Temple of Time"), - ("0x3B", "Escape from Lon Lon Ranch", "Escape from Lon Lon Ranch"), - ("0x3C", "Kokiri Forest", "Kokiri Forest"), - ("0x3D", "Obtain Fairy Ocarina", "Obtain Fairy Ocarina"), - ("0x3E", "Lost Woods", "Lost Woods"), - ("0x3F", "Spirit Temple", "Spirit Temple"), - ("0x40", "Horse Race", "Horse Race"), - ("0x41", "Horse Race Goal", "Horse Race Goal"), - ("0x42", "Ingo's Theme", "Ingo's Theme"), - ("0x43", "Obtain Medallion", "Obtain Medallion"), - ("0x44", "Ocarina Saria's Song", "Ocarina Saria's Song"), - ("0x45", "Ocarina Epona's Song", "Ocarina Epona's Song"), - ("0x46", "Ocarina Zelda's Lullaby", "Ocarina Zelda's Lullaby"), - ("0x47", "Sun's Song", "Sun's Song"), - ("0x48", "Song of Time", "Song of Time"), - ("0x49", "Song of Storms", "Song of Storms"), - ("0x4A", "Fairy Flying", "Fairy Flying"), - ("0x4B", "Deku Tree", "Deku Tree"), - ("0x4C", "Windmill Hut", "Windmill Hut"), - ("0x4D", "Legend of Hyrule", "Legend of Hyrule"), - ("0x4E", "Shooting Gallery", "Shooting Gallery"), - ("0x4F", "Sheik's Theme", "Sheik's Theme"), - ("0x50", "Zora's Domain", "Zora's Domain"), - ("0x51", "Enter Zelda", "Enter Zelda"), - ("0x52", "Goodbye to Zelda", "Goodbye to Zelda"), - ("0x53", "Master Sword", "Master Sword"), - ("0x54", "Ganon Intro", "Ganon Intro"), - ("0x55", "Shop", "Shop"), - ("0x56", "Chamber of the Sages", "Chamber of the Sages"), - ("0x57", "File Select", "File Select"), - ("0x58", "Ice Cavern", "Ice Cavern"), - ("0x59", "Open Door of Temple of Time", "Open Door of Temple of Time"), - ("0x5A", "Kaepora Gaebora's Theme", "Kaepora Gaebora's Theme"), - ("0x5B", "Shadow Temple", "Shadow Temple"), - ("0x5C", "Water Temple", "Water Temple"), - ("0x5D", "Ganon's Castle Bridge", "Ganon's Castle Bridge"), - ("0x5E", "Ocarina of Time", "Ocarina of Time"), - ("0x5F", "Gerudo Valley", "Gerudo Valley"), - ("0x60", "Potion Shop", "Potion Shop"), - ("0x61", "Kotake & Koume's Theme", "Kotake & Koume's Theme"), - ("0x62", "Escape from Ganon's Castle", "Escape from Ganon's Castle"), - ("0x63", "Ganon's Castle Under Ground", "Ganon's Castle Under Ground"), - ("0x64", "Ganondorf Battle", "Ganondorf Battle"), - ("0x65", "Ganon Battle", "Ganon Battle"), - ("0x66", "Seal of Six Sages", "Seal of Six Sages"), - ("0x67", "End Credits I", "End Credits I"), - ("0x68", "End Credits II", "End Credits II"), - ("0x69", "End Credits III", "End Credits III"), - ("0x6A", "End Credits IV", "End Credits IV"), - ("0x6B", "King Dodongo & Volvagia Boss Battle", "King Dodongo & Volvagia Boss Battle"), - ("0x6C", "Mini-Game", "Mini-Game"), + ("NA_BGM_GENERAL_SFX", "General Sound Effects", "General Sound Effects"), + ("NA_BGM_NATURE_AMBIENCE", "Nature Ambiance", "Nature Ambiance"), + ("NA_BGM_FIELD_LOGIC", "Hyrule Field", "Hyrule Field"), + ("NA_BGM_FIELD_INIT", "Hyrule Field (Initial Segment From Loading Area)", "Hyrule Field (Initial Segment From Loading Area)"), + ("NA_BGM_FIELD_DEFAULT_1", "Hyrule Field (Moving Segment 1)", "Hyrule Field (Moving Segment 1)"), + ("NA_BGM_FIELD_DEFAULT_2", "Hyrule Field (Moving Segment 2)", "Hyrule Field (Moving Segment 2)"), + ("NA_BGM_FIELD_DEFAULT_3", "Hyrule Field (Moving Segment 3)", "Hyrule Field (Moving Segment 3)"), + ("NA_BGM_FIELD_DEFAULT_4", "Hyrule Field (Moving Segment 4)", "Hyrule Field (Moving Segment 4)"), + ("NA_BGM_FIELD_DEFAULT_5", "Hyrule Field (Moving Segment 5)", "Hyrule Field (Moving Segment 5)"), + ("NA_BGM_FIELD_DEFAULT_6", "Hyrule Field (Moving Segment 6)", "Hyrule Field (Moving Segment 6)"), + ("NA_BGM_FIELD_DEFAULT_7", "Hyrule Field (Moving Segment 7)", "Hyrule Field (Moving Segment 7)"), + ("NA_BGM_FIELD_DEFAULT_8", "Hyrule Field (Moving Segment 8)", "Hyrule Field (Moving Segment 8)"), + ("NA_BGM_FIELD_DEFAULT_9", "Hyrule Field (Moving Segment 9)", "Hyrule Field (Moving Segment 9)"), + ("NA_BGM_FIELD_DEFAULT_A", "Hyrule Field (Moving Segment 10)", "Hyrule Field (Moving Segment 10)"), + ("NA_BGM_FIELD_DEFAULT_B", "Hyrule Field (Moving Segment 11)", "Hyrule Field (Moving Segment 11)"), + ("NA_BGM_FIELD_ENEMY_INIT", "Hyrule Field (Enemy Approaches)", "Hyrule Field (Enemy Approaches)"), + ("NA_BGM_FIELD_ENEMY_1", "Hyrule Field (Enemy Near Segment 1)", "Hyrule Field (Enemy Near Segment 1)"), + ("NA_BGM_FIELD_ENEMY_2", "Hyrule Field (Enemy Near Segment 2)", "Hyrule Field (Enemy Near Segment 2)"), + ("NA_BGM_FIELD_ENEMY_3", "Hyrule Field (Enemy Near Segment 3)", "Hyrule Field (Enemy Near Segment 3)"), + ("NA_BGM_FIELD_ENEMY_4", "Hyrule Field (Enemy Near Segment 4)", "Hyrule Field (Enemy Near Segment 4)"), + ("NA_BGM_FIELD_STILL_1", "Hyrule Field (Standing Still Segment 1)", "Hyrule Field (Standing Still Segment 1)"), + ("NA_BGM_FIELD_STILL_2", "Hyrule Field (Standing Still Segment 2)", "Hyrule Field (Standing Still Segment 2)"), + ("NA_BGM_FIELD_STILL_3", "Hyrule Field (Standing Still Segment 3)", "Hyrule Field (Standing Still Segment 3)"), + ("NA_BGM_FIELD_STILL_4", "Hyrule Field (Standing Still Segment 4)", "Hyrule Field (Standing Still Segment 4)"), + ("NA_BGM_DUNGEON", "Dodongo's Cavern", "Dodongo's Cavern"), + ("NA_BGM_KAKARIKO_ADULT", "Kakariko Village (Adult)", "Kakariko Village (Adult)"), + ("NA_BGM_ENEMY", "Enemy Battle", "Enemy Battle"), + ("NA_BGM_BOSS", "Boss Battle 00", "Boss Battle 00"), + ("NA_BGM_INSIDE_DEKU_TREE", "Inside the Deku Tree", "Inside the Deku Tree"), + ("NA_BGM_MARKET", "Market", "Market"), + ("NA_BGM_TITLE", "Title Theme", "Title Theme"), + ("NA_BGM_LINK_HOUSE", "Link's House", "Link's House"), + ("NA_BGM_GAME_OVER", "Game Over", "Game Over"), + ("NA_BGM_BOSS_CLEAR", "Boss Clear", "Boss Clear"), + ("NA_BGM_ITEM_GET", "Item Get", "Item Get"), + ("NA_BGM_OPENING_GANON", "Opening Ganon", "Opening Ganon"), + ("NA_BGM_HEART_GET", "Heart Get", "Heart Get"), + ("NA_BGM_OCA_LIGHT", "Prelude Of Light", "Prelude Of Light"), + ("NA_BGM_JABU_JABU", "Inside Jabu-Jabu's Belly", "Inside Jabu-Jabu's Belly"), + ("NA_BGM_KAKARIKO_KID", "Kakariko Village (Child)", "Kakariko Village (Child)"), + ("NA_BGM_GREAT_FAIRY", "Great Fairy's Fountain", "Great Fairy's Fountain"), + ("NA_BGM_ZELDA_THEME", "Zelda's Theme", "Zelda's Theme"), + ("NA_BGM_FIRE_TEMPLE", "Fire Temple", "Fire Temple"), + ("NA_BGM_OPEN_TRE_BOX", "Open Treasure Chest", "Open Treasure Chest"), + ("NA_BGM_FOREST_TEMPLE", "Forest Temple", "Forest Temple"), + ("NA_BGM_COURTYARD", "Hyrule Castle Courtyard", "Hyrule Castle Courtyard"), + ("NA_BGM_GANON_TOWER", "Ganondorf's Theme", "Ganondorf's Theme"), + ("NA_BGM_LONLON", "Lon Lon Ranch", "Lon Lon Ranch"), + ("NA_BGM_GORON_CITY", "Goron City", "Goron City"), + ("NA_BGM_FIELD_MORNING", "Hyrule Field Morning Theme", "Hyrule Field Morning Theme"), + ("NA_BGM_SPIRITUAL_STONE", "Spiritual Stone Get", "Spiritual Stone Get"), + ("NA_BGM_OCA_BOLERO", "Bolero of Fire", "Bolero of Fire"), + ("NA_BGM_OCA_MINUET", "Minuet of Woods", "Minuet of Woods"), + ("NA_BGM_OCA_SERENADE", "Serenade of Water", "Serenade of Water"), + ("NA_BGM_OCA_REQUIEM", "Requiem of Spirit", "Requiem of Spirit"), + ("NA_BGM_OCA_NOCTURNE", "Nocturne of Shadow", "Nocturne of Shadow"), + ("NA_BGM_MINI_BOSS", "Mini-Boss Battle", "Mini-Boss Battle"), + ("NA_BGM_SMALL_ITEM_GET", "Obtain Small Item", "Obtain Small Item"), + ("NA_BGM_TEMPLE_OF_TIME", "Temple of Time", "Temple of Time"), + ("NA_BGM_EVENT_CLEAR", "Escape from Lon Lon Ranch", "Escape from Lon Lon Ranch"), + ("NA_BGM_KOKIRI", "Kokiri Forest", "Kokiri Forest"), + ("NA_BGM_OCA_FAIRY_GET", "Obtain Fairy Ocarina", "Obtain Fairy Ocarina"), + ("NA_BGM_SARIA_THEME", "Lost Woods", "Lost Woods"), + ("NA_BGM_SPIRIT_TEMPLE", "Spirit Temple", "Spirit Temple"), + ("NA_BGM_HORSE", "Horse Race", "Horse Race"), + ("NA_BGM_HORSE_GOAL", "Horse Race Goal", "Horse Race Goal"), + ("NA_BGM_INGO", "Ingo's Theme", "Ingo's Theme"), + ("NA_BGM_MEDALLION_GET", "Obtain Medallion", "Obtain Medallion"), + ("NA_BGM_OCA_SARIA", "Ocarina Saria's Song", "Ocarina Saria's Song"), + ("NA_BGM_OCA_EPONA", "Ocarina Epona's Song", "Ocarina Epona's Song"), + ("NA_BGM_OCA_ZELDA", "Ocarina Zelda's Lullaby", "Ocarina Zelda's Lullaby"), + ("NA_BGM_OCA_SUNS", "Sun's Song", "Sun's Song"), + ("NA_BGM_OCA_TIME", "Song of Time", "Song of Time"), + ("NA_BGM_OCA_STORM", "Song of Storms", "Song of Storms"), + ("NA_BGM_NAVI_OPENING", "Fairy Flying", "Fairy Flying"), + ("NA_BGM_DEKU_TREE_CS", "Deku Tree", "Deku Tree"), + ("NA_BGM_WINDMILL", "Windmill Hut", "Windmill Hut"), + ("NA_BGM_HYRULE_CS", "Legend of Hyrule", "Legend of Hyrule"), + ("NA_BGM_MINI_GAME", "Shooting Gallery", "Shooting Gallery"), + ("NA_BGM_SHEIK", "Sheik's Theme", "Sheik's Theme"), + ("NA_BGM_ZORA_DOMAIN", "Zora's Domain", "Zora's Domain"), + ("NA_BGM_APPEAR", "Enter Zelda", "Enter Zelda"), + ("NA_BGM_ADULT_LINK", "Goodbye to Zelda", "Goodbye to Zelda"), + ("NA_BGM_MASTER_SWORD", "Master Sword", "Master Sword"), + ("NA_BGM_INTRO_GANON", "Ganon Intro", "Ganon Intro"), + ("NA_BGM_SHOP", "Shop", "Shop"), + ("NA_BGM_CHAMBER_OF_SAGES", "Chamber of the Sages", "Chamber of the Sages"), + ("NA_BGM_FILE_SELECT", "File Select", "File Select"), + ("NA_BGM_ICE_CAVERN", "Ice Cavern", "Ice Cavern"), + ("NA_BGM_DOOR_OF_TIME", "Open Door of Temple of Time", "Open Door of Temple of Time"), + ("NA_BGM_OWL", "Kaepora Gaebora's Theme", "Kaepora Gaebora's Theme"), + ("NA_BGM_SHADOW_TEMPLE", "Shadow Temple", "Shadow Temple"), + ("NA_BGM_WATER_TEMPLE", "Water Temple", "Water Temple"), + ("NA_BGM_BRIDGE_TO_GANONS", "Ganon's Castle Bridge", "Ganon's Castle Bridge"), + ("NA_BGM_OCARINA_OF_TIME", "Ocarina of Time", "Ocarina of Time"), + ("NA_BGM_GERUDO_VALLEY", "Gerudo Valley", "Gerudo Valley"), + ("NA_BGM_POTION_SHOP", "Potion Shop", "Potion Shop"), + ("NA_BGM_KOTAKE_KOUME", "Kotake & Koume's Theme", "Kotake & Koume's Theme"), + ("NA_BGM_ESCAPE", "Escape from Ganon's Castle", "Escape from Ganon's Castle"), + ("NA_BGM_UNDERGROUND", "Ganon's Castle Under Ground", "Ganon's Castle Under Ground"), + ("NA_BGM_GANONDORF_BOSS", "Ganondorf Battle", "Ganondorf Battle"), + ("NA_BGM_GANON_BOSS", "Ganon Battle", "Ganon Battle"), + ("NA_BGM_END_DEMO", "Seal of Six Sages", "Seal of Six Sages"), + ("NA_BGM_STAFF_1", "End Credits I", "End Credits I"), + ("NA_BGM_STAFF_2", "End Credits II", "End Credits II"), + ("NA_BGM_STAFF_3", "End Credits III", "End Credits III"), + ("NA_BGM_STAFF_4", "End Credits IV", "End Credits IV"), + ("NA_BGM_FIRE_BOSS", "King Dodongo & Volvagia Boss Battle", "King Dodongo & Volvagia Boss Battle"), + ("NA_BGM_TIMED_MINI_GAME", "Mini-Game", "Mini-Game"), + ("NA_BGM_CUTSCENE_EFFECTS", "Various Cutscene Sounds", "Various Cutscene Sounds"), + ("NA_BGM_NO_MUSIC", "No Music", "No Music"), + ("NA_BGM_NATURE_SFX_RAIN", "Nature Ambiance: Rain", "Nature Ambiance: Rain"), ] ootEnumNightSeq = [ diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index e182d9a1f..b1e2f927d 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -22,8 +22,6 @@ def ootCutsceneDataToC(csParent, csName): ) for list in csParent.csLists: data.source += "\t" + ootEnumCSListTypeListC[list.listType] + "(" - if list.listType == "Unk": - data.source += list.unkType + ", " if list.listType == "FX": data.source += list.fxType + ", " + str(list.fxStartFrame) + ", " + str(list.fxEndFrame) else: @@ -107,32 +105,6 @@ def ootCutsceneDataToC(csParent, csName): + e.unk4 + ", 0, 0" ) - elif list.listType == "Unk": - data.source += ( - e.unk1 - + ", " - + e.unk2 - + ", " - + e.unk3 - + ", " - + e.unk4 - + ", " - + e.unk5 - + ", " - + e.unk6 - + ", " - + e.unk7 - + ", " - + e.unk8 - + ", " - + e.unk9 - + ", " - + e.unk10 - + ", " - + e.unk11 - + ", " - + e.unk12 - ) else: raise PluginError("Internal error: invalid cutscene list type " + list.listType) data.source += "),\n" diff --git a/fast64_internal/oot/scene/operators.py b/fast64_internal/oot/scene/operators.py index 0c28b72f3..5c478b580 100644 --- a/fast64_internal/oot/scene/operators.py +++ b/fast64_internal/oot/scene/operators.py @@ -81,7 +81,7 @@ class OOT_SearchMusicSeqEnumOperator(Operator): bl_property = "ootMusicSeq" bl_options = {"REGISTER", "UNDO"} - ootMusicSeq: EnumProperty(items=ootEnumMusicSeq, default="0x02") + ootMusicSeq: EnumProperty(items=ootEnumMusicSeq, default="NA_BGM_FIELD_LOGIC") headerIndex: IntProperty(default=0, min=0) objName: StringProperty() diff --git a/fast64_internal/oot/scene/properties.py b/fast64_internal/oot/scene/properties.py index b81af4cc9..aaa03363d 100644 --- a/fast64_internal/oot/scene/properties.py +++ b/fast64_internal/oot/scene/properties.py @@ -250,7 +250,7 @@ class OOTSceneHeaderProperty(PropertyGroup): cameraMode: EnumProperty(name="Camera Mode", items=ootEnumCameraMode, default="0x00") cameraModeCustom: StringProperty(name="Camera Mode Custom", default="0x00") - musicSeq: EnumProperty(name="Music Sequence", items=ootEnumMusicSeq, default="0x02") + musicSeq: EnumProperty(name="Music Sequence", items=ootEnumMusicSeq, default="NA_BGM_FIELD_LOGIC") musicSeqCustom: StringProperty(name="Music Sequence ID", default="0x00") nightSeq: EnumProperty(name="Nighttime SFX", items=ootEnumNightSeq, default="0x00") nightSeqCustom: StringProperty(name="Nighttime SFX ID", default="0x00") @@ -371,9 +371,12 @@ def draw_props(self, layout: UILayout, dropdownLabel: str, headerIndex: int, obj r.prop(self, "csTermStart", text="Start Frm") r.prop(self, "csTermEnd", text="End Frm") collectionType = "CSHdr." + str(0 if headerIndex is None else headerIndex) + + drawCSListAddOp(cutscene, objName, collectionType) + for i, p in enumerate(self.csLists): p.draw_props(cutscene, i, objName, collectionType) - drawCSListAddOp(cutscene, objName, collectionType) + if headerIndex is None or headerIndex == 0: cutscene.label(text="Extra cutscenes (not in any header):") for i in range(len(self.extraCutscenes)): From cf807235eeb51c40be0ea8fce07ab54435ded25d Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Tue, 10 Jan 2023 17:48:02 +0100 Subject: [PATCH 02/39] cs C code cleanup + other UI tweaks --- fast64_internal/oot/cutscene/constants.py | 75 +++++++-- .../oot/cutscene/exporter/functions.py | 17 +- fast64_internal/oot/cutscene/properties.py | 43 ++++- fast64_internal/oot/oot_level_writer.py | 11 +- .../oot/scene/exporter/to_c/scene_cutscene.py | 159 +++++++----------- 5 files changed, 184 insertions(+), 121 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index b313bd1fa..6829e805c 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -19,7 +19,7 @@ ootEnumCSListTypeEntryC = { "Textbox": None, # special case "FX": None, # no list entries - "Lighting": "CS_LIGHTING", + "Lighting": "CS_LIGHT_SETTING", "Time": "CS_TIME", "PlayBGM": "CS_START_SEQ", "StopBGM": "CS_STOP_SEQ", @@ -63,22 +63,26 @@ ootEnumCSTextboxTypeIcons = ["FILE_TEXT", "HIDE_ON", "FILE_SOUND"] ootEnumCSTransitionType = [ - ("1", "To White +", "Also plays whiteout sound for certain scenes/entrances"), - ("2", "To Blue", "To Blue"), - ("3", "From Red", "From Red"), - ("4", "From Green", "From Green"), - ("5", "From White", "From White"), - ("6", "From Blue", "From Blue"), - ("7", "To Red", "To Red"), - ("8", "To Green", "To Green"), - ("9", "Set Unk", "gSaveContext.unk_1410 = 1, works with scene xn 11/17"), - ("10", "From Black", "From Black"), - ("11", "To Black", "To Black"), - ("12", "To Dim Unk", "Fade gSaveContext.unk_1410 255>100, works with scene xn 11/17"), - ("13", "From Dim", "Alpha 100>255"), + # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L219-L233 + ("Custom", "Custom", "Custom"), + ("CS_TRANS_GRAY_FILL_IN", "Gray Fill In", "Gray Fill In"), + ("CS_TRANS_BLUE_FILL_IN", "Blue Fill In", "Blue Fill In"), + ("CS_TRANS_RED_FILL_OUT", "Red Fill Out", "Red Fill Out"), + ("CS_TRANS_GREEN_FILL_OUT", "Green Fill Out", "Green Fill Out"), + ("CS_TRANS_GRAY_FILL_OUT", "Gray Fill Out", "Gray Fill Out"), + ("CS_TRANS_BLUE_FILL_OUT", "Blue Fill Out", "Blue Fill Out"), + ("CS_TRANS_RED_FILL_IN", "Red Fill In", "Red Fill In"), + ("CS_TRANS_GREEN_FILL_IN", "Green Fill In", "Green Fill In"), + ("CS_TRANS_TRIGGER_INSTANCE", "Trigger Instance", "Trigger Instance"), + ("CS_TRANS_BLACK_FILL_OUT", "Black Fill Out", "Black Fill Out"), + ("CS_TRANS_BLACK_FILL_IN", "Black Fill In", "Black Fill In"), + ("CS_TRANS_BLACK_FILL_OUT_TO_HALF", "Black Fill Out To Half", "Black Fill Out To Half"), + ("CS_TRANS_BLACK_FILL_IN_FROM_HALF", "Black Fill In From Half", "Black Fill In From Half"), ] ootEnumCSMiscType = [ + # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L167-L204 + ("Custom", "Custom", "Custom"), ("CS_MISC_SET_LOCKED_VIEWPOINT", "Set Locked Viewpoint", "Set Locked Viewpoint"), ("CS_MISC_SHOW_TITLE_CARD", "Show Area Title Card", "Show Area Title Card"), ("CS_MISC_RAIN", "Rain", "Rain"), @@ -115,6 +119,8 @@ ] ootEnumCSDestinationType = [ + # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L235-L356 + ("Custom", "Custom", "Custom"), ("CS_DEST_CUTSCENE_MAP_GANON_HORSE", "Cutscene Map Ganon Horse", "Cutscene Map Ganon Horse"), ("CS_DEST_CUTSCENE_MAP_THREE_GODDESSES", "Cutscene Map Three Goddesses", "Cutscene Map Three Goddesses"), ("CS_DEST_GERUDO_VALLEY_DIN_PART_1", "Gerudo Valley Din Part 1", "Gerudo Valley Din Part 1"), @@ -233,6 +239,7 @@ ] ootEnumTextType = [ + ("Custom", "Custom", "Custom"), ("CS_TEXT_NORMAL", "Normal Text", "Normal Text"), ("CS_TEXT_CHOICE", "Choice", "Choice"), ("CS_TEXT_OCARINA_ACTION", "Ocarina Action", "Ocarina Action"), @@ -240,13 +247,50 @@ ("CS_TEXT_ZORA_SAPPHIRE", "Zora Sapphire (use alt text)", "Zora Sapphire (use alt text)"), ] +ootEnumOcarinaAction = [ + # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64ocarina.h#L25-L76 + # note: "teach" and "playback" are the only types used in cutscenes but in theory every ones could be used + ("Custom", "Custom", "Custom"), + ("OCARINA_ACTION_TEACH_MINUET", "Teach Minuet", "Teach Minuet"), + ("OCARINA_ACTION_TEACH_BOLERO", "Teach Bolero", "Teach Bolero"), + ("OCARINA_ACTION_TEACH_SERENADE", "Teach Serenade", "Teach Serenade"), + ("OCARINA_ACTION_TEACH_REQUIEM", "Teach Requiem", "Teach Requiem"), + ("OCARINA_ACTION_TEACH_NOCTURNE", "Teach Nocturne", "Teach Nocturne"), + ("OCARINA_ACTION_TEACH_PRELUDE", "Teach Prelude", "Teach Prelude"), + ("OCARINA_ACTION_TEACH_SARIA", "Teach Saria", "Teach Saria"), + ("OCARINA_ACTION_TEACH_EPONA", "Teach Epona", "Teach Epona"), + ("OCARINA_ACTION_TEACH_LULLABY", "Teach Lullaby", "Teach Lullaby"), + ("OCARINA_ACTION_TEACH_SUNS", "Teach Suns", "Teach Suns"), + ("OCARINA_ACTION_TEACH_TIME", "Teach Time", "Teach Time"), + ("OCARINA_ACTION_TEACH_STORMS", "Teach Storms", "Teach Storms"), + ("OCARINA_ACTION_PLAYBACK_MINUET", "Play back Minuet", "Play back Minuet"), + ("OCARINA_ACTION_PLAYBACK_BOLERO", "Play back Bolero", "Play back Bolero"), + ("OCARINA_ACTION_PLAYBACK_SERENADE", "Play back Serenade", "Play back Serenade"), + ("OCARINA_ACTION_PLAYBACK_REQUIEM", "Play back Requiem", "Play back Requiem"), + ("OCARINA_ACTION_PLAYBACK_NOCTURNE", "Play back Nocturne", "Play back Nocturne"), + ("OCARINA_ACTION_PLAYBACK_PRELUDE", "Play back Prelude", "Play back Prelude"), + ("OCARINA_ACTION_PLAYBACK_SARIA", "Play back Saria", "Play back Saria"), + ("OCARINA_ACTION_PLAYBACK_EPONA", "Play back Epona", "Play back Epona"), + ("OCARINA_ACTION_PLAYBACK_LULLABY", "Play back Lullaby", "Play back Lullaby"), + ("OCARINA_ACTION_PLAYBACK_SUNS", "Play back Suns", "Play back Suns"), + ("OCARINA_ACTION_PLAYBACK_TIME", "Play back Time", "Play back Time"), + ("OCARINA_ACTION_PLAYBACK_STORMS", "Play back Storms", "Play back Storms"), +] + +ootEnumSeqPlayer = [ + # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L214-L217 + ("Custom", "Custom", "Custom"), + ("CS_FADE_OUT_FANFARE", "Fanfare", "Fanfare"), + ("CS_FADE_OUT_BGM_MAIN", "BGM Main", "BGM Main"), +] + ootCSSubPropToName = { "startFrame": "Start Frame", "endFrame": "End Frame", # TextBox "messageId": "Text ID", - "ocarinaSongAction": "Ocarina Action", + "ocarinaAction": "Ocarina Action", "csTextType": "Text Type", "topOptionBranch": "Text ID for Top Option", "bottomOptionBranch": "Text ID for Bottom Option", @@ -261,6 +305,7 @@ # BGM "csSeqID": "BGM ID", + "csSeqPlayer": "Seq Player Type", # Misc "csMiscType": "Misc Type", diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index c51a8a9b3..54d084a69 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -17,22 +17,24 @@ def readCutsceneData(csParentOut, csParentIn): for listIn in csParentIn.csLists: listOut = OOTCSList() listOut.listType = listIn.listType + listOut.unkType, listOut.fxType, listOut.fxStartFrame, listOut.fxEndFrame = ( listIn.unkType, - listIn.fxType, + getCustomProperty(listIn, "fxType"), listIn.fxStartFrame, listIn.fxEndFrame, ) + listData = [] if listOut.listType == "Textbox": for entryIn in listIn.textbox: entryOut = OOTCSTextbox() entryOut.textboxType = entryIn.textboxType entryOut.messageId = entryIn.messageId - entryOut.ocarinaSongAction = entryIn.ocarinaSongAction + entryOut.ocarinaSongAction = getCustomProperty(entryIn, "ocarinaAction") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame - entryOut.type = entryIn.type + entryOut.type = entryIn.csTextType entryOut.topOptionBranch = entryIn.topOptionBranch entryOut.bottomOptionBranch = entryIn.bottomOptionBranch entryOut.ocarinaMessageId = entryIn.ocarinaMessageId @@ -53,14 +55,15 @@ def readCutsceneData(csParentOut, csParentIn): elif listOut.listType in {"PlayBGM", "StopBGM", "FadeBGM"}: for entryIn in listIn.bgm: entryOut = OOTCSBGM() - entryOut.value = entryIn.value + csSeqPropSuffix = "ID" if listOut.listType != "FadeBGM" else "Player" + entryOut.value = getCustomProperty(entryIn, f"csSeq{csSeqPropSuffix}") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) elif listOut.listType == "Misc": for entryIn in listIn.misc: entryOut = OOTCSMisc() - entryOut.operation = entryIn.operation + entryOut.operation = getCustomProperty(entryIn, "csMiscType") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) @@ -77,12 +80,14 @@ def readCutsceneData(csParentOut, csParentIn): def convertCutsceneObject(obj): cs = OOTCutscene() + cs.name = getCutsceneName(obj) csprop = obj.ootCutsceneProperty cs.csEndFrame = getCustomProperty(csprop, "csEndFrame") cs.csWriteTerminator = getCustomProperty(csprop, "csWriteTerminator") - cs.csTermIdx = getCustomProperty(csprop, "csTermIdx") + cs.csTermIdx = getCustomProperty(csprop, "csDestination") cs.csTermStart = getCustomProperty(csprop, "csTermStart") cs.csTermEnd = getCustomProperty(csprop, "csTermEnd") readCutsceneData(cs, csprop) + return cs diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 3b938fab3..01f4e20ee 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -14,6 +14,8 @@ ootEnumCSMiscType, ootEnumTextType, ootCSSubPropToName, + ootEnumOcarinaAction, + ootEnumSeqPlayer, ) @@ -52,9 +54,28 @@ def draw(self, layout: UILayout, listProp: "OOTCSListProperty", listIndex: int, drawCollectionOps(box, cmdIndex, collectionType + "." + self.attrName, listIndex, objName) + print(self.subprops) for p in self.subprops: if self.filterProp(p, listProp): - prop_split(box, self, p, ootCSSubPropToName[self.filterName(p, listProp)]) + name = self.filterName(p, listProp) + displayName = ootCSSubPropToName[name] + + if name == "csSeqPlayer": + # change the property name to draw the other enum for fade seq command + p = name + + prop_split(box, self, p, displayName) + + customValues = [ + "csMiscType", + "csTextType", + "csDestination", + "ocarinaAction", + "csSeqID", + "csSeqPlayer", + ] + if name in customValues and getattr(self, p) == "Custom": + prop_split(box, self, f"{name}Custom", f"{displayName} Custom") class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): @@ -62,7 +83,7 @@ class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): attrName = "textbox" subprops = [ "messageId", - "ocarinaSongAction", + "ocarinaAction", "startFrame", "endFrame", "csTextType", @@ -73,12 +94,15 @@ class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): textboxType: EnumProperty(items=ootEnumCSTextboxType) messageId: StringProperty(name="", default="0x0000") ocarinaSongAction: StringProperty(name="", default="0x0000") + ocarinaAction: EnumProperty(name="Ocarina Action", items=ootEnumOcarinaAction, default="OCARINA_ACTION_TEACH_MINUET") + ocarinaActionCustom: StringProperty(default="OCARINA_ACTION_CUSTOM") type: StringProperty(name="", default="0x0000") topOptionBranch: StringProperty(name="", default="0x0000") bottomOptionBranch: StringProperty(name="", default="0x0000") ocarinaMessageId: StringProperty(name="", default="0x0000") csTextType: EnumProperty(name="Text Type", items=ootEnumTextType, default="CS_TEXT_NORMAL") + csTextTypeCustom: StringProperty(default="CS_TEXT_CUSTOM") def getName(self): return self.textboxType @@ -115,13 +139,16 @@ class OOTCSBGMProperty(OOTCSProperty, PropertyGroup): subprops = ["csSeqID", "startFrame", "endFrame"] value: StringProperty(name="", default="0x0000") csSeqID: EnumProperty(name="Seq ID", items=ootEnumMusicSeq, default="NA_BGM_GENERAL_SFX") + csSeqIDCustom: StringProperty(default="NA_BGM_CUSTOM") + csSeqPlayer: EnumProperty(name="Seq Player", items=ootEnumSeqPlayer, default="CS_FADE_OUT_BGM_MAIN") + csSeqPlayerCustom: StringProperty(default="NA_BGM_CUSTOM") def filterProp(self, name, listProp): return name != "endFrame" or listProp.listType == "FadeBGM" def filterName(self, name, listProp): - if name == "value": - return "Fade Type" if listProp.listType == "FadeBGM" else "Sequence" + if name == "csSeqID" and listProp.listType == "FadeBGM": + return "csSeqPlayer" return name @@ -131,6 +158,7 @@ class OOTCSMiscProperty(OOTCSProperty, PropertyGroup): subprops = ["csMiscType", "startFrame", "endFrame"] operation: IntProperty(name="", default=1, min=1, max=35) csMiscType: EnumProperty(name="Type", items=ootEnumCSMiscType, default="CS_MISC_SET_LOCKED_VIEWPOINT") + csMiscTypeCustom: StringProperty(default="CS_MISC_CUSTOM") class OOTCS0x09Property(OOTCSProperty, PropertyGroup): @@ -155,6 +183,7 @@ class OOTCSListProperty(PropertyGroup): unkType: StringProperty(name="", default="0x0001") fxType: EnumProperty(items=ootEnumCSTransitionType) + fxTypeCustom: StringProperty(default="CS_TRANS_CUSTOM") fxStartFrame: IntProperty(name="", default=0, min=0) fxEndFrame: IntProperty(name="", default=1, min=0) @@ -179,6 +208,9 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT attrName = "textbox" elif self.listType == "FX": prop_split(box, self, "fxType", "Transition Type") + if self.fxType == "Custom": + prop_split(box, self, "fxTypeCustom", "Transition Type Custom") + prop_split(box, self, "fxStartFrame", "Start Frame") prop_split(box, self, "fxEndFrame", "End Frame") return @@ -230,7 +262,8 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT class OOTCutsceneProperty(PropertyGroup): csEndFrame: IntProperty(name="End Frame", min=0, default=100) csWriteTerminator: BoolProperty(name="Cutscene Destination (Scene Change)") - csDestination: EnumProperty(name="Destination", items=ootEnumCSDestinationType) + csDestination: EnumProperty(name="Destination", items=ootEnumCSDestinationType, default="CS_DEST_CUTSCENE_MAP_GANON_HORSE") + csDestinationCustom: StringProperty(default="CS_DEST_CUSTOM") csTermIdx: IntProperty(name="Index", min=0) csTermStart: IntProperty(name="Start Frame", min=0, default=99) csTermEnd: IntProperty(name="End Frame", min=0, default=100) diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index a4b83d3be..8abfcb314 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -1,6 +1,7 @@ import bpy, os, math, mathutils from ..f3d.f3d_gbi import TextureExportSettings from ..f3d.f3d_writer import TriangleConverterInfo, saveStaticModel, getInfoDict +from .scene.properties import OOTSceneProperties, OOTSceneHeaderProperty, OOTAlternateSceneHeaderProperty from .room.properties import OOTRoomHeaderProperty, OOTAlternateRoomHeaderProperty from .oot_constants import ootData from .cutscene.exporter import convertCutsceneObject, readCutsceneData @@ -230,7 +231,12 @@ def writeOtherSceneProperties(scene, exportInfo, levelC): modifySceneFiles(scene, exportInfo) -def readSceneData(scene, scene_properties, sceneHeader, alternateSceneHeaders): +def readSceneData( + scene: OOTScene, + scene_properties: OOTSceneProperties, + sceneHeader: OOTSceneHeaderProperty, + alternateSceneHeaders: OOTAlternateSceneHeaderProperty +): scene.write_dummy_room_list = scene_properties.write_dummy_room_list scene.sceneTableEntry.drawConfig = getCustomProperty(sceneHeader.sceneTableEntry, "drawConfig") scene.globalObject = getCustomProperty(sceneHeader, "globalObject") @@ -265,6 +271,7 @@ def readSceneData(scene, scene_properties, sceneHeader, alternateSceneHeaders): scene.writeCutscene = getCustomProperty(sceneHeader, "writeCutscene") if scene.writeCutscene: scene.csWriteType = getattr(sceneHeader, "csWriteType") + if scene.csWriteType == "Embedded": scene.csEndFrame = getCustomProperty(sceneHeader, "csEndFrame") scene.csWriteTerminator = getCustomProperty(sceneHeader, "csWriteTerminator") @@ -272,8 +279,10 @@ def readSceneData(scene, scene_properties, sceneHeader, alternateSceneHeaders): scene.csTermStart = getCustomProperty(sceneHeader, "csTermStart") scene.csTermEnd = getCustomProperty(sceneHeader, "csTermEnd") readCutsceneData(scene, sceneHeader) + elif scene.csWriteType == "Custom": scene.csWriteCustom = getCustomProperty(sceneHeader, "csWriteCustom") + elif scene.csWriteType == "Object": if sceneHeader.csWriteObject is None: raise PluginError("No object selected for cutscene reference") diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index b1e2f927d..241f436e5 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -1,116 +1,87 @@ -from .....utility import CData, PluginError +from .....utility import CData, PluginError, indent from ....oot_level_classes import OOTScene from ....cutscene.constants import ootEnumCSTextboxTypeEntryC, ootEnumCSListTypeListC, ootEnumCSListTypeEntryC +from ....cutscene.exporter import OOTCutscene -def ootCutsceneDataToC(csParent, csName): - # csParent can be OOTCutscene or OOTScene - data = CData() - data.header = "extern CutsceneData " + csName + "[];\n" - data.source = "CutsceneData " + csName + "[] = {\n" +def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): + csData = CData() + arrayName = f"CutsceneData {csName}[]" nentries = len(csParent.csLists) + (1 if csParent.csWriteTerminator else 0) - data.source += "\tCS_BEGIN_CUTSCENE(" + str(nentries) + ", " + str(csParent.csEndFrame) + "),\n" - if csParent.csWriteTerminator: - data.source += ( - "\tCS_TERMINATOR(" - + str(csParent.csTermIdx) - + ", " - + str(csParent.csTermStart) - + ", " - + str(csParent.csTermEnd) - + "),\n" + + # .h + csData.header = f"extern {arrayName};\n" + + # .c + csData.source = ( + arrayName + " = {\n" + + (indent + f"CS_BEGIN_CUTSCENE({nentries}, {csParent.csEndFrame}),\n") + + ( + (indent * 2) + f"CS_DESTINATION({csParent.csTermIdx}, {csParent.csTermStart}, {csParent.csTermEnd}),\n" + if csParent.csWriteTerminator else "" ) + ) + for list in csParent.csLists: - data.source += "\t" + ootEnumCSListTypeListC[list.listType] + "(" - if list.listType == "FX": - data.source += list.fxType + ", " + str(list.fxStartFrame) + ", " + str(list.fxEndFrame) - else: - data.source += str(len(list.entries)) - data.source += "),\n" + # CS "XXXX List" Command + csData.source += ( + (indent * 2) + ootEnumCSListTypeListC[list.listType] + "(" + + ( + f"{list.fxType}, {list.fxStartFrame}, {list.fxEndFrame}" + if list.listType == "FX" else str(len(list.entries)) + ) + + "),\n" + ) + for e in list.entries: - data.source += "\t\t" - if list.listType == "Textbox": - data.source += ootEnumCSTextboxTypeEntryC[e.textboxType] - else: - data.source += ootEnumCSListTypeEntryC[list.listType] - data.source += "(" + csData.source += ( + indent * 3 + + ( + ootEnumCSTextboxTypeEntryC[e.textboxType] + if list.listType == "Textbox" else ootEnumCSListTypeEntryC[list.listType] + ) + + "(" + ) + if list.listType == "Textbox": if e.textboxType == "Text": - data.source += ( - e.messageId - + ", " - + str(e.startFrame) - + ", " - + str(e.endFrame) - + ", " - + e.type - + ", " - + e.topOptionBranch - + ", " - + e.bottomOptionBranch + csData.source += ( + f"{e.messageId}, {e.startFrame}, {e.endFrame}, {e.type}, {e.topOptionBranch}, {e.bottomOptionBranch}" ) + elif e.textboxType == "None": - data.source += str(e.startFrame) + ", " + str(e.endFrame) + csData.source += f"{e.startFrame}, {e.endFrame}" + elif e.textboxType == "LearnSong": - data.source += ( - e.ocarinaSongAction - + ", " - + str(e.startFrame) - + ", " - + str(e.endFrame) - + ", " - + e.ocarinaMessageId - ) + csData.source += f"{e.ocarinaSongAction}, {e.startFrame}, {e.endFrame}, {e.ocarinaMessageId}" + elif list.listType == "Lighting": - data.source += ( - str(e.index) + ", " + str(e.startFrame) + ", " + str(e.startFrame + 1) + ", 0, 0, 0, 0, 0, 0, 0, 0" - ) + # the endFrame variable is not used in the implementation of the commend + # so the value doesn't matter + csData.source += f"{e.index}, {e.startFrame}" + (", 0" * 9) + elif list.listType == "Time": - data.source += ( - "1, " - + str(e.startFrame) - + ", " - + str(e.startFrame + 1) - + ", " - + str(e.hour) - + ", " - + str(e.minute) - + ", 0" - ) + # same as above + csData.source += f"0, {e.startFrame}, 0, {e.hour}, {e.minute}" + + elif list.listType == "0x09": # rumble command + # same as above + csData.source += f"0, {e.startFrame}, 0, {e.unk2}, {e.unk3}, {e.unk4}, 0, 0" + elif list.listType in ["PlayBGM", "StopBGM", "FadeBGM"]: - data.source += e.value - if list.listType != "FadeBGM": - data.source += " + 1" # Game subtracts 1 to get actual seq - data.source += ", " + str(e.startFrame) + ", " + str(e.endFrame) + ", 0, 0, 0, 0, 0, 0, 0, 0" + endFrame = e.endFrame if list.listType == "FadeBGM" else "0" + csData.source += f"{e.value}, {e.startFrame}, {endFrame}" + (", 0" * 8) + elif list.listType == "Misc": - data.source += ( - str(e.operation) - + ", " - + str(e.startFrame) - + ", " - + str(e.endFrame) - + ", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0" - ) - elif list.listType == "0x09": - data.source += ( - "0, " - + str(e.startFrame) - + ", " - + str(e.startFrame + 1) - + ", " - + e.unk2 - + ", " - + e.unk3 - + ", " - + e.unk4 - + ", 0, 0" - ) + csData.source += f"{e.operation}, {e.startFrame}, {e.endFrame}" + (", 0" * 11) + else: raise PluginError("Internal error: invalid cutscene list type " + list.listType) - data.source += "),\n" - data.source += "\tCS_END(),\n" - data.source += "};\n\n" - return data + + csData.source += "),\n" + + csData.source += indent + "CS_END(),\n};\n\n" + return csData def getSceneCutscenes(outScene: OOTScene): From 44df89f17f01cfa357b40f8a847534cf187cec1e Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:00:14 +0100 Subject: [PATCH 03/39] fixed cs dest custom now showing --- fast64_internal/oot/cutscene/properties.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 01f4e20ee..dac0b1645 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -69,7 +69,6 @@ def draw(self, layout: UILayout, listProp: "OOTCSListProperty", listIndex: int, customValues = [ "csMiscType", "csTextType", - "csDestination", "ocarinaAction", "csSeqID", "csSeqPlayer", @@ -277,10 +276,13 @@ def draw_props(self, layout: UILayout, obj: Object): if self.csWriteTerminator: r = csDestLayout.row() - searchBox = r.box().row() - searchOp = searchBox.operator(OOT_SearchCSDestinationEnumOperator.bl_idname, icon="VIEWZOOM", text="") + searchBox = r.box() + boxRow = searchBox.row() + searchOp = boxRow.operator(OOT_SearchCSDestinationEnumOperator.bl_idname, icon="VIEWZOOM", text="") searchOp.objName = obj.name - searchBox.label(text=getEnumName(ootEnumCSDestinationType, self.csDestination)) + boxRow.label(text=getEnumName(ootEnumCSDestinationType, self.csDestination)) + if self.csDestination == "Custom": + prop_split(searchBox.column(), self, "csDestinationCustom", "Cutscene Destination Custom") r = csDestLayout.row() r.prop(self, "csTermStart") From db12ad56e30636912a9da8f0b276dd42df1e0c65 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:13:48 +0100 Subject: [PATCH 04/39] fixes for ocarina action enum & cs_text --- fast64_internal/oot/cutscene/exporter/functions.py | 2 +- fast64_internal/oot/cutscene/properties.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index 54d084a69..1874945c4 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -34,7 +34,7 @@ def readCutsceneData(csParentOut, csParentIn): entryOut.ocarinaSongAction = getCustomProperty(entryIn, "ocarinaAction") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame - entryOut.type = entryIn.csTextType + entryOut.type = getCustomProperty(entryIn, "csTextType") entryOut.topOptionBranch = entryIn.topOptionBranch entryOut.bottomOptionBranch = entryIn.bottomOptionBranch entryOut.ocarinaMessageId = entryIn.ocarinaMessageId diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index dac0b1645..30289056e 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -108,11 +108,11 @@ def getName(self): def filterProp(self, name, listProp): if self.textboxType == "Text": - return name not in ["ocarinaSongAction", "ocarinaMessageId"] + return name not in ["ocarinaAction", "ocarinaMessageId"] elif self.textboxType == "None": return name in ["startFrame", "endFrame"] elif self.textboxType == "LearnSong": - return name in ["ocarinaSongAction", "startFrame", "endFrame", "ocarinaMessageId"] + return name in ["ocarinaAction", "startFrame", "endFrame", "ocarinaMessageId"] else: raise PluginError("Invalid property name for OOTCSTextboxProperty") From 35628f587025bd47305d3b978e359b5b9a71be9d Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:21:37 +0100 Subject: [PATCH 05/39] remove debug print --- fast64_internal/oot/cutscene/properties.py | 1 - 1 file changed, 1 deletion(-) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 30289056e..f7c83bb86 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -54,7 +54,6 @@ def draw(self, layout: UILayout, listProp: "OOTCSListProperty", listIndex: int, drawCollectionOps(box, cmdIndex, collectionType + "." + self.attrName, listIndex, objName) - print(self.subprops) for p in self.subprops: if self.filterProp(p, listProp): name = self.filterName(p, listProp) From 091c7240c068b7203a3393f4bcc9572a68886a33 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Thu, 12 Jan 2023 18:39:23 +0100 Subject: [PATCH 06/39] wip upgrade system --- fast64_internal/oot/cutscene/constants.py | 1 + fast64_internal/oot/cutscene/properties.py | 1 + fast64_internal/oot/oot_upgrade.py | 70 ++++++++++++++++++++++ fast64_internal/oot/room/properties.py | 5 +- 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 6829e805c..abefce6be 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -239,6 +239,7 @@ ] ootEnumTextType = [ + # see https://github.com/zeldaret/oot/blob/542012efa68d110d6b631f9d149f6e5f4e68cc8e/include/z64cutscene.h#L206-L212 ("Custom", "Custom", "Custom"), ("CS_TEXT_NORMAL", "Normal Text", "Normal Text"), ("CS_TEXT_CHOICE", "Choice", "Choice"), diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index f7c83bb86..fa98a6520 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -160,6 +160,7 @@ class OOTCSMiscProperty(OOTCSProperty, PropertyGroup): class OOTCS0x09Property(OOTCSProperty, PropertyGroup): + # see https://github.com/zeldaret/oot/blob/542012efa68d110d6b631f9d149f6e5f4e68cc8e/src/code/z_rumble.c#L58-L77 propName = "0x09" attrName = "nine" subprops = ["startFrame", "unk2", "unk3", "unk4"] diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 945458dcc..bc68ae6d2 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -1,5 +1,12 @@ from bpy.types import Object, CollectionProperty from .data import OoT_ObjectData +from .oot_utility import getEvalParams +from .oot_constants import ootEnumMusicSeq +from .cutscene.constants import ( + ootEnumCSTextboxType, + ootEnumCSMiscType, + ootEnumOcarinaAction, +) def upgradeObjectList(objList: CollectionProperty, objData: OoT_ObjectData): @@ -35,3 +42,66 @@ def upgradeRoomHeaders(roomObj: Object, objData: OoT_ObjectData): upgradeObjectList(sceneLayer.objectList, objData) for i in range(len(altHeaders.cutsceneHeaders)): upgradeObjectList(altHeaders.cutsceneHeaders[i].objectList, objData) + + +def upgradeCutsceneProperties(csObj: Object): + # based on ``upgradeObjectList`` + + oldNamesToNewNames = { + # TextBox + "messageId": "textID", + "topOptionBranch": "topOptionTextID", + "bottomOptionBranch": "bottomOptionTextID", + + # Lighting + "index": "lightSettingsIndex", + + # Rumble + "unk2": "rumbleSourceStrength", + "unk3": "rumbleDuration", + "unk4": "rumbleDecreaseRate", + } + + differentPropsData = [ + # TextBox + ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction) + ("type", "textboxType", ootEnumCSTextboxType) + + # BGM + ("value", "csSeqID", ootEnumMusicSeq), + + # Misc + ("operation", "csMiscType", ootEnumCSMiscType), + ] + + + # conversion to the same prop type + # simply transfer the old data to the new one + for oldName, newName in oldNamesToNewNames.items(): + if oldName in csObj: + csObj[newName] = csObj[oldName] + + del csObj[oldName] + + # conversion to another prop type + for (oldName, newName, enumList) in differentPropsData: + if oldName in csObj: + # get the old data + oldData = csObj[oldName] + + # if anything goes wrong there set the value to custom to avoid any data loss + try: + # get the value, doing an eval for strings + value = int(getEvalParams(oldData), base=16) + + # if the value is in the list find the identifier + if value < len(enumList): + setattr(csObj, newName, enumList[value][0]) + else: + # else raise an error to default to custom + raise IndexError + except: + setattr(csObj, newName, "Custom") + setattr(csObj, f"{newName}Custom", oldData) + + del csObj[oldName] diff --git a/fast64_internal/oot/room/properties.py b/fast64_internal/oot/room/properties.py index 1ad2c4437..5f0a05d36 100644 --- a/fast64_internal/oot/room/properties.py +++ b/fast64_internal/oot/room/properties.py @@ -3,7 +3,7 @@ from bpy.utils import register_class, unregister_class from ...utility import prop_split from ..oot_utility import drawCollectionOps, onMenuTabChange, onHeaderMenuTabChange, drawEnumWithCustom, drawAddButton -from ..oot_upgrade import upgradeRoomHeaders +from ..oot_upgrade import upgradeRoomHeaders, upgradeCutsceneProperties from .operators import OOT_SearchObjectEnumOperator from bpy.props import ( @@ -38,6 +38,9 @@ def upgrade_object(obj): print(f"Processing '{obj.name}'...") upgradeRoomHeaders(obj, ootData.objectData) + # if obj.type == "EMPTY" and obj.ootEmptyType == "Cutscene": + # upgradeCutsceneProperties(obj) + def draw_props(self, layout: UILayout, headerIndex: int, index: int, objName: str): isLegacy = True if "objectID" in self else False From c9db27483a3d7865cd6c312a9d92e45a5cdbe6bb Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Thu, 12 Jan 2023 19:13:12 +0100 Subject: [PATCH 07/39] renamed subprops --- fast64_internal/oot/cutscene/constants.py | 14 +++---- .../oot/cutscene/exporter/classes.py | 29 +++++++------- .../oot/cutscene/exporter/functions.py | 25 ++++++------ fast64_internal/oot/cutscene/properties.py | 39 +++++++++---------- fast64_internal/oot/oot_upgrade.py | 12 ++++-- .../oot/scene/exporter/to_c/scene_cutscene.py | 12 +++--- 6 files changed, 66 insertions(+), 65 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index abefce6be..edc6b43be 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -290,15 +290,15 @@ "endFrame": "End Frame", # TextBox - "messageId": "Text ID", + "textID": "Text ID", "ocarinaAction": "Ocarina Action", "csTextType": "Text Type", - "topOptionBranch": "Text ID for Top Option", - "bottomOptionBranch": "Text ID for Bottom Option", + "topOptionTextID": "Text ID for Top Option", + "bottomOptionTextID": "Text ID for Bottom Option", "ocarinaMessageId": "Ocarina Message ID", # Lighting - "index": "Light Settings Index", + "lightSettingsIndex": "Light Settings Index", # Time "hour": "Hour", @@ -312,7 +312,7 @@ "csMiscType": "Misc Type", # Rumble - "unk2": "Source Strength", - "unk3": "Duration", - "unk4": "Decrease Rate", + "rumbleSourceStrength": "Source Strength", + "rumbleDuration": "Duration", + "rumbleDecreaseRate": "Decrease Rate", } diff --git a/fast64_internal/oot/cutscene/exporter/classes.py b/fast64_internal/oot/cutscene/exporter/classes.py index d5e637713..de3bae87d 100644 --- a/fast64_internal/oot/cutscene/exporter/classes.py +++ b/fast64_internal/oot/cutscene/exporter/classes.py @@ -1,19 +1,19 @@ class OOTCSTextbox: def __init__(self): self.textboxType = None - self.messageId = "0x0000" - self.ocarinaSongAction = "0x0000" + self.textID = "0x0000" + self.ocarinaAction = "0x0000" self.startFrame = 0 self.endFrame = 1 - self.type = "0x0000" - self.topOptionBranch = "0x0000" - self.bottomOptionBranch = "0x0000" + self.textboxType = "0x0000" + self.topOptionTextID = "0x0000" + self.bottomOptionTextID = "0x0000" self.ocarinaMessageId = "0x0000" class OOTCSLighting: def __init__(self): - self.index = 1 + self.lightSettingsIndex = 1 self.startFrame = 0 @@ -26,14 +26,14 @@ def __init__(self): class OOTCSBGM: def __init__(self): - self.value = "0x0000" + self.csSeqID = "0x0000" self.startFrame = 0 self.endFrame = 1 class OOTCSMisc: def __init__(self): - self.operation = 1 + self.csMiscType = 1 self.startFrame = 0 self.endFrame = 1 @@ -41,17 +41,17 @@ def __init__(self): class OOTCS0x09: def __init__(self): self.startFrame = 0 - self.unk2 = "0x00" - self.unk3 = "0x00" - self.unk4 = "0x00" + self.rumbleSourceStrength = "0x00" + self.rumbleDuration = "0x00" + self.rumbleDecreaseRate = "0x00" class OOTCSUnk: def __unk__(self): self.unk1 = "0x00000000" - self.unk2 = "0x00000000" - self.unk3 = "0x00000000" - self.unk4 = "0x00000000" + self.rumbleSourceStrength = "0x00000000" + self.rumbleDuration = "0x00000000" + self.rumbleDecreaseRate = "0x00000000" self.unk5 = "0x00000000" self.unk6 = "0x00000000" self.unk7 = "0x00000000" @@ -66,7 +66,6 @@ class OOTCSList: def __init__(self): self.listType = None self.entries = [] - self.unkType = "0x0001" self.fxType = "1" self.fxStartFrame = 0 self.fxEndFrame = 0 diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index 1874945c4..9dc1d87f5 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -18,8 +18,7 @@ def readCutsceneData(csParentOut, csParentIn): listOut = OOTCSList() listOut.listType = listIn.listType - listOut.unkType, listOut.fxType, listOut.fxStartFrame, listOut.fxEndFrame = ( - listIn.unkType, + listOut.fxType, listOut.fxStartFrame, listOut.fxEndFrame = ( getCustomProperty(listIn, "fxType"), listIn.fxStartFrame, listIn.fxEndFrame, @@ -30,19 +29,19 @@ def readCutsceneData(csParentOut, csParentIn): for entryIn in listIn.textbox: entryOut = OOTCSTextbox() entryOut.textboxType = entryIn.textboxType - entryOut.messageId = entryIn.messageId - entryOut.ocarinaSongAction = getCustomProperty(entryIn, "ocarinaAction") + entryOut.textID = entryIn.textID + entryOut.ocarinaAction = getCustomProperty(entryIn, "ocarinaAction") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame - entryOut.type = getCustomProperty(entryIn, "csTextType") - entryOut.topOptionBranch = entryIn.topOptionBranch - entryOut.bottomOptionBranch = entryIn.bottomOptionBranch + entryOut.textboxType = getCustomProperty(entryIn, "csTextType") + entryOut.topOptionTextID = entryIn.topOptionTextID + entryOut.bottomOptionTextID = entryIn.bottomOptionTextID entryOut.ocarinaMessageId = entryIn.ocarinaMessageId listOut.entries.append(entryOut) elif listOut.listType == "Lighting": for entryIn in listIn.lighting: entryOut = OOTCSLighting() - entryOut.index = entryIn.index + entryOut.lightSettingsIndex = entryIn.lightSettingsIndex entryOut.startFrame = entryIn.startFrame listOut.entries.append(entryOut) elif listOut.listType == "Time": @@ -56,14 +55,14 @@ def readCutsceneData(csParentOut, csParentIn): for entryIn in listIn.bgm: entryOut = OOTCSBGM() csSeqPropSuffix = "ID" if listOut.listType != "FadeBGM" else "Player" - entryOut.value = getCustomProperty(entryIn, f"csSeq{csSeqPropSuffix}") + entryOut.csSeqID = getCustomProperty(entryIn, f"csSeq{csSeqPropSuffix}") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) elif listOut.listType == "Misc": for entryIn in listIn.misc: entryOut = OOTCSMisc() - entryOut.operation = getCustomProperty(entryIn, "csMiscType") + entryOut.csMiscType = getCustomProperty(entryIn, "csMiscType") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) @@ -71,9 +70,9 @@ def readCutsceneData(csParentOut, csParentIn): for entryIn in listIn.nine: entryOut = OOTCS0x09() entryOut.startFrame = entryIn.startFrame - entryOut.unk2 = entryIn.unk2 - entryOut.unk3 = entryIn.unk3 - entryOut.unk4 = entryIn.unk4 + entryOut.rumbleSourceStrength = entryIn.rumbleSourceStrength + entryOut.rumbleDuration = entryIn.rumbleDuration + entryOut.rumbleDecreaseRate = entryIn.rumbleDecreaseRate listOut.entries.append(entryOut) csParentOut.csLists.append(listOut) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index fa98a6520..8b6a5d7e8 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -80,23 +80,21 @@ class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): propName = "Textbox" attrName = "textbox" subprops = [ - "messageId", + "textID", "ocarinaAction", "startFrame", "endFrame", "csTextType", - "topOptionBranch", - "bottomOptionBranch", + "topOptionTextID", + "bottomOptionTextID", "ocarinaMessageId", ] textboxType: EnumProperty(items=ootEnumCSTextboxType) - messageId: StringProperty(name="", default="0x0000") - ocarinaSongAction: StringProperty(name="", default="0x0000") + textID: StringProperty(name="", default="0x0000") ocarinaAction: EnumProperty(name="Ocarina Action", items=ootEnumOcarinaAction, default="OCARINA_ACTION_TEACH_MINUET") ocarinaActionCustom: StringProperty(default="OCARINA_ACTION_CUSTOM") - type: StringProperty(name="", default="0x0000") - topOptionBranch: StringProperty(name="", default="0x0000") - bottomOptionBranch: StringProperty(name="", default="0x0000") + topOptionTextID: StringProperty(name="", default="0x0000") + bottomOptionTextID: StringProperty(name="", default="0x0000") ocarinaMessageId: StringProperty(name="", default="0x0000") csTextType: EnumProperty(name="Text Type", items=ootEnumTextType, default="CS_TEXT_NORMAL") @@ -119,8 +117,8 @@ def filterProp(self, name, listProp): class OOTCSLightingProperty(OOTCSProperty, PropertyGroup): propName = "Lighting" attrName = "lighting" - subprops = ["index", "startFrame"] - index: IntProperty(name="", default=1, min=1) + subprops = ["lightSettingsIndex", "startFrame"] + lightSettingsIndex: IntProperty(name="", default=1, min=1) class OOTCSTimeProperty(OOTCSProperty, PropertyGroup): @@ -135,7 +133,6 @@ class OOTCSBGMProperty(OOTCSProperty, PropertyGroup): propName = "BGM" attrName = "bgm" subprops = ["csSeqID", "startFrame", "endFrame"] - value: StringProperty(name="", default="0x0000") csSeqID: EnumProperty(name="Seq ID", items=ootEnumMusicSeq, default="NA_BGM_GENERAL_SFX") csSeqIDCustom: StringProperty(default="NA_BGM_CUSTOM") csSeqPlayer: EnumProperty(name="Seq Player", items=ootEnumSeqPlayer, default="CS_FADE_OUT_BGM_MAIN") @@ -154,19 +151,20 @@ class OOTCSMiscProperty(OOTCSProperty, PropertyGroup): propName = "Misc" attrName = "misc" subprops = ["csMiscType", "startFrame", "endFrame"] - operation: IntProperty(name="", default=1, min=1, max=35) csMiscType: EnumProperty(name="Type", items=ootEnumCSMiscType, default="CS_MISC_SET_LOCKED_VIEWPOINT") csMiscTypeCustom: StringProperty(default="CS_MISC_CUSTOM") -class OOTCS0x09Property(OOTCSProperty, PropertyGroup): - # see https://github.com/zeldaret/oot/blob/542012efa68d110d6b631f9d149f6e5f4e68cc8e/src/code/z_rumble.c#L58-L77 +class OOTCSRumbleProperty(OOTCSProperty, PropertyGroup): propName = "0x09" attrName = "nine" - subprops = ["startFrame", "unk2", "unk3", "unk4"] - unk2: StringProperty(name="", default="0x00") - unk3: StringProperty(name="", default="0x00") - unk4: StringProperty(name="", default="0x00") + subprops = ["startFrame", "rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"] + + # those variables are unsigned chars in decomp + # see https://github.com/zeldaret/oot/blob/542012efa68d110d6b631f9d149f6e5f4e68cc8e/src/code/z_rumble.c#L58-L77 + rumbleSourceStrength: IntProperty(name="", default=0, min=0, max=255) + rumbleDuration: IntProperty(name="", default=0, min=0, max=255) + rumbleDecreaseRate: IntProperty(name="", default=0, min=0, max=255) class OOTCSListProperty(PropertyGroup): @@ -178,9 +176,8 @@ class OOTCSListProperty(PropertyGroup): time: CollectionProperty(type=OOTCSTimeProperty) bgm: CollectionProperty(type=OOTCSBGMProperty) misc: CollectionProperty(type=OOTCSMiscProperty) - nine: CollectionProperty(type=OOTCS0x09Property) + nine: CollectionProperty(type=OOTCSRumbleProperty) - unkType: StringProperty(name="", default="0x0001") fxType: EnumProperty(items=ootEnumCSTransitionType) fxTypeCustom: StringProperty(default="CS_TRANS_CUSTOM") fxStartFrame: IntProperty(name="", default=0, min=0) @@ -300,7 +297,7 @@ def draw_props(self, layout: UILayout, obj: Object): OOTCSTimeProperty, OOTCSBGMProperty, OOTCSMiscProperty, - OOTCS0x09Property, + OOTCSRumbleProperty, OOTCSListProperty, OOTCutsceneProperty, ) diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index bc68ae6d2..2387a31d4 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -64,8 +64,8 @@ def upgradeCutsceneProperties(csObj: Object): differentPropsData = [ # TextBox - ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction) - ("type", "textboxType", ootEnumCSTextboxType) + ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), + ("type", "textboxType", ootEnumCSTextboxType), # BGM ("value", "csSeqID", ootEnumMusicSeq), @@ -77,9 +77,15 @@ def upgradeCutsceneProperties(csObj: Object): # conversion to the same prop type # simply transfer the old data to the new one + # special case for rumble props where it's a string to int conversion for oldName, newName in oldNamesToNewNames.items(): if oldName in csObj: - csObj[newName] = csObj[oldName] + value = csObj[oldName] + + if newName in ["rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"]: + value = int(getEvalParams(csObj[oldName]), base=16) + + csObj[newName] = value del csObj[oldName] diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 241f436e5..eaad98bdf 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -46,19 +46,19 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): if list.listType == "Textbox": if e.textboxType == "Text": csData.source += ( - f"{e.messageId}, {e.startFrame}, {e.endFrame}, {e.type}, {e.topOptionBranch}, {e.bottomOptionBranch}" + f"{e.textID}, {e.startFrame}, {e.endFrame}, {e.textboxType}, {e.topOptionTextID}, {e.bottomOptionTextID}" ) elif e.textboxType == "None": csData.source += f"{e.startFrame}, {e.endFrame}" elif e.textboxType == "LearnSong": - csData.source += f"{e.ocarinaSongAction}, {e.startFrame}, {e.endFrame}, {e.ocarinaMessageId}" + csData.source += f"{e.ocarinaAction}, {e.startFrame}, {e.endFrame}, {e.ocarinaMessageId}" elif list.listType == "Lighting": # the endFrame variable is not used in the implementation of the commend # so the value doesn't matter - csData.source += f"{e.index}, {e.startFrame}" + (", 0" * 9) + csData.source += f"{e.lightSettingsIndex}, {e.startFrame}" + (", 0" * 9) elif list.listType == "Time": # same as above @@ -66,14 +66,14 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): elif list.listType == "0x09": # rumble command # same as above - csData.source += f"0, {e.startFrame}, 0, {e.unk2}, {e.unk3}, {e.unk4}, 0, 0" + csData.source += f"0, {e.startFrame}, 0, {e.rumbleSourceStrength}, {e.rumbleDuration}, {e.rumbleDecreaseRate}, 0, 0" elif list.listType in ["PlayBGM", "StopBGM", "FadeBGM"]: endFrame = e.endFrame if list.listType == "FadeBGM" else "0" - csData.source += f"{e.value}, {e.startFrame}, {endFrame}" + (", 0" * 8) + csData.source += f"{e.csSeqID}, {e.startFrame}, {endFrame}" + (", 0" * 8) elif list.listType == "Misc": - csData.source += f"{e.operation}, {e.startFrame}, {e.endFrame}" + (", 0" * 11) + csData.source += f"{e.csMiscType}, {e.startFrame}, {e.endFrame}" + (", 0" * 11) else: raise PluginError("Internal error: invalid cutscene list type " + list.listType) From 76a7d0efdc1eff2a8651742a99d3290b2c376022 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Thu, 12 Jan 2023 23:35:49 +0100 Subject: [PATCH 08/39] finished upgrade system --- fast64_internal/oot/cutscene/constants.py | 66 +++++++++++----------- fast64_internal/oot/cutscene/properties.py | 8 ++- fast64_internal/oot/oot_upgrade.py | 61 ++++++++++++++------ fast64_internal/oot/props_panel_main.py | 12 +++- fast64_internal/oot/room/properties.py | 5 +- 5 files changed, 97 insertions(+), 55 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index edc6b43be..067b7709e 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -83,39 +83,39 @@ ootEnumCSMiscType = [ # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L167-L204 ("Custom", "Custom", "Custom"), - ("CS_MISC_SET_LOCKED_VIEWPOINT", "Set Locked Viewpoint", "Set Locked Viewpoint"), - ("CS_MISC_SHOW_TITLE_CARD", "Show Area Title Card", "Show Area Title Card"), - ("CS_MISC_RAIN", "Rain", "Rain"), - ("CS_MISC_SNOW", "Snow", "Snow"), - ("CS_MISC_LIGHTNING", "Lightning", "Lightning"), - ("CS_MISC_LIFT_FOG", "Lift Fog", "Lift Fog"), - ("CS_MISC_CLOUDY_SKY", "Cloudy Sky", "Cloudy Sky"), - ("CS_MISC_QUAKE_START", "Start Quake", "Start Quake"), - ("CS_MISC_QUAKE_STOP", "Stop Quake", "Stop Quake"), - ("CS_MISC_SANDSTORM_FILL", "Sandstorm Fill", "Sandstorm Fill"), - ("CS_MISC_SUNSSONG_START", "Start Sun's Song", "Start Sun's Song"), - ("CS_MISC_STOP_STORM_AND_ADVANCE_TO_DAY", "Stop Storm And Advance To Day", "Stop Storm And Advance To Day"), - ("CS_MISC_FREEZE_TIME", "Freeze Time", "Freeze Time"), - ("CS_MISC_TIME_ADVANCE_TO_NIGHT", "Advance Time to Night", "Advance Time to Night"), - ("CS_MISC_SET_TIME_BASED_LIGHT_SETTING", "Set Time Based on Light Settings", "Set Time Based on Light Settings"), - ("CS_MISC_FADE_KOKIRI_GRASS_ENV_ALPHA", "Grass fade in Kokiri Forest", "Grass fade in Kokiri Forest"), - ("CS_MISC_DEKU_TREE_DEATH", "Deku Tree Death", "Deku Tree Death"), - ("CS_MISC_TRIFORCE_FLASH", "Triforce Flash", "Triforce Flash"), - ("CS_MISC_HIDE_ROOM", "Hide Current Room", "Hide Current Room"), - ("CS_MISC_VISMONO_BLACK_AND_WHITE", "Set Screen to Black & White", "Set Screen to Black & White"), - ("CS_MISC_VISMONO_SEPIA", "Set Screen to Sepia", "Set Screen to Sepia"), - ("CS_MISC_HALT_ALL_ACTORS", "Halt All Actors", "Halt All Actors"), - ("CS_MISC_RESUME_ALL_ACTORS", "Resume All Actors", "Resume All Actors"), - ("CS_MISC_RED_PULSATING_LIGHTS", "Red Pulsating Lights", "Red Pulsating Lights"), - ("CS_MISC_LONG_SCARECROW_SONG", "Play Long Scarecrow Song", "Play Long Scarecrow Song"), - ("CS_MISC_SET_CSFLAG_0", "Set CS Flag 0", "Set CS Flag 0"), - ("CS_MISC_SET_CSFLAG_1", "Set CS Flag 1", "Set CS Flag 1"), - ("CS_MISC_SET_CSFLAG_3", "Set CS Flag 3", "Set CS Flag 3"), - ("CS_MISC_SET_CSFLAG_4", "Set CS Flag 4", "Set CS Flag 4"), - ("CS_MISC_SET_FLAG_FAST_WINDMILL", "Set Fast Windmill Flag", "Set Fast Windmill Flag"), - ("CS_MISC_SET_FLAG_WELL_DRAINED", "Set Well Drained Flag", "Set Well Drained Flag"), - ("CS_MISC_SET_FLAG_LAKE_HYLIA_RESTORED", "Set Lake Hylia Restored Flag", "Set Lake Hylia Restored Flag"), - ("CS_MISC_STOP_CUTSCENE", "Stop Cutscene", "Stop Cutscene"), + ("CS_MISC_RAIN", " Rain", " Rain"), + ("CS_MISC_LIGHTNING", " Lightning", " Lightning"), + ("CS_MISC_SET_CSFLAG_0", " Set CS Flag 0", " Set CS Flag 0"), + ("CS_MISC_LIFT_FOG", " Lift Fog", " Lift Fog"), + ("CS_MISC_CLOUDY_SKY", " Cloudy Sky", " Cloudy Sky"), + ("CS_MISC_FADE_KOKIRI_GRASS_ENV_ALPHA", " Fade Kokiri Grass Env Alpha", " Fade Kokiri Grass Env Alpha"), + ("CS_MISC_SNOW", " Snow", " Snow"), + ("CS_MISC_SET_CSFLAG_1", " Set CS Flag 1", " Set CS Flag 1"), + ("CS_MISC_DEKU_TREE_DEATH", " Deku Tree Death", " Deku Tree Death"), + ("CS_MISC_STOP_CUTSCENE", " Stop Cutscene", " Stop Cutscene"), + ("CS_MISC_TRIFORCE_FLASH", " Triforce Flash", " Triforce Flash"), + ("CS_MISC_SET_LOCKED_VIEWPOINT", " Set Locked Viewpoint", " Set Locked Viewpoint"), + ("CS_MISC_SHOW_TITLE_CARD", " Show Title Card", " Show Title Card"), + ("CS_MISC_QUAKE_START", " Quake Start", " Quake Start"), + ("CS_MISC_QUAKE_STOP", " Quake Stop", " Quake Stop"), + ("CS_MISC_STOP_STORM_AND_ADVANCE_TO_DAY", " Stop Storm And Advance To Day", " Stop Storm And Advance To Day"), + ("CS_MISC_SET_FLAG_FAST_WINDMILL", " Set Flag Fast Windmill", " Set Flag Fast Windmill"), + ("CS_MISC_SET_FLAG_WELL_DRAINED", " Set Flag Well Drained", " Set Flag Well Drained"), + ("CS_MISC_SET_FLAG_LAKE_HYLIA_RESTORED", " Set Flag Lake Hylia Restored", " Set Flag Lake Hylia Restored"), + ("CS_MISC_VISMONO_BLACK_AND_WHITE", " Vismono Black And White", " Vismono Black And White"), + ("CS_MISC_VISMONO_SEPIA", " Vismono Sepia", " Vismono Sepia"), + ("CS_MISC_HIDE_ROOM", " Hide Room", " Hide Room"), + ("CS_MISC_TIME_ADVANCE_TO_NIGHT", " Time Advance To Night", " Time Advance To Night"), + ("CS_MISC_SET_TIME_BASED_LIGHT_SETTING", " Set Time Based Light Setting", " Set Time Based Light Setting"), + ("CS_MISC_RED_PULSATING_LIGHTS", " Red Pulsating Lights", " Red Pulsating Lights"), + ("CS_MISC_HALT_ALL_ACTORS", " Halt All Actors", " Halt All Actors"), + ("CS_MISC_RESUME_ALL_ACTORS", " Resume All Actors", " Resume All Actors"), + ("CS_MISC_SET_CSFLAG_3", " Set CS Flag 3", " Set CS Flag 3"), + ("CS_MISC_SET_CSFLAG_4", " Set CS Flag 4", " Set CS Flag 4"), + ("CS_MISC_SANDSTORM_FILL", " Sandstorm Fill", " Sandstorm Fill"), + ("CS_MISC_SUNSSONG_START", " Sun's Song Start", " Sunssong Start"), + ("CS_MISC_FREEZE_TIME", " Freeze Time", " Freeze Time"), + ("CS_MISC_LONG_SCARECROW_SONG", " Long Scarecrow Song", " Long Scarecrow Song"), ] ootEnumCSDestinationType = [ diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 8b6a5d7e8..d2aeea203 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -4,6 +4,7 @@ from ...utility import PluginError, prop_split from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName from ..oot_constants import ootEnumMusicSeq +from ..oot_upgrade import upgradeCutsceneProperties from .operators import OOTCSTextboxAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp from .constants import ( ootEnumCSTextboxType, @@ -90,13 +91,14 @@ class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): "ocarinaMessageId", ] textboxType: EnumProperty(items=ootEnumCSTextboxType) + + # subprops textID: StringProperty(name="", default="0x0000") ocarinaAction: EnumProperty(name="Ocarina Action", items=ootEnumOcarinaAction, default="OCARINA_ACTION_TEACH_MINUET") ocarinaActionCustom: StringProperty(default="OCARINA_ACTION_CUSTOM") topOptionTextID: StringProperty(name="", default="0x0000") bottomOptionTextID: StringProperty(name="", default="0x0000") ocarinaMessageId: StringProperty(name="", default="0x0000") - csTextType: EnumProperty(name="Text Type", items=ootEnumTextType, default="CS_TEXT_NORMAL") csTextTypeCustom: StringProperty(default="CS_TEXT_CUSTOM") @@ -265,6 +267,10 @@ class OOTCutsceneProperty(PropertyGroup): csTermEnd: IntProperty(name="End Frame", min=0, default=100) csLists: CollectionProperty(type=OOTCSListProperty, name="Cutscene Lists") + @staticmethod + def upgrade_object(csListProp: OOTCSTextboxProperty | OOTCSBGMProperty | OOTCSMiscProperty | OOTCSRumbleProperty): + upgradeCutsceneProperties(csListProp) + def draw_props(self, layout: UILayout, obj: Object): layout.prop(self, "csEndFrame") diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 2387a31d4..5a52a17b2 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -3,7 +3,7 @@ from .oot_utility import getEvalParams from .oot_constants import ootEnumMusicSeq from .cutscene.constants import ( - ootEnumCSTextboxType, + ootEnumTextType, ootEnumCSMiscType, ootEnumOcarinaAction, ) @@ -44,7 +44,8 @@ def upgradeRoomHeaders(roomObj: Object, objData: OoT_ObjectData): upgradeObjectList(altHeaders.cutsceneHeaders[i].objectList, objData) -def upgradeCutsceneProperties(csObj: Object): +def upgradeCutsceneProperties(csListProp): + # ``csListProp`` types: OOTCSTextboxProperty | OOTCSBGMProperty | OOTCSMiscProperty | OOTCSRumbleProperty # based on ``upgradeObjectList`` oldNamesToNewNames = { @@ -65,7 +66,7 @@ def upgradeCutsceneProperties(csObj: Object): differentPropsData = [ # TextBox ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), - ("type", "textboxType", ootEnumCSTextboxType), + ("type", "csTextType", ootEnumTextType), # BGM ("value", "csSeqID", ootEnumMusicSeq), @@ -79,35 +80,63 @@ def upgradeCutsceneProperties(csObj: Object): # simply transfer the old data to the new one # special case for rumble props where it's a string to int conversion for oldName, newName in oldNamesToNewNames.items(): - if oldName in csObj: - value = csObj[oldName] + if oldName in csListProp: + value = csListProp[oldName] if newName in ["rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"]: - value = int(getEvalParams(csObj[oldName]), base=16) + value = int(getEvalParams(csListProp[oldName]), base=16) - csObj[newName] = value + csListProp[newName] = value - del csObj[oldName] + del csListProp[oldName] # conversion to another prop type for (oldName, newName, enumList) in differentPropsData: - if oldName in csObj: + if oldName in csListProp: # get the old data - oldData = csObj[oldName] + oldData = csListProp[oldName] # if anything goes wrong there set the value to custom to avoid any data loss try: - # get the value, doing an eval for strings - value = int(getEvalParams(oldData), base=16) + if isinstance(oldData, str): + # get the value, doing an eval for strings + # account for custom elements in the enums by adding 1 + value = int(getEvalParams(oldData), base=16) + 1 + + # special cases for ocarina action enum + # since we don't have everything the value need to be shifted + if newName == "ocarinaAction": + if value in [0x00, 0x01, 0x0E] or value > 0x1A: + raise IndexError + + if value > 0x0E: + value -= 1 + + value -= 2 + elif isinstance(oldData, int): + # account for custom elements in the enums by adding 1 + value = oldData + 1 + + # another special case, this time for the misc enum + if newName == "csMiscType": + if value in [0x00, 0x04, 0x05]: + raise IndexError + + if value > 0x05: + value -= 2 + + value -= 1 + else: + raise NotImplementedError # if the value is in the list find the identifier if value < len(enumList): - setattr(csObj, newName, enumList[value][0]) + setattr(csListProp, newName, enumList[value][0]) else: # else raise an error to default to custom raise IndexError except: - setattr(csObj, newName, "Custom") - setattr(csObj, f"{newName}Custom", oldData) + setattr(csListProp, newName, "Custom") + setattr(csListProp, f"{newName}Custom", str(oldData)) - del csObj[oldName] + del csListProp[oldName] diff --git a/fast64_internal/oot/props_panel_main.py b/fast64_internal/oot/props_panel_main.py index 39177faa3..6bdb401ca 100644 --- a/fast64_internal/oot/props_panel_main.py +++ b/fast64_internal/oot/props_panel_main.py @@ -154,10 +154,20 @@ class OOT_ObjectProperties(bpy.types.PropertyGroup): @staticmethod def upgrade_changed_props(): for obj in bpy.data.objects: - if obj.data is None: + if obj.type == "EMPTY": if obj.ootEmptyType == "Room": OOTObjectProperty.upgrade_object(obj) + if obj.ootEmptyType == "Cutscene": + print(f"Processing '{obj.name}'...") + csListsNames = ["textbox", "lighting", "time", "bgm", "misc", "nine"] + + for csList in obj.ootCutsceneProperty.csLists: + for listName in csListsNames: + for csListProp in getattr(csList, listName): + # print(type(elem)) + OOTCutsceneProperty.upgrade_object(csListProp) + class OOTCullGroupProperty(bpy.types.PropertyGroup): sizeControlsCull: bpy.props.BoolProperty(default=True, name="Empty Size Controls Cull Depth") diff --git a/fast64_internal/oot/room/properties.py b/fast64_internal/oot/room/properties.py index 5f0a05d36..1ad2c4437 100644 --- a/fast64_internal/oot/room/properties.py +++ b/fast64_internal/oot/room/properties.py @@ -3,7 +3,7 @@ from bpy.utils import register_class, unregister_class from ...utility import prop_split from ..oot_utility import drawCollectionOps, onMenuTabChange, onHeaderMenuTabChange, drawEnumWithCustom, drawAddButton -from ..oot_upgrade import upgradeRoomHeaders, upgradeCutsceneProperties +from ..oot_upgrade import upgradeRoomHeaders from .operators import OOT_SearchObjectEnumOperator from bpy.props import ( @@ -38,9 +38,6 @@ def upgrade_object(obj): print(f"Processing '{obj.name}'...") upgradeRoomHeaders(obj, ootData.objectData) - # if obj.type == "EMPTY" and obj.ootEmptyType == "Cutscene": - # upgradeCutsceneProperties(obj) - def draw_props(self, layout: UILayout, headerIndex: int, index: int, objName: str): isLegacy = True if "objectID" in self else False From 3fa16a00c39f18b4582a8f6b594cd6c97b5c3244 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:12:39 +0100 Subject: [PATCH 09/39] more renames/upgrade, "fixed" issues with fade out seq and fixed transition, minor ui changes --- fast64_internal/oot/cutscene/constants.py | 60 +++---- .../oot/cutscene/exporter/functions.py | 2 +- fast64_internal/oot/cutscene/properties.py | 167 ++++++++++-------- fast64_internal/oot/oot_upgrade.py | 131 +++++++++----- fast64_internal/oot/props_panel_main.py | 9 +- .../oot/scene/exporter/to_c/scene_cutscene.py | 21 +-- 6 files changed, 219 insertions(+), 171 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 067b7709e..094ddb3f5 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -1,49 +1,49 @@ ootEnumCSTextboxTypeEntryC = { "Text": "CS_TEXT", "None": "CS_TEXT_NONE", - "LearnSong": "CS_TEXT_OCARINA_ACTION", + "OcarinaAction": "CS_TEXT_OCARINA_ACTION", } ootEnumCSListTypeListC = { - "Textbox": "CS_TEXT_LIST", - "FX": "CS_TRANSITION", - "Lighting": "CS_LIGHT_SETTING_LIST", - "Time": "CS_TIME_LIST", - "PlayBGM": "CS_START_SEQ_LIST", - "StopBGM": "CS_STOP_SEQ_LIST", - "FadeBGM": "CS_FADE_OUT_SEQ_LIST", - "Misc": "CS_MISC_LIST", - "0x09": "CS_RUMBLE_CONTROLLER_LIST", + "TextList": "CS_TEXT_LIST", + "Transition": "CS_TRANSITION", + "LightSettingsList": "CS_LIGHT_SETTING_LIST", + "TimeList": "CS_TIME_LIST", + "StartSeqList": "CS_START_SEQ_LIST", + "StopSeqList": "CS_STOP_SEQ_LIST", + "FadeOutSeqList": "CS_FADE_OUT_SEQ_LIST", + "MiscList": "CS_MISC_LIST", + "RumbleList": "CS_RUMBLE_CONTROLLER_LIST", } ootEnumCSListTypeEntryC = { - "Textbox": None, # special case - "FX": None, # no list entries - "Lighting": "CS_LIGHT_SETTING", + "Text": None, # special case + "Transition": None, # no list entries + "LightSettings": "CS_LIGHT_SETTING", "Time": "CS_TIME", - "PlayBGM": "CS_START_SEQ", - "StopBGM": "CS_STOP_SEQ", - "FadeBGM": "CS_FADE_OUT_SEQ", + "StartSeq": "CS_START_SEQ", + "StopSeq": "CS_STOP_SEQ", + "FadeOutSeq": "CS_FADE_OUT_SEQ", "Misc": "CS_MISC", - "0x09": "CS_RUMBLE_CONTROLLER", + "Rumble": "CS_RUMBLE_CONTROLLER", } ootEnumCSWriteType = [ ("Custom", "Custom", "Provide the name of a cutscene header variable"), - ("Embedded", "Embedded", "Cutscene data is within scene header (deprecated)"), + ("Embedded", "(Deprecated) Embedded", "Cutscene data is within scene header"), ("Object", "Object", "Reference to Blender object representing cutscene"), ] ootEnumCSListType = [ - ("Textbox", "Textbox", "Textbox"), - ("FX", "Transition", "Transition"), - ("Lighting", "Lighting", "Lighting"), - ("Time", "Time", "Time"), - ("PlayBGM", "Play BGM", "Play BGM"), - ("StopBGM", "Stop BGM", "Stop BGM"), - ("FadeBGM", "Fade BGM", "Fade BGM"), - ("Misc", "Misc", "Misc"), - ("0x09", "Rumble Controller", "Rumble Controller"), + ("TextList", "Text List", "Textbox"), + ("Transition", "Transition", "Transition"), + ("LightSettingsList", "Light Settings List", "Lighting"), + ("TimeList", "Time List", "Time"), + ("StartSeqList", "Start Seq List", "Play BGM"), + ("StopSeqList", "Stop Seq List", "Stop BGM"), + ("FadeOutSeqList", "Fade-Out Seq List", "Fade BGM"), + ("MiscList", "Misc List", "Misc"), + ("RumbleList", "Rumble List", "Rumble Controller"), ] ootEnumCSListTypeIcons = [ @@ -58,7 +58,7 @@ "OUTLINER_OB_FORCE_FIELD", ] -ootEnumCSTextboxType = [("Text", "Text", "Text"), ("None", "None", "None"), ("LearnSong", "Learn Song", "Learn Song")] +ootEnumCSTextboxType = [("Text", "Text", "Text"), ("None", "None", "None"), ("OcarinaAction", "Ocarina Action", "Learn Song")] ootEnumCSTextboxTypeIcons = ["FILE_TEXT", "HIDE_ON", "FILE_SOUND"] @@ -304,8 +304,8 @@ "hour": "Hour", "minute": "Minute", - # BGM - "csSeqID": "BGM ID", + # Seq + "csSeqID": "Seq ID", "csSeqPlayer": "Seq Player Type", # Misc diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index 9dc1d87f5..b82908a17 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -66,7 +66,7 @@ def readCutsceneData(csParentOut, csParentIn): entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) - elif listOut.listType == "0x09": + elif listOut.listType == "Rumble": for entryIn in listIn.nine: entryOut = OOTCS0x09() entryOut.startFrame = entryIn.startFrame diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index d2aeea203..631f3ccaa 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -4,7 +4,7 @@ from ...utility import PluginError, prop_split from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName from ..oot_constants import ootEnumMusicSeq -from ..oot_upgrade import upgradeCutsceneProperties +from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps from .operators import OOTCSTextboxAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp from .constants import ( ootEnumCSTextboxType, @@ -20,11 +20,7 @@ ) -# Perhaps this should have been called something like OOTCSParentPropertyType, -# but now it needs to keep the same name to not break existing scenes which use -# the cutscene system. -class OOTCSProperty: - propName = None +class OOTCutsceneCommon: attrName = None subprops = ["startFrame", "endFrame"] expandTab: BoolProperty(default=True) @@ -32,7 +28,7 @@ class OOTCSProperty: endFrame: IntProperty(name="", default=1, min=0) def getName(self): - return self.propName + pass def filterProp(self, name, listProp): return True @@ -40,14 +36,23 @@ def filterProp(self, name, listProp): def filterName(self, name, listProp): return name - def draw(self, layout: UILayout, listProp: "OOTCSListProperty", listIndex: int, cmdIndex: int, objName: str, collectionType: str): + def draw_props( + self, + layout: UILayout, + listProp: "OOTCSListProperty", + listIndex: int, + cmdIndex: int, + objName: str, + collectionType: str, + tabName: str, + ): # Draws list elements box = layout.box().column() box.prop( self, "expandTab", - text=self.getName() + " " + str(cmdIndex), + text=f"{tabName if tabName != 'Text' else self.getName()} No. {cmdIndex}", icon="TRIA_DOWN" if self.expandTab else "TRIA_RIGHT", ) if not self.expandTab: @@ -77,9 +82,8 @@ def draw(self, layout: UILayout, listProp: "OOTCSListProperty", listIndex: int, prop_split(box, self, f"{name}Custom", f"{displayName} Custom") -class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): - propName = "Textbox" - attrName = "textbox" +class OOTCSTextProperty(OOTCutsceneCommon, PropertyGroup): + attrName = "textList" subprops = [ "textID", "ocarinaAction", @@ -103,63 +107,58 @@ class OOTCSTextboxProperty(OOTCSProperty, PropertyGroup): csTextTypeCustom: StringProperty(default="CS_TEXT_CUSTOM") def getName(self): - return self.textboxType + return getEnumName(ootEnumCSTextboxType, self.textboxType) def filterProp(self, name, listProp): if self.textboxType == "Text": return name not in ["ocarinaAction", "ocarinaMessageId"] elif self.textboxType == "None": return name in ["startFrame", "endFrame"] - elif self.textboxType == "LearnSong": + elif self.textboxType == "OcarinaAction": return name in ["ocarinaAction", "startFrame", "endFrame", "ocarinaMessageId"] else: - raise PluginError("Invalid property name for OOTCSTextboxProperty") + raise PluginError("Invalid property name for OOTCSTextProperty") -class OOTCSLightingProperty(OOTCSProperty, PropertyGroup): - propName = "Lighting" - attrName = "lighting" +class OOTCSLightSettingsProperty(OOTCutsceneCommon, PropertyGroup): + attrName = "lightSettingsList" subprops = ["lightSettingsIndex", "startFrame"] lightSettingsIndex: IntProperty(name="", default=1, min=1) -class OOTCSTimeProperty(OOTCSProperty, PropertyGroup): - propName = "Time" - attrName = "time" +class OOTCSTimeProperty(OOTCutsceneCommon, PropertyGroup): + attrName = "timeList" subprops = ["startFrame", "hour", "minute"] hour: IntProperty(name="", default=23, min=0, max=23) minute: IntProperty(name="", default=59, min=0, max=59) -class OOTCSBGMProperty(OOTCSProperty, PropertyGroup): - propName = "BGM" - attrName = "bgm" +class OOTCSSeqProperty(OOTCutsceneCommon, PropertyGroup): + attrName = "seqList" subprops = ["csSeqID", "startFrame", "endFrame"] csSeqID: EnumProperty(name="Seq ID", items=ootEnumMusicSeq, default="NA_BGM_GENERAL_SFX") csSeqIDCustom: StringProperty(default="NA_BGM_CUSTOM") csSeqPlayer: EnumProperty(name="Seq Player", items=ootEnumSeqPlayer, default="CS_FADE_OUT_BGM_MAIN") - csSeqPlayerCustom: StringProperty(default="NA_BGM_CUSTOM") + csSeqPlayerCustom: StringProperty(default="CS_FADE_OUT_CUSTOM") def filterProp(self, name, listProp): - return name != "endFrame" or listProp.listType == "FadeBGM" + return name != "endFrame" or listProp.listType == "FadeOutSeqList" def filterName(self, name, listProp): - if name == "csSeqID" and listProp.listType == "FadeBGM": + if name == "csSeqID" and listProp.listType == "FadeOutSeqList": return "csSeqPlayer" return name -class OOTCSMiscProperty(OOTCSProperty, PropertyGroup): - propName = "Misc" - attrName = "misc" +class OOTCSMiscProperty(OOTCutsceneCommon, PropertyGroup): + attrName = "miscList" subprops = ["csMiscType", "startFrame", "endFrame"] csMiscType: EnumProperty(name="Type", items=ootEnumCSMiscType, default="CS_MISC_SET_LOCKED_VIEWPOINT") csMiscTypeCustom: StringProperty(default="CS_MISC_CUSTOM") -class OOTCSRumbleProperty(OOTCSProperty, PropertyGroup): - propName = "0x09" - attrName = "nine" +class OOTCSRumbleProperty(OOTCutsceneCommon, PropertyGroup): + attrName = "rumbleList" subprops = ["startFrame", "rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"] # those variables are unsigned chars in decomp @@ -173,26 +172,27 @@ class OOTCSListProperty(PropertyGroup): expandTab: BoolProperty(default=True) listType: EnumProperty(items=ootEnumCSListType) - textbox: CollectionProperty(type=OOTCSTextboxProperty) - lighting: CollectionProperty(type=OOTCSLightingProperty) - time: CollectionProperty(type=OOTCSTimeProperty) - bgm: CollectionProperty(type=OOTCSBGMProperty) - misc: CollectionProperty(type=OOTCSMiscProperty) - nine: CollectionProperty(type=OOTCSRumbleProperty) - - fxType: EnumProperty(items=ootEnumCSTransitionType) - fxTypeCustom: StringProperty(default="CS_TRANS_CUSTOM") - fxStartFrame: IntProperty(name="", default=0, min=0) - fxEndFrame: IntProperty(name="", default=1, min=0) + textList: CollectionProperty(type=OOTCSTextProperty) + lightSettingsList: CollectionProperty(type=OOTCSLightSettingsProperty) + timeList: CollectionProperty(type=OOTCSTimeProperty) + seqList: CollectionProperty(type=OOTCSSeqProperty) + miscList: CollectionProperty(type=OOTCSMiscProperty) + rumbleList: CollectionProperty(type=OOTCSRumbleProperty) + + transitionType: EnumProperty(items=ootEnumCSTransitionType) + transitionTypeCustom: StringProperty(default="CS_TRANS_CUSTOM") + transitionStartFrame: IntProperty(name="", default=0, min=0) + transitionEndFrame: IntProperty(name="", default=1, min=0) def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionType: str): box = layout.box().column() + enumName = getEnumName(ootEnumCSListType, self.listType) # Draw current command tab box.prop( self, "expandTab", - text=self.listType + " List" if self.listType != "FX" else "Transition", + text=enumName, icon="TRIA_DOWN" if self.expandTab else "TRIA_RIGHT", ) @@ -202,32 +202,32 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT drawCollectionOps(box, listIndex, collectionType, None, objName, False) # Draw current command content - if self.listType == "Textbox": - attrName = "textbox" - elif self.listType == "FX": - prop_split(box, self, "fxType", "Transition Type") - if self.fxType == "Custom": - prop_split(box, self, "fxTypeCustom", "Transition Type Custom") - - prop_split(box, self, "fxStartFrame", "Start Frame") - prop_split(box, self, "fxEndFrame", "End Frame") + if self.listType == "TextList": + attrName = "textList" + elif self.listType == "Transition": + prop_split(box, self, "transitionType", "Transition Type") + if self.transitionType == "Custom": + prop_split(box, self, "transitionTypeCustom", "Transition Type Custom") + + prop_split(box, self, "transitionStartFrame", "Start Frame") + prop_split(box, self, "transitionEndFrame", "End Frame") return - elif self.listType == "Lighting": - attrName = "lighting" - elif self.listType == "Time": - attrName = "time" - elif self.listType in ["PlayBGM", "StopBGM", "FadeBGM"]: - attrName = "bgm" - elif self.listType == "Misc": - attrName = "misc" - elif self.listType == "0x09": - attrName = "nine" + elif self.listType == "LightSettingsList": + attrName = "lightSettingsList" + elif self.listType == "TimeList": + attrName = "timeList" + elif self.listType in ["StartSeqList", "StopSeqList", "FadeOutSeqList"]: + attrName = "seqList" + elif self.listType == "MiscList": + attrName = "miscList" + elif self.listType == "RumbleList": + attrName = "rumbleList" else: raise PluginError("Internal error: invalid listType " + self.listType) dat = getattr(self, attrName) - if self.listType == "Textbox": + if self.listType == "TextList": subBox = box.box() subBox.label(text="TextBox Commands") row = subBox.row(align=True) @@ -239,22 +239,25 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT icon=ootEnumCSTextboxTypeIcons[l], ) - addOp.collectionType = collectionType + ".textbox" + addOp.collectionType = collectionType + ".textList" addOp.textboxType = ootEnumCSTextboxType[l][0] addOp.listIndex = listIndex addOp.objName = objName else: - addOp = box.operator(OOTCollectionAdd.bl_idname, text="Add item to " + self.listType + " List") + addOp = box.operator(OOTCollectionAdd.bl_idname, text="Add item to " + getEnumName(ootEnumCSListType, self.listType)) addOp.option = len(dat) addOp.collectionType = collectionType + "." + attrName addOp.subIndex = listIndex addOp.objName = objName for i, p in enumerate(dat): - p.draw(box, self, listIndex, i, objName, collectionType) + # ``p`` type: + # OOTCSTextProperty | OOTCSLightSettingsProperty | OOTCSTimeProperty | + # OOTCSSeqProperty | OOTCSMiscProperty | OOTCSRumbleProperty + p.draw_props(box, self, listIndex, i, objName, collectionType, enumName.removesuffix(" List")) if len(dat) == 0: - box.label(text="No items in " + self.listType + " List.") + box.label(text="No items in " + getEnumName(ootEnumCSListType, self.listType)) class OOTCutsceneProperty(PropertyGroup): @@ -268,8 +271,19 @@ class OOTCutsceneProperty(PropertyGroup): csLists: CollectionProperty(type=OOTCSListProperty, name="Cutscene Lists") @staticmethod - def upgrade_object(csListProp: OOTCSTextboxProperty | OOTCSBGMProperty | OOTCSMiscProperty | OOTCSRumbleProperty): - upgradeCutsceneProperties(csListProp) + def upgrade_object(obj): + print(f"Processing '{obj.name}'...") + + # using the new names since the old ones will be deleted before this is used + csListsNames = ["textList", "lightSettingsList", "timeList", "seqList", "miscList", "rumbleList"] + + for csListProp in obj.ootCutsceneProperty.csLists: + upgradeCSListProps(csListProp) + + for listName in csListsNames: + for csListSubProp in getattr(csListProp, listName): + upgradeCutsceneSubProps(csListSubProp) + def draw_props(self, layout: UILayout, obj: Object): layout.prop(self, "csEndFrame") @@ -293,15 +307,16 @@ def draw_props(self, layout: UILayout, obj: Object): drawCSListAddOp(layout, obj.name, "Cutscene") - for i, p in enumerate(self.csLists): - p.draw_props(layout, i, obj.name, "Cutscene") + for i, csListProp in enumerate(self.csLists): + # ``csListProp`` type: OOTCSListProperty + csListProp.draw_props(layout, i, obj.name, "Cutscene") classes = ( - OOTCSTextboxProperty, - OOTCSLightingProperty, + OOTCSTextProperty, + OOTCSLightSettingsProperty, OOTCSTimeProperty, - OOTCSBGMProperty, + OOTCSSeqProperty, OOTCSMiscProperty, OOTCSRumbleProperty, OOTCSListProperty, diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 5a52a17b2..60d47e24b 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -6,6 +6,7 @@ ootEnumTextType, ootEnumCSMiscType, ootEnumOcarinaAction, + ootEnumCSTransitionType, ) @@ -44,57 +45,28 @@ def upgradeRoomHeaders(roomObj: Object, objData: OoT_ObjectData): upgradeObjectList(altHeaders.cutsceneHeaders[i].objectList, objData) -def upgradeCutsceneProperties(csListProp): - # ``csListProp`` types: OOTCSTextboxProperty | OOTCSBGMProperty | OOTCSMiscProperty | OOTCSRumbleProperty - # based on ``upgradeObjectList`` - - oldNamesToNewNames = { - # TextBox - "messageId": "textID", - "topOptionBranch": "topOptionTextID", - "bottomOptionBranch": "bottomOptionTextID", - - # Lighting - "index": "lightSettingsIndex", - - # Rumble - "unk2": "rumbleSourceStrength", - "unk3": "rumbleDuration", - "unk4": "rumbleDecreaseRate", - } - - differentPropsData = [ - # TextBox - ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), - ("type", "csTextType", ootEnumTextType), - - # BGM - ("value", "csSeqID", ootEnumMusicSeq), - - # Misc - ("operation", "csMiscType", ootEnumCSMiscType), - ] - - +def transferOldDataToNew(data, oldDataToNewData: dict): # conversion to the same prop type # simply transfer the old data to the new one - # special case for rumble props where it's a string to int conversion - for oldName, newName in oldNamesToNewNames.items(): - if oldName in csListProp: - value = csListProp[oldName] + # special case for rumble subprops where it's a string to int conversion + for oldName, newName in oldDataToNewData.items(): + if oldName in data: + value = data[oldName] if newName in ["rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"]: - value = int(getEvalParams(csListProp[oldName]), base=16) + value = int(getEvalParams(data[oldName]), base=16) + + data[newName] = value - csListProp[newName] = value + del data[oldName] - del csListProp[oldName] +def convertOldDataToEnumData(data, oldDataToEnumData: list[tuple[str, str, list[tuple[str, str, str]]]]): # conversion to another prop type - for (oldName, newName, enumList) in differentPropsData: - if oldName in csListProp: + for (oldName, newName, enumList) in oldDataToEnumData: + if oldName in data: # get the old data - oldData = csListProp[oldName] + oldData = data[oldName] # if anything goes wrong there set the value to custom to avoid any data loss try: @@ -113,6 +85,13 @@ def upgradeCutsceneProperties(csListProp): value -= 1 value -= 2 + + if newName == "csSeqID": + # the old fade out value is wrong, it assumes it's a seq id + # but it's not, it's a seq player id, + # hence why we raise an error so it defaults to "custom" to avoid any data loss + # @TODO: find a way to check properly which seq command it is + raise NotImplementedError elif isinstance(oldData, int): # account for custom elements in the enums by adding 1 value = oldData + 1 @@ -131,12 +110,72 @@ def upgradeCutsceneProperties(csListProp): # if the value is in the list find the identifier if value < len(enumList): - setattr(csListProp, newName, enumList[value][0]) + setattr(data, newName, enumList[value][0]) else: # else raise an error to default to custom raise IndexError except: - setattr(csListProp, newName, "Custom") - setattr(csListProp, f"{newName}Custom", str(oldData)) + setattr(data, newName, "Custom") + setattr(data, f"{newName}Custom", str(oldData)) + + # @TODO: find a way to check properly which seq command it is + if newName == "csSeqID": + setattr(data, "csSeqPlayer", "Custom") + setattr(data, "csSeqPlayerCustom", str(oldData)) + + del data[oldName] + + +def upgradeCutsceneSubProps(csListSubProp): + # ``csListSubProp`` types: OOTCSTextProperty | OOTCSSeqProperty | OOTCSMiscProperty | OOTCSRumbleProperty + # based on ``upgradeObjectList`` + + subPropsOldToNew = { + # TextBox + "messageId": "textID", + "topOptionBranch": "topOptionTextID", + "bottomOptionBranch": "bottomOptionTextID", + + # Lighting + "index": "lightSettingsIndex", + + # Rumble + "unk2": "rumbleSourceStrength", + "unk3": "rumbleDuration", + "unk4": "rumbleDecreaseRate", + } + + subPropsToEnum = [ + # TextBox + ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), + ("type", "csTextType", ootEnumTextType), + + # Seq + ("value", "csSeqID", ootEnumMusicSeq), + + # Misc + ("operation", "csMiscType", ootEnumCSMiscType), + ] + + transferOldDataToNew(csListSubProp, subPropsOldToNew) + convertOldDataToEnumData(csListSubProp, subPropsToEnum) + + +def upgradeCSListProps(csListProp): + # ``csListProp`` type: ``OOTCSListProperty`` + + csListPropOldToNew = { + "textbox": "textList", + "lighting": "lightSettingsList", + "time": "timeList", + "bgm": "seqList", + "misc": "miscList", + "nine": "rumbleList", + "fxStartFrame": "transitionStartFrame", + "fxEndFrame": "transitionEndFrame", + } + + transferOldDataToNew(csListProp, csListPropOldToNew) - del csListProp[oldName] + # both are enums but the item list is different (the old one doesn't have a "custom" entry) + convertOldDataToEnumData(csListProp, [("fxType", "transitionType", ootEnumCSTransitionType)]) diff --git a/fast64_internal/oot/props_panel_main.py b/fast64_internal/oot/props_panel_main.py index 6bdb401ca..8e181cc94 100644 --- a/fast64_internal/oot/props_panel_main.py +++ b/fast64_internal/oot/props_panel_main.py @@ -159,14 +159,7 @@ def upgrade_changed_props(): OOTObjectProperty.upgrade_object(obj) if obj.ootEmptyType == "Cutscene": - print(f"Processing '{obj.name}'...") - csListsNames = ["textbox", "lighting", "time", "bgm", "misc", "nine"] - - for csList in obj.ootCutsceneProperty.csLists: - for listName in csListsNames: - for csListProp in getattr(csList, listName): - # print(type(elem)) - OOTCutsceneProperty.upgrade_object(csListProp) + OOTCutsceneProperty.upgrade_object(obj) class OOTCullGroupProperty(bpy.types.PropertyGroup): diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index eaad98bdf..223edac9c 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -28,7 +28,7 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): (indent * 2) + ootEnumCSListTypeListC[list.listType] + "(" + ( f"{list.fxType}, {list.fxStartFrame}, {list.fxEndFrame}" - if list.listType == "FX" else str(len(list.entries)) + if list.listType == "Transition" else str(len(list.entries)) ) + "),\n" ) @@ -38,12 +38,13 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): indent * 3 + ( ootEnumCSTextboxTypeEntryC[e.textboxType] - if list.listType == "Textbox" else ootEnumCSListTypeEntryC[list.listType] + # @TODO make a separate variable for ``ootEnumCSListTypeEntryC`` + if list.listType == "TextList" else ootEnumCSListTypeEntryC[list.listType.replace("List", "")] ) + "(" ) - if list.listType == "Textbox": + if list.listType == "TextList": if e.textboxType == "Text": csData.source += ( f"{e.textID}, {e.startFrame}, {e.endFrame}, {e.textboxType}, {e.topOptionTextID}, {e.bottomOptionTextID}" @@ -52,27 +53,27 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): elif e.textboxType == "None": csData.source += f"{e.startFrame}, {e.endFrame}" - elif e.textboxType == "LearnSong": + elif e.textboxType == "OcarinaAction": csData.source += f"{e.ocarinaAction}, {e.startFrame}, {e.endFrame}, {e.ocarinaMessageId}" - elif list.listType == "Lighting": + elif list.listType == "LightSettingsList": # the endFrame variable is not used in the implementation of the commend # so the value doesn't matter csData.source += f"{e.lightSettingsIndex}, {e.startFrame}" + (", 0" * 9) - elif list.listType == "Time": + elif list.listType == "TimeList": # same as above csData.source += f"0, {e.startFrame}, 0, {e.hour}, {e.minute}" - elif list.listType == "0x09": # rumble command + elif list.listType == "RumbleList": # same as above csData.source += f"0, {e.startFrame}, 0, {e.rumbleSourceStrength}, {e.rumbleDuration}, {e.rumbleDecreaseRate}, 0, 0" - elif list.listType in ["PlayBGM", "StopBGM", "FadeBGM"]: - endFrame = e.endFrame if list.listType == "FadeBGM" else "0" + elif list.listType in ["StartSeqList", "StopSeqList", "FadeOutSeqList"]: + endFrame = e.endFrame if list.listType == "FadeOutSeqList" else "0" csData.source += f"{e.csSeqID}, {e.startFrame}, {endFrame}" + (", 0" * 8) - elif list.listType == "Misc": + elif list.listType == "MiscList": csData.source += f"{e.csMiscType}, {e.startFrame}, {e.endFrame}" + (", 0" * 11) else: From 07c4f85e85999e26f00cc0fb3036fc9f3d42e50d Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:40:25 +0100 Subject: [PATCH 10/39] fixed export --- .../oot/cutscene/exporter/__init__.py | 9 ++- .../oot/cutscene/exporter/classes.py | 35 ++++-------- .../oot/cutscene/exporter/functions.py | 56 +++++++++---------- fast64_internal/oot/cutscene/operators.py | 4 +- fast64_internal/oot/cutscene/properties.py | 4 +- .../oot/scene/exporter/to_c/scene_cutscene.py | 7 ++- 6 files changed, 50 insertions(+), 65 deletions(-) diff --git a/fast64_internal/oot/cutscene/exporter/__init__.py b/fast64_internal/oot/cutscene/exporter/__init__.py index 39486d43c..eefb84717 100644 --- a/fast64_internal/oot/cutscene/exporter/__init__.py +++ b/fast64_internal/oot/cutscene/exporter/__init__.py @@ -2,12 +2,11 @@ from .classes import ( OOTCSList, - OOTCSTextbox, - OOTCSLighting, + OOTCSText, + OOTCSLightSettings, OOTCSTime, - OOTCSBGM, + OOTCSSeq, OOTCSMisc, - OOTCS0x09, - OOTCSUnk, + OOTCSRumble, OOTCutscene, ) diff --git a/fast64_internal/oot/cutscene/exporter/classes.py b/fast64_internal/oot/cutscene/exporter/classes.py index de3bae87d..a6811884a 100644 --- a/fast64_internal/oot/cutscene/exporter/classes.py +++ b/fast64_internal/oot/cutscene/exporter/classes.py @@ -1,17 +1,17 @@ -class OOTCSTextbox: +class OOTCSText: def __init__(self): - self.textboxType = None + self.textboxType = "0x0000" self.textID = "0x0000" self.ocarinaAction = "0x0000" self.startFrame = 0 self.endFrame = 1 - self.textboxType = "0x0000" + self.textType = "0x0000" self.topOptionTextID = "0x0000" self.bottomOptionTextID = "0x0000" self.ocarinaMessageId = "0x0000" -class OOTCSLighting: +class OOTCSLightSettings: def __init__(self): self.lightSettingsIndex = 1 self.startFrame = 0 @@ -24,9 +24,10 @@ def __init__(self): self.minute = 59 -class OOTCSBGM: +class OOTCSSeq: def __init__(self): self.csSeqID = "0x0000" + self.csSeqPlayer = "0x0000" self.startFrame = 0 self.endFrame = 1 @@ -38,7 +39,7 @@ def __init__(self): self.endFrame = 1 -class OOTCS0x09: +class OOTCSRumble: def __init__(self): self.startFrame = 0 self.rumbleSourceStrength = "0x00" @@ -46,29 +47,13 @@ def __init__(self): self.rumbleDecreaseRate = "0x00" -class OOTCSUnk: - def __unk__(self): - self.unk1 = "0x00000000" - self.rumbleSourceStrength = "0x00000000" - self.rumbleDuration = "0x00000000" - self.rumbleDecreaseRate = "0x00000000" - self.unk5 = "0x00000000" - self.unk6 = "0x00000000" - self.unk7 = "0x00000000" - self.unk8 = "0x00000000" - self.unk9 = "0x00000000" - self.unk10 = "0x00000000" - self.unk11 = "0x00000000" - self.unk12 = "0x00000000" - - class OOTCSList: def __init__(self): self.listType = None self.entries = [] - self.fxType = "1" - self.fxStartFrame = 0 - self.fxEndFrame = 0 + self.transitionType = "1" + self.transitionStartFrame = 0 + self.transitionEndFrame = 0 class OOTCutscene: diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index b82908a17..3736f73cd 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -2,13 +2,12 @@ from .classes import ( OOTCSList, - OOTCSTextbox, - OOTCSLighting, + OOTCSText, + OOTCSLightSettings, OOTCSTime, - OOTCSBGM, + OOTCSSeq, OOTCSMisc, - OOTCS0x09, - OOTCSUnk, + OOTCSRumble, OOTCutscene, ) @@ -18,57 +17,58 @@ def readCutsceneData(csParentOut, csParentIn): listOut = OOTCSList() listOut.listType = listIn.listType - listOut.fxType, listOut.fxStartFrame, listOut.fxEndFrame = ( - getCustomProperty(listIn, "fxType"), - listIn.fxStartFrame, - listIn.fxEndFrame, + listOut.transitionType, listOut.transitionStartFrame, listOut.transitionEndFrame = ( + getCustomProperty(listIn, "transitionType"), + listIn.transitionStartFrame, + listIn.transitionEndFrame, ) listData = [] - if listOut.listType == "Textbox": - for entryIn in listIn.textbox: - entryOut = OOTCSTextbox() + if listOut.listType == "TextList": + for entryIn in listIn.textList: + entryOut = OOTCSText() entryOut.textboxType = entryIn.textboxType entryOut.textID = entryIn.textID entryOut.ocarinaAction = getCustomProperty(entryIn, "ocarinaAction") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame - entryOut.textboxType = getCustomProperty(entryIn, "csTextType") + entryOut.textType = getCustomProperty(entryIn, "csTextType") entryOut.topOptionTextID = entryIn.topOptionTextID entryOut.bottomOptionTextID = entryIn.bottomOptionTextID entryOut.ocarinaMessageId = entryIn.ocarinaMessageId listOut.entries.append(entryOut) - elif listOut.listType == "Lighting": - for entryIn in listIn.lighting: - entryOut = OOTCSLighting() + elif listOut.listType == "LightSettingsList": + for entryIn in listIn.lightSettingsList: + entryOut = OOTCSLightSettings() entryOut.lightSettingsIndex = entryIn.lightSettingsIndex entryOut.startFrame = entryIn.startFrame listOut.entries.append(entryOut) - elif listOut.listType == "Time": - for entryIn in listIn.time: + elif listOut.listType == "TimeList": + for entryIn in listIn.timeList: entryOut = OOTCSTime() entryOut.startFrame = entryIn.startFrame entryOut.hour = entryIn.hour entryOut.minute = entryIn.minute listOut.entries.append(entryOut) - elif listOut.listType in {"PlayBGM", "StopBGM", "FadeBGM"}: - for entryIn in listIn.bgm: - entryOut = OOTCSBGM() - csSeqPropSuffix = "ID" if listOut.listType != "FadeBGM" else "Player" - entryOut.csSeqID = getCustomProperty(entryIn, f"csSeq{csSeqPropSuffix}") + elif listOut.listType in {"StartSeqList", "StopSeqList", "FadeOutSeqList"}: + for entryIn in listIn.seqList: + entryOut = OOTCSSeq() + entryOut.csSeqID = getCustomProperty(entryIn, "csSeqID") + entryOut.csSeqPlayer = getCustomProperty(entryIn, "csSeqPlayer") + print(entryOut.csSeqPlayer) entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) - elif listOut.listType == "Misc": - for entryIn in listIn.misc: + elif listOut.listType == "MiscList": + for entryIn in listIn.miscList: entryOut = OOTCSMisc() entryOut.csMiscType = getCustomProperty(entryIn, "csMiscType") entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) - elif listOut.listType == "Rumble": - for entryIn in listIn.nine: - entryOut = OOTCS0x09() + elif listOut.listType == "RumbleList": + for entryIn in listIn.rumbleList: + entryOut = OOTCSRumble() entryOut.startFrame = entryIn.startFrame entryOut.rumbleSourceStrength = entryIn.rumbleSourceStrength entryOut.rumbleDuration = entryIn.rumbleDuration diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index c2648bd45..99f3ae576 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -58,7 +58,7 @@ def addButton(row): box.label(text="Install zcamedit for camera/actor motion.") -class OOTCSTextboxAdd(Operator): +class OOTCSTextAdd(Operator): bl_idname = "object.oot_cstextbox_add" bl_label = "Add CS Textbox" bl_options = {"REGISTER", "UNDO"} @@ -175,7 +175,7 @@ def invoke(self, context, event): oot_cutscene_classes = ( - OOTCSTextboxAdd, + OOTCSTextAdd, OOTCSListAdd, OOT_ExportCutscene, OOT_ExportAllCutscenes, diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 631f3ccaa..2360ed210 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -5,7 +5,7 @@ from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName from ..oot_constants import ootEnumMusicSeq from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps -from .operators import OOTCSTextboxAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp +from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp from .constants import ( ootEnumCSTextboxType, ootEnumCSListType, @@ -234,7 +234,7 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT for l in range(3): addOp = row.operator( - OOTCSTextboxAdd.bl_idname, + OOTCSTextAdd.bl_idname, text="Add " + ootEnumCSTextboxType[l][1], icon=ootEnumCSTextboxTypeIcons[l], ) diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 223edac9c..8504877ce 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -27,7 +27,7 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): csData.source += ( (indent * 2) + ootEnumCSListTypeListC[list.listType] + "(" + ( - f"{list.fxType}, {list.fxStartFrame}, {list.fxEndFrame}" + f"{list.transitionType}, {list.transitionStartFrame}, {list.transitionEndFrame}" if list.listType == "Transition" else str(len(list.entries)) ) + "),\n" @@ -47,7 +47,7 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): if list.listType == "TextList": if e.textboxType == "Text": csData.source += ( - f"{e.textID}, {e.startFrame}, {e.endFrame}, {e.textboxType}, {e.topOptionTextID}, {e.bottomOptionTextID}" + f"{e.textID}, {e.startFrame}, {e.endFrame}, {e.textType}, {e.topOptionTextID}, {e.bottomOptionTextID}" ) elif e.textboxType == "None": @@ -71,7 +71,8 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): elif list.listType in ["StartSeqList", "StopSeqList", "FadeOutSeqList"]: endFrame = e.endFrame if list.listType == "FadeOutSeqList" else "0" - csData.source += f"{e.csSeqID}, {e.startFrame}, {endFrame}" + (", 0" * 8) + firstArg = e.csSeqPlayer if list.listType == "FadeOutSeqList" else e.csSeqID + csData.source += f"{firstArg}, {e.startFrame}, {endFrame}" + (", 0" * 8) elif list.listType == "MiscList": csData.source += f"{e.csMiscType}, {e.startFrame}, {e.endFrame}" + (", 0" * 11) From a70f877a92c06bafe0f5fcf6e8966af4c7eebf71 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:45:51 +0100 Subject: [PATCH 11/39] black --- fast64_internal/oot/cutscene/constants.py | 240 ++++++++++++++---- fast64_internal/oot/cutscene/properties.py | 13 +- fast64_internal/oot/oot_constants.py | 6 +- fast64_internal/oot/oot_level_writer.py | 4 +- fast64_internal/oot/oot_upgrade.py | 4 - .../oot/scene/exporter/to_c/scene_cutscene.py | 24 +- 6 files changed, 226 insertions(+), 65 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 094ddb3f5..0e7d08576 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -58,7 +58,11 @@ "OUTLINER_OB_FORCE_FIELD", ] -ootEnumCSTextboxType = [("Text", "Text", "Text"), ("None", "None", "None"), ("OcarinaAction", "Ocarina Action", "Learn Song")] +ootEnumCSTextboxType = [ + ("Text", "Text", "Text"), + ("None", "None", "None"), + ("OcarinaAction", "Ocarina Action", "Learn Song"), +] ootEnumCSTextboxTypeIcons = ["FILE_TEXT", "HIDE_ON", "FILE_SOUND"] @@ -127,33 +131,101 @@ ("CS_DEST_DEATH_MOUNTAIN_TRAIL_NAYRU", "Death Mountain Trail Nayru", "Death Mountain Trail Nayru"), ("CS_DEST_KOKIRI_FOREST_FARORE", "Kokiri Forest Farore", "Kokiri Forest Farore"), ("CS_DEST_CUTSCENE_MAP_TRIFORCE_CREATION", "Cutscene Map Triforce Creation", "Cutscene Map Triforce Creation"), - ("CS_DEST_KOKIRI_FOREST_RECEIVE_KOKIRI_EMERALD", "Kokiri Forest Receive Kokiri Emerald", "Kokiri Forest Receive Kokiri Emerald"), - ("CS_DEST_TEMPLE_OF_TIME_FROM_MASTER_SWORD", "Temple Of Time From Master Sword", "Temple Of Time From Master Sword"), + ( + "CS_DEST_KOKIRI_FOREST_RECEIVE_KOKIRI_EMERALD", + "Kokiri Forest Receive Kokiri Emerald", + "Kokiri Forest Receive Kokiri Emerald", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_FROM_MASTER_SWORD", + "Temple Of Time From Master Sword", + "Temple Of Time From Master Sword", + ), ("CS_DEST_GERUDO_VALLEY_DIN_PART_2", "Gerudo Valley Din Part 2", "Gerudo Valley Din Part 2"), ("CS_DEST_LINKS_HOUSE_INTRO", "Links House Intro", "Links House Intro"), ("CS_DEST_KOKIRI_FOREST_INTRO", "Kokiri Forest Intro", "Kokiri Forest Intro"), - ("CS_DEST_DEATH_MOUNTAIN_TRAIL_FROM_GORON_RUBY", "Death Mountain Trail From Goron Ruby", "Death Mountain Trail From Goron Ruby"), - ("CS_DEST_ZORAS_FOUNTAIN_FROM_ZORAS_SAPPHIRE", "Zoras Fountain From Zoras Sapphire", "Zoras Fountain From Zoras Sapphire"), - ("CS_DEST_KOKIRI_FOREST_FROM_KOKIRI_EMERALD", "Kokiri Forest From Kokiri Emerald", "Kokiri Forest From Kokiri Emerald"), - ("CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED", "Temple Of Time Kokiri Emerald Restored", "Temple Of Time Kokiri Emerald Restored"), - ("CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED", "Temple Of Time Goron Ruby Restored", "Temple Of Time Goron Ruby Restored"), - ("CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED", "Temple Of Time Zoras Sapphire Restored", "Temple Of Time Zoras Sapphire Restored"), - ("CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION", "Temple Of Time After Light Medallion", "Temple Of Time After Light Medallion"), + ( + "CS_DEST_DEATH_MOUNTAIN_TRAIL_FROM_GORON_RUBY", + "Death Mountain Trail From Goron Ruby", + "Death Mountain Trail From Goron Ruby", + ), + ( + "CS_DEST_ZORAS_FOUNTAIN_FROM_ZORAS_SAPPHIRE", + "Zoras Fountain From Zoras Sapphire", + "Zoras Fountain From Zoras Sapphire", + ), + ( + "CS_DEST_KOKIRI_FOREST_FROM_KOKIRI_EMERALD", + "Kokiri Forest From Kokiri Emerald", + "Kokiri Forest From Kokiri Emerald", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED", + "Temple Of Time Kokiri Emerald Restored", + "Temple Of Time Kokiri Emerald Restored", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED", + "Temple Of Time Goron Ruby Restored", + "Temple Of Time Goron Ruby Restored", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED", + "Temple Of Time Zoras Sapphire Restored", + "Temple Of Time Zoras Sapphire Restored", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION", + "Temple Of Time After Light Medallion", + "Temple Of Time After Light Medallion", + ), ("CS_DEST_DEATH_MOUNTAIN_TRAIL", "Death Mountain Trail", "Death Mountain Trail"), ("CS_DEST_LAKE_HYLIA_WATER_RESTORED", "Lake Hylia Water Restored", "Lake Hylia Water Restored"), ("CS_DEST_DESERT_COLOSSUS_REQUIEM", "Desert Colossus Requiem", "Desert Colossus Requiem"), - ("CS_DEST_CUTSCENE_MAP_GANONDORF_DEFEATED_CREDITS", "Cutscene Map Ganondorf Defeated Credits", "Cutscene Map Ganondorf Defeated Credits"), + ( + "CS_DEST_CUTSCENE_MAP_GANONDORF_DEFEATED_CREDITS", + "Cutscene Map Ganondorf Defeated Credits", + "Cutscene Map Ganondorf Defeated Credits", + ), ("CS_DEST_JABU_JABU", "Jabu Jabu", "Jabu Jabu"), - ("CS_DEST_CHAMBER_OF_SAGES_LIGHT_MEDALLION", "Chamber Of Sages Light Medallion", "Chamber Of Sages Light Medallion"), - ("CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED_2", "Temple Of Time Kokiri Emerald Restored 2", "Temple Of Time Kokiri Emerald Restored 2"), - ("CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED_2", "Temple Of Time Goron Ruby Restored 2", "Temple Of Time Goron Ruby Restored 2"), - ("CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED_2", "Temple Of Time Zoras Sapphire Restored 2", "Temple Of Time Zoras Sapphire Restored 2"), - ("CS_DEST_CHAMBER_OF_SAGES_FOREST_MEDALLION", "Chamber Of Sages Forest Medallion", "Chamber Of Sages Forest Medallion"), + ( + "CS_DEST_CHAMBER_OF_SAGES_LIGHT_MEDALLION", + "Chamber Of Sages Light Medallion", + "Chamber Of Sages Light Medallion", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED_2", + "Temple Of Time Kokiri Emerald Restored 2", + "Temple Of Time Kokiri Emerald Restored 2", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED_2", + "Temple Of Time Goron Ruby Restored 2", + "Temple Of Time Goron Ruby Restored 2", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED_2", + "Temple Of Time Zoras Sapphire Restored 2", + "Temple Of Time Zoras Sapphire Restored 2", + ), + ( + "CS_DEST_CHAMBER_OF_SAGES_FOREST_MEDALLION", + "Chamber Of Sages Forest Medallion", + "Chamber Of Sages Forest Medallion", + ), ("CS_DEST_CHAMBER_OF_SAGES_FIRE_MEDALLION", "Chamber Of Sages Fire Medallion", "Chamber Of Sages Fire Medallion"), - ("CS_DEST_CHAMBER_OF_SAGES_WATER_MEDALLION", "Chamber Of Sages Water Medallion", "Chamber Of Sages Water Medallion"), + ( + "CS_DEST_CHAMBER_OF_SAGES_WATER_MEDALLION", + "Chamber Of Sages Water Medallion", + "Chamber Of Sages Water Medallion", + ), ("CS_DEST_HYRULE_FIELD_FLASHBACK", "Hyrule Field Flashback", "Hyrule Field Flashback"), ("CS_DEST_HYRULE_FIELD_FROM_ZELDA_ESCAPE", "Hyrule Field From Zelda Escape", "Hyrule Field From Zelda Escape"), - ("CS_DEST_CUTSCENE_MAP_GANONDORF_FROM_MASTER_SWORD", "Cutscene Map Ganondorf From Master Sword", "Cutscene Map Ganondorf From Master Sword"), + ( + "CS_DEST_CUTSCENE_MAP_GANONDORF_FROM_MASTER_SWORD", + "Cutscene Map Ganondorf From Master Sword", + "Cutscene Map Ganondorf From Master Sword", + ), ("CS_DEST_HYRULE_FIELD_INTRO_DREAM", "Hyrule Field Intro Dream", "Hyrule Field Intro Dream"), ("CS_DEST_CUTSCENE_MAP_SHEIKAH_LEGEND", "Cutscene Map Sheikah Legend", "Cutscene Map Sheikah Legend"), ("CS_DEST_TEMPLE_OF_TIME_ZELDA_REVEAL", "Temple Of Time Zelda Reveal", "Temple Of Time Zelda Reveal"), @@ -161,19 +233,43 @@ ("CS_DEST_LAKE_HYLIA_FROM_LAKE_RESTORED", "Lake Hylia From Lake Restored", "Lake Hylia From Lake Restored"), ("CS_DEST_KAKARIKO_VILLAGE_DRAIN_WELL", "Kakariko Village Drain Well", "Kakariko Village Drain Well"), ("CS_DEST_WINDMILL_FROM_WELL_DRAINED", "Windmill From Well Drained", "Windmill From Well Drained"), - ("CS_DEST_TEMPLE_OF_TIME_FROM_ALL_STONES_RESTORED", "Temple Of Time From All Stones Restored", "Temple Of Time From All Stones Restored"), - ("CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION_ALT", "Temple Of Time After Light Medallion Alt", "Temple Of Time After Light Medallion Alt"), - ("CS_DEST_KAKARIKO_VILLAGE_NOCTURNE_PART_2", "Kakariko Village Nocturne Part 2", "Kakariko Village Nocturne Part 2"), + ( + "CS_DEST_TEMPLE_OF_TIME_FROM_ALL_STONES_RESTORED", + "Temple Of Time From All Stones Restored", + "Temple Of Time From All Stones Restored", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION_ALT", + "Temple Of Time After Light Medallion Alt", + "Temple Of Time After Light Medallion Alt", + ), + ( + "CS_DEST_KAKARIKO_VILLAGE_NOCTURNE_PART_2", + "Kakariko Village Nocturne Part 2", + "Kakariko Village Nocturne Part 2", + ), ("CS_DEST_DESERT_COLOSSUS_FROM_REQUIEM", "Desert Colossus From Requiem", "Desert Colossus From Requiem"), - ("CS_DEST_TEMPLE_OF_TIME_FROM_LIGHT_ARROWS", "Temple Of Time From Light Arrows", "Temple Of Time From Light Arrows"), + ( + "CS_DEST_TEMPLE_OF_TIME_FROM_LIGHT_ARROWS", + "Temple Of Time From Light Arrows", + "Temple Of Time From Light Arrows", + ), ("CS_DEST_KAKARIKO_VILLAGE_FROM_NOCTURNE", "Kakariko Village From Nocturne", "Kakariko Village From Nocturne"), - ("CS_DEST_HYRULE_FIELD_FROM_ZELDAS_COURTYARD", "Hyrule Field From Zeldas Courtyard", "Hyrule Field From Zeldas Courtyard"), + ( + "CS_DEST_HYRULE_FIELD_FROM_ZELDAS_COURTYARD", + "Hyrule Field From Zeldas Courtyard", + "Hyrule Field From Zeldas Courtyard", + ), ("CS_DEST_TEMPLE_OF_TIME_SONG_OF_TIME", "Temple Of Time Song Of Time", "Temple Of Time Song Of Time"), ("CS_DEST_HYRULE_FIELD_FROM_SONG_OF_TIME", "Hyrule Field From Song Of Time", "Hyrule Field From Song Of Time"), ("CS_DEST_GERUDO_VALLEY_CREDITS", "Gerudo Valley Credits", "Gerudo Valley Credits"), ("CS_DEST_GERUDO_FORTRESS_CREDITS", "Gerudo Fortress Credits", "Gerudo Fortress Credits"), ("CS_DEST_KAKARIKO_VILLAGE_CREDITS", "Kakariko Village Credits", "Kakariko Village Credits"), - ("CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_1", "Death Mountain Trail Credits Part 1", "Death Mountain Trail Credits Part 1"), + ( + "CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_1", + "Death Mountain Trail Credits Part 1", + "Death Mountain Trail Credits Part 1", + ), ("CS_DEST_GORON_CITY_CREDITS", "Goron City Credits", "Goron City Credits"), ("CS_DEST_LAKE_HYLIA_CREDITS", "Lake Hylia Credits", "Lake Hylia Credits"), ("CS_DEST_ZORAS_FOUNTAIN_CREDITS", "Zoras Fountain Credits", "Zoras Fountain Credits"), @@ -181,12 +277,28 @@ ("CS_DEST_KOKIRI_FOREST_CREDITS_PART_1", "Kokiri Forest Credits Part 1", "Kokiri Forest Credits Part 1"), ("CS_DEST_KOKIRI_FOREST_CREDITS_PART_2", "Kokiri Forest Credits Part 2", "Kokiri Forest Credits Part 2"), ("CS_DEST_HYRULE_FIELD_CREDITS", "Hyrule Field Credits", "Hyrule Field Credits"), - ("CS_DEST_LON_LON_RANCH_CREDITS_PART_1_ALT", "Lon Lon Ranch Credits Part 1 Alt", "Lon Lon Ranch Credits Part 1 Alt"), + ( + "CS_DEST_LON_LON_RANCH_CREDITS_PART_1_ALT", + "Lon Lon Ranch Credits Part 1 Alt", + "Lon Lon Ranch Credits Part 1 Alt", + ), ("CS_DEST_KAKARIKO_VILLAGE_FROM_TRAIL_OWL", "Kakariko Village From Trail Owl", "Kakariko Village From Trail Owl"), - ("CS_DEST_HYRULE_FIELD_FROM_LAKE_HYLIA_OWL", "Hyrule Field From Lake Hylia Owl", "Hyrule Field From Lake Hylia Owl"), + ( + "CS_DEST_HYRULE_FIELD_FROM_LAKE_HYLIA_OWL", + "Hyrule Field From Lake Hylia Owl", + "Hyrule Field From Lake Hylia Owl", + ), ("CS_DEST_CUTSCENE_MAP_DEKU_SPROUT_PART_2", "Cutscene Map Deku Sprout Part 2", "Cutscene Map Deku Sprout Part 2"), - ("CS_DEST_KOKIRI_FOREST_DEKU_SPROUT_PART_3", "Kokiri Forest Deku Sprout Part 3", "Kokiri Forest Deku Sprout Part 3"), - ("CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_2", "Death Mountain Trail Credits Part 2", "Death Mountain Trail Credits Part 2"), + ( + "CS_DEST_KOKIRI_FOREST_DEKU_SPROUT_PART_3", + "Kokiri Forest Deku Sprout Part 3", + "Kokiri Forest Deku Sprout Part 3", + ), + ( + "CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_2", + "Death Mountain Trail Credits Part 2", + "Death Mountain Trail Credits Part 2", + ), ("CS_DEST_TEMPLE_OF_TIME_CREDITS", "Temple Of Time Credits", "Temple Of Time Credits"), ("CS_DEST_ZELDAS_COURTYARD_CREDITS", "Zeldas Courtyard Credits", "Zeldas Courtyard Credits"), ("CS_DEST_LON_LON_RANCH_CREDITS_PART_1", "Lon Lon Ranch Credits Part 1", "Lon Lon Ranch Credits Part 1"), @@ -212,27 +324,71 @@ ("CS_DEST_LON_LON_RANCH_15", "Lon Lon Ranch 15", "Lon Lon Ranch 15"), ("CS_DEST_LON_LON_RANCH_FROM_EPONAS_SONG", "Lon Lon Ranch From Eponas Song", "Lon Lon Ranch From Eponas Song"), ("CS_DEST_STONES_RESTORED_CONDITIONAL", "Stones Restored Conditional", "Stones Restored Conditional"), - ("CS_DEST_DESERT_COLOSSUS_FROM_CHAMBER_OF_SAGES", "Desert Colossus From Chamber Of Sages", "Desert Colossus From Chamber Of Sages"), + ( + "CS_DEST_DESERT_COLOSSUS_FROM_CHAMBER_OF_SAGES", + "Desert Colossus From Chamber Of Sages", + "Desert Colossus From Chamber Of Sages", + ), ("CS_DEST_GRAVEYARD_FROM_CHAMBER_OF_SAGES", "Graveyard From Chamber Of Sages", "Graveyard From Chamber Of Sages"), - ("CS_DEST_DEATH_MOUNTAIN_CRATER_FROM_CHAMBER_OF_SAGES", "Death Mountain Crater From Chamber Of Sages", "Death Mountain Crater From Chamber Of Sages"), + ( + "CS_DEST_DEATH_MOUNTAIN_CRATER_FROM_CHAMBER_OF_SAGES", + "Death Mountain Crater From Chamber Of Sages", + "Death Mountain Crater From Chamber Of Sages", + ), ("CS_DEST_SACRED_FOREST_MEADOW_WARP_PAD", "Sacred Forest Meadow Warp Pad", "Sacred Forest Meadow Warp Pad"), - ("CS_DEST_KOKIRI_FOREST_FROM_CHAMBER_OF_SAGES", "Kokiri Forest From Chamber Of Sages", "Kokiri Forest From Chamber Of Sages"), - ("CS_DEST_DESERT_COLOSSUS_FROM_NABOORU_CAPTURE", "Desert Colossus From Nabooru Capture", "Desert Colossus From Nabooru Capture"), - ("CS_DEST_TEMPLE_OF_TIME_FRONT_OF_PEDESTAL", "Temple Of Time Front Of Pedestal", "Temple Of Time Front Of Pedestal"), + ( + "CS_DEST_KOKIRI_FOREST_FROM_CHAMBER_OF_SAGES", + "Kokiri Forest From Chamber Of Sages", + "Kokiri Forest From Chamber Of Sages", + ), + ( + "CS_DEST_DESERT_COLOSSUS_FROM_NABOORU_CAPTURE", + "Desert Colossus From Nabooru Capture", + "Desert Colossus From Nabooru Capture", + ), + ( + "CS_DEST_TEMPLE_OF_TIME_FRONT_OF_PEDESTAL", + "Temple Of Time Front Of Pedestal", + "Temple Of Time Front Of Pedestal", + ), ("CS_DEST_HYRULE_FIELD_TITLE_SCREEN", "Hyrule Field Title Screen", "Hyrule Field Title Screen"), ("CS_DEST_TITLE_SCREEN_DEMO", "Title Screen Demo", "Title Screen Demo"), ("CS_DEST_GRAVEYARD_SUNS_SONG_PART_2", "Graveyard Suns Song Part 2", "Graveyard Suns Song Part 2"), - ("CS_DEST_ROYAL_FAMILYS_TOMB_SUNS_SONG_PART_3", "Royal Familys Tomb Suns Song Part 3", "Royal Familys Tomb Suns Song Part 3"), - ("CS_DEST_GANONS_CASTLE_DISPEL_FOREST_BEAM", "Ganons Castle Dispel Forest Beam", "Ganons Castle Dispel Forest Beam"), + ( + "CS_DEST_ROYAL_FAMILYS_TOMB_SUNS_SONG_PART_3", + "Royal Familys Tomb Suns Song Part 3", + "Royal Familys Tomb Suns Song Part 3", + ), + ( + "CS_DEST_GANONS_CASTLE_DISPEL_FOREST_BEAM", + "Ganons Castle Dispel Forest Beam", + "Ganons Castle Dispel Forest Beam", + ), ("CS_DEST_GANONS_CASTLE_DISPEL_WATER_BEAM", "Ganons Castle Dispel Water Beam", "Ganons Castle Dispel Water Beam"), - ("CS_DEST_GANONS_CASTLE_DISPEL_SHADOW_BEAM", "Ganons Castle Dispel Shadow Beam", "Ganons Castle Dispel Shadow Beam"), + ( + "CS_DEST_GANONS_CASTLE_DISPEL_SHADOW_BEAM", + "Ganons Castle Dispel Shadow Beam", + "Ganons Castle Dispel Shadow Beam", + ), ("CS_DEST_GANONS_CASTLE_DISPEL_FIRE_BEAM", "Ganons Castle Dispel Fire Beam", "Ganons Castle Dispel Fire Beam"), ("CS_DEST_GANONS_CASTLE_DISPEL_LIGHT_BEAM", "Ganons Castle Dispel Light Beam", "Ganons Castle Dispel Light Beam"), - ("CS_DEST_GANONS_CASTLE_DISPEL_SPIRIT_BEAM", "Ganons Castle Dispel Spirit Beam", "Ganons Castle Dispel Spirit Beam"), - ("CS_DEST_GANONS_CASTLE_DISPEL_BARRIER_CONDITONAL", "Ganons Castle Dispel Barrier Conditonal", "Ganons Castle Dispel Barrier Conditonal"), + ( + "CS_DEST_GANONS_CASTLE_DISPEL_SPIRIT_BEAM", + "Ganons Castle Dispel Spirit Beam", + "Ganons Castle Dispel Spirit Beam", + ), + ( + "CS_DEST_GANONS_CASTLE_DISPEL_BARRIER_CONDITONAL", + "Ganons Castle Dispel Barrier Conditonal", + "Ganons Castle Dispel Barrier Conditonal", + ), ("CS_DEST_HYRULE_FIELD_FROM_FAIRY_OCARINA", "Hyrule Field From Fairy Ocarina", "Hyrule Field From Fairy Ocarina"), ("CS_DEST_HYRULE_FIELD_FROM_IMPA_ESCORT", "Hyrule Field From Impa Escort", "Hyrule Field From Impa Escort"), - ("CS_DEST_FROM_RAURU_FINAL_MESSAGE_CONDITIONAL", "From Rauru Final Message Conditional", "From Rauru Final Message Conditional"), + ( + "CS_DEST_FROM_RAURU_FINAL_MESSAGE_CONDITIONAL", + "From Rauru Final Message Conditional", + "From Rauru Final Message Conditional", + ), ("CS_DEST_HYRULE_FIELD_CREDITS_SKY", "Hyrule Field Credits Sky", "Hyrule Field Credits Sky"), ("CS_DEST_GANON_BATTLE_TOWER_COLLAPSE", "Ganon Battle Tower Collapse", "Ganon Battle Tower Collapse"), ("CS_DEST_ZELDAS_COURTYARD_RECEIVE_LETTER", "Zeldas Courtyard Receive Letter", "Zeldas Courtyard Receive Letter"), @@ -288,7 +444,6 @@ ootCSSubPropToName = { "startFrame": "Start Frame", "endFrame": "End Frame", - # TextBox "textID": "Text ID", "ocarinaAction": "Ocarina Action", @@ -296,21 +451,16 @@ "topOptionTextID": "Text ID for Top Option", "bottomOptionTextID": "Text ID for Bottom Option", "ocarinaMessageId": "Ocarina Message ID", - # Lighting "lightSettingsIndex": "Light Settings Index", - # Time "hour": "Hour", "minute": "Minute", - # Seq "csSeqID": "Seq ID", "csSeqPlayer": "Seq Player Type", - # Misc "csMiscType": "Misc Type", - # Rumble "rumbleSourceStrength": "Source Strength", "rumbleDuration": "Duration", diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 2360ed210..c1e4d0282 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -98,7 +98,9 @@ class OOTCSTextProperty(OOTCutsceneCommon, PropertyGroup): # subprops textID: StringProperty(name="", default="0x0000") - ocarinaAction: EnumProperty(name="Ocarina Action", items=ootEnumOcarinaAction, default="OCARINA_ACTION_TEACH_MINUET") + ocarinaAction: EnumProperty( + name="Ocarina Action", items=ootEnumOcarinaAction, default="OCARINA_ACTION_TEACH_MINUET" + ) ocarinaActionCustom: StringProperty(default="OCARINA_ACTION_CUSTOM") topOptionTextID: StringProperty(name="", default="0x0000") bottomOptionTextID: StringProperty(name="", default="0x0000") @@ -244,7 +246,9 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT addOp.listIndex = listIndex addOp.objName = objName else: - addOp = box.operator(OOTCollectionAdd.bl_idname, text="Add item to " + getEnumName(ootEnumCSListType, self.listType)) + addOp = box.operator( + OOTCollectionAdd.bl_idname, text="Add item to " + getEnumName(ootEnumCSListType, self.listType) + ) addOp.option = len(dat) addOp.collectionType = collectionType + "." + attrName addOp.subIndex = listIndex @@ -263,7 +267,9 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT class OOTCutsceneProperty(PropertyGroup): csEndFrame: IntProperty(name="End Frame", min=0, default=100) csWriteTerminator: BoolProperty(name="Cutscene Destination (Scene Change)") - csDestination: EnumProperty(name="Destination", items=ootEnumCSDestinationType, default="CS_DEST_CUTSCENE_MAP_GANON_HORSE") + csDestination: EnumProperty( + name="Destination", items=ootEnumCSDestinationType, default="CS_DEST_CUTSCENE_MAP_GANON_HORSE" + ) csDestinationCustom: StringProperty(default="CS_DEST_CUSTOM") csTermIdx: IntProperty(name="Index", min=0) csTermStart: IntProperty(name="Start Frame", min=0, default=99) @@ -284,7 +290,6 @@ def upgrade_object(obj): for csListSubProp in getattr(csListProp, listName): upgradeCutsceneSubProps(csListSubProp) - def draw_props(self, layout: UILayout, obj: Object): layout.prop(self, "csEndFrame") diff --git a/fast64_internal/oot/oot_constants.py b/fast64_internal/oot/oot_constants.py index a3d9cf169..119b22b2a 100644 --- a/fast64_internal/oot/oot_constants.py +++ b/fast64_internal/oot/oot_constants.py @@ -193,7 +193,11 @@ ("NA_BGM_GENERAL_SFX", "General Sound Effects", "General Sound Effects"), ("NA_BGM_NATURE_AMBIENCE", "Nature Ambiance", "Nature Ambiance"), ("NA_BGM_FIELD_LOGIC", "Hyrule Field", "Hyrule Field"), - ("NA_BGM_FIELD_INIT", "Hyrule Field (Initial Segment From Loading Area)", "Hyrule Field (Initial Segment From Loading Area)"), + ( + "NA_BGM_FIELD_INIT", + "Hyrule Field (Initial Segment From Loading Area)", + "Hyrule Field (Initial Segment From Loading Area)", + ), ("NA_BGM_FIELD_DEFAULT_1", "Hyrule Field (Moving Segment 1)", "Hyrule Field (Moving Segment 1)"), ("NA_BGM_FIELD_DEFAULT_2", "Hyrule Field (Moving Segment 2)", "Hyrule Field (Moving Segment 2)"), ("NA_BGM_FIELD_DEFAULT_3", "Hyrule Field (Moving Segment 3)", "Hyrule Field (Moving Segment 3)"), diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index 8abfcb314..2058cbba0 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -235,7 +235,7 @@ def readSceneData( scene: OOTScene, scene_properties: OOTSceneProperties, sceneHeader: OOTSceneHeaderProperty, - alternateSceneHeaders: OOTAlternateSceneHeaderProperty + alternateSceneHeaders: OOTAlternateSceneHeaderProperty, ): scene.write_dummy_room_list = scene_properties.write_dummy_room_list scene.sceneTableEntry.drawConfig = getCustomProperty(sceneHeader.sceneTableEntry, "drawConfig") @@ -282,7 +282,7 @@ def readSceneData( elif scene.csWriteType == "Custom": scene.csWriteCustom = getCustomProperty(sceneHeader, "csWriteCustom") - + elif scene.csWriteType == "Object": if sceneHeader.csWriteObject is None: raise PluginError("No object selected for cutscene reference") diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 60d47e24b..5d5078f38 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -135,10 +135,8 @@ def upgradeCutsceneSubProps(csListSubProp): "messageId": "textID", "topOptionBranch": "topOptionTextID", "bottomOptionBranch": "bottomOptionTextID", - # Lighting "index": "lightSettingsIndex", - # Rumble "unk2": "rumbleSourceStrength", "unk3": "rumbleDuration", @@ -149,10 +147,8 @@ def upgradeCutsceneSubProps(csListSubProp): # TextBox ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), ("type", "csTextType", ootEnumTextType), - # Seq ("value", "csSeqID", ootEnumMusicSeq), - # Misc ("operation", "csMiscType", ootEnumCSMiscType), ] diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 8504877ce..98ac0b32f 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -14,21 +14,26 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): # .c csData.source = ( - arrayName + " = {\n" + arrayName + + " = {\n" + (indent + f"CS_BEGIN_CUTSCENE({nentries}, {csParent.csEndFrame}),\n") + ( (indent * 2) + f"CS_DESTINATION({csParent.csTermIdx}, {csParent.csTermStart}, {csParent.csTermEnd}),\n" - if csParent.csWriteTerminator else "" + if csParent.csWriteTerminator + else "" ) ) for list in csParent.csLists: # CS "XXXX List" Command csData.source += ( - (indent * 2) + ootEnumCSListTypeListC[list.listType] + "(" + (indent * 2) + + ootEnumCSListTypeListC[list.listType] + + "(" + ( f"{list.transitionType}, {list.transitionStartFrame}, {list.transitionEndFrame}" - if list.listType == "Transition" else str(len(list.entries)) + if list.listType == "Transition" + else str(len(list.entries)) ) + "),\n" ) @@ -39,16 +44,15 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): + ( ootEnumCSTextboxTypeEntryC[e.textboxType] # @TODO make a separate variable for ``ootEnumCSListTypeEntryC`` - if list.listType == "TextList" else ootEnumCSListTypeEntryC[list.listType.replace("List", "")] + if list.listType == "TextList" + else ootEnumCSListTypeEntryC[list.listType.replace("List", "")] ) + "(" ) if list.listType == "TextList": if e.textboxType == "Text": - csData.source += ( - f"{e.textID}, {e.startFrame}, {e.endFrame}, {e.textType}, {e.topOptionTextID}, {e.bottomOptionTextID}" - ) + csData.source += f"{e.textID}, {e.startFrame}, {e.endFrame}, {e.textType}, {e.topOptionTextID}, {e.bottomOptionTextID}" elif e.textboxType == "None": csData.source += f"{e.startFrame}, {e.endFrame}" @@ -67,7 +71,9 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): elif list.listType == "RumbleList": # same as above - csData.source += f"0, {e.startFrame}, 0, {e.rumbleSourceStrength}, {e.rumbleDuration}, {e.rumbleDecreaseRate}, 0, 0" + csData.source += ( + f"0, {e.startFrame}, 0, {e.rumbleSourceStrength}, {e.rumbleDuration}, {e.rumbleDecreaseRate}, 0, 0" + ) elif list.listType in ["StartSeqList", "StopSeqList", "FadeOutSeqList"]: endFrame = e.endFrame if list.listType == "FadeOutSeqList" else "0" From 28bc02f79307a5a9bda4f6a74ba0372407902d08 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 13 Jan 2023 13:50:13 +0100 Subject: [PATCH 12/39] ``OOTCutsceneProperty`` rename & upgrade and other minor changes --- .../oot/cutscene/exporter/classes.py | 7 ++- .../oot/cutscene/exporter/functions.py | 7 ++- fast64_internal/oot/cutscene/properties.py | 20 ++++----- fast64_internal/oot/oot_level_classes.py | 6 +-- fast64_internal/oot/oot_level_writer.py | 6 +-- fast64_internal/oot/oot_upgrade.py | 44 +++++++++++++++++-- .../oot/scene/exporter/to_c/scene_cutscene.py | 6 +-- fast64_internal/oot/scene/properties.py | 16 +++---- 8 files changed, 70 insertions(+), 42 deletions(-) diff --git a/fast64_internal/oot/cutscene/exporter/classes.py b/fast64_internal/oot/cutscene/exporter/classes.py index a6811884a..df8f150cc 100644 --- a/fast64_internal/oot/cutscene/exporter/classes.py +++ b/fast64_internal/oot/cutscene/exporter/classes.py @@ -60,8 +60,7 @@ class OOTCutscene: def __init__(self): self.name = "" self.csEndFrame = 100 - self.csWriteTerminator = False - self.csTermIdx = 0 - self.csTermStart = 99 - self.csTermEnd = 100 + self.csUseDestination = False + self.csDestination = 0 + self.csDestinationStartFrame = 99 self.csLists = [] diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index 3736f73cd..c683e6a62 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -83,10 +83,9 @@ def convertCutsceneObject(obj): cs.name = getCutsceneName(obj) csprop = obj.ootCutsceneProperty cs.csEndFrame = getCustomProperty(csprop, "csEndFrame") - cs.csWriteTerminator = getCustomProperty(csprop, "csWriteTerminator") - cs.csTermIdx = getCustomProperty(csprop, "csDestination") - cs.csTermStart = getCustomProperty(csprop, "csTermStart") - cs.csTermEnd = getCustomProperty(csprop, "csTermEnd") + cs.csUseDestination = getCustomProperty(csprop, "csUseDestination") + cs.csDestination = getCustomProperty(csprop, "csDestination") + cs.csDestinationStartFrame = getCustomProperty(csprop, "csDestinationStartFrame") readCutsceneData(cs, csprop) return cs diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index c1e4d0282..19d19e89c 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -4,7 +4,7 @@ from ...utility import PluginError, prop_split from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName from ..oot_constants import ootEnumMusicSeq -from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps +from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps, upgradeCutsceneProperty from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp from .constants import ( ootEnumCSTextboxType, @@ -266,14 +266,12 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT class OOTCutsceneProperty(PropertyGroup): csEndFrame: IntProperty(name="End Frame", min=0, default=100) - csWriteTerminator: BoolProperty(name="Cutscene Destination (Scene Change)") + csUseDestination: BoolProperty(name="Cutscene Destination (Scene Change)") csDestination: EnumProperty( name="Destination", items=ootEnumCSDestinationType, default="CS_DEST_CUTSCENE_MAP_GANON_HORSE" ) csDestinationCustom: StringProperty(default="CS_DEST_CUSTOM") - csTermIdx: IntProperty(name="Index", min=0) - csTermStart: IntProperty(name="Start Frame", min=0, default=99) - csTermEnd: IntProperty(name="End Frame", min=0, default=100) + csDestinationStartFrame: IntProperty(name="Start Frame", min=0, default=99) csLists: CollectionProperty(type=OOTCSListProperty, name="Cutscene Lists") @staticmethod @@ -283,7 +281,10 @@ def upgrade_object(obj): # using the new names since the old ones will be deleted before this is used csListsNames = ["textList", "lightSettingsList", "timeList", "seqList", "miscList", "rumbleList"] - for csListProp in obj.ootCutsceneProperty.csLists: + csProp: "OOTCutsceneProperty" = obj.ootCutsceneProperty + upgradeCutsceneProperty(csProp) + + for csListProp in csProp.csLists: upgradeCSListProps(csListProp) for listName in csListsNames: @@ -294,8 +295,8 @@ def draw_props(self, layout: UILayout, obj: Object): layout.prop(self, "csEndFrame") csDestLayout = layout.box() - csDestLayout.prop(self, "csWriteTerminator") - if self.csWriteTerminator: + csDestLayout.prop(self, "csUseDestination") + if self.csUseDestination: r = csDestLayout.row() searchBox = r.box() @@ -307,8 +308,7 @@ def draw_props(self, layout: UILayout, obj: Object): prop_split(searchBox.column(), self, "csDestinationCustom", "Cutscene Destination Custom") r = csDestLayout.row() - r.prop(self, "csTermStart") - r.prop(self, "csTermEnd") + r.prop(self, "csDestinationStartFrame") drawCSListAddOp(layout, obj.name, "Cutscene") diff --git a/fast64_internal/oot/oot_level_classes.py b/fast64_internal/oot/oot_level_classes.py index 185d03fb5..12ba953f7 100644 --- a/fast64_internal/oot/oot_level_classes.py +++ b/fast64_internal/oot/oot_level_classes.py @@ -115,10 +115,8 @@ def __init__(self, name, model): self.csWriteCustom = "" self.csWriteObject = None self.csEndFrame = 100 - self.csWriteTerminator = False - self.csTermIdx = 0 - self.csTermStart = 99 - self.csTermEnd = 100 + self.csUseDestination = False + self.csDestinationStartFrame = 99 self.csLists = [] self.extraCutscenes = [] diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index 2058cbba0..18d81430c 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -274,10 +274,8 @@ def readSceneData( if scene.csWriteType == "Embedded": scene.csEndFrame = getCustomProperty(sceneHeader, "csEndFrame") - scene.csWriteTerminator = getCustomProperty(sceneHeader, "csWriteTerminator") - scene.csTermIdx = getCustomProperty(sceneHeader, "csTermIdx") - scene.csTermStart = getCustomProperty(sceneHeader, "csTermStart") - scene.csTermEnd = getCustomProperty(sceneHeader, "csTermEnd") + scene.csUseDestination = getCustomProperty(sceneHeader, "csUseDestination") + scene.csDestinationStartFrame = getCustomProperty(sceneHeader, "csDestinationStartFrame") readCutsceneData(scene, sceneHeader) elif scene.csWriteType == "Custom": diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 5d5078f38..5b3d42729 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -7,9 +7,13 @@ ootEnumCSMiscType, ootEnumOcarinaAction, ootEnumCSTransitionType, + ootEnumCSDestinationType, ) +##################################### +# Room Header +##################################### def upgradeObjectList(objList: CollectionProperty, objData: OoT_ObjectData): """Transition to the XML object system""" for obj in objList: @@ -45,18 +49,22 @@ def upgradeRoomHeaders(roomObj: Object, objData: OoT_ObjectData): upgradeObjectList(altHeaders.cutsceneHeaders[i].objectList, objData) +##################################### +# Cutscene +##################################### def transferOldDataToNew(data, oldDataToNewData: dict): # conversion to the same prop type # simply transfer the old data to the new one # special case for rumble subprops where it's a string to int conversion for oldName, newName in oldDataToNewData.items(): if oldName in data: - value = data[oldName] + if newName is not None: + value = data[oldName] - if newName in ["rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"]: - value = int(getEvalParams(data[oldName]), base=16) + if newName in ["rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"]: + value = int(getEvalParams(data[oldName]), base=16) - data[newName] = value + data[newName] = value del data[oldName] @@ -141,6 +149,21 @@ def upgradeCutsceneSubProps(csListSubProp): "unk2": "rumbleSourceStrength", "unk3": "rumbleDuration", "unk4": "rumbleDecreaseRate", + # Unk (Deprecated) + "unk": None, + "unkType": None, + "unk1": None, + "unk2": None, + "unk3": None, + "unk4": None, + "unk5": None, + "unk6": None, + "unk7": None, + "unk8": None, + "unk9": None, + "unk10": None, + "unk11": None, + "unk12": None, } subPropsToEnum = [ @@ -175,3 +198,16 @@ def upgradeCSListProps(csListProp): # both are enums but the item list is different (the old one doesn't have a "custom" entry) convertOldDataToEnumData(csListProp, [("fxType", "transitionType", ootEnumCSTransitionType)]) + + +def upgradeCutsceneProperty(csProp): + # ``csProp`` type: ``OOTCutsceneProperty`` + + csPropOldToNew = { + "csWriteTerminator": "csUseDestination", + "csTermStart": "csDestinationStartFrame", + "csTermEnd": None, + } + + transferOldDataToNew(csProp, csPropOldToNew) + convertOldDataToEnumData(csProp, [("csTermIdx", "csDestination", ootEnumCSDestinationType)]) diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 98ac0b32f..4c4675002 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -7,7 +7,7 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): csData = CData() arrayName = f"CutsceneData {csName}[]" - nentries = len(csParent.csLists) + (1 if csParent.csWriteTerminator else 0) + nentries = len(csParent.csLists) + (1 if csParent.csUseDestination else 0) # .h csData.header = f"extern {arrayName};\n" @@ -18,8 +18,8 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): + " = {\n" + (indent + f"CS_BEGIN_CUTSCENE({nentries}, {csParent.csEndFrame}),\n") + ( - (indent * 2) + f"CS_DESTINATION({csParent.csTermIdx}, {csParent.csTermStart}, {csParent.csTermEnd}),\n" - if csParent.csWriteTerminator + (indent * 2) + f"CS_DESTINATION({csParent.csDestination}, {csParent.csDestinationStartFrame}, 0),\n" + if csParent.csUseDestination else "" ) ) diff --git a/fast64_internal/oot/scene/properties.py b/fast64_internal/oot/scene/properties.py index aaa03363d..4141b8b14 100644 --- a/fast64_internal/oot/scene/properties.py +++ b/fast64_internal/oot/scene/properties.py @@ -270,10 +270,9 @@ class OOTSceneHeaderProperty(PropertyGroup): # not been removed as doing so would break any existing scenes made with this # type of cutscene data. csEndFrame: IntProperty(name="End Frame", min=0, default=100) - csWriteTerminator: BoolProperty(name="Write Terminator (Code Execution)") - csTermIdx: IntProperty(name="Index", min=0) - csTermStart: IntProperty(name="Start Frm", min=0, default=99) - csTermEnd: IntProperty(name="End Frm", min=0, default=100) + csUseDestination: BoolProperty(name="Write Terminator (Code Execution)") + csDestination: IntProperty(name="Index", min=0) + csDestinationStartFrame: IntProperty(name="Start Frm", min=0, default=99) csLists: CollectionProperty(type=OOTCSListProperty, name="Cutscene Lists") extraCutscenes: CollectionProperty(type=OOTExtraCutsceneProperty, name="Extra Cutscenes") @@ -364,12 +363,11 @@ def draw_props(self, layout: UILayout, dropdownLabel: str, headerIndex: int, obj # of cutscene data. cutscene.label(text='Embedded cutscenes are deprecated. Please use "Object" instead.') cutscene.prop(self, "csEndFrame", text="End Frame") - cutscene.prop(self, "csWriteTerminator", text="Write Terminator (Code Execution)") - if self.csWriteTerminator: + cutscene.prop(self, "csUseDestination", text="Write Terminator (Code Execution)") + if self.csUseDestination: r = cutscene.row() - r.prop(self, "csTermIdx", text="Index") - r.prop(self, "csTermStart", text="Start Frm") - r.prop(self, "csTermEnd", text="End Frm") + r.prop(self, "csDestination", text="Index") + r.prop(self, "csDestinationStartFrame", text="Start Frm") collectionType = "CSHdr." + str(0 if headerIndex is None else headerIndex) drawCSListAddOp(cutscene, objName, collectionType) From 06bdce55f12d5d23155f3c0bfbf914c9d68b959e Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 13 Jan 2023 15:36:07 +0100 Subject: [PATCH 13/39] small UI changes, updated oot readme --- fast64_internal/oot/README.md | 19 ++++++++++++++----- .../oot/cutscene/exporter/functions.py | 14 +++++++++++--- fast64_internal/oot/cutscene/properties.py | 7 ++++++- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/fast64_internal/oot/README.md b/fast64_internal/oot/README.md index 69ba2e02d..428c759c6 100644 --- a/fast64_internal/oot/README.md +++ b/fast64_internal/oot/README.md @@ -32,9 +32,9 @@ Read the "Getting Started" section for information on scene exporting. To add an actor you need to create a new empty object in Blender, the shape doesn't matter. When the empty object is created you can set the ``Actor`` object type in the ``Object Properties`` panel. -To add actors to a scene, create a new Empty and parent it to a Room, otherwise they will not be exported in the room C code. Then in the Object Properties panel select ``Actor`` as the Object Type. Use the ``Select Actor ID`` button to choose an actor, and then set the Actor Parameter value as desired (see the list of Actor Parameters below). +To add actors to a scene, create a new Empty and parent it to a Room, otherwise they will not be exported in the room C code. Then in the Object Properties panel select ``Actor`` as the Object Type. Use the ``Select Actor ID`` button to choose an actor, and then set the Actor Parameter value as desired (see the list of Actor Parameters below). -Finally, every actors you are using needs their assets. In OoT they're called "Objects", if an actor is missing an object the code will not spawn the actor. To do this select the Room that your actor is parented to, select the "Objects" tab in its Object Properties window, and click "Add Item". +Finally, every actors you are using needs their assets. In OoT they're called "Objects", if an actor is missing an object the code will not spawn the actor. To do this select the Room that your actor is parented to, select the "Objects" tab in its Object Properties window, and click "Add Item". Then "Search Object ID" to find the actor object you need. For example, if adding a Deku Baba actor (EN_DEKUBABA) you need to add the "Dekubaba" object to the Room's object dependencies. Note that the object list must not contain more than 15 items. @@ -82,7 +82,7 @@ To import an animation, select the armature the animation belongs to then click To export an animation, select an armature and click "Export", which will export the active animation of the armature. ### Flipbook Textures -Many actors in OOT will animate textures through code using a flipbook method, like with Link's eyes/mouth. A flipbook material will use a texture reference pointing to an address formatted as 0x0?000000. You can find the flipbook texture frames in the material properties tab underneath the dynamic material section. +Many actors in OOT will animate textures through code using a flipbook method, like with Link's eyes/mouth. A flipbook material will use a texture reference pointing to an address formatted as 0x0?000000. You can find the flipbook texture frames in the material properties tab underneath the dynamic material section. ![](/images/oot_flipbook.png) On import, Fast64 will try to read the provided actors code for flipbook textures. On export, Fast64 will try to modify texture arrays used for flipbook textures. @@ -107,7 +107,7 @@ For Link, the eyes/mouth materials use flipbook textures. For Link animations yo 11. Common Issues: - Corrupted mesh: Make sure the root, upper control, and lower control bones are the only bones set to non-deform. - Incorrect waist DL: Go to src/code/z_player_lib.c and modify sPlayerWaistDLs to include your own waist DL. - + Note on Link's bone-weighting requirements in depth: Heavy modifications of Links model can cause his matrices array to shift from what many display lists in the game expect. Changing the amount of display lists Link's skeleton has can cause some references to matrices in segment 0xD to break, and those display lists must be updated to reflect your changes. @@ -140,7 +140,7 @@ To create custom cutscenes you need to get [zcamedit, made by Sauraen](https://g To get more informations about the game's cutscene system/camera system, read [zcamedit's readme](https://github.com/sauraen/zcamedit#setting-up-a-cutscene) -Note: a "cutscene terminator" is a cutscene command that makes a scene transition. For example, this is used in the intro cutscene or in the credits. +Note: a cutscene "destination", (previously called "terminator"), is a cutscene command that makes a scene transition. For example, this is used in the intro cutscene or in the credits to run another cutscene from another scene.
Armature Data Properties Panel @@ -166,8 +166,17 @@ To be able to actually watch your cutscene you need to have a way to trigger it, - ``gHyruleFieldIntroCs`` is the name of the array with the cutscene commands, as defined in ``assets/scenes/overworld/spot00_scene.c``, ``CutsceneData gHyruleFieldIntroCs[]`` 4. Compile the game again and use the entrance you chose for ``sEntranceCutsceneTable`` and your cutscene should play. +Alternatively, you can use the map select to watch your cutscene, though note that this won't make it watchable during normal gameplay: + +1. Open ``src/overlays/gamestates/ovl_select/z_select.c`` +2. Either edit or add an entry inside ``SceneSelectEntry sScenes[]``, for instance: ``{ "My Scene", MapSelect_LoadGame, ENTR_MYSCENE_0 },`` (note that the entrance used is the first of the block you need to have for the scene) +3. Compile the game, you may or may not need to run ``make clean`` first if you edited the entrance table +4. Get on the map select then scroll until you see your new entry (in the previous example is will be called "My Scene") then press R to change the header, on the vanilla map select the first cutscene header will be called ``デモ00``, on HackerOoT it will be ``Cutscene 0`` then press A to start the cutscene. + Note that you can have the actual address of your cutscene if you use ``sym_info.py`` from decomp. Example with ``gHyruleFieldIntroCs``: - Command: ``./sym_info.py gHyruleFieldIntroCs`` - Result: ``Symbol gHyruleFieldIntroCs (RAM: 0x02013AA0, ROM: 0x27E9AA0, build/assets/scenes/overworld/spot00/spot00_scene.o)`` If you have a softlock in-game then you probably did something wrong when creating the cutscene. Make sure you set up the bones properly. The softlock means the game is playing a cutscene but it's probably reading wrong data. Make sure the cutscene is exported, if it's not export it again. + +If the game crash check the transitions if you use the transition command (check both the ones from the entrance table and your cutscene script), also it will crash if you try to use the map select without having a 5th entrance (or more depending on the number of cutscenes you have) in the group for your scene. diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index c683e6a62..3c1d9c1a0 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -33,8 +33,11 @@ def readCutsceneData(csParentOut, csParentIn): entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame entryOut.textType = getCustomProperty(entryIn, "csTextType") - entryOut.topOptionTextID = entryIn.topOptionTextID - entryOut.bottomOptionTextID = entryIn.bottomOptionTextID + + if entryOut.textType == "CS_TEXT_CHOICE": + entryOut.topOptionTextID = entryIn.topOptionTextID + entryOut.bottomOptionTextID = entryIn.bottomOptionTextID + entryOut.ocarinaMessageId = entryIn.ocarinaMessageId listOut.entries.append(entryOut) elif listOut.listType == "LightSettingsList": @@ -71,7 +74,12 @@ def readCutsceneData(csParentOut, csParentIn): entryOut = OOTCSRumble() entryOut.startFrame = entryIn.startFrame entryOut.rumbleSourceStrength = entryIn.rumbleSourceStrength - entryOut.rumbleDuration = entryIn.rumbleDuration + + # the duration's unit are vertical retraces, this happens 3 times per frame + # so we're multiplying the value by 3 to get a frame unit on the UI + # to keep consistency between start frame and duration + entryOut.rumbleDuration = entryIn.rumbleDuration * 3 + entryOut.rumbleDecreaseRate = entryIn.rumbleDecreaseRate listOut.entries.append(entryOut) csParentOut.csLists.append(listOut) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 19d19e89c..cf73fb955 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -64,6 +64,8 @@ def draw_props( if self.filterProp(p, listProp): name = self.filterName(p, listProp) displayName = ootCSSubPropToName[name] + value = getattr(self, p) + if name == "csSeqPlayer": # change the property name to draw the other enum for fade seq command @@ -78,9 +80,12 @@ def draw_props( "csSeqID", "csSeqPlayer", ] - if name in customValues and getattr(self, p) == "Custom": + if name in customValues and value == "Custom": prop_split(box, self, f"{name}Custom", f"{displayName} Custom") + if name == "csTextType" and value != "CS_TEXT_CHOICE": + break + class OOTCSTextProperty(OOTCutsceneCommon, PropertyGroup): attrName = "textList" From bdd66ea37d4ad1e60135a4792f13b437d0e18964 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 13 Jan 2023 15:36:20 +0100 Subject: [PATCH 14/39] black --- fast64_internal/oot/cutscene/properties.py | 1 - 1 file changed, 1 deletion(-) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index cf73fb955..bf1e8b787 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -66,7 +66,6 @@ def draw_props( displayName = ootCSSubPropToName[name] value = getattr(self, p) - if name == "csSeqPlayer": # change the property name to draw the other enum for fade seq command p = name From 79c45c6337ff30b2065c7ebacb103ca60c1c761e Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 20 Jan 2023 18:38:28 +0100 Subject: [PATCH 15/39] review --- fast64_internal/oot/README.md | 2 +- fast64_internal/oot/oot_constants.py | 1 + fast64_internal/oot/oot_upgrade.py | 48 +++++++++++-------- .../oot/scene/exporter/to_c/actor.py | 24 +++++----- .../oot/scene/exporter/to_c/room_commands.py | 6 +-- .../oot/scene/exporter/to_c/room_header.py | 12 ++--- .../oot/scene/exporter/to_c/room_shape.py | 12 ++--- .../oot/scene/exporter/to_c/scene_commands.py | 6 +-- .../oot/scene/exporter/to_c/scene_cutscene.py | 8 ++-- .../oot/scene/exporter/to_c/scene_header.py | 24 +++++----- .../oot/scene/exporter/to_c/scene_pathways.py | 12 ++--- 11 files changed, 82 insertions(+), 73 deletions(-) diff --git a/fast64_internal/oot/README.md b/fast64_internal/oot/README.md index 428c759c6..70e049bee 100644 --- a/fast64_internal/oot/README.md +++ b/fast64_internal/oot/README.md @@ -179,4 +179,4 @@ Note that you can have the actual address of your cutscene if you use ``sym_info If you have a softlock in-game then you probably did something wrong when creating the cutscene. Make sure you set up the bones properly. The softlock means the game is playing a cutscene but it's probably reading wrong data. Make sure the cutscene is exported, if it's not export it again. -If the game crash check the transitions if you use the transition command (check both the ones from the entrance table and your cutscene script), also it will crash if you try to use the map select without having a 5th entrance (or more depending on the number of cutscenes you have) in the group for your scene. +If the game crashes check the transitions if you use the transition command (check both the ones from the entrance table and your cutscene script), also it will crash if you try to use the map select without having a 5th entrance (or more depending on the number of cutscenes you have) in the group for your scene. diff --git a/fast64_internal/oot/oot_constants.py b/fast64_internal/oot/oot_constants.py index 119b22b2a..bbf5e5339 100644 --- a/fast64_internal/oot/oot_constants.py +++ b/fast64_internal/oot/oot_constants.py @@ -189,6 +189,7 @@ ] ootEnumMusicSeq = [ + # see https://github.com/zeldaret/oot/blob/9f09505d34619883748a7dab05071883281c14fd/include/sequence.h#L4-L118 ("Custom", "Custom", "Custom"), ("NA_BGM_GENERAL_SFX", "General Sound Effects", "General Sound Effects"), ("NA_BGM_NATURE_AMBIENCE", "Nature Ambiance", "Nature Ambiance"), diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 5b3d42729..64681597d 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass from bpy.types import Object, CollectionProperty from .data import OoT_ObjectData from .oot_utility import getEvalParams @@ -52,7 +53,14 @@ def upgradeRoomHeaders(roomObj: Object, objData: OoT_ObjectData): ##################################### # Cutscene ##################################### -def transferOldDataToNew(data, oldDataToNewData: dict): +@dataclass +class Cutscene_UpgradeData: + oldPropName: str + newPropName: str + enumData: list[tuple[str, str, str]] # this is the list used for enum properties + + +def transferOldDataToNew(data, oldDataToNewData: dict[str, str]): # conversion to the same prop type # simply transfer the old data to the new one # special case for rumble subprops where it's a string to int conversion @@ -69,12 +77,12 @@ def transferOldDataToNew(data, oldDataToNewData: dict): del data[oldName] -def convertOldDataToEnumData(data, oldDataToEnumData: list[tuple[str, str, list[tuple[str, str, str]]]]): +def convertOldDataToEnumData(data, oldDataToEnumData: list[Cutscene_UpgradeData]): # conversion to another prop type - for (oldName, newName, enumList) in oldDataToEnumData: - if oldName in data: + for csUpgradeData in oldDataToEnumData: + if csUpgradeData.oldPropName in data: # get the old data - oldData = data[oldName] + oldData = data[csUpgradeData.oldPropName] # if anything goes wrong there set the value to custom to avoid any data loss try: @@ -85,7 +93,7 @@ def convertOldDataToEnumData(data, oldDataToEnumData: list[tuple[str, str, list[ # special cases for ocarina action enum # since we don't have everything the value need to be shifted - if newName == "ocarinaAction": + if csUpgradeData.newPropName == "ocarinaAction": if value in [0x00, 0x01, 0x0E] or value > 0x1A: raise IndexError @@ -94,7 +102,7 @@ def convertOldDataToEnumData(data, oldDataToEnumData: list[tuple[str, str, list[ value -= 2 - if newName == "csSeqID": + if csUpgradeData.newPropName == "csSeqID": # the old fade out value is wrong, it assumes it's a seq id # but it's not, it's a seq player id, # hence why we raise an error so it defaults to "custom" to avoid any data loss @@ -105,7 +113,7 @@ def convertOldDataToEnumData(data, oldDataToEnumData: list[tuple[str, str, list[ value = oldData + 1 # another special case, this time for the misc enum - if newName == "csMiscType": + if csUpgradeData.newPropName == "csMiscType": if value in [0x00, 0x04, 0x05]: raise IndexError @@ -117,21 +125,21 @@ def convertOldDataToEnumData(data, oldDataToEnumData: list[tuple[str, str, list[ raise NotImplementedError # if the value is in the list find the identifier - if value < len(enumList): - setattr(data, newName, enumList[value][0]) + if value < len(csUpgradeData.enumData): + setattr(data, csUpgradeData.newPropName, csUpgradeData.enumData[value][0]) else: # else raise an error to default to custom raise IndexError except: - setattr(data, newName, "Custom") - setattr(data, f"{newName}Custom", str(oldData)) + setattr(data, csUpgradeData.newPropName, "Custom") + setattr(data, f"{csUpgradeData.newPropName}Custom", str(oldData)) # @TODO: find a way to check properly which seq command it is - if newName == "csSeqID": + if csUpgradeData.newPropName == "csSeqID": setattr(data, "csSeqPlayer", "Custom") setattr(data, "csSeqPlayerCustom", str(oldData)) - del data[oldName] + del data[csUpgradeData.oldPropName] def upgradeCutsceneSubProps(csListSubProp): @@ -168,12 +176,12 @@ def upgradeCutsceneSubProps(csListSubProp): subPropsToEnum = [ # TextBox - ("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), - ("type", "csTextType", ootEnumTextType), + Cutscene_UpgradeData("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), + Cutscene_UpgradeData("type", "csTextType", ootEnumTextType), # Seq - ("value", "csSeqID", ootEnumMusicSeq), + Cutscene_UpgradeData("value", "csSeqID", ootEnumMusicSeq), # Misc - ("operation", "csMiscType", ootEnumCSMiscType), + Cutscene_UpgradeData("operation", "csMiscType", ootEnumCSMiscType), ] transferOldDataToNew(csListSubProp, subPropsOldToNew) @@ -197,7 +205,7 @@ def upgradeCSListProps(csListProp): transferOldDataToNew(csListProp, csListPropOldToNew) # both are enums but the item list is different (the old one doesn't have a "custom" entry) - convertOldDataToEnumData(csListProp, [("fxType", "transitionType", ootEnumCSTransitionType)]) + convertOldDataToEnumData(csListProp, [Cutscene_UpgradeData("fxType", "transitionType", ootEnumCSTransitionType)]) def upgradeCutsceneProperty(csProp): @@ -210,4 +218,4 @@ def upgradeCutsceneProperty(csProp): } transferOldDataToNew(csProp, csPropOldToNew) - convertOldDataToEnumData(csProp, [("csTermIdx", "csDestination", ootEnumCSDestinationType)]) + convertOldDataToEnumData(csProp, [Cutscene_UpgradeData("csTermIdx", "csDestination", ootEnumCSDestinationType)]) diff --git a/fast64_internal/oot/scene/exporter/to_c/actor.py b/fast64_internal/oot/scene/exporter/to_c/actor.py index 653a3f075..446efc331 100644 --- a/fast64_internal/oot/scene/exporter/to_c/actor.py +++ b/fast64_internal/oot/scene/exporter/to_c/actor.py @@ -29,14 +29,14 @@ def getActorEntry(actor: OOTActor): def getActorList(outRoom: OOTRoom, headerIndex: int): """Returns the actor list for the current header""" actorList = CData() - listName = f"ActorEntry {outRoom.actorListName(headerIndex)}" + declarationBase = f"ActorEntry {outRoom.actorListName(headerIndex)}" # .h - actorList.header = f"extern {listName}[];\n" + actorList.header = f"extern {declarationBase}[];\n" # .c actorList.source = ( - (f"{listName}[{outRoom.getActorLengthDefineName(headerIndex)}]" + " = {\n") + (f"{declarationBase}[{outRoom.getActorLengthDefineName(headerIndex)}]" + " = {\n") + "\n".join(getActorEntry(actor) for actor in outRoom.actorList) + "};\n\n" ) @@ -72,14 +72,14 @@ def getTransitionActorEntry(transActor: OOTTransitionActor): def getTransitionActorList(outScene: OOTScene, headerIndex: int): """Returns the transition actor list for the current header""" transActorList = CData() - listName = f"TransitionActorEntry {outScene.transitionActorListName(headerIndex)}" + declarationBase = f"TransitionActorEntry {outScene.transitionActorListName(headerIndex)}" # .h - transActorList.header = f"extern {listName}[];\n" + transActorList.header = f"extern {declarationBase}[];\n" # .c transActorList.source = ( - (f"{listName}[]" + " = {\n") + (f"{declarationBase}[]" + " = {\n") + "\n".join(getTransitionActorEntry(transActor) for transActor in outScene.transitionActorList) + "};\n\n" ) @@ -93,14 +93,14 @@ def getTransitionActorList(outScene: OOTScene, headerIndex: int): def getSpawnActorList(outScene: OOTScene, headerIndex: int): """Returns the spawn actor list for the current header""" spawnActorList = CData() - listName = f"ActorEntry {outScene.startPositionsName(headerIndex)}" + declarationBase = f"ActorEntry {outScene.startPositionsName(headerIndex)}" # .h - spawnActorList.header = f"extern {listName}[];\n" + spawnActorList.header = f"extern {declarationBase}[];\n" # .c spawnActorList.source = ( - (f"{listName}[]" + " = {\n") + (f"{declarationBase}[]" + " = {\n") + "".join(getActorEntry(spawnActor) for spawnActor in outScene.startPositions.values()) + "};\n\n" ) @@ -116,14 +116,14 @@ def getSpawnEntry(entrance: OOTEntrance): def getSpawnList(outScene: OOTScene, headerIndex: int): """Returns the spawn list for the current header""" spawnList = CData() - listName = f"Spawn {outScene.entranceListName(headerIndex)}" + declarationBase = f"Spawn {outScene.entranceListName(headerIndex)}" # .h - spawnList.header = f"extern {listName}[];\n" + spawnList.header = f"extern {declarationBase}[];\n" # .c spawnList.source = ( - (f"{listName}[]" + " = {\n") + (f"{declarationBase}[]" + " = {\n") + (indent + "// { Spawn Actor List Index, Room Index }\n") + "".join(getSpawnEntry(entrance) for entrance in outScene.entranceList) + "};\n\n" diff --git a/fast64_internal/oot/scene/exporter/to_c/room_commands.py b/fast64_internal/oot/scene/exporter/to_c/room_commands.py index 21f3f063d..cb8f7037b 100644 --- a/fast64_internal/oot/scene/exporter/to_c/room_commands.py +++ b/fast64_internal/oot/scene/exporter/to_c/room_commands.py @@ -52,7 +52,7 @@ def getActorListCmd(outRoom: OOTRoom, headerIndex: int): def getRoomCommandList(outRoom: OOTRoom, headerIndex: int): cmdListData = CData() - listName = f"SceneCmd {outRoom.roomName()}_header{headerIndex:02}" + declarationBase = f"SceneCmd {outRoom.roomName()}_header{headerIndex:02}" getCmdFuncList = [ getEchoSettingsCmd, @@ -72,9 +72,9 @@ def getRoomCommandList(outRoom: OOTRoom, headerIndex: int): ) # .h - cmdListData.header = f"extern {listName}[];\n" + cmdListData.header = f"extern {declarationBase}[];\n" # .c - cmdListData.source = f"{listName}[]" + " = {\n" + roomCmdData + "};\n\n" + cmdListData.source = f"{declarationBase}[]" + " = {\n" + roomCmdData + "};\n\n" return cmdListData diff --git a/fast64_internal/oot/scene/exporter/to_c/room_header.py b/fast64_internal/oot/scene/exporter/to_c/room_header.py index 333e764f2..ac93c14ce 100644 --- a/fast64_internal/oot/scene/exporter/to_c/room_header.py +++ b/fast64_internal/oot/scene/exporter/to_c/room_header.py @@ -20,14 +20,14 @@ def getHeaderDefines(outRoom: OOTRoom, headerIndex: int): # Object List def getObjectList(outRoom: OOTRoom, headerIndex: int): objectList = CData() - listName = f"s16 {outRoom.objectListName(headerIndex)}" + declarationBase = f"s16 {outRoom.objectListName(headerIndex)}" # .h - objectList.header = f"extern {listName}[];\n" + objectList.header = f"extern {declarationBase}[];\n" # .c objectList.source = ( - (f"{listName}[{outRoom.getObjectLengthDefineName(headerIndex)}]" + " = {\n") + (f"{declarationBase}[{outRoom.getObjectLengthDefineName(headerIndex)}]" + " = {\n") + ",\n".join(indent + objectID for objectID in outRoom.objectIDList) + ",\n};\n\n" ) @@ -48,14 +48,14 @@ def getRoomData(outRoom: OOTRoom): for i, csHeader in enumerate(outRoom.cutsceneHeaders): roomHeaders.append((csHeader, f"Cutscene No. {i + 1}")) - altHeaderPtrListName = f"SceneCmd* {outRoom.alternateHeadersName()}" + declarationBase = f"SceneCmd* {outRoom.alternateHeadersName()}" # .h - roomC.header = f"extern {altHeaderPtrListName}[];\n" + roomC.header = f"extern {declarationBase}[];\n" # .c altHeaderPtrList = ( - f"{altHeaderPtrListName}[]" + f"{declarationBase}[]" + " = {\n" + "\n".join( indent + f"{curHeader.roomName()}_header{i:02}," if curHeader is not None else indent + "NULL," diff --git a/fast64_internal/oot/scene/exporter/to_c/room_shape.py b/fast64_internal/oot/scene/exporter/to_c/room_shape.py index e4f6bdfde..462e18ab6 100644 --- a/fast64_internal/oot/scene/exporter/to_c/room_shape.py +++ b/fast64_internal/oot/scene/exporter/to_c/room_shape.py @@ -24,13 +24,13 @@ def getRoomShapeImageData(roomMesh: OOTRoomMesh, textureSettings: TextureExportS code = CData() if len(roomMesh.bgImages) > 1: - multiBgImageName = f"RoomShapeImageMultiBgEntry {roomMesh.getMultiBgStructName()}" + declarationBase = f"RoomShapeImageMultiBgEntry {roomMesh.getMultiBgStructName()}" # .h - code.header += f"extern {multiBgImageName}[{len(roomMesh.bgImages)}];\n" + code.header += f"extern {declarationBase}[{len(roomMesh.bgImages)}];\n" # .c - code.source += f"{multiBgImageName}[{len(roomMesh.bgImages)}] = {{\n" + code.source += f"{declarationBase}[{len(roomMesh.bgImages)}] = {{\n" for i in range(len(roomMesh.bgImages)): bgImage = roomMesh.bgImages[i] code.source += indent + "{\n" + bgImage.multiPropertiesC(2, i) + indent + "},\n" @@ -70,7 +70,7 @@ def getRoomShape(outRoom: OOTRoom): if mesh.roomShape != "ROOM_SHAPE_TYPE_IMAGE": entryName = mesh.entriesName() - dlEntryArrayName = f"{dlEntryType} {mesh.entriesName()}[{len(mesh.meshEntries)}]" + dlEntryDeclarationBase = f"{dlEntryType} {mesh.entriesName()}[{len(mesh.meshEntries)}]" roomShapeInfo.source = ( "\n".join( @@ -86,8 +86,8 @@ def getRoomShape(outRoom: OOTRoom): + "\n\n" ) - roomShapeDLArray.header = f"extern {dlEntryArrayName};\n" - roomShapeDLArray.source = dlEntryArrayName + " = {\n" + roomShapeDLArray.header = f"extern {dlEntryDeclarationBase};\n" + roomShapeDLArray.source = dlEntryDeclarationBase + " = {\n" for entry in mesh.meshEntries: roomShapeDLArray.source += indent + getRoomShapeDLEntry(entry, mesh.roomShape) diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_commands.py b/fast64_internal/oot/scene/exporter/to_c/scene_commands.py index a972ee473..ccb52ab1f 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_commands.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_commands.py @@ -77,7 +77,7 @@ def getCutsceneDataCmd(outScene: OOTScene, headerIndex: int): def getSceneCommandList(outScene: OOTScene, headerIndex: int): cmdListData = CData() - listName = f"SceneCmd {outScene.sceneName()}_header{headerIndex:02}" + declarationBase = f"SceneCmd {outScene.sceneName()}_header{headerIndex:02}" getCmdFunc1ArgList = [ getSoundSettingsCmd, @@ -110,9 +110,9 @@ def getSceneCommandList(outScene: OOTScene, headerIndex: int): ) # .h - cmdListData.header = f"extern {listName}[]" + ";\n" + cmdListData.header = f"extern {declarationBase}[]" + ";\n" # .c - cmdListData.source = f"{listName}[]" + " = {\n" + sceneCmdData + "};\n\n" + cmdListData.source = f"{declarationBase}[]" + " = {\n" + sceneCmdData + "};\n\n" return cmdListData diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 4c4675002..e9a63fe58 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -6,15 +6,15 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): csData = CData() - arrayName = f"CutsceneData {csName}[]" + declarationBase = f"CutsceneData {csName}[]" nentries = len(csParent.csLists) + (1 if csParent.csUseDestination else 0) # .h - csData.header = f"extern {arrayName};\n" + csData.header = f"extern {declarationBase};\n" # .c csData.source = ( - arrayName + declarationBase + " = {\n" + (indent + f"CS_BEGIN_CUTSCENE({nentries}, {csParent.csEndFrame}),\n") + ( @@ -61,7 +61,7 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): csData.source += f"{e.ocarinaAction}, {e.startFrame}, {e.endFrame}, {e.ocarinaMessageId}" elif list.listType == "LightSettingsList": - # the endFrame variable is not used in the implementation of the commend + # the endFrame variable is not used in the implementation of the command # so the value doesn't matter csData.source += f"{e.lightSettingsIndex}, {e.startFrame}" + (", 0" * 9) diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_header.py b/fast64_internal/oot/scene/exporter/to_c/scene_header.py index b85c826a1..531fd5cef 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_header.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_header.py @@ -59,14 +59,14 @@ def getLightSettingsEntry(light: OOTLight, lightMode: str, isLightingCustom: boo def getLightSettings(outScene: OOTScene, headerIndex: int): lightSettingsData = CData() - lightName = f"LightSettings {outScene.lightListName(headerIndex)}[{len(outScene.lights)}]" + declarationBase = f"LightSettings {outScene.lightListName(headerIndex)}[{len(outScene.lights)}]" # .h - lightSettingsData.header = f"extern {lightName};\n" + lightSettingsData.header = f"extern {declarationBase};\n" # .c lightSettingsData.source = ( - (lightName + " = {\n") + (declarationBase + " = {\n") + "".join( getLightSettingsEntry(light, outScene.skyboxLighting, outScene.isSkyboxLightingCustom, i) for i, light in enumerate(outScene.lights) @@ -90,14 +90,14 @@ def getSceneModel(outScene: OOTScene, textureExportSettings: TextureExportSettin ############# def getExitList(outScene: OOTScene, headerIndex: int): exitList = CData() - listName = f"u16 {outScene.exitListName(headerIndex)}[{len(outScene.exitList)}]" + declarationBase = f"u16 {outScene.exitListName(headerIndex)}[{len(outScene.exitList)}]" # .h - exitList.header = f"extern {listName};\n" + exitList.header = f"extern {declarationBase};\n" # .c exitList.source = ( - (listName + " = {\n") + (declarationBase + " = {\n") # @TODO: use the enum name instead of the raw index + "\n".join(indent + f"{exitEntry.index}," for exitEntry in outScene.exitList) + "\n};\n\n" @@ -111,7 +111,7 @@ def getExitList(outScene: OOTScene, headerIndex: int): ############# def getRoomList(outScene: OOTScene): roomList = CData() - listName = f"RomFile {outScene.roomListName()}[]" + declarationBase = f"RomFile {outScene.roomListName()}[]" # generating segment rom names for every room segNames = [] @@ -120,7 +120,7 @@ def getRoomList(outScene: OOTScene): segNames.append((f"_{roomName}SegmentRomStart", f"_{roomName}SegmentRomEnd")) # .h - roomList.header += f"extern {listName};\n" + roomList.header += f"extern {declarationBase};\n" if not outScene.write_dummy_room_list: # Write externs for rom segments @@ -129,7 +129,7 @@ def getRoomList(outScene: OOTScene): ) # .c - roomList.source = listName + " = {\n" + roomList.source = declarationBase + " = {\n" if outScene.write_dummy_room_list: roomList.source = ( @@ -207,9 +207,9 @@ def getSceneData(outScene: OOTScene): if i == 0: if outScene.hasAlternateHeaders(): - altHeaderListName = f"SceneCmd* {outScene.alternateHeadersName()}[]" - sceneC.header += f"extern {altHeaderListName};\n" - sceneC.source += altHeaderListName + " = {\n" + altHeaderPtrs + "\n};\n\n" + declarationBase = f"SceneCmd* {outScene.alternateHeadersName()}[]" + sceneC.header += f"extern {declarationBase};\n" + sceneC.source += declarationBase + " = {\n" + altHeaderPtrs + "\n};\n\n" # Write the room segment list sceneC.append(getRoomList(outScene)) diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_pathways.py b/fast64_internal/oot/scene/exporter/to_c/scene_pathways.py index 8b6292ef2..48aad26bc 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_pathways.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_pathways.py @@ -5,14 +5,14 @@ def getPathPointData(path: OOTPath, headerIndex: int, pathIndex: int): pathData = CData() - pathName = f"Vec3s {path.pathName(headerIndex, pathIndex)}" + declarationBase = f"Vec3s {path.pathName(headerIndex, pathIndex)}" # .h - pathData.header = f"extern {pathName}[];\n" + pathData.header = f"extern {declarationBase}[];\n" # .c pathData.source = ( - f"{pathName}[]" + f"{declarationBase}[]" + " = {\n" + "\n".join( indent + "{ " + ", ".join(f"{round(curPoint):5}" for curPoint in point) + " }," for point in path.points @@ -26,13 +26,13 @@ def getPathPointData(path: OOTPath, headerIndex: int, pathIndex: int): def getPathData(outScene: OOTScene, headerIndex: int): pathData = CData() pathListData = CData() - listName = f"Path {outScene.pathListName(headerIndex)}[{len(outScene.pathList)}]" + declarationBase = f"Path {outScene.pathListName(headerIndex)}[{len(outScene.pathList)}]" # .h - pathListData.header = f"extern {listName};\n" + pathListData.header = f"extern {declarationBase};\n" # .c - pathListData.source = listName + " = {\n" + pathListData.source = declarationBase + " = {\n" # Parse in alphabetical order of names sortedPathList = sorted(outScene.pathList, key=lambda x: x.objName.lower()) From dfe1d86e39641f0364ceff84fb221a09a30b3543 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Wed, 18 Oct 2023 11:58:33 +0200 Subject: [PATCH 16/39] use xml data for enums --- fast64_internal/oot/cutscene/constants.py | 375 ------------------ .../oot/cutscene/exporter/functions.py | 37 +- fast64_internal/oot/cutscene/operators.py | 5 +- fast64_internal/oot/cutscene/properties.py | 22 +- fast64_internal/oot/data/oot_enum_data.py | 33 +- fast64_internal/oot/data/xml/EnumData.xml | 58 ++- fast64_internal/oot/oot_upgrade.py | 17 +- 7 files changed, 132 insertions(+), 415 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 0e7d08576..a2b6091b6 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -66,381 +66,6 @@ ootEnumCSTextboxTypeIcons = ["FILE_TEXT", "HIDE_ON", "FILE_SOUND"] -ootEnumCSTransitionType = [ - # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L219-L233 - ("Custom", "Custom", "Custom"), - ("CS_TRANS_GRAY_FILL_IN", "Gray Fill In", "Gray Fill In"), - ("CS_TRANS_BLUE_FILL_IN", "Blue Fill In", "Blue Fill In"), - ("CS_TRANS_RED_FILL_OUT", "Red Fill Out", "Red Fill Out"), - ("CS_TRANS_GREEN_FILL_OUT", "Green Fill Out", "Green Fill Out"), - ("CS_TRANS_GRAY_FILL_OUT", "Gray Fill Out", "Gray Fill Out"), - ("CS_TRANS_BLUE_FILL_OUT", "Blue Fill Out", "Blue Fill Out"), - ("CS_TRANS_RED_FILL_IN", "Red Fill In", "Red Fill In"), - ("CS_TRANS_GREEN_FILL_IN", "Green Fill In", "Green Fill In"), - ("CS_TRANS_TRIGGER_INSTANCE", "Trigger Instance", "Trigger Instance"), - ("CS_TRANS_BLACK_FILL_OUT", "Black Fill Out", "Black Fill Out"), - ("CS_TRANS_BLACK_FILL_IN", "Black Fill In", "Black Fill In"), - ("CS_TRANS_BLACK_FILL_OUT_TO_HALF", "Black Fill Out To Half", "Black Fill Out To Half"), - ("CS_TRANS_BLACK_FILL_IN_FROM_HALF", "Black Fill In From Half", "Black Fill In From Half"), -] - -ootEnumCSMiscType = [ - # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L167-L204 - ("Custom", "Custom", "Custom"), - ("CS_MISC_RAIN", " Rain", " Rain"), - ("CS_MISC_LIGHTNING", " Lightning", " Lightning"), - ("CS_MISC_SET_CSFLAG_0", " Set CS Flag 0", " Set CS Flag 0"), - ("CS_MISC_LIFT_FOG", " Lift Fog", " Lift Fog"), - ("CS_MISC_CLOUDY_SKY", " Cloudy Sky", " Cloudy Sky"), - ("CS_MISC_FADE_KOKIRI_GRASS_ENV_ALPHA", " Fade Kokiri Grass Env Alpha", " Fade Kokiri Grass Env Alpha"), - ("CS_MISC_SNOW", " Snow", " Snow"), - ("CS_MISC_SET_CSFLAG_1", " Set CS Flag 1", " Set CS Flag 1"), - ("CS_MISC_DEKU_TREE_DEATH", " Deku Tree Death", " Deku Tree Death"), - ("CS_MISC_STOP_CUTSCENE", " Stop Cutscene", " Stop Cutscene"), - ("CS_MISC_TRIFORCE_FLASH", " Triforce Flash", " Triforce Flash"), - ("CS_MISC_SET_LOCKED_VIEWPOINT", " Set Locked Viewpoint", " Set Locked Viewpoint"), - ("CS_MISC_SHOW_TITLE_CARD", " Show Title Card", " Show Title Card"), - ("CS_MISC_QUAKE_START", " Quake Start", " Quake Start"), - ("CS_MISC_QUAKE_STOP", " Quake Stop", " Quake Stop"), - ("CS_MISC_STOP_STORM_AND_ADVANCE_TO_DAY", " Stop Storm And Advance To Day", " Stop Storm And Advance To Day"), - ("CS_MISC_SET_FLAG_FAST_WINDMILL", " Set Flag Fast Windmill", " Set Flag Fast Windmill"), - ("CS_MISC_SET_FLAG_WELL_DRAINED", " Set Flag Well Drained", " Set Flag Well Drained"), - ("CS_MISC_SET_FLAG_LAKE_HYLIA_RESTORED", " Set Flag Lake Hylia Restored", " Set Flag Lake Hylia Restored"), - ("CS_MISC_VISMONO_BLACK_AND_WHITE", " Vismono Black And White", " Vismono Black And White"), - ("CS_MISC_VISMONO_SEPIA", " Vismono Sepia", " Vismono Sepia"), - ("CS_MISC_HIDE_ROOM", " Hide Room", " Hide Room"), - ("CS_MISC_TIME_ADVANCE_TO_NIGHT", " Time Advance To Night", " Time Advance To Night"), - ("CS_MISC_SET_TIME_BASED_LIGHT_SETTING", " Set Time Based Light Setting", " Set Time Based Light Setting"), - ("CS_MISC_RED_PULSATING_LIGHTS", " Red Pulsating Lights", " Red Pulsating Lights"), - ("CS_MISC_HALT_ALL_ACTORS", " Halt All Actors", " Halt All Actors"), - ("CS_MISC_RESUME_ALL_ACTORS", " Resume All Actors", " Resume All Actors"), - ("CS_MISC_SET_CSFLAG_3", " Set CS Flag 3", " Set CS Flag 3"), - ("CS_MISC_SET_CSFLAG_4", " Set CS Flag 4", " Set CS Flag 4"), - ("CS_MISC_SANDSTORM_FILL", " Sandstorm Fill", " Sandstorm Fill"), - ("CS_MISC_SUNSSONG_START", " Sun's Song Start", " Sunssong Start"), - ("CS_MISC_FREEZE_TIME", " Freeze Time", " Freeze Time"), - ("CS_MISC_LONG_SCARECROW_SONG", " Long Scarecrow Song", " Long Scarecrow Song"), -] - -ootEnumCSDestinationType = [ - # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L235-L356 - ("Custom", "Custom", "Custom"), - ("CS_DEST_CUTSCENE_MAP_GANON_HORSE", "Cutscene Map Ganon Horse", "Cutscene Map Ganon Horse"), - ("CS_DEST_CUTSCENE_MAP_THREE_GODDESSES", "Cutscene Map Three Goddesses", "Cutscene Map Three Goddesses"), - ("CS_DEST_GERUDO_VALLEY_DIN_PART_1", "Gerudo Valley Din Part 1", "Gerudo Valley Din Part 1"), - ("CS_DEST_DEATH_MOUNTAIN_TRAIL_NAYRU", "Death Mountain Trail Nayru", "Death Mountain Trail Nayru"), - ("CS_DEST_KOKIRI_FOREST_FARORE", "Kokiri Forest Farore", "Kokiri Forest Farore"), - ("CS_DEST_CUTSCENE_MAP_TRIFORCE_CREATION", "Cutscene Map Triforce Creation", "Cutscene Map Triforce Creation"), - ( - "CS_DEST_KOKIRI_FOREST_RECEIVE_KOKIRI_EMERALD", - "Kokiri Forest Receive Kokiri Emerald", - "Kokiri Forest Receive Kokiri Emerald", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_FROM_MASTER_SWORD", - "Temple Of Time From Master Sword", - "Temple Of Time From Master Sword", - ), - ("CS_DEST_GERUDO_VALLEY_DIN_PART_2", "Gerudo Valley Din Part 2", "Gerudo Valley Din Part 2"), - ("CS_DEST_LINKS_HOUSE_INTRO", "Links House Intro", "Links House Intro"), - ("CS_DEST_KOKIRI_FOREST_INTRO", "Kokiri Forest Intro", "Kokiri Forest Intro"), - ( - "CS_DEST_DEATH_MOUNTAIN_TRAIL_FROM_GORON_RUBY", - "Death Mountain Trail From Goron Ruby", - "Death Mountain Trail From Goron Ruby", - ), - ( - "CS_DEST_ZORAS_FOUNTAIN_FROM_ZORAS_SAPPHIRE", - "Zoras Fountain From Zoras Sapphire", - "Zoras Fountain From Zoras Sapphire", - ), - ( - "CS_DEST_KOKIRI_FOREST_FROM_KOKIRI_EMERALD", - "Kokiri Forest From Kokiri Emerald", - "Kokiri Forest From Kokiri Emerald", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED", - "Temple Of Time Kokiri Emerald Restored", - "Temple Of Time Kokiri Emerald Restored", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED", - "Temple Of Time Goron Ruby Restored", - "Temple Of Time Goron Ruby Restored", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED", - "Temple Of Time Zoras Sapphire Restored", - "Temple Of Time Zoras Sapphire Restored", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION", - "Temple Of Time After Light Medallion", - "Temple Of Time After Light Medallion", - ), - ("CS_DEST_DEATH_MOUNTAIN_TRAIL", "Death Mountain Trail", "Death Mountain Trail"), - ("CS_DEST_LAKE_HYLIA_WATER_RESTORED", "Lake Hylia Water Restored", "Lake Hylia Water Restored"), - ("CS_DEST_DESERT_COLOSSUS_REQUIEM", "Desert Colossus Requiem", "Desert Colossus Requiem"), - ( - "CS_DEST_CUTSCENE_MAP_GANONDORF_DEFEATED_CREDITS", - "Cutscene Map Ganondorf Defeated Credits", - "Cutscene Map Ganondorf Defeated Credits", - ), - ("CS_DEST_JABU_JABU", "Jabu Jabu", "Jabu Jabu"), - ( - "CS_DEST_CHAMBER_OF_SAGES_LIGHT_MEDALLION", - "Chamber Of Sages Light Medallion", - "Chamber Of Sages Light Medallion", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED_2", - "Temple Of Time Kokiri Emerald Restored 2", - "Temple Of Time Kokiri Emerald Restored 2", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED_2", - "Temple Of Time Goron Ruby Restored 2", - "Temple Of Time Goron Ruby Restored 2", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED_2", - "Temple Of Time Zoras Sapphire Restored 2", - "Temple Of Time Zoras Sapphire Restored 2", - ), - ( - "CS_DEST_CHAMBER_OF_SAGES_FOREST_MEDALLION", - "Chamber Of Sages Forest Medallion", - "Chamber Of Sages Forest Medallion", - ), - ("CS_DEST_CHAMBER_OF_SAGES_FIRE_MEDALLION", "Chamber Of Sages Fire Medallion", "Chamber Of Sages Fire Medallion"), - ( - "CS_DEST_CHAMBER_OF_SAGES_WATER_MEDALLION", - "Chamber Of Sages Water Medallion", - "Chamber Of Sages Water Medallion", - ), - ("CS_DEST_HYRULE_FIELD_FLASHBACK", "Hyrule Field Flashback", "Hyrule Field Flashback"), - ("CS_DEST_HYRULE_FIELD_FROM_ZELDA_ESCAPE", "Hyrule Field From Zelda Escape", "Hyrule Field From Zelda Escape"), - ( - "CS_DEST_CUTSCENE_MAP_GANONDORF_FROM_MASTER_SWORD", - "Cutscene Map Ganondorf From Master Sword", - "Cutscene Map Ganondorf From Master Sword", - ), - ("CS_DEST_HYRULE_FIELD_INTRO_DREAM", "Hyrule Field Intro Dream", "Hyrule Field Intro Dream"), - ("CS_DEST_CUTSCENE_MAP_SHEIKAH_LEGEND", "Cutscene Map Sheikah Legend", "Cutscene Map Sheikah Legend"), - ("CS_DEST_TEMPLE_OF_TIME_ZELDA_REVEAL", "Temple Of Time Zelda Reveal", "Temple Of Time Zelda Reveal"), - ("CS_DEST_TEMPLE_OF_TIME_GET_LIGHT_ARROWS", "Temple Of Time Get Light Arrows", "Temple Of Time Get Light Arrows"), - ("CS_DEST_LAKE_HYLIA_FROM_LAKE_RESTORED", "Lake Hylia From Lake Restored", "Lake Hylia From Lake Restored"), - ("CS_DEST_KAKARIKO_VILLAGE_DRAIN_WELL", "Kakariko Village Drain Well", "Kakariko Village Drain Well"), - ("CS_DEST_WINDMILL_FROM_WELL_DRAINED", "Windmill From Well Drained", "Windmill From Well Drained"), - ( - "CS_DEST_TEMPLE_OF_TIME_FROM_ALL_STONES_RESTORED", - "Temple Of Time From All Stones Restored", - "Temple Of Time From All Stones Restored", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION_ALT", - "Temple Of Time After Light Medallion Alt", - "Temple Of Time After Light Medallion Alt", - ), - ( - "CS_DEST_KAKARIKO_VILLAGE_NOCTURNE_PART_2", - "Kakariko Village Nocturne Part 2", - "Kakariko Village Nocturne Part 2", - ), - ("CS_DEST_DESERT_COLOSSUS_FROM_REQUIEM", "Desert Colossus From Requiem", "Desert Colossus From Requiem"), - ( - "CS_DEST_TEMPLE_OF_TIME_FROM_LIGHT_ARROWS", - "Temple Of Time From Light Arrows", - "Temple Of Time From Light Arrows", - ), - ("CS_DEST_KAKARIKO_VILLAGE_FROM_NOCTURNE", "Kakariko Village From Nocturne", "Kakariko Village From Nocturne"), - ( - "CS_DEST_HYRULE_FIELD_FROM_ZELDAS_COURTYARD", - "Hyrule Field From Zeldas Courtyard", - "Hyrule Field From Zeldas Courtyard", - ), - ("CS_DEST_TEMPLE_OF_TIME_SONG_OF_TIME", "Temple Of Time Song Of Time", "Temple Of Time Song Of Time"), - ("CS_DEST_HYRULE_FIELD_FROM_SONG_OF_TIME", "Hyrule Field From Song Of Time", "Hyrule Field From Song Of Time"), - ("CS_DEST_GERUDO_VALLEY_CREDITS", "Gerudo Valley Credits", "Gerudo Valley Credits"), - ("CS_DEST_GERUDO_FORTRESS_CREDITS", "Gerudo Fortress Credits", "Gerudo Fortress Credits"), - ("CS_DEST_KAKARIKO_VILLAGE_CREDITS", "Kakariko Village Credits", "Kakariko Village Credits"), - ( - "CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_1", - "Death Mountain Trail Credits Part 1", - "Death Mountain Trail Credits Part 1", - ), - ("CS_DEST_GORON_CITY_CREDITS", "Goron City Credits", "Goron City Credits"), - ("CS_DEST_LAKE_HYLIA_CREDITS", "Lake Hylia Credits", "Lake Hylia Credits"), - ("CS_DEST_ZORAS_FOUNTAIN_CREDITS", "Zoras Fountain Credits", "Zoras Fountain Credits"), - ("CS_DEST_ZORAS_DOMAIN_CREDITS", "Zoras Domain Credits", "Zoras Domain Credits"), - ("CS_DEST_KOKIRI_FOREST_CREDITS_PART_1", "Kokiri Forest Credits Part 1", "Kokiri Forest Credits Part 1"), - ("CS_DEST_KOKIRI_FOREST_CREDITS_PART_2", "Kokiri Forest Credits Part 2", "Kokiri Forest Credits Part 2"), - ("CS_DEST_HYRULE_FIELD_CREDITS", "Hyrule Field Credits", "Hyrule Field Credits"), - ( - "CS_DEST_LON_LON_RANCH_CREDITS_PART_1_ALT", - "Lon Lon Ranch Credits Part 1 Alt", - "Lon Lon Ranch Credits Part 1 Alt", - ), - ("CS_DEST_KAKARIKO_VILLAGE_FROM_TRAIL_OWL", "Kakariko Village From Trail Owl", "Kakariko Village From Trail Owl"), - ( - "CS_DEST_HYRULE_FIELD_FROM_LAKE_HYLIA_OWL", - "Hyrule Field From Lake Hylia Owl", - "Hyrule Field From Lake Hylia Owl", - ), - ("CS_DEST_CUTSCENE_MAP_DEKU_SPROUT_PART_2", "Cutscene Map Deku Sprout Part 2", "Cutscene Map Deku Sprout Part 2"), - ( - "CS_DEST_KOKIRI_FOREST_DEKU_SPROUT_PART_3", - "Kokiri Forest Deku Sprout Part 3", - "Kokiri Forest Deku Sprout Part 3", - ), - ( - "CS_DEST_DEATH_MOUNTAIN_TRAIL_CREDITS_PART_2", - "Death Mountain Trail Credits Part 2", - "Death Mountain Trail Credits Part 2", - ), - ("CS_DEST_TEMPLE_OF_TIME_CREDITS", "Temple Of Time Credits", "Temple Of Time Credits"), - ("CS_DEST_ZELDAS_COURTYARD_CREDITS", "Zeldas Courtyard Credits", "Zeldas Courtyard Credits"), - ("CS_DEST_LON_LON_RANCH_CREDITS_PART_1", "Lon Lon Ranch Credits Part 1", "Lon Lon Ranch Credits Part 1"), - ("CS_DEST_LON_LON_RANCH_CREDITS_PART_2", "Lon Lon Ranch Credits Part 2", "Lon Lon Ranch Credits Part 2"), - ("CS_DEST_LON_LON_RANCH_CREDITS_PART_3", "Lon Lon Ranch Credits Part 3", "Lon Lon Ranch Credits Part 3"), - ("CS_DEST_LON_LON_RANCH_CREDITS_PART_4", "Lon Lon Ranch Credits Part 4", "Lon Lon Ranch Credits Part 4"), - ("CS_DEST_LON_LON_RANCH_CREDITS_PART_5", "Lon Lon Ranch Credits Part 5", "Lon Lon Ranch Credits Part 5"), - ("CS_DEST_LON_LON_RANCH_CREDITS_PART_6", "Lon Lon Ranch Credits Part 6", "Lon Lon Ranch Credits Part 6"), - ("CS_DEST_LON_LON_RANCH_1", "Lon Lon Ranch 1", "Lon Lon Ranch 1"), - ("CS_DEST_LON_LON_RANCH_2", "Lon Lon Ranch 2", "Lon Lon Ranch 2"), - ("CS_DEST_LON_LON_RANCH_3", "Lon Lon Ranch 3", "Lon Lon Ranch 3"), - ("CS_DEST_LON_LON_RANCH_4", "Lon Lon Ranch 4", "Lon Lon Ranch 4"), - ("CS_DEST_LON_LON_RANCH_5", "Lon Lon Ranch 5", "Lon Lon Ranch 5"), - ("CS_DEST_LON_LON_RANCH_6", "Lon Lon Ranch 6", "Lon Lon Ranch 6"), - ("CS_DEST_LON_LON_RANCH_7", "Lon Lon Ranch 7", "Lon Lon Ranch 7"), - ("CS_DEST_LON_LON_RANCH_8", "Lon Lon Ranch 8", "Lon Lon Ranch 8"), - ("CS_DEST_LON_LON_RANCH_9", "Lon Lon Ranch 9", "Lon Lon Ranch 9"), - ("CS_DEST_LON_LON_RANCH_10", "Lon Lon Ranch 10", "Lon Lon Ranch 10"), - ("CS_DEST_LON_LON_RANCH_11", "Lon Lon Ranch 11", "Lon Lon Ranch 11"), - ("CS_DEST_LON_LON_RANCH_12", "Lon Lon Ranch 12", "Lon Lon Ranch 12"), - ("CS_DEST_LON_LON_RANCH_13", "Lon Lon Ranch 13", "Lon Lon Ranch 13"), - ("CS_DEST_LON_LON_RANCH_14", "Lon Lon Ranch 14", "Lon Lon Ranch 14"), - ("CS_DEST_LON_LON_RANCH_15", "Lon Lon Ranch 15", "Lon Lon Ranch 15"), - ("CS_DEST_LON_LON_RANCH_FROM_EPONAS_SONG", "Lon Lon Ranch From Eponas Song", "Lon Lon Ranch From Eponas Song"), - ("CS_DEST_STONES_RESTORED_CONDITIONAL", "Stones Restored Conditional", "Stones Restored Conditional"), - ( - "CS_DEST_DESERT_COLOSSUS_FROM_CHAMBER_OF_SAGES", - "Desert Colossus From Chamber Of Sages", - "Desert Colossus From Chamber Of Sages", - ), - ("CS_DEST_GRAVEYARD_FROM_CHAMBER_OF_SAGES", "Graveyard From Chamber Of Sages", "Graveyard From Chamber Of Sages"), - ( - "CS_DEST_DEATH_MOUNTAIN_CRATER_FROM_CHAMBER_OF_SAGES", - "Death Mountain Crater From Chamber Of Sages", - "Death Mountain Crater From Chamber Of Sages", - ), - ("CS_DEST_SACRED_FOREST_MEADOW_WARP_PAD", "Sacred Forest Meadow Warp Pad", "Sacred Forest Meadow Warp Pad"), - ( - "CS_DEST_KOKIRI_FOREST_FROM_CHAMBER_OF_SAGES", - "Kokiri Forest From Chamber Of Sages", - "Kokiri Forest From Chamber Of Sages", - ), - ( - "CS_DEST_DESERT_COLOSSUS_FROM_NABOORU_CAPTURE", - "Desert Colossus From Nabooru Capture", - "Desert Colossus From Nabooru Capture", - ), - ( - "CS_DEST_TEMPLE_OF_TIME_FRONT_OF_PEDESTAL", - "Temple Of Time Front Of Pedestal", - "Temple Of Time Front Of Pedestal", - ), - ("CS_DEST_HYRULE_FIELD_TITLE_SCREEN", "Hyrule Field Title Screen", "Hyrule Field Title Screen"), - ("CS_DEST_TITLE_SCREEN_DEMO", "Title Screen Demo", "Title Screen Demo"), - ("CS_DEST_GRAVEYARD_SUNS_SONG_PART_2", "Graveyard Suns Song Part 2", "Graveyard Suns Song Part 2"), - ( - "CS_DEST_ROYAL_FAMILYS_TOMB_SUNS_SONG_PART_3", - "Royal Familys Tomb Suns Song Part 3", - "Royal Familys Tomb Suns Song Part 3", - ), - ( - "CS_DEST_GANONS_CASTLE_DISPEL_FOREST_BEAM", - "Ganons Castle Dispel Forest Beam", - "Ganons Castle Dispel Forest Beam", - ), - ("CS_DEST_GANONS_CASTLE_DISPEL_WATER_BEAM", "Ganons Castle Dispel Water Beam", "Ganons Castle Dispel Water Beam"), - ( - "CS_DEST_GANONS_CASTLE_DISPEL_SHADOW_BEAM", - "Ganons Castle Dispel Shadow Beam", - "Ganons Castle Dispel Shadow Beam", - ), - ("CS_DEST_GANONS_CASTLE_DISPEL_FIRE_BEAM", "Ganons Castle Dispel Fire Beam", "Ganons Castle Dispel Fire Beam"), - ("CS_DEST_GANONS_CASTLE_DISPEL_LIGHT_BEAM", "Ganons Castle Dispel Light Beam", "Ganons Castle Dispel Light Beam"), - ( - "CS_DEST_GANONS_CASTLE_DISPEL_SPIRIT_BEAM", - "Ganons Castle Dispel Spirit Beam", - "Ganons Castle Dispel Spirit Beam", - ), - ( - "CS_DEST_GANONS_CASTLE_DISPEL_BARRIER_CONDITONAL", - "Ganons Castle Dispel Barrier Conditonal", - "Ganons Castle Dispel Barrier Conditonal", - ), - ("CS_DEST_HYRULE_FIELD_FROM_FAIRY_OCARINA", "Hyrule Field From Fairy Ocarina", "Hyrule Field From Fairy Ocarina"), - ("CS_DEST_HYRULE_FIELD_FROM_IMPA_ESCORT", "Hyrule Field From Impa Escort", "Hyrule Field From Impa Escort"), - ( - "CS_DEST_FROM_RAURU_FINAL_MESSAGE_CONDITIONAL", - "From Rauru Final Message Conditional", - "From Rauru Final Message Conditional", - ), - ("CS_DEST_HYRULE_FIELD_CREDITS_SKY", "Hyrule Field Credits Sky", "Hyrule Field Credits Sky"), - ("CS_DEST_GANON_BATTLE_TOWER_COLLAPSE", "Ganon Battle Tower Collapse", "Ganon Battle Tower Collapse"), - ("CS_DEST_ZELDAS_COURTYARD_RECEIVE_LETTER", "Zeldas Courtyard Receive Letter", "Zeldas Courtyard Receive Letter"), -] - -ootEnumTextType = [ - # see https://github.com/zeldaret/oot/blob/542012efa68d110d6b631f9d149f6e5f4e68cc8e/include/z64cutscene.h#L206-L212 - ("Custom", "Custom", "Custom"), - ("CS_TEXT_NORMAL", "Normal Text", "Normal Text"), - ("CS_TEXT_CHOICE", "Choice", "Choice"), - ("CS_TEXT_OCARINA_ACTION", "Ocarina Action", "Ocarina Action"), - ("CS_TEXT_GORON_RUBY", "Goron Ruby (use alt text)", "Goron Ruby (use alt text)"), - ("CS_TEXT_ZORA_SAPPHIRE", "Zora Sapphire (use alt text)", "Zora Sapphire (use alt text)"), -] - -ootEnumOcarinaAction = [ - # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64ocarina.h#L25-L76 - # note: "teach" and "playback" are the only types used in cutscenes but in theory every ones could be used - ("Custom", "Custom", "Custom"), - ("OCARINA_ACTION_TEACH_MINUET", "Teach Minuet", "Teach Minuet"), - ("OCARINA_ACTION_TEACH_BOLERO", "Teach Bolero", "Teach Bolero"), - ("OCARINA_ACTION_TEACH_SERENADE", "Teach Serenade", "Teach Serenade"), - ("OCARINA_ACTION_TEACH_REQUIEM", "Teach Requiem", "Teach Requiem"), - ("OCARINA_ACTION_TEACH_NOCTURNE", "Teach Nocturne", "Teach Nocturne"), - ("OCARINA_ACTION_TEACH_PRELUDE", "Teach Prelude", "Teach Prelude"), - ("OCARINA_ACTION_TEACH_SARIA", "Teach Saria", "Teach Saria"), - ("OCARINA_ACTION_TEACH_EPONA", "Teach Epona", "Teach Epona"), - ("OCARINA_ACTION_TEACH_LULLABY", "Teach Lullaby", "Teach Lullaby"), - ("OCARINA_ACTION_TEACH_SUNS", "Teach Suns", "Teach Suns"), - ("OCARINA_ACTION_TEACH_TIME", "Teach Time", "Teach Time"), - ("OCARINA_ACTION_TEACH_STORMS", "Teach Storms", "Teach Storms"), - ("OCARINA_ACTION_PLAYBACK_MINUET", "Play back Minuet", "Play back Minuet"), - ("OCARINA_ACTION_PLAYBACK_BOLERO", "Play back Bolero", "Play back Bolero"), - ("OCARINA_ACTION_PLAYBACK_SERENADE", "Play back Serenade", "Play back Serenade"), - ("OCARINA_ACTION_PLAYBACK_REQUIEM", "Play back Requiem", "Play back Requiem"), - ("OCARINA_ACTION_PLAYBACK_NOCTURNE", "Play back Nocturne", "Play back Nocturne"), - ("OCARINA_ACTION_PLAYBACK_PRELUDE", "Play back Prelude", "Play back Prelude"), - ("OCARINA_ACTION_PLAYBACK_SARIA", "Play back Saria", "Play back Saria"), - ("OCARINA_ACTION_PLAYBACK_EPONA", "Play back Epona", "Play back Epona"), - ("OCARINA_ACTION_PLAYBACK_LULLABY", "Play back Lullaby", "Play back Lullaby"), - ("OCARINA_ACTION_PLAYBACK_SUNS", "Play back Suns", "Play back Suns"), - ("OCARINA_ACTION_PLAYBACK_TIME", "Play back Time", "Play back Time"), - ("OCARINA_ACTION_PLAYBACK_STORMS", "Play back Storms", "Play back Storms"), -] - -ootEnumSeqPlayer = [ - # see https://github.com/zeldaret/oot/blob/b4c97ce17eb35329b4a7e3d98d7f06d558683f6d/include/z64cutscene.h#L214-L217 - ("Custom", "Custom", "Custom"), - ("CS_FADE_OUT_FANFARE", "Fanfare", "Fanfare"), - ("CS_FADE_OUT_BGM_MAIN", "BGM Main", "BGM Main"), -] - ootCSSubPropToName = { "startFrame": "Start Frame", "endFrame": "End Frame", diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index 3c1d9c1a0..e60a57342 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -1,4 +1,5 @@ from ...oot_utility import getCutsceneName, getCustomProperty +from ...oot_constants import ootData from .classes import ( OOTCSList, @@ -17,8 +18,9 @@ def readCutsceneData(csParentOut, csParentIn): listOut = OOTCSList() listOut.listType = listIn.listType + value = getCustomProperty(listIn, "transitionType") listOut.transitionType, listOut.transitionStartFrame, listOut.transitionEndFrame = ( - getCustomProperty(listIn, "transitionType"), + ootData.enumData.enumByKey["csTransitionType"].itemByKey[value] if value != "Custom" else value, listIn.transitionStartFrame, listIn.transitionEndFrame, ) @@ -29,12 +31,21 @@ def readCutsceneData(csParentOut, csParentIn): entryOut = OOTCSText() entryOut.textboxType = entryIn.textboxType entryOut.textID = entryIn.textID - entryOut.ocarinaAction = getCustomProperty(entryIn, "ocarinaAction") + + value = getCustomProperty(entryIn, "ocarinaAction") + entryOut.ocarinaAction = ( + ootData.enumData.enumByKey["ocarinaSongActionId"].itemByKey[value] if value != "Custom" else value + ) + entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame - entryOut.textType = getCustomProperty(entryIn, "csTextType") - if entryOut.textType == "CS_TEXT_CHOICE": + value = getCustomProperty(entryIn, "csTextType") + entryOut.textType = ( + ootData.enumData.enumByKey["csTextType"].itemByKey[value] if value != "Custom" else value + ) + + if entryOut.textType == "choice": entryOut.topOptionTextID = entryIn.topOptionTextID entryOut.bottomOptionTextID = entryIn.bottomOptionTextID @@ -57,15 +68,22 @@ def readCutsceneData(csParentOut, csParentIn): for entryIn in listIn.seqList: entryOut = OOTCSSeq() entryOut.csSeqID = getCustomProperty(entryIn, "csSeqID") - entryOut.csSeqPlayer = getCustomProperty(entryIn, "csSeqPlayer") - print(entryOut.csSeqPlayer) + + value = getCustomProperty(entryIn, "csSeqPlayer") + entryOut.csSeqPlayer = ( + ootData.enumData.enumByKey["csFadeOutSeqPlayer"].itemByKey[value] if value != "Custom" else value + ) + entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) elif listOut.listType == "MiscList": for entryIn in listIn.miscList: entryOut = OOTCSMisc() - entryOut.csMiscType = getCustomProperty(entryIn, "csMiscType") + value = getCustomProperty(entryIn, "csMiscType") + entryOut.csMiscType = ( + ootData.enumData.enumByKey["csMiscType"].itemByKey[value] if value != "Custom" else value + ) entryOut.startFrame = entryIn.startFrame entryOut.endFrame = entryIn.endFrame listOut.entries.append(entryOut) @@ -92,7 +110,10 @@ def convertCutsceneObject(obj): csprop = obj.ootCutsceneProperty cs.csEndFrame = getCustomProperty(csprop, "csEndFrame") cs.csUseDestination = getCustomProperty(csprop, "csUseDestination") - cs.csDestination = getCustomProperty(csprop, "csDestination") + value = getCustomProperty(csprop, "csDestination") + cs.csDestination = ( + ootData.enumData.enumByKey["csDestination"].itemByKey[value] if value != "Custom" else value + ) cs.csDestinationStartFrame = getCustomProperty(csprop, "csDestinationStartFrame") readCutsceneData(cs, csprop) diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index 6f93f8392..8c9fd0611 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -9,9 +9,10 @@ from bpy.utils import register_class, unregister_class from ...utility import CData, PluginError, writeCData, raisePluginError from ..oot_utility import getCollection +from ..oot_constants import ootData from ..scene.exporter.to_c import ootCutsceneDataToC from .exporter import convertCutsceneObject -from .constants import ootEnumCSTextboxType, ootEnumCSListType, ootEnumCSListTypeIcons, ootEnumCSDestinationType +from .constants import ootEnumCSTextboxType, ootEnumCSListType, ootEnumCSListTypeIcons from .motion.importer import importCutsceneData from .motion.exporter import getCutsceneMotionData @@ -257,7 +258,7 @@ class OOT_SearchCSDestinationEnumOperator(Operator): bl_property = "csDestination" bl_options = {"REGISTER", "UNDO"} - csDestination: EnumProperty(items=ootEnumCSDestinationType, default="CS_DEST_CUTSCENE_MAP_GANON_HORSE") + csDestination: EnumProperty(items=ootData.enumData.ootEnumCsDestination, default="cutscene_map_ganon_horse") objName: StringProperty() def execute(self, context): diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 2dcef4fbd..d4fd8d68f 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -4,7 +4,7 @@ from bpy.utils import register_class, unregister_class from ...utility import PluginError, prop_split from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName -from ..oot_constants import ootEnumMusicSeq +from ..oot_constants import ootData, ootEnumMusicSeq from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps, upgradeCutsceneProperty from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp from .motion.preview import previewFrameHandler @@ -19,14 +19,8 @@ from .constants import ( ootEnumCSTextboxType, ootEnumCSListType, - ootEnumCSTransitionType, ootEnumCSTextboxTypeIcons, - ootEnumCSDestinationType, - ootEnumCSMiscType, - ootEnumTextType, ootCSSubPropToName, - ootEnumOcarinaAction, - ootEnumSeqPlayer, ) @@ -113,13 +107,13 @@ class OOTCSTextProperty(OOTCutsceneCommon, PropertyGroup): # subprops textID: StringProperty(name="", default="0x0000") ocarinaAction: EnumProperty( - name="Ocarina Action", items=ootEnumOcarinaAction, default="OCARINA_ACTION_TEACH_MINUET" + name="Ocarina Action", items=ootData.enumData.ootEnumOcarinaSongActionId, default="teach_minuet" ) ocarinaActionCustom: StringProperty(default="OCARINA_ACTION_CUSTOM") topOptionTextID: StringProperty(name="", default="0x0000") bottomOptionTextID: StringProperty(name="", default="0x0000") ocarinaMessageId: StringProperty(name="", default="0x0000") - csTextType: EnumProperty(name="Text Type", items=ootEnumTextType, default="CS_TEXT_NORMAL") + csTextType: EnumProperty(name="Text Type", items=ootData.enumData.ootEnumCsTextType, default="normal") csTextTypeCustom: StringProperty(default="CS_TEXT_CUSTOM") def getName(self): @@ -154,7 +148,7 @@ class OOTCSSeqProperty(OOTCutsceneCommon, PropertyGroup): subprops = ["csSeqID", "startFrame", "endFrame"] csSeqID: EnumProperty(name="Seq ID", items=ootEnumMusicSeq, default="NA_BGM_GENERAL_SFX") csSeqIDCustom: StringProperty(default="NA_BGM_CUSTOM") - csSeqPlayer: EnumProperty(name="Seq Player", items=ootEnumSeqPlayer, default="CS_FADE_OUT_BGM_MAIN") + csSeqPlayer: EnumProperty(name="Seq Player", items=ootData.enumData.ootEnumCsFadeOutSeqPlayer, default="fade_out_fanfare") csSeqPlayerCustom: StringProperty(default="CS_FADE_OUT_CUSTOM") def filterProp(self, name, listProp): @@ -169,7 +163,7 @@ def filterName(self, name, listProp): class OOTCSMiscProperty(OOTCutsceneCommon, PropertyGroup): attrName = "miscList" subprops = ["csMiscType", "startFrame", "endFrame"] - csMiscType: EnumProperty(name="Type", items=ootEnumCSMiscType, default="CS_MISC_SET_LOCKED_VIEWPOINT") + csMiscType: EnumProperty(name="Type", items=ootData.enumData.ootEnumCsMiscType, default="rain") csMiscTypeCustom: StringProperty(default="CS_MISC_CUSTOM") @@ -195,7 +189,7 @@ class OOTCSListProperty(PropertyGroup): miscList: CollectionProperty(type=OOTCSMiscProperty) rumbleList: CollectionProperty(type=OOTCSRumbleProperty) - transitionType: EnumProperty(items=ootEnumCSTransitionType) + transitionType: EnumProperty(items=ootData.enumData.ootEnumCsTransitionType, default="gray_fill_in") transitionTypeCustom: StringProperty(default="CS_TRANS_CUSTOM") transitionStartFrame: IntProperty(name="", default=0, min=0) transitionEndFrame: IntProperty(name="", default=1, min=0) @@ -319,7 +313,7 @@ class OOTCutsceneProperty(PropertyGroup): csEndFrame: IntProperty(name="End Frame", min=0, default=100) csUseDestination: BoolProperty(name="Cutscene Destination (Scene Change)") csDestination: EnumProperty( - name="Destination", items=ootEnumCSDestinationType, default="CS_DEST_CUTSCENE_MAP_GANON_HORSE" + name="Destination", items=ootData.enumData.ootEnumCsDestination, default="cutscene_map_ganon_horse" ) csDestinationCustom: StringProperty(default="CS_DEST_CUSTOM") csDestinationStartFrame: IntProperty(name="Start Frame", min=0, default=99) @@ -370,7 +364,7 @@ def draw_props(self, layout: UILayout, obj: Object): boxRow = searchBox.row() searchOp = boxRow.operator(OOT_SearchCSDestinationEnumOperator.bl_idname, icon="VIEWZOOM", text="") searchOp.objName = obj.name - boxRow.label(text=getEnumName(ootEnumCSDestinationType, self.csDestination)) + boxRow.label(text=getEnumName(ootData.enumData.ootEnumCsDestination, self.csDestination)) if self.csDestination == "Custom": prop_split(searchBox.column(), self, "csDestinationCustom", "Cutscene Destination Custom") diff --git a/fast64_internal/oot/data/oot_enum_data.py b/fast64_internal/oot/data/oot_enum_data.py index df5cf7e5f..ff119b608 100644 --- a/fast64_internal/oot/data/oot_enum_data.py +++ b/fast64_internal/oot/data/oot_enum_data.py @@ -1,5 +1,6 @@ from dataclasses import dataclass, field from os import path +from ...utility import PluginError from .oot_getters import getXMLRoot from .oot_data import OoT_BaseElement @@ -8,7 +9,33 @@ @dataclass class OoT_ItemElement(OoT_BaseElement): - pass + parentKey: str + + def __post_init__(self): + # generate the name from the id + + keyToPrefix = { + "csCmd": "CS_CMD", + "csMiscType": "CS_MISC", + "csTextType": "CS_TEXT", + "csFadeOutSeqPlayer": "CS_FADE_OUT", + "csTransitionType": "CS_TRANS", + "csDestination": "CS_DEST", + "csPlayerCueId": "PLAYER_CUEID", + "naviQuestHintType": "NAVI_QUEST_HINTS", + "ocarinaSongActionId": "OCARINA_ACTION", + } + + self.name = self.id.removeprefix(f"{keyToPrefix[self.parentKey]}_") + + if self.parentKey in ["csCmd", "csPlayerCueId"]: + split = self.name.split("_") + if self.parentKey == "csCmd" and "ACTOR_CUE" in self.id: + self.name = f"Actor Cue {split[-2]}_{split[-1]}" + else: + self.name = f"Player Cue Id {split[-1]}" + else: + self.name = self.name.replace("_", " ").title() @dataclass @@ -46,8 +73,9 @@ def __init__(self): OoT_ItemElement( item.attrib["ID"], item.attrib["Key"], - item.attrib["ID"], + None, # note: the name sets automatically after the init int(item.attrib["Index"]), + enum.attrib["Key"], ) for item in enum ], @@ -65,6 +93,7 @@ def __init__(self): self.ootEnumCsDestination: list[tuple[str, str, str]] = [] self.ootEnumCsPlayerCueId: list[tuple[str, str, str]] = [] self.ootEnumNaviQuestHintType: list[tuple[str, str, str]] = [] + self.ootEnumOcarinaSongActionId: list[tuple[str, str, str]] = [] self.enumByID = {enum.id: enum for enum in self.enumDataList} self.enumByKey = {enum.key: enum for enum in self.enumDataList} diff --git a/fast64_internal/oot/data/xml/EnumData.xml b/fast64_internal/oot/data/xml/EnumData.xml index 96277683e..d96fadbf2 100644 --- a/fast64_internal/oot/data/xml/EnumData.xml +++ b/fast64_internal/oot/data/xml/EnumData.xml @@ -200,8 +200,9 @@ - - + + + @@ -429,4 +430,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 01118f425..68a652b2c 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -4,13 +4,6 @@ from .oot_utility import getEvalParams from .oot_constants import ootData, ootEnumMusicSeq from .cutscene.motion.constants import ootEnumCSMotionCamMode -from .cutscene.constants import ( - ootEnumTextType, - ootEnumCSMiscType, - ootEnumOcarinaAction, - ootEnumCSTransitionType, - ootEnumCSDestinationType, -) ##################################### @@ -176,12 +169,12 @@ def upgradeCutsceneSubProps(csListSubProp): subPropsToEnum = [ # TextBox - Cutscene_UpgradeData("ocarinaSongAction", "ocarinaAction", ootEnumOcarinaAction), - Cutscene_UpgradeData("type", "csTextType", ootEnumTextType), + Cutscene_UpgradeData("ocarinaSongAction", "ocarinaAction", ootData.enumData.ootEnumOcarinaSongActionId), + Cutscene_UpgradeData("type", "csTextType", ootData.enumData.ootEnumCsTextType), # Seq Cutscene_UpgradeData("value", "csSeqID", ootEnumMusicSeq), # Misc - Cutscene_UpgradeData("operation", "csMiscType", ootEnumCSMiscType), + Cutscene_UpgradeData("operation", "csMiscType", ootData.enumData.ootEnumCsMiscType), ] transferOldDataToNew(csListSubProp, subPropsOldToNew) @@ -205,7 +198,7 @@ def upgradeCSListProps(csListProp): transferOldDataToNew(csListProp, csListPropOldToNew) # both are enums but the item list is different (the old one doesn't have a "custom" entry) - convertOldDataToEnumData(csListProp, [Cutscene_UpgradeData("fxType", "transitionType", ootEnumCSTransitionType)]) + convertOldDataToEnumData(csListProp, [Cutscene_UpgradeData("fxType", "transitionType", ootData.enumData.ootEnumCsTransitionType)]) def upgradeCutsceneProperty(csProp): @@ -218,7 +211,7 @@ def upgradeCutsceneProperty(csProp): } transferOldDataToNew(csProp, csPropOldToNew) - convertOldDataToEnumData(csProp, [Cutscene_UpgradeData("csTermIdx", "csDestination", ootEnumCSDestinationType)]) + convertOldDataToEnumData(csProp, [Cutscene_UpgradeData("csTermIdx", "csDestination", ootData.enumData.ootEnumCsDestination)]) def upgradeCutsceneMotion(csMotionObj: Object): From f8b0712f4f5c7382e6ed30f215bdad695bdf3772 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Wed, 18 Oct 2023 11:59:27 +0200 Subject: [PATCH 17/39] black --- fast64_internal/oot/cutscene/exporter/functions.py | 6 ++---- fast64_internal/oot/cutscene/properties.py | 4 +++- fast64_internal/oot/data/oot_enum_data.py | 2 +- fast64_internal/oot/oot_upgrade.py | 10 +++++++--- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index e60a57342..d1241179c 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -31,7 +31,7 @@ def readCutsceneData(csParentOut, csParentIn): entryOut = OOTCSText() entryOut.textboxType = entryIn.textboxType entryOut.textID = entryIn.textID - + value = getCustomProperty(entryIn, "ocarinaAction") entryOut.ocarinaAction = ( ootData.enumData.enumByKey["ocarinaSongActionId"].itemByKey[value] if value != "Custom" else value @@ -111,9 +111,7 @@ def convertCutsceneObject(obj): cs.csEndFrame = getCustomProperty(csprop, "csEndFrame") cs.csUseDestination = getCustomProperty(csprop, "csUseDestination") value = getCustomProperty(csprop, "csDestination") - cs.csDestination = ( - ootData.enumData.enumByKey["csDestination"].itemByKey[value] if value != "Custom" else value - ) + cs.csDestination = ootData.enumData.enumByKey["csDestination"].itemByKey[value] if value != "Custom" else value cs.csDestinationStartFrame = getCustomProperty(csprop, "csDestinationStartFrame") readCutsceneData(cs, csprop) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index d4fd8d68f..123577bba 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -148,7 +148,9 @@ class OOTCSSeqProperty(OOTCutsceneCommon, PropertyGroup): subprops = ["csSeqID", "startFrame", "endFrame"] csSeqID: EnumProperty(name="Seq ID", items=ootEnumMusicSeq, default="NA_BGM_GENERAL_SFX") csSeqIDCustom: StringProperty(default="NA_BGM_CUSTOM") - csSeqPlayer: EnumProperty(name="Seq Player", items=ootData.enumData.ootEnumCsFadeOutSeqPlayer, default="fade_out_fanfare") + csSeqPlayer: EnumProperty( + name="Seq Player", items=ootData.enumData.ootEnumCsFadeOutSeqPlayer, default="fade_out_fanfare" + ) csSeqPlayerCustom: StringProperty(default="CS_FADE_OUT_CUSTOM") def filterProp(self, name, listProp): diff --git a/fast64_internal/oot/data/oot_enum_data.py b/fast64_internal/oot/data/oot_enum_data.py index ff119b608..73657ed12 100644 --- a/fast64_internal/oot/data/oot_enum_data.py +++ b/fast64_internal/oot/data/oot_enum_data.py @@ -73,7 +73,7 @@ def __init__(self): OoT_ItemElement( item.attrib["ID"], item.attrib["Key"], - None, # note: the name sets automatically after the init + None, # note: the name sets automatically after the init int(item.attrib["Index"]), enum.attrib["Key"], ) diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 68a652b2c..7154be552 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -50,7 +50,7 @@ def upgradeRoomHeaders(roomObj: Object, objData: OoT_ObjectData): class Cutscene_UpgradeData: oldPropName: str newPropName: str - enumData: list[tuple[str, str, str]] # this is the list used for enum properties + enumData: list[tuple[str, str, str]] # this is the list used for enum properties def transferOldDataToNew(data, oldDataToNewData: dict[str, str]): @@ -198,7 +198,9 @@ def upgradeCSListProps(csListProp): transferOldDataToNew(csListProp, csListPropOldToNew) # both are enums but the item list is different (the old one doesn't have a "custom" entry) - convertOldDataToEnumData(csListProp, [Cutscene_UpgradeData("fxType", "transitionType", ootData.enumData.ootEnumCsTransitionType)]) + convertOldDataToEnumData( + csListProp, [Cutscene_UpgradeData("fxType", "transitionType", ootData.enumData.ootEnumCsTransitionType)] + ) def upgradeCutsceneProperty(csProp): @@ -211,7 +213,9 @@ def upgradeCutsceneProperty(csProp): } transferOldDataToNew(csProp, csPropOldToNew) - convertOldDataToEnumData(csProp, [Cutscene_UpgradeData("csTermIdx", "csDestination", ootData.enumData.ootEnumCsDestination)]) + convertOldDataToEnumData( + csProp, [Cutscene_UpgradeData("csTermIdx", "csDestination", ootData.enumData.ootEnumCsDestination)] + ) def upgradeCutsceneMotion(csMotionObj: Object): From 441e7e8a5dc16e967caf59da848db5a3335bcd6a Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Wed, 18 Oct 2023 12:54:26 +0200 Subject: [PATCH 18/39] preview update --- fast64_internal/oot/cutscene/preview.py | 44 +++++++++++++++++-------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/fast64_internal/oot/cutscene/preview.py b/fast64_internal/oot/cutscene/preview.py index 7693099df..68443f342 100644 --- a/fast64_internal/oot/cutscene/preview.py +++ b/fast64_internal/oot/cutscene/preview.py @@ -121,7 +121,7 @@ def processCurrentFrame(csObj: Object, curFrame: float, useNodeFeatures: bool, c startFrame = transitionCmd.startFrame endFrame = transitionCmd.endFrame frameCur = curFrame - isTriggerInstance = transitionCmd.type == "CS_TRANS_TRIGGER_INSTANCE" + isTriggerInstance = transitionCmd.type == "trigger_instance" linear160 = getColor(160.0) if transitionCmd.type == "Unknown": @@ -144,24 +144,24 @@ def processCurrentFrame(csObj: Object, curFrame: float, useNodeFeatures: bool, c if isTriggerInstance: previewProp.trigger = True - if transitionCmd.type.endswith("IN"): + if transitionCmd.type.endswith("in"): alpha = linear255 * lerp else: alpha = (1.0 - lerp) * linear255 - if "HALF" in transitionCmd.type: - if "_IN_" in transitionCmd.type: + if "half" in transitionCmd.type: + if "_in_" in transitionCmd.type: alpha = linear255 - ((1.0 - lerp) * linear155) else: alpha = linear255 - (linear155 * lerp) - if "_GRAY_" in transitionCmd.type or previewProp.trigger: + if "gray_" in transitionCmd.type or previewProp.trigger: color[0] = color[1] = color[2] = linear160 * alpha - elif "_RED_" in transitionCmd.type: + elif "red_" in transitionCmd.type: color[0] = linear255 * alpha - elif "_GREEN_" in transitionCmd.type: + elif "green_" in transitionCmd.type: color[1] = linear255 * alpha - elif "_BLUE_" in transitionCmd.type: + elif "blue_" in transitionCmd.type: color[2] = linear255 * alpha color[3] = alpha @@ -175,11 +175,11 @@ def processCurrentFrame(csObj: Object, curFrame: float, useNodeFeatures: bool, c print("ERROR: Unknown command!") if curFrame == startFrame: - if miscCmd.type == "CS_MISC_SET_LOCKED_VIEWPOINT" and not None in cameraObjects: + if miscCmd.type == "set_locked_viewpoint" and not None in cameraObjects: bpy.context.scene.camera = cameraObjects[int(csObj.ootCutsceneProperty.preview.isFixedCamSet)] csObj.ootCutsceneProperty.preview.isFixedCamSet ^= True - if miscCmd.type == "CS_MISC_STOP_CUTSCENE": + elif miscCmd.type == "stop_cutscene": # stop the playback and set the frame to 0 bpy.ops.screen.animation_cancel() bpy.context.scene.frame_set(bpy.context.scene.frame_start) @@ -189,8 +189,8 @@ def processCurrentFrame(csObj: Object, curFrame: float, useNodeFeatures: bool, c color = [0.0, 0.0, 0.0, 0.0] lerp = getLerp(endFrame - 1, startFrame, curFrame) - if miscCmd.type in ["CS_MISC_VISMONO_SEPIA", "CS_MISC_VISMONO_BLACK_AND_WHITE"]: - if miscCmd.type == "CS_MISC_VISMONO_SEPIA": + if miscCmd.type in ["vismono_sepia", "vismono_black_and_white"]: + if miscCmd.type == "vismono_sepia": col = [255.0, 180.0, 100.0] else: col = [255.0, 255.0, 254.0] @@ -201,7 +201,7 @@ def processCurrentFrame(csObj: Object, curFrame: float, useNodeFeatures: bool, c color[3] = getColor(255.0) * lerp bpy.context.scene.node_tree.nodes["CSMisc_RGB"].outputs[0].default_value = color - if miscCmd.type == "CS_MISC_RED_PULSATING_LIGHTS": + elif miscCmd.type == "red_pulsating_lights": color = bpy.context.scene.node_tree.nodes["CSMisc_RGB"].outputs[0].default_value color[0] = getColor(255.0) color[1] = color[2] = 0.0 @@ -253,9 +253,25 @@ def cutscenePreviewFrameHandler(scene: Scene): # setup nodes bpy.context.scene.ootCSPreviewNodesReady = False setupCompositorNodes() + previewProp = csObj.ootCutsceneProperty.preview + + # set preview properties + previewProp.miscList.clear() + previewProp.transitionList.clear() + for item in csObj.ootCutsceneProperty.csLists: + if item.listType == "Transition": + newProp = previewProp.transitionList.add() + newProp.startFrame = item.transitionStartFrame + newProp.endFrame = item.transitionEndFrame + newProp.type = item.transitionType + elif item.listType == "MiscList": + for normalMisc in item.miscList: + newProp = previewProp.miscList.add() + newProp.startFrame = normalMisc.startFrame + newProp.endFrame = normalMisc.endFrame + newProp.type = normalMisc.csMiscType # execute the main preview logic - previewProp = csObj.ootCutsceneProperty.preview curFrame = bpy.context.scene.frame_current if isclose(curFrame, previewProp.prevFrame, abs_tol=1) and isclose(curFrame, previewProp.nextFrame, abs_tol=1): processCurrentFrame(csObj, curFrame, bpy.context.scene.ootCSPreviewNodesReady, cameraObjects) From bed836601decf8d056ef0826125d61ccd3d2e5ec Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Wed, 18 Oct 2023 21:56:45 +0200 Subject: [PATCH 19/39] importer v1 --- .../oot/cutscene/motion/constants.py | 10 + .../oot/cutscene/motion/importer/classes.py | 308 ++++++++++++++++-- .../oot/cutscene/motion/io_classes.py | 134 ++++++++ fast64_internal/oot/cutscene/properties.py | 8 +- fast64_internal/oot/data/oot_enum_data.py | 48 +-- fast64_internal/oot/data/xml/EnumData.xml | 121 ++++++- fast64_internal/oot/oot_upgrade.py | 7 +- 7 files changed, 579 insertions(+), 57 deletions(-) diff --git a/fast64_internal/oot/cutscene/motion/constants.py b/fast64_internal/oot/cutscene/motion/constants.py index 236da1915..2e0cf84df 100644 --- a/fast64_internal/oot/cutscene/motion/constants.py +++ b/fast64_internal/oot/cutscene/motion/constants.py @@ -35,6 +35,12 @@ "CS_FADE_BGM_LIST": "CS_FADE_OUT_SEQ_LIST", "CS_FADE_BGM": "CS_FADE_OUT_SEQ", "CS_TERMINATOR": "CS_DESTINATION", + "CS_LIGHTING_LIST": "CS_LIGHT_SETTING_LIST", + "CS_LIGHTING": "L_CS_LIGHT_SETTING", + "CS_PLAY_BGM_LIST": "CS_START_SEQ_LIST", + "CS_PLAY_BGM": "L_CS_START_SEQ", + "CS_STOP_BGM_LIST": "CS_STOP_SEQ_LIST", + "CS_STOP_BGM": "L_CS_STOP_SEQ", } ootCSMotionListCommands = [ @@ -78,6 +84,10 @@ "CS_PLAY_BGM", "CS_STOP_BGM", "CS_LIGHTING", + # some old commands need to remove 1 to the first argument to stay accurate + "L_CS_LIGHT_SETTING", + "L_CS_START_SEQ", + "L_CS_STOP_SEQ", ] ootCSMotionSingleCommands = [ diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/motion/importer/classes.py index 4d04af3d4..67daa2ade 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/motion/importer/classes.py @@ -2,11 +2,15 @@ from dataclasses import dataclass from struct import unpack +from typing import TYPE_CHECKING from bpy.types import Object, Armature from .....utility import PluginError from ....oot_constants import ootData from ..utility import setupCutscene, getBlenderPosition, getRotation +if TYPE_CHECKING: + from ...properties import OOTCSListProperty + from ..constants import ( ootCSMotionLegacyToNewCmdNames, ootCSMotionListCommands, @@ -31,6 +35,20 @@ OOTCSMotionMisc, OOTCSMotionMiscList, OOTCSMotionTransition, + OOTCSMotionText, + OOTCSMotionTextNone, + OOTCSMotionTextOcarinaAction, + OOTCSMotionTextList, + OOTCSMotionLightSetting, + OOTCSMotionLightSettingList, + OOTCSMotionTime, + OOTCSMotionTimeList, + OOTCSMotionStartStopSeq, + OOTCSMotionStartStopSeqList, + OOTCSMotionFadeSeq, + OOTCSMotionFadeSeqList, + OOTCSMotionRumbleController, + OOTCSMotionRumbleControllerList, ) @@ -48,8 +66,10 @@ class OOTCSMotionImportCommands: def getCmdParams(self, data: str, cmdName: str, paramNumber: int): """Returns the list of every parameter of the given command""" - params = data.strip().removeprefix(f"{cmdName}(").replace(" ", "").removesuffix(")").split(",") - if len(params) != paramNumber: + parenthesis = "(" if not cmdName.endswith("(") else "" + params = data.strip().removeprefix(f"{cmdName}{parenthesis}").replace(" ", "").removesuffix(")").split(",") + validTimeCmd = cmdName == "CS_TIME" and len(params) == 6 and paramNumber == 5 + if len(params) != paramNumber and not validTimeCmd: raise PluginError( f"ERROR: The number of expected parameters for `{cmdName}` " + "and the number of found ones is not the same!" @@ -146,8 +166,8 @@ def getNewMisc(self, cmdData: str): miscEnum = ootData.enumData.enumByKey["csMiscType"] item = miscEnum.itemById.get(params[0]) if item is None: - item = miscEnum.itemByIndex[self.getInteger(params[0])] - miscType = item.id + item = miscEnum.itemByIndex.get(self.getInteger(params[0])) + miscType = item.key if item is not None else params[0] return OOTCSMotionMisc(self.getInteger(params[1]), self.getInteger(params[2]), miscType) def getNewMiscList(self, cmdData: str): @@ -159,10 +179,137 @@ def getNewTransition(self, cmdData: str): transitionEnum = ootData.enumData.enumByKey["csTransitionType"] item = transitionEnum.itemById.get(params[0]) if item is None: - item = transitionEnum.itemByIndex[self.getInteger(params[0])] - transType = item.id + item = transitionEnum.itemByIndex.get(self.getInteger(params[0])) + transType = item.key if item is not None else params[0] return OOTCSMotionTransition(self.getInteger(params[1]), self.getInteger(params[2]), transType) + def getNewText(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_TEXT(", OOTCSMotionText.paramNumber) + textEnum = ootData.enumData.enumByKey["csTextType"] + item = textEnum.itemById.get(params[3]) + if item is None: + item = textEnum.itemByIndex.get(self.getInteger(params[3])) + textType = item.key if item is not None else params[3] + return OOTCSMotionText( + self.getInteger(params[1]), + self.getInteger(params[2]), + self.getInteger(params[0]), + textType, + self.getInteger(params[4]), + self.getInteger(params[5]), + ) + + def getNewTextNone(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_TEXT_NONE", OOTCSMotionTextNone.paramNumber) + return OOTCSMotionTextNone(self.getInteger(params[0]), self.getInteger(params[1])) + + def getNewTextOcarinaAction(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_TEXT_OCARINA_ACTION", OOTCSMotionTextOcarinaAction.paramNumber) + actionEnum = ootData.enumData.enumByKey["ocarinaSongActionId"] + item = actionEnum.itemById.get(params[0]) + if item is None: + item = actionEnum.itemByIndex.get(self.getInteger(params[0])) + actionId = item.key if item is not None else params[0] + return OOTCSMotionTextOcarinaAction( + self.getInteger(params[1]), + self.getInteger(params[2]), + actionId, + self.getInteger(params[3]) + ) + + def getNewTextEntry(self, cmdData: str): + if cmdData.startswith("CS_TEXT("): + return self.getNewText(cmdData) + elif cmdData.startswith("CS_TEXT_NONE("): + return self.getNewTextNone(cmdData) + elif cmdData.startswith("CS_TEXT_OCARINA_ACTION("): + return self.getNewTextOcarinaAction(cmdData) + return None + + def getNewTextList(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_TEXT_LIST", OOTCSMotionTextList.paramNumber) + return OOTCSMotionTextList(self.getInteger(params[0])) + + def getNewLightSetting(self, cmdData: str): + isLegacy = cmdData.startswith("L_") + if isLegacy: + cmdData = cmdData.removeprefix("L_") + params = self.getCmdParams(cmdData, "CS_LIGHT_SETTING", OOTCSMotionLightSetting.paramNumber) + setting = self.getInteger(params[0]) + + if isLegacy: + setting -= 1 + return OOTCSMotionLightSetting( + self.getInteger(params[1]), self.getInteger(params[2]), setting + ) + + def getNewLightSettingList(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_LIGHT_SETTING_LIST", OOTCSMotionLightSettingList.paramNumber) + return OOTCSMotionLightSettingList(self.getInteger(params[0])) + + def getNewTime(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_TIME", OOTCSMotionTime.paramNumber) + return OOTCSMotionTime( + self.getInteger(params[1]), self.getInteger(params[2]), self.getInteger(params[3]), self.getInteger(params[4]) + ) + + def getNewTimeList(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_TIME_LIST", OOTCSMotionTimeList.paramNumber) + return OOTCSMotionTimeList(self.getInteger(params[0])) + + def getNewStartStopSeq(self, cmdData: str, type: str): + isLegacy = cmdData.startswith("L_") + if isLegacy: + cmdData = cmdData.removeprefix("L_") + cmdName = f"CS_{'START' if type == 'start' else 'STOP'}_SEQ" + params = self.getCmdParams(cmdData, cmdName, OOTCSMotionStartStopSeq.paramNumber) + try: + seqEnum = ootData.enumData.enumByKey["seqId"] + item = seqEnum.itemById.get(params[0]) + if item is None: + setting = self.getInteger(params[0]) + if isLegacy: + setting -= 1 + item = seqEnum.itemByIndex.get(setting) + seqId = item.key if item is not None else params[0] + except: + seqId = params[0] + return OOTCSMotionStartStopSeq( + self.getInteger(params[1]), self.getInteger(params[2]), seqId, + ) + + def getNewStartStopSeqList(self, cmdData: str, type: str): + cmdName = f"CS_{'START' if type == 'start' else 'STOP'}_SEQ_LIST" + params = self.getCmdParams(cmdData, cmdName, OOTCSMotionStartStopSeqList.paramNumber) + return OOTCSMotionStartStopSeqList(self.getInteger(params[0]), type) + + def getNewFadeSeq(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_FADE_OUT_SEQ", OOTCSMotionFadeSeq.paramNumber) + fadePlayerEnum = ootData.enumData.enumByKey["csFadeOutSeqPlayer"] + item = fadePlayerEnum.itemById.get(params[0]) + if item is None: + item = fadePlayerEnum.itemByIndex.get(self.getInteger(params[0])) + fadePlayerType = item.key if item is not None else params[0] + return OOTCSMotionFadeSeq(self.getInteger(params[1]), self.getInteger(params[2]), fadePlayerType) + + def getNewFadeSeqList(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_FADE_OUT_SEQ_LIST", OOTCSMotionFadeSeqList.paramNumber) + return OOTCSMotionFadeSeqList(self.getInteger(params[0])) + + def getNewRumbleController(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_RUMBLE_CONTROLLER", OOTCSMotionRumbleController.paramNumber) + return OOTCSMotionRumbleController( + self.getInteger(params[1]), + self.getInteger(params[2]), + self.getInteger(params[3]), + self.getInteger(params[4]), + self.getInteger(params[5]), + ) + + def getNewRumbleControllerList(self, cmdData: str): + params = self.getCmdParams(cmdData, "CS_RUMBLE_CONTROLLER_LIST", OOTCSMotionRumbleControllerList.paramNumber) + return OOTCSMotionRumbleControllerList(self.getInteger(params[0])) + @dataclass class OOTCSMotionImport(OOTCSMotionImportCommands, OOTCSMotionObjectFactory): @@ -250,7 +397,7 @@ def getParsedCutscenes(self): # camera and lighting have "non-standard" list names if curCmd.startswith("CS_CAM"): curCmdPrefix = "CS_CAM" - elif curCmd.startswith("CS_LIGHT"): + elif curCmd.startswith("CS_LIGHT") or curCmd.startswith("L_CS_LIGHT"): curCmdPrefix = "CS_LIGHT" else: curCmdPrefix = curCmd[:-5] @@ -304,6 +451,12 @@ def getCutsceneList(self): ("CAM_AT", self.getNewCamAT, self.getNewCamPoint, "camAT"), ("MISC_LIST", self.getNewMiscList, self.getNewMisc, "misc"), ("TRANSITION", self.getNewTransition, None, "transition"), + ("TEXT_LIST", self.getNewTextList, self.getNewTextEntry, "text"), + ("LIGHT_SETTING_LIST", self.getNewLightSettingList, self.getNewLightSetting, "lightSetting"), + ("TIME_LIST", self.getNewTimeList, self.getNewTime, "time"), + ("SEQ_LIST", self.getNewStartStopSeqList, self.getNewStartStopSeq, "seq"), + ("FADE_OUT_SEQ_LIST", self.getNewFadeSeqList, self.getNewFadeSeq, "fadeSeq"), + ("RUMBLE_CONTROLLER_LIST", self.getNewRumbleControllerList, self.getNewRumbleController, "rumble"), ] # for each cutscene from the list returned by getParsedCutscenes(), @@ -312,6 +465,7 @@ def getCutsceneList(self): for parsedCS in parsedCutscenes: cutscene = None for data in parsedCS.csData: + # print(data) # create a new cutscene data if "CS_BEGIN_CUTSCENE(" in data: cutscene = self.getNewCutscene(data, parsedCS.csName) @@ -322,21 +476,35 @@ def getCutsceneList(self): cmdListData = cmdData.pop(0) for cmd, getListFunc, getFunc, listName in cmdDataList: isPlayer = cmd == "PLAYER_CUE_LIST" + isStartSeq = cmd == "SEQ_LIST" and cmdListData.startswith("CS_START_SEQ_LIST") + isStopSeq = cmd == "SEQ_LIST" and cmdListData.startswith("CS_STOP_SEQ_LIST") - if f"CS_{cmd}(" in data: + if isStartSeq or isStopSeq or f"CS_{cmd}(" in data: cmdList = getattr(cutscene, f"{listName}List") if getListFunc is not None: if not isPlayer and not cmd == "ACTOR_CUE_LIST": - commandData = getListFunc(cmdListData) + if isStartSeq: + commandData = getListFunc(cmdListData, "start") + elif isStopSeq: + commandData = getListFunc(cmdListData, "stop") + else: + commandData = getListFunc(cmdListData) else: commandData = getListFunc(cmdListData, isPlayer) + else: + raise PluginError("ERROR: List getter callback is None!") if getFunc is not None: foundEndCmd = False for d in cmdData: if not isPlayer and not cmd == "ACTOR_CUE_LIST": - listEntry = getFunc(d) + if isStartSeq: + listEntry = getFunc(d, "start") + elif isStopSeq: + listEntry = getFunc(d, "stop") + else: + listEntry = getFunc(d) if "CAM" in cmd: flag = d.removeprefix("CS_CAM_POINT(").split(",")[0] if foundEndCmd: @@ -344,7 +512,9 @@ def getCutsceneList(self): foundEndCmd = "CS_CAM_STOP" in flag or "-1" in flag else: listEntry = getFunc(d, isPlayer) - commandData.entries.append(listEntry) + + if listEntry is not None: + commandData.entries.append(listEntry) cmdList.append(commandData) @@ -492,6 +662,16 @@ def setCameraShotData( endIndex = i return endIndex + 1 + + def setListData(self, prop, typeName: str, startFrame: int, endFrame: int, type: str): + prop.startFrame = startFrame + prop.endFrame = endFrame + if typeName is not None and type is not None: + try: + setattr(prop, typeName, type) + except TypeError: + setattr(prop, typeName, "Custom") + setattr(prop, f"{typeName}Custom", type) def setCutsceneData(self, csNumber): """Creates the cutscene empty objects from the file data""" @@ -507,6 +687,7 @@ def setCutsceneData(self, csNumber): self.validateCameraData(cutscene) csName = f"Cutscene.{cutscene.name}" csObj = self.getNewCutsceneObject(csName, cutscene.frameCount, None) + csProp = csObj.ootCutsceneProperty csNumber = i print("Importing Actor Cues...") @@ -535,20 +716,97 @@ def setCutsceneData(self, csNumber): csObj, cutscene.camEyeList, cutscene.camATList, "eyeOrAT", lastIndex, i ) - if len(cutscene.miscList) > 0: - for miscList in cutscene.miscList: - for miscCmd in miscList.entries: - miscProp = csObj.ootCutsceneProperty.preview.miscList.add() - miscProp.startFrame = miscCmd.startFrame - miscProp.endFrame = miscCmd.endFrame - miscProp.type = miscCmd.type - - if len(cutscene.transitionList) > 0: - for transition in cutscene.transitionList: - transitionProp = csObj.ootCutsceneProperty.preview.transitionList.add() - transitionProp.startFrame = transition.startFrame - transitionProp.endFrame = transition.endFrame - transitionProp.type = transition.type + for miscList in cutscene.miscList: + miscElem: "OOTCSListProperty" = csProp.csLists.add() + miscElem.listType = "MiscList" + for miscCmd in miscList.entries: + miscProp = miscElem.miscList.add() + self.setListData(miscProp, "csMiscType", miscCmd.startFrame, miscCmd.endFrame, miscCmd.type) + + for transition in cutscene.transitionList: + transitionElem: "OOTCSListProperty" = csProp.csLists.add() + transitionElem.listType = "Transition" + transitionElem.transitionStartFrame = transition.startFrame + transitionElem.transitionEndFrame = transition.endFrame + try: + transitionElem.transitionType = transition.type + except TypeError: + transitionElem.transitionType = "Custom" + transitionElem.transitionTypeCustom = transition.type + + for textList in cutscene.textList: + textElem: "OOTCSListProperty" = csProp.csLists.add() + textElem.listType = "TextList" + textList.entries.sort(key=lambda elem: elem.startFrame) + for textCmd in textList.entries: + textProp = textElem.textList.add() + textProp.textboxType = textCmd.id + match textCmd.id: + case "Text": + textProp.textID = f"0x{textCmd.textId:04X}" + typeName = "csTextType" + type = textCmd.type + case "None": + typeName = type = None + case "OcarinaAction": + textProp.ocarinaMessageId = f"0x{textCmd.messageId:04X}" + typeName = "ocarinaAction" + type = textCmd.ocarinaActionId + case _: + raise PluginError("ERROR: Unknown text type!") + self.setListData(textProp, typeName, textCmd.startFrame, textCmd.endFrame, type) + + for lightList in cutscene.lightSettingList: + lightElem: "OOTCSListProperty" = csProp.csLists.add() + lightElem.listType = "LightSettingsList" + for lightCmd in lightList.entries: + lightProp = lightElem.lightSettingsList.add() + lightProp.lightSettingsIndex = lightCmd.lightSetting + lightProp.startFrame = lightCmd.startFrame + + for timeList in cutscene.timeList: + timeElem: "OOTCSListProperty" = csProp.csLists.add() + timeElem.listType = "TimeList" + for timeCmd in timeList.entries: + timeProp = timeElem.timeList.add() + timeProp.hour = timeCmd.hour + timeProp.minute = timeCmd.minute + timeProp.startFrame = timeCmd.startFrame + + for seqList in cutscene.seqList: + seqElem: "OOTCSListProperty" = csProp.csLists.add() + seqElem.listType = "StartSeqList" if seqList.type == "start" else "StopSeqList" + for seqCmd in seqList.entries: + seqProp = seqElem.seqList.add() + try: + seqProp.csSeqID = seqCmd.seqId + except TypeError: + seqProp.csSeqID = "Custom" + transitionElem.csSeqIDCustom = seqCmd.seqId + seqProp.startFrame = seqCmd.startFrame + + for fadeList in cutscene.fadeSeqList: + fadeElem: "OOTCSListProperty" = csProp.csLists.add() + fadeElem.listType = "FadeOutSeqList" + for fadeCmd in fadeList.entries: + fadeProp = fadeElem.seqList.add() + try: + fadeProp.csSeqPlayer = fadeCmd.seqPlayer + except TypeError: + fadeProp.csSeqPlayer = "Custom" + transitionElem.csSeqPlayerCustom = fadeCmd.seqPlayer + fadeProp.startFrame = fadeCmd.startFrame + fadeProp.endFrame = fadeCmd.endFrame + + for rumbleList in cutscene.rumbleList: + rumbleElem: "OOTCSListProperty" = csProp.csLists.add() + rumbleElem.listType = "RumbleList" + for rumbleCmd in rumbleList.entries: + rumbleProp = rumbleElem.rumbleList.add() + rumbleProp.startFrame = rumbleCmd.startFrame + rumbleProp.rumbleSourceStrength = rumbleCmd.sourceStrength + rumbleProp.rumbleDuration = rumbleCmd.duration + rumbleProp.rumbleDecreaseRate = rumbleCmd.decreaseRate # Init camera + preview objects and setup the scene setupCutscene(csObj) diff --git a/fast64_internal/oot/cutscene/motion/io_classes.py b/fast64_internal/oot/cutscene/motion/io_classes.py index 462eeb2f6..1269eace9 100644 --- a/fast64_internal/oot/cutscene/motion/io_classes.py +++ b/fast64_internal/oot/cutscene/motion/io_classes.py @@ -126,6 +126,134 @@ class OOTCSMotionTransition(OOTCSMotionBase): paramNumber: int = 3 +@dataclass +class OOTCSMotionText(OOTCSMotionBase): + """This class contains Text command data""" + + textId: int + type: str + altTextId1: int + altTextId2: int + paramNumber: int = 6 + id: str = "Text" + + +@dataclass +class OOTCSMotionTextNone(OOTCSMotionBase): + """This class contains Text None command data""" + + paramNumber: int = 2 + id: str = "None" + + +@dataclass +class OOTCSMotionTextOcarinaAction(OOTCSMotionBase): + """This class contains Text Ocarina Action command data""" + + ocarinaActionId: str + messageId: int + paramNumber: int = 4 + id: str = "OcarinaAction" + + +@dataclass +class OOTCSMotionTextList: + """This class contains Text List command data""" + + entryTotal: int + entries: list[OOTCSMotionText | OOTCSMotionTextNone | OOTCSMotionTextOcarinaAction] = field(default_factory=list) + paramNumber: int = 1 + + +@dataclass +class OOTCSMotionLightSetting(OOTCSMotionBase): + """This class contains Light Setting command data""" + + lightSetting: int + paramNumber: int = 11 + + +@dataclass +class OOTCSMotionLightSettingList: + """This class contains Light Setting List command data""" + + entryTotal: int + entries: list[OOTCSMotionLightSetting] = field(default_factory=list) + paramNumber: int = 1 + + +@dataclass +class OOTCSMotionTime(OOTCSMotionBase): + """This class contains Time Ocarina Action command data""" + + hour: int + minute: int + paramNumber: int = 5 + + +@dataclass +class OOTCSMotionTimeList: + """This class contains Time List command data""" + + entryTotal: int + entries: list[OOTCSMotionTime] = field(default_factory=list) + paramNumber: int = 1 + + +@dataclass +class OOTCSMotionStartStopSeq(OOTCSMotionBase): + """This class contains Start/Stop Seq command data""" + + seqId: str + paramNumber: int = 11 + + +@dataclass +class OOTCSMotionStartStopSeqList: + """This class contains Start/Stop Seq List command data""" + + entryTotal: int + type: str + entries: list[OOTCSMotionStartStopSeq] = field(default_factory=list) + paramNumber: int = 1 + + +@dataclass +class OOTCSMotionFadeSeq(OOTCSMotionBase): + """This class contains Fade Seq command data""" + + seqPlayer: str + paramNumber: int = 11 + + +@dataclass +class OOTCSMotionFadeSeqList: + """This class contains Fade Seq List command data""" + + entryTotal: int + entries: list[OOTCSMotionFadeSeq] = field(default_factory=list) + paramNumber: int = 1 + + +@dataclass +class OOTCSMotionRumbleController(OOTCSMotionBase): + """This class contains Rumble Controller command data""" + + sourceStrength: int + duration: int + decreaseRate: int + paramNumber: int = 8 + + +@dataclass +class OOTCSMotionRumbleControllerList: + """This class contains Rumble Controller List command data""" + + entryTotal: int + entries: list[OOTCSMotionRumbleController] = field(default_factory=list) + paramNumber: int = 1 + + @dataclass class OOTCSMotionCutscene: """This class contains a Cutscene's data, including every commands' data""" @@ -145,6 +273,12 @@ class OOTCSMotionCutscene: camATList: list[OOTCSMotionCamAT] = field(default_factory=list) miscList: list[OOTCSMotionMiscList] = field(default_factory=list) transitionList: list[OOTCSMotionTransition] = field(default_factory=list) + textList: list[OOTCSMotionTextList] = field(default_factory=list) + lightSettingList: list[OOTCSMotionLightSettingList] = field(default_factory=list) + timeList: list[OOTCSMotionTimeList] = field(default_factory=list) + seqList: list[OOTCSMotionStartStopSeqList] = field(default_factory=list) + fadeSeqList: list[OOTCSMotionFadeSeqList] = field(default_factory=list) + rumbleList: list[OOTCSMotionRumbleControllerList] = field(default_factory=list) class OOTCSMotionObjectFactory: diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 123577bba..8e9ada4de 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -4,7 +4,7 @@ from bpy.utils import register_class, unregister_class from ...utility import PluginError, prop_split from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName -from ..oot_constants import ootData, ootEnumMusicSeq +from ..oot_constants import ootData from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps, upgradeCutsceneProperty from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp from .motion.preview import previewFrameHandler @@ -68,7 +68,6 @@ def draw_props( if self.filterProp(p, listProp): name = self.filterName(p, listProp) displayName = ootCSSubPropToName[name] - value = getattr(self, p) if name == "csSeqPlayer": # change the property name to draw the other enum for fade seq command @@ -83,6 +82,7 @@ def draw_props( "csSeqID", "csSeqPlayer", ] + value = getattr(self, p) if name in customValues and value == "Custom": prop_split(box, self, f"{name}Custom", f"{displayName} Custom") @@ -133,7 +133,7 @@ def filterProp(self, name, listProp): class OOTCSLightSettingsProperty(OOTCutsceneCommon, PropertyGroup): attrName = "lightSettingsList" subprops = ["lightSettingsIndex", "startFrame"] - lightSettingsIndex: IntProperty(name="", default=1, min=1) + lightSettingsIndex: IntProperty(name="", default=0, min=0) class OOTCSTimeProperty(OOTCutsceneCommon, PropertyGroup): @@ -146,7 +146,7 @@ class OOTCSTimeProperty(OOTCutsceneCommon, PropertyGroup): class OOTCSSeqProperty(OOTCutsceneCommon, PropertyGroup): attrName = "seqList" subprops = ["csSeqID", "startFrame", "endFrame"] - csSeqID: EnumProperty(name="Seq ID", items=ootEnumMusicSeq, default="NA_BGM_GENERAL_SFX") + csSeqID: EnumProperty(name="Seq ID", items=ootData.enumData.ootEnumSeqId, default="general_sfx") csSeqIDCustom: StringProperty(default="NA_BGM_CUSTOM") csSeqPlayer: EnumProperty( name="Seq Player", items=ootData.enumData.ootEnumCsFadeOutSeqPlayer, default="fade_out_fanfare" diff --git a/fast64_internal/oot/data/oot_enum_data.py b/fast64_internal/oot/data/oot_enum_data.py index 73657ed12..0644c6f4b 100644 --- a/fast64_internal/oot/data/oot_enum_data.py +++ b/fast64_internal/oot/data/oot_enum_data.py @@ -1,6 +1,5 @@ from dataclasses import dataclass, field from os import path -from ...utility import PluginError from .oot_getters import getXMLRoot from .oot_data import OoT_BaseElement @@ -14,28 +13,29 @@ class OoT_ItemElement(OoT_BaseElement): def __post_init__(self): # generate the name from the id - keyToPrefix = { - "csCmd": "CS_CMD", - "csMiscType": "CS_MISC", - "csTextType": "CS_TEXT", - "csFadeOutSeqPlayer": "CS_FADE_OUT", - "csTransitionType": "CS_TRANS", - "csDestination": "CS_DEST", - "csPlayerCueId": "PLAYER_CUEID", - "naviQuestHintType": "NAVI_QUEST_HINTS", - "ocarinaSongActionId": "OCARINA_ACTION", - } - - self.name = self.id.removeprefix(f"{keyToPrefix[self.parentKey]}_") - - if self.parentKey in ["csCmd", "csPlayerCueId"]: - split = self.name.split("_") - if self.parentKey == "csCmd" and "ACTOR_CUE" in self.id: - self.name = f"Actor Cue {split[-2]}_{split[-1]}" + if self.name is None: + keyToPrefix = { + "csCmd": "CS_CMD", + "csMiscType": "CS_MISC", + "csTextType": "CS_TEXT", + "csFadeOutSeqPlayer": "CS_FADE_OUT", + "csTransitionType": "CS_TRANS", + "csDestination": "CS_DEST", + "csPlayerCueId": "PLAYER_CUEID", + "naviQuestHintType": "NAVI_QUEST_HINTS", + "ocarinaSongActionId": "OCARINA_ACTION", + } + + self.name = self.id.removeprefix(f"{keyToPrefix[self.parentKey]}_") + + if self.parentKey in ["csCmd", "csPlayerCueId"]: + split = self.name.split("_") + if self.parentKey == "csCmd" and "ACTOR_CUE" in self.id: + self.name = f"Actor Cue {split[-2]}_{split[-1]}" + else: + self.name = f"Player Cue Id {split[-1]}" else: - self.name = f"Player Cue Id {split[-1]}" - else: - self.name = self.name.replace("_", " ").title() + self.name = self.name.replace("_", " ").title() @dataclass @@ -73,7 +73,8 @@ def __init__(self): OoT_ItemElement( item.attrib["ID"], item.attrib["Key"], - None, # note: the name sets automatically after the init + # note: the name sets automatically after the init if None + item.attrib["Name"] if enum.attrib["Key"] == "seqId" else None, int(item.attrib["Index"]), enum.attrib["Key"], ) @@ -94,6 +95,7 @@ def __init__(self): self.ootEnumCsPlayerCueId: list[tuple[str, str, str]] = [] self.ootEnumNaviQuestHintType: list[tuple[str, str, str]] = [] self.ootEnumOcarinaSongActionId: list[tuple[str, str, str]] = [] + self.ootEnumSeqId: list[tuple[str, str, str]] = [] self.enumByID = {enum.id: enum for enum in self.enumDataList} self.enumByKey = {enum.key: enum for enum in self.enumDataList} diff --git a/fast64_internal/oot/data/xml/EnumData.xml b/fast64_internal/oot/data/xml/EnumData.xml index d96fadbf2..c379af7a4 100644 --- a/fast64_internal/oot/data/xml/EnumData.xml +++ b/fast64_internal/oot/data/xml/EnumData.xml @@ -13,6 +13,7 @@ Parameters: * Key: identifier that should never be changed * ID: the actual enum name from decomp, this may change hence the need of the Key parameter + * Name: a descriptive name about the current item * Index: the location of the item in the enum (should match decomp) Notes: @@ -200,9 +201,8 @@ - - - + + @@ -483,4 +483,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index 7154be552..f08030f52 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -56,14 +56,17 @@ class Cutscene_UpgradeData: def transferOldDataToNew(data, oldDataToNewData: dict[str, str]): # conversion to the same prop type # simply transfer the old data to the new one - # special case for rumble subprops where it's a string to int conversion for oldName, newName in oldDataToNewData.items(): if oldName in data: if newName is not None: value = data[oldName] + # special case for rumble subprops where it's a string to int conversion + # another special case for light setting index where the value need to be minus one if newName in ["rumbleSourceStrength", "rumbleDuration", "rumbleDecreaseRate"]: value = int(getEvalParams(data[oldName]), base=16) + elif newName == "lightSettingsIndex": + value -= 1 data[newName] = value @@ -172,7 +175,7 @@ def upgradeCutsceneSubProps(csListSubProp): Cutscene_UpgradeData("ocarinaSongAction", "ocarinaAction", ootData.enumData.ootEnumOcarinaSongActionId), Cutscene_UpgradeData("type", "csTextType", ootData.enumData.ootEnumCsTextType), # Seq - Cutscene_UpgradeData("value", "csSeqID", ootEnumMusicSeq), + Cutscene_UpgradeData("value", "csSeqID", ootData.enumData.ootEnumSeqId), # Misc Cutscene_UpgradeData("operation", "csMiscType", ootData.enumData.ootEnumCsMiscType), ] From 359f3e985763856b8c77eda4215749c9123ee026 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Wed, 18 Oct 2023 21:56:56 +0200 Subject: [PATCH 20/39] black --- .../oot/cutscene/motion/importer/classes.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/motion/importer/classes.py index 67daa2ade..9a5629b48 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/motion/importer/classes.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from struct import unpack -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING from bpy.types import Object, Armature from .....utility import PluginError from ....oot_constants import ootData @@ -198,11 +198,11 @@ def getNewText(self, cmdData: str): self.getInteger(params[4]), self.getInteger(params[5]), ) - + def getNewTextNone(self, cmdData: str): params = self.getCmdParams(cmdData, "CS_TEXT_NONE", OOTCSMotionTextNone.paramNumber) return OOTCSMotionTextNone(self.getInteger(params[0]), self.getInteger(params[1])) - + def getNewTextOcarinaAction(self, cmdData: str): params = self.getCmdParams(cmdData, "CS_TEXT_OCARINA_ACTION", OOTCSMotionTextOcarinaAction.paramNumber) actionEnum = ootData.enumData.enumByKey["ocarinaSongActionId"] @@ -211,10 +211,7 @@ def getNewTextOcarinaAction(self, cmdData: str): item = actionEnum.itemByIndex.get(self.getInteger(params[0])) actionId = item.key if item is not None else params[0] return OOTCSMotionTextOcarinaAction( - self.getInteger(params[1]), - self.getInteger(params[2]), - actionId, - self.getInteger(params[3]) + self.getInteger(params[1]), self.getInteger(params[2]), actionId, self.getInteger(params[3]) ) def getNewTextEntry(self, cmdData: str): @@ -225,7 +222,7 @@ def getNewTextEntry(self, cmdData: str): elif cmdData.startswith("CS_TEXT_OCARINA_ACTION("): return self.getNewTextOcarinaAction(cmdData) return None - + def getNewTextList(self, cmdData: str): params = self.getCmdParams(cmdData, "CS_TEXT_LIST", OOTCSMotionTextList.paramNumber) return OOTCSMotionTextList(self.getInteger(params[0])) @@ -239,9 +236,7 @@ def getNewLightSetting(self, cmdData: str): if isLegacy: setting -= 1 - return OOTCSMotionLightSetting( - self.getInteger(params[1]), self.getInteger(params[2]), setting - ) + return OOTCSMotionLightSetting(self.getInteger(params[1]), self.getInteger(params[2]), setting) def getNewLightSettingList(self, cmdData: str): params = self.getCmdParams(cmdData, "CS_LIGHT_SETTING_LIST", OOTCSMotionLightSettingList.paramNumber) @@ -250,7 +245,10 @@ def getNewLightSettingList(self, cmdData: str): def getNewTime(self, cmdData: str): params = self.getCmdParams(cmdData, "CS_TIME", OOTCSMotionTime.paramNumber) return OOTCSMotionTime( - self.getInteger(params[1]), self.getInteger(params[2]), self.getInteger(params[3]), self.getInteger(params[4]) + self.getInteger(params[1]), + self.getInteger(params[2]), + self.getInteger(params[3]), + self.getInteger(params[4]), ) def getNewTimeList(self, cmdData: str): @@ -275,7 +273,9 @@ def getNewStartStopSeq(self, cmdData: str, type: str): except: seqId = params[0] return OOTCSMotionStartStopSeq( - self.getInteger(params[1]), self.getInteger(params[2]), seqId, + self.getInteger(params[1]), + self.getInteger(params[2]), + seqId, ) def getNewStartStopSeqList(self, cmdData: str, type: str): @@ -662,7 +662,7 @@ def setCameraShotData( endIndex = i return endIndex + 1 - + def setListData(self, prop, typeName: str, startFrame: int, endFrame: int, type: str): prop.startFrame = startFrame prop.endFrame = endFrame From 4b39a6973e82f5e43c41947dfbbaca9d070a543b Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Thu, 19 Oct 2023 19:03:46 +0200 Subject: [PATCH 21/39] importer improvements part 1 --- .../oot/cutscene/motion/importer/classes.py | 393 ++++-------------- .../oot/cutscene/motion/io_classes.py | 257 +++++++++--- .../oot/cutscene/motion/utility.py | 13 + 3 files changed, 306 insertions(+), 357 deletions(-) diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/motion/importer/classes.py index 9a5629b48..f70a57841 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/motion/importer/classes.py @@ -1,12 +1,11 @@ import bpy from dataclasses import dataclass -from struct import unpack from typing import TYPE_CHECKING from bpy.types import Object, Armature from .....utility import PluginError from ....oot_constants import ootData -from ..utility import setupCutscene, getBlenderPosition, getRotation +from ..utility import setupCutscene, getBlenderPosition, getInteger if TYPE_CHECKING: from ...properties import OOTCSListProperty @@ -76,239 +75,9 @@ def getCmdParams(self, data: str, cmdName: str, paramNumber: int): ) return params - def getInteger(self, number: str): - """Returns an int number (handles properly negative hex numbers)""" - - if number.startswith("0x"): - number = number.removeprefix("0x") - - # ``"0" * (8 - len(number)`` adds the missing zeroes (if necessary) to have a 8 digit hex number - return unpack("!i", bytes.fromhex("0" * (8 - len(number)) + number))[0] - else: - return int(number) - def getNewCutscene(self, csData: str, name: str): params = self.getCmdParams(csData, "CS_BEGIN_CUTSCENE", OOTCSMotionCutscene.paramNumber) - return OOTCSMotionCutscene(name, self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewActorCueList(self, cmdData: str, isPlayer: bool): - paramNumber = OOTCSMotionActorCueList.paramNumber - paramNumber = paramNumber - 1 if isPlayer else paramNumber - params = self.getCmdParams(cmdData, f"CS_{'PLAYER' if isPlayer else 'ACTOR'}_CUE_LIST", paramNumber) - - if isPlayer: - actorCueList = OOTCSMotionActorCueList("Player", params[0]) - else: - commandType = params[0] - if commandType.startswith("0x"): - # make it a 4 digit hex - commandType = commandType.removeprefix("0x") - commandType = "0x" + "0" * (4 - len(commandType)) + commandType - actorCueList = OOTCSMotionActorCueList(commandType, self.getInteger(params[1].strip())) - - return actorCueList - - def getNewCamEyeSpline(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_CAM_EYE_SPLINE", OOTCSMotionCamEyeSpline.paramNumber) - return OOTCSMotionCamEyeSpline(self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewCamATSpline(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_CAM_AT_SPLINE", OOTCSMotionCamATSpline.paramNumber) - return OOTCSMotionCamATSpline(self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewCamEyeSplineRelToPlayer(self, cmdData: str): - params = self.getCmdParams( - cmdData, "CS_CAM_EYE_SPLINE_REL_TO_PLAYER", OOTCSMotionCamEyeSplineRelToPlayer.paramNumber - ) - return OOTCSMotionCamEyeSplineRelToPlayer(self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewCamATSplineRelToPlayer(self, cmdData: str): - params = self.getCmdParams( - cmdData, "CS_CAM_AT_SPLINE_REL_TO_PLAYER", OOTCSMotionCamATSplineRelToPlayer.paramNumber - ) - return OOTCSMotionCamATSplineRelToPlayer(self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewCamEye(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_CAM_EYE", OOTCSMotionCamEye.paramNumber) - return OOTCSMotionCamEye(self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewCamAT(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_CAM_AT", OOTCSMotionCamAT.paramNumber) - return OOTCSMotionCamAT(self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewActorCue(self, cmdData: str, isPlayer: bool): - params = self.getCmdParams( - cmdData, f"CS_{'PLAYER' if isPlayer else 'ACTOR'}_CUE", OOTCSMotionActorCue.paramNumber - ) - - return OOTCSMotionActorCue( - self.getInteger(params[1]), - self.getInteger(params[2]), - self.getInteger(params[0]), - [getRotation(params[3]), getRotation(params[4]), getRotation(params[5])], - [self.getInteger(params[6]), self.getInteger(params[7]), self.getInteger(params[8])], - [self.getInteger(params[9]), self.getInteger(params[10]), self.getInteger(params[11])], - ) - - def getNewCamPoint(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_CAM_POINT", OOTCSMotionCamPoint.paramNumber) - - return OOTCSMotionCamPoint( - params[0], - self.getInteger(params[1]), - self.getInteger(params[2]), - float(params[3][:-1]), - [self.getInteger(params[4]), self.getInteger(params[5]), self.getInteger(params[6])], - ) - - def getNewMisc(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_MISC", OOTCSMotionMisc.paramNumber) - miscEnum = ootData.enumData.enumByKey["csMiscType"] - item = miscEnum.itemById.get(params[0]) - if item is None: - item = miscEnum.itemByIndex.get(self.getInteger(params[0])) - miscType = item.key if item is not None else params[0] - return OOTCSMotionMisc(self.getInteger(params[1]), self.getInteger(params[2]), miscType) - - def getNewMiscList(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_MISC_LIST", OOTCSMotionMiscList.paramNumber) - return OOTCSMotionMiscList(params[0]) - - def getNewTransition(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_TRANSITION", OOTCSMotionTransition.paramNumber) - transitionEnum = ootData.enumData.enumByKey["csTransitionType"] - item = transitionEnum.itemById.get(params[0]) - if item is None: - item = transitionEnum.itemByIndex.get(self.getInteger(params[0])) - transType = item.key if item is not None else params[0] - return OOTCSMotionTransition(self.getInteger(params[1]), self.getInteger(params[2]), transType) - - def getNewText(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_TEXT(", OOTCSMotionText.paramNumber) - textEnum = ootData.enumData.enumByKey["csTextType"] - item = textEnum.itemById.get(params[3]) - if item is None: - item = textEnum.itemByIndex.get(self.getInteger(params[3])) - textType = item.key if item is not None else params[3] - return OOTCSMotionText( - self.getInteger(params[1]), - self.getInteger(params[2]), - self.getInteger(params[0]), - textType, - self.getInteger(params[4]), - self.getInteger(params[5]), - ) - - def getNewTextNone(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_TEXT_NONE", OOTCSMotionTextNone.paramNumber) - return OOTCSMotionTextNone(self.getInteger(params[0]), self.getInteger(params[1])) - - def getNewTextOcarinaAction(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_TEXT_OCARINA_ACTION", OOTCSMotionTextOcarinaAction.paramNumber) - actionEnum = ootData.enumData.enumByKey["ocarinaSongActionId"] - item = actionEnum.itemById.get(params[0]) - if item is None: - item = actionEnum.itemByIndex.get(self.getInteger(params[0])) - actionId = item.key if item is not None else params[0] - return OOTCSMotionTextOcarinaAction( - self.getInteger(params[1]), self.getInteger(params[2]), actionId, self.getInteger(params[3]) - ) - - def getNewTextEntry(self, cmdData: str): - if cmdData.startswith("CS_TEXT("): - return self.getNewText(cmdData) - elif cmdData.startswith("CS_TEXT_NONE("): - return self.getNewTextNone(cmdData) - elif cmdData.startswith("CS_TEXT_OCARINA_ACTION("): - return self.getNewTextOcarinaAction(cmdData) - return None - - def getNewTextList(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_TEXT_LIST", OOTCSMotionTextList.paramNumber) - return OOTCSMotionTextList(self.getInteger(params[0])) - - def getNewLightSetting(self, cmdData: str): - isLegacy = cmdData.startswith("L_") - if isLegacy: - cmdData = cmdData.removeprefix("L_") - params = self.getCmdParams(cmdData, "CS_LIGHT_SETTING", OOTCSMotionLightSetting.paramNumber) - setting = self.getInteger(params[0]) - - if isLegacy: - setting -= 1 - return OOTCSMotionLightSetting(self.getInteger(params[1]), self.getInteger(params[2]), setting) - - def getNewLightSettingList(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_LIGHT_SETTING_LIST", OOTCSMotionLightSettingList.paramNumber) - return OOTCSMotionLightSettingList(self.getInteger(params[0])) - - def getNewTime(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_TIME", OOTCSMotionTime.paramNumber) - return OOTCSMotionTime( - self.getInteger(params[1]), - self.getInteger(params[2]), - self.getInteger(params[3]), - self.getInteger(params[4]), - ) - - def getNewTimeList(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_TIME_LIST", OOTCSMotionTimeList.paramNumber) - return OOTCSMotionTimeList(self.getInteger(params[0])) - - def getNewStartStopSeq(self, cmdData: str, type: str): - isLegacy = cmdData.startswith("L_") - if isLegacy: - cmdData = cmdData.removeprefix("L_") - cmdName = f"CS_{'START' if type == 'start' else 'STOP'}_SEQ" - params = self.getCmdParams(cmdData, cmdName, OOTCSMotionStartStopSeq.paramNumber) - try: - seqEnum = ootData.enumData.enumByKey["seqId"] - item = seqEnum.itemById.get(params[0]) - if item is None: - setting = self.getInteger(params[0]) - if isLegacy: - setting -= 1 - item = seqEnum.itemByIndex.get(setting) - seqId = item.key if item is not None else params[0] - except: - seqId = params[0] - return OOTCSMotionStartStopSeq( - self.getInteger(params[1]), - self.getInteger(params[2]), - seqId, - ) - - def getNewStartStopSeqList(self, cmdData: str, type: str): - cmdName = f"CS_{'START' if type == 'start' else 'STOP'}_SEQ_LIST" - params = self.getCmdParams(cmdData, cmdName, OOTCSMotionStartStopSeqList.paramNumber) - return OOTCSMotionStartStopSeqList(self.getInteger(params[0]), type) - - def getNewFadeSeq(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_FADE_OUT_SEQ", OOTCSMotionFadeSeq.paramNumber) - fadePlayerEnum = ootData.enumData.enumByKey["csFadeOutSeqPlayer"] - item = fadePlayerEnum.itemById.get(params[0]) - if item is None: - item = fadePlayerEnum.itemByIndex.get(self.getInteger(params[0])) - fadePlayerType = item.key if item is not None else params[0] - return OOTCSMotionFadeSeq(self.getInteger(params[1]), self.getInteger(params[2]), fadePlayerType) - - def getNewFadeSeqList(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_FADE_OUT_SEQ_LIST", OOTCSMotionFadeSeqList.paramNumber) - return OOTCSMotionFadeSeqList(self.getInteger(params[0])) - - def getNewRumbleController(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_RUMBLE_CONTROLLER", OOTCSMotionRumbleController.paramNumber) - return OOTCSMotionRumbleController( - self.getInteger(params[1]), - self.getInteger(params[2]), - self.getInteger(params[3]), - self.getInteger(params[4]), - self.getInteger(params[5]), - ) - - def getNewRumbleControllerList(self, cmdData: str): - params = self.getCmdParams(cmdData, "CS_RUMBLE_CONTROLLER_LIST", OOTCSMotionRumbleControllerList.paramNumber) - return OOTCSMotionRumbleControllerList(self.getInteger(params[0])) + return OOTCSMotionCutscene(name, getInteger(params[0]), getInteger(params[1])) @dataclass @@ -430,34 +199,39 @@ def getCutsceneList(self): return None cutsceneList: list[OOTCSMotionCutscene] = [] - cmdDataList = [ - ("ACTOR_CUE_LIST", self.getNewActorCueList, self.getNewActorCue, "actorCue"), - ("PLAYER_CUE_LIST", self.getNewActorCueList, self.getNewActorCue, "playerCue"), - ("CAM_EYE_SPLINE", self.getNewCamEyeSpline, self.getNewCamPoint, "camEyeSpline"), - ("CAM_AT_SPLINE", self.getNewCamATSpline, self.getNewCamPoint, "camATSpline"), - ( - "CAM_EYE_SPLINE_REL_TO_PLAYER", - self.getNewCamEyeSplineRelToPlayer, - self.getNewCamPoint, - "camEyeSplineRelPlayer", - ), - ( - "CAM_AT_SPLINE_REL_TO_PLAYER", - self.getNewCamATSplineRelToPlayer, - self.getNewCamPoint, - "camATSplineRelPlayer", - ), - ("CAM_EYE", self.getNewCamEye, self.getNewCamPoint, "camEye"), - ("CAM_AT", self.getNewCamAT, self.getNewCamPoint, "camAT"), - ("MISC_LIST", self.getNewMiscList, self.getNewMisc, "misc"), - ("TRANSITION", self.getNewTransition, None, "transition"), - ("TEXT_LIST", self.getNewTextList, self.getNewTextEntry, "text"), - ("LIGHT_SETTING_LIST", self.getNewLightSettingList, self.getNewLightSetting, "lightSetting"), - ("TIME_LIST", self.getNewTimeList, self.getNewTime, "time"), - ("SEQ_LIST", self.getNewStartStopSeqList, self.getNewStartStopSeq, "seq"), - ("FADE_OUT_SEQ_LIST", self.getNewFadeSeqList, self.getNewFadeSeq, "fadeSeq"), - ("RUMBLE_CONTROLLER_LIST", self.getNewRumbleControllerList, self.getNewRumbleController, "rumble"), - ] + + cmdToClass = { + "CS_CAM_POINT": OOTCSMotionCamPoint, + "CS_MISC": OOTCSMotionMisc, + "CS_LIGHT_SETTING": OOTCSMotionLightSetting, + "CS_TIME": OOTCSMotionTime, + "CS_FADE_OUT_SEQ": OOTCSMotionFadeSeq, + "CS_RUMBLE_CONTROLLER": OOTCSMotionRumbleController, + "CS_TEXT": OOTCSMotionText, + "CS_TEXT_NONE": OOTCSMotionTextNone, + "CS_TEXT_OCARINA_ACTION": OOTCSMotionTextOcarinaAction, + "CS_START_SEQ": OOTCSMotionStartStopSeq, + "CS_STOP_SEQ": OOTCSMotionStartStopSeq, + "CS_ACTOR_CUE": OOTCSMotionActorCue, + "CS_PLAYER_CUE": OOTCSMotionActorCue, + "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, + "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, + "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, + "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, + "CS_CAM_EYE": OOTCSMotionCamEye, + "CS_CAM_AT": OOTCSMotionCamAT, + "CS_MISC_LIST": OOTCSMotionMiscList, + "CS_TRANSITION": OOTCSMotionTransition, + "CS_TEXT_LIST": OOTCSMotionTextList, + "CS_LIGHT_SETTING_LIST": OOTCSMotionLightSettingList, + "CS_TIME_LIST": OOTCSMotionTimeList, + "CS_FADE_OUT_SEQ_LIST": OOTCSMotionFadeSeqList, + "CS_RUMBLE_CONTROLLER_LIST": OOTCSMotionRumbleControllerList, + "CS_START_SEQ_LIST": OOTCSMotionStartStopSeqList, + "CS_STOP_SEQ_LIST": OOTCSMotionStartStopSeqList, + "CS_ACTOR_CUE_LIST": OOTCSMotionActorCueList, + "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, + } # for each cutscene from the list returned by getParsedCutscenes(), # create classes containing the cutscene's informations @@ -465,58 +239,59 @@ def getCutsceneList(self): for parsedCS in parsedCutscenes: cutscene = None for data in parsedCS.csData: - # print(data) + cmdData = data.removesuffix("\n").split("\n") + cmdListData = cmdData.pop(0) + cmdListName = cmdListData.strip().split("(")[0] + # create a new cutscene data - if "CS_BEGIN_CUTSCENE(" in data: + if cmdListName == "CS_BEGIN_CUTSCENE": cutscene = self.getNewCutscene(data, parsedCS.csName) # if we have a cutscene, create and add the commands data in it - if cutscene is not None: - cmdData = data.removesuffix("\n").split("\n") - cmdListData = cmdData.pop(0) - for cmd, getListFunc, getFunc, listName in cmdDataList: - isPlayer = cmd == "PLAYER_CUE_LIST" - isStartSeq = cmd == "SEQ_LIST" and cmdListData.startswith("CS_START_SEQ_LIST") - isStopSeq = cmd == "SEQ_LIST" and cmdListData.startswith("CS_STOP_SEQ_LIST") - - if isStartSeq or isStopSeq or f"CS_{cmd}(" in data: - cmdList = getattr(cutscene, f"{listName}List") - - if getListFunc is not None: - if not isPlayer and not cmd == "ACTOR_CUE_LIST": - if isStartSeq: - commandData = getListFunc(cmdListData, "start") - elif isStopSeq: - commandData = getListFunc(cmdListData, "stop") - else: - commandData = getListFunc(cmdListData) + elif cutscene is not None and data.startswith(f"{cmdListName}("): + isPlayer = cmdListData.startswith("CS_PLAYER_CUE_LIST(") + isStartSeq = cmdListData.startswith("CS_START_SEQ_LIST(") + isStopSeq = cmdListData.startswith("CS_STOP_SEQ_LIST(") + + cmd = cmdToClass.get(cmdListName) + if cmd is not None: + cmdList = getattr(cutscene, "playerCueList" if isPlayer else cmd.listName) + + paramNumber = cmd.paramNumber - 1 if isPlayer else cmd.paramNumber + params = self.getCmdParams(cmdListData, cmdListName, paramNumber) + if isStartSeq or isStopSeq: + commandData = cmd(params, type="start" if isStartSeq else "stop") + elif cmdListData.startswith("CS_ACTOR_CUE_LIST(") or isPlayer: + commandData = cmd(params, isPlayer=isPlayer) + else: + commandData = cmd(params) + + if cmdListName != "CS_TRANSITION": + foundEndCmd = False + for d in cmdData: + cmdEntryName = d.strip().split("(")[0] + isLegacy = d.startswith("L_") + if isLegacy: + cmdEntryName = cmdEntryName.removeprefix("L_") + d = d.removeprefix("L_") + + if "CAM" in cmdListName: + flag = d.removeprefix("CS_CAM_POINT(").split(",")[0] + if foundEndCmd: + raise PluginError("ERROR: More camera commands after last one!") + foundEndCmd = "CS_CAM_STOP" in flag or "-1" in flag + + entryCmd = cmdToClass[cmdEntryName] + params = self.getCmdParams(d, cmdEntryName, entryCmd.paramNumber) + + if "CS_LIGHT_SETTING(" in d or isStartSeq or isStopSeq: + listEntry = entryCmd(params, isLegacy=isLegacy) else: - commandData = getListFunc(cmdListData, isPlayer) - else: - raise PluginError("ERROR: List getter callback is None!") - - if getFunc is not None: - foundEndCmd = False - for d in cmdData: - if not isPlayer and not cmd == "ACTOR_CUE_LIST": - if isStartSeq: - listEntry = getFunc(d, "start") - elif isStopSeq: - listEntry = getFunc(d, "stop") - else: - listEntry = getFunc(d) - if "CAM" in cmd: - flag = d.removeprefix("CS_CAM_POINT(").split(",")[0] - if foundEndCmd: - raise PluginError("ERROR: More camera commands after last one!") - foundEndCmd = "CS_CAM_STOP" in flag or "-1" in flag - else: - listEntry = getFunc(d, isPlayer) - - if listEntry is not None: - commandData.entries.append(listEntry) - - cmdList.append(commandData) + listEntry = entryCmd(params) + commandData.entries.append(listEntry) + cmdList.append(commandData) + else: + print(f"WARNING: `{cmdListName}` is not implemented yet!") # after processing the commands we can add the cutscene to the cutscene list if cutscene is not None: @@ -756,7 +531,7 @@ def setCutsceneData(self, csNumber): raise PluginError("ERROR: Unknown text type!") self.setListData(textProp, typeName, textCmd.startFrame, textCmd.endFrame, type) - for lightList in cutscene.lightSettingList: + for lightList in cutscene.lightSettingsList: lightElem: "OOTCSListProperty" = csProp.csLists.add() lightElem.listType = "LightSettingsList" for lightCmd in lightList.entries: diff --git a/fast64_internal/oot/cutscene/motion/io_classes.py b/fast64_internal/oot/cutscene/motion/io_classes.py index 1269eace9..c0aa28c96 100644 --- a/fast64_internal/oot/cutscene/motion/io_classes.py +++ b/fast64_internal/oot/cutscene/motion/io_classes.py @@ -3,7 +3,7 @@ from dataclasses import dataclass, field from bpy.types import Object from ...oot_constants import ootData -from .utility import getBlenderPosition, getBlenderRotation +from .utility import getBlenderPosition, getBlenderRotation, getRotation, getInteger # NOTE: ``paramNumber`` is the expected number of parameters inside the parsed commands, @@ -14,41 +14,82 @@ class OOTCSMotionBase: """This class contains common Cutscene data""" - startFrame: int - endFrame: int + params: list[str] + + startFrame: int = None + endFrame: int = None + + def getEnumValue(self, enumKey: str, index: int, isSeqLegacy: bool = False): + enum = ootData.enumData.enumByKey[enumKey] + item = enum.itemById.get(self.params[index]) + if item is None: + setting = getInteger(self.params[index]) + if isSeqLegacy: + setting -= 1 + item = enum.itemByIndex.get(setting) + return item.key if item is not None else self.params[index] @dataclass -class OOTCSMotionCamPoint: +class OOTCSMotionCamPoint(OOTCSMotionBase): """This class contains a single Camera Point command data""" - continueFlag: str - camRoll: int - frame: int - viewAngle: float - pos: list[int, int, int] + continueFlag: str = None + camRoll: int = None + frame: int = None + viewAngle: float = None + pos: list[int, int, int] = field(default_factory=list) paramNumber: int = 8 + def __post_init__(self): + self.continueFlag = self.params[0] + self.camRoll = getInteger(self.params[1]) + self.frame = getInteger(self.params[2]) + self.viewAngle = float(self.params[3][:-1]) + self.pos = [getInteger(self.params[4]), getInteger(self.params[5]), getInteger(self.params[6])] + @dataclass class OOTCSMotionActorCue(OOTCSMotionBase): """This class contains a single Actor Cue command data""" - actionID: int - rot: list[str, str, str] - startPos: list[int, int, int] - endPos: list[int, int, int] + actionID: int = None + rot: list[str, str, str] = field(default_factory=list) + startPos: list[int, int, int] = field(default_factory=list) + endPos: list[int, int, int] = field(default_factory=list) paramNumber: int = 15 + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.actionID = getInteger(self.params[0]) + self.rot = [getRotation(self.params[3]), getRotation(self.params[4]), getRotation(self.params[5])] + self.startPos = [getInteger(self.params[6]), getInteger(self.params[7]), getInteger(self.params[8])] + self.endPos = [getInteger(self.params[9]), getInteger(self.params[10]), getInteger(self.params[11])] + @dataclass -class OOTCSMotionActorCueList: +class OOTCSMotionActorCueList(OOTCSMotionBase): """This class contains the Actor Cue List command data""" - commandType: str - entryTotal: int + isPlayer: bool = False + commandType: str = None + entryTotal: int = None entries: list[OOTCSMotionActorCue] = field(default_factory=list) paramNumber: int = 2 + listName: str = "actorCueList" + + def __post_init__(self): + if self.isPlayer: + self.commandType = "Player" + self.entryTotal = getInteger(self.params[0]) + else: + self.commandType = self.params[0] + if self.commandType.startswith("0x"): + # make it a 4 digit hex + self.commandType = self.commandType.removeprefix("0x") + self.commandType = "0x" + "0" * (4 - len(self.commandType)) + self.commandType + self.entryTotal = getInteger(self.params[1].strip()) @dataclass @@ -57,6 +98,11 @@ class OOTCSMotionCamEyeSpline(OOTCSMotionBase): entries: list[OOTCSMotionCamPoint] = field(default_factory=list) paramNumber: int = 2 + listName: str = "camEyeSplineList" + + def __post_init__(self): + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -65,6 +111,11 @@ class OOTCSMotionCamATSpline(OOTCSMotionBase): entries: list[OOTCSMotionCamPoint] = field(default_factory=list) paramNumber: int = 2 + listName: str = "camATSplineList" + + def __post_init__(self): + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -73,6 +124,11 @@ class OOTCSMotionCamEyeSplineRelToPlayer(OOTCSMotionBase): entries: list[OOTCSMotionCamPoint] = field(default_factory=list) paramNumber: int = 2 + listName: str = "camEyeSplineRelPlayerList" + + def __post_init__(self): + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -81,6 +137,11 @@ class OOTCSMotionCamATSplineRelToPlayer(OOTCSMotionBase): entries: list[OOTCSMotionCamPoint] = field(default_factory=list) paramNumber: int = 2 + listName: str = "camATSplineRelPlayerList" + + def __post_init__(self): + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -90,6 +151,11 @@ class OOTCSMotionCamEye(OOTCSMotionBase): # This feature is not used in the final game and lacks polish, it is recommended to use splines in all cases. entries: list = field(default_factory=list) paramNumber: int = 2 + listName: str = "camEyeList" + + def __post_init__(self): + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -99,44 +165,72 @@ class OOTCSMotionCamAT(OOTCSMotionBase): # This feature is not used in the final game and lacks polish, it is recommended to use splines in all cases. entries: list = field(default_factory=list) paramNumber: int = 2 + listName: str = "camATList" + + def __post_init__(self): + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass class OOTCSMotionMisc(OOTCSMotionBase): """This class contains a single misc command entry""" - type: str # see ``CutsceneMiscType`` in decomp + type: str = None # see ``CutsceneMiscType`` in decomp paramNumber: int = 14 + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.type = self.getEnumValue("csMiscType", 0) + @dataclass -class OOTCSMotionMiscList: +class OOTCSMotionMiscList(OOTCSMotionBase): """This class contains Misc command data""" - entryTotal: int + entryTotal: int = None entries: list[OOTCSMotionMisc] = field(default_factory=list) paramNumber: int = 1 + listName: str = "miscList" + + def __post_init__(self): + self.entryTotal = getInteger(self.params[0]) @dataclass class OOTCSMotionTransition(OOTCSMotionBase): """This class contains Transition command data""" - type: str + type: str = None paramNumber: int = 3 + listName: str = "transitionList" + + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.type = self.getEnumValue("csTransitionType", 0) @dataclass class OOTCSMotionText(OOTCSMotionBase): """This class contains Text command data""" - textId: int - type: str - altTextId1: int - altTextId2: int + textId: int = None + type: str = None + altTextId1: int = None + altTextId2: int = None paramNumber: int = 6 id: str = "Text" + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.textId = getInteger(self.params[0]) + self.type = self.getEnumValue("csTextType", 3) + self.altTextId1 = (getInteger(self.params[4]),) + self.altTextId2 = (getInteger(self.params[5]),) + @dataclass class OOTCSMotionTextNone(OOTCSMotionBase): @@ -145,113 +239,180 @@ class OOTCSMotionTextNone(OOTCSMotionBase): paramNumber: int = 2 id: str = "None" + def __post_init__(self): + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) + @dataclass class OOTCSMotionTextOcarinaAction(OOTCSMotionBase): """This class contains Text Ocarina Action command data""" - ocarinaActionId: str - messageId: int + ocarinaActionId: str = None + messageId: int = None paramNumber: int = 4 id: str = "OcarinaAction" + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.ocarinaActionId = self.getEnumValue("ocarinaSongActionId", 0) + self.messageId = getInteger(self.params[3]) + @dataclass -class OOTCSMotionTextList: +class OOTCSMotionTextList(OOTCSMotionBase): """This class contains Text List command data""" - entryTotal: int + entryTotal: int = None entries: list[OOTCSMotionText | OOTCSMotionTextNone | OOTCSMotionTextOcarinaAction] = field(default_factory=list) paramNumber: int = 1 + listName: str = "textList" + + def __post_init__(self): + self.entryTotal = getInteger(self.params[0]) @dataclass class OOTCSMotionLightSetting(OOTCSMotionBase): """This class contains Light Setting command data""" - lightSetting: int + isLegacy: bool = None + lightSetting: int = None paramNumber: int = 11 + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.lightSetting = getInteger(self.params[0]) + if self.isLegacy: + self.lightSetting -= 1 + @dataclass -class OOTCSMotionLightSettingList: +class OOTCSMotionLightSettingList(OOTCSMotionBase): """This class contains Light Setting List command data""" - entryTotal: int + entryTotal: int = None entries: list[OOTCSMotionLightSetting] = field(default_factory=list) paramNumber: int = 1 + listName: str = "lightSettingsList" + + def __post_init__(self): + self.entryTotal = getInteger(self.params[0]) @dataclass class OOTCSMotionTime(OOTCSMotionBase): """This class contains Time Ocarina Action command data""" - hour: int - minute: int + hour: int = None + minute: int = None paramNumber: int = 5 + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.hour = getInteger(self.params[3]) + self.minute = getInteger(self.params[4]) + @dataclass -class OOTCSMotionTimeList: +class OOTCSMotionTimeList(OOTCSMotionBase): """This class contains Time List command data""" - entryTotal: int + entryTotal: int = None entries: list[OOTCSMotionTime] = field(default_factory=list) paramNumber: int = 1 + listName: str = "timeList" + + def __post_init__(self): + self.entryTotal = getInteger(self.params[0]) @dataclass class OOTCSMotionStartStopSeq(OOTCSMotionBase): """This class contains Start/Stop Seq command data""" - seqId: str + isLegacy: bool = None + seqId: str = None paramNumber: int = 11 + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.seqId = self.getEnumValue("seqId", 0, self.isLegacy) + @dataclass -class OOTCSMotionStartStopSeqList: +class OOTCSMotionStartStopSeqList(OOTCSMotionBase): """This class contains Start/Stop Seq List command data""" - entryTotal: int - type: str + entryTotal: int = None + type: str = None entries: list[OOTCSMotionStartStopSeq] = field(default_factory=list) paramNumber: int = 1 + listName: str = "seqList" + + def __post_init__(self): + self.entryTotal = getInteger(self.params[0]) @dataclass class OOTCSMotionFadeSeq(OOTCSMotionBase): """This class contains Fade Seq command data""" - seqPlayer: str + seqPlayer: str = None paramNumber: int = 11 + enumKey: str = "csFadeOutSeqPlayer" + + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.seqPlayer = self.getEnumValue("csFadeOutSeqPlayer", 0) @dataclass -class OOTCSMotionFadeSeqList: +class OOTCSMotionFadeSeqList(OOTCSMotionBase): """This class contains Fade Seq List command data""" - entryTotal: int + entryTotal: int = None entries: list[OOTCSMotionFadeSeq] = field(default_factory=list) paramNumber: int = 1 + listName: str = "fadeSeqList" + + def __post_init__(self): + self.entryTotal = getInteger(self.params[0]) @dataclass class OOTCSMotionRumbleController(OOTCSMotionBase): """This class contains Rumble Controller command data""" - sourceStrength: int - duration: int - decreaseRate: int + sourceStrength: int = None + duration: int = None + decreaseRate: int = None paramNumber: int = 8 + def __post_init__(self): + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.sourceStrength = getInteger(self.params[3]) + self.duration = getInteger(self.params[4]) + self.decreaseRate = getInteger(self.params[5]) + @dataclass -class OOTCSMotionRumbleControllerList: +class OOTCSMotionRumbleControllerList(OOTCSMotionBase): """This class contains Rumble Controller List command data""" - entryTotal: int + entryTotal: int = None entries: list[OOTCSMotionRumbleController] = field(default_factory=list) paramNumber: int = 1 + listName: str = "rumbleList" + + def __post_init__(self): + self.entryTotal = getInteger(self.params[0]) @dataclass @@ -274,7 +435,7 @@ class OOTCSMotionCutscene: miscList: list[OOTCSMotionMiscList] = field(default_factory=list) transitionList: list[OOTCSMotionTransition] = field(default_factory=list) textList: list[OOTCSMotionTextList] = field(default_factory=list) - lightSettingList: list[OOTCSMotionLightSettingList] = field(default_factory=list) + lightSettingsList: list[OOTCSMotionLightSettingList] = field(default_factory=list) timeList: list[OOTCSMotionTimeList] = field(default_factory=list) seqList: list[OOTCSMotionStartStopSeqList] = field(default_factory=list) fadeSeqList: list[OOTCSMotionFadeSeqList] = field(default_factory=list) diff --git a/fast64_internal/oot/cutscene/motion/utility.py b/fast64_internal/oot/cutscene/motion/utility.py index a7c4c8954..c2b06c19e 100644 --- a/fast64_internal/oot/cutscene/motion/utility.py +++ b/fast64_internal/oot/cutscene/motion/utility.py @@ -1,5 +1,6 @@ import bpy +from struct import unpack from bpy.types import Object, Bone, Context, EditBone, Armature from mathutils import Vector from ....utility import yUpToZUp @@ -83,6 +84,18 @@ def getBlenderPosition(pos: list[int], scale: int): return [float(pos[0]) / scale, -float(pos[2]) / scale, float(pos[1]) / scale] +def getInteger(number: str): + """Returns an int number (handles properly negative hex numbers)""" + + if number.startswith("0x"): + number = number.removeprefix("0x") + + # ``"0" * (8 - len(number)`` adds the missing zeroes (if necessary) to have a 8 digit hex number + return unpack("!i", bytes.fromhex("0" * (8 - len(number)) + number))[0] + else: + return int(number) + + def getRotation(data: str): """Returns the rotation converted to hexadecimal""" From c2b8408a69f40c1ece208b1566bc58bc59106f5b Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Thu, 19 Oct 2023 19:08:42 +0200 Subject: [PATCH 22/39] improvements part 2 --- .../oot/cutscene/motion/importer/classes.py | 216 +++++++++--------- 1 file changed, 110 insertions(+), 106 deletions(-) diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/motion/importer/classes.py index f70a57841..f953d7a89 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/motion/importer/classes.py @@ -8,7 +8,7 @@ from ..utility import setupCutscene, getBlenderPosition, getInteger if TYPE_CHECKING: - from ...properties import OOTCSListProperty + from ...properties import OOTCSListProperty, OOTCutsceneProperty from ..constants import ( ootCSMotionLegacyToNewCmdNames, @@ -59,6 +59,13 @@ class ParsedCutscene: csData: list[str] # contains every command lists or standalone ones like ``CS_TRANSITION()`` +@dataclass +class PropertyData: + listType: str + subPropsData: dict[str, str] + useEndFrame: bool + + class OOTCSMotionImportCommands: """This class contains functions to create the cutscene dataclasses""" @@ -233,6 +240,22 @@ def getCutsceneList(self): "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, } + cmdToDefinition = { + "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, + "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, + "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, + "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, + "CS_CAM_EYE": OOTCSMotionCamEye, + "CS_CAM_AT": OOTCSMotionCamAT, + "TRANSITION": OOTCSMotionTransition, + "MISC_LIST" : OOTCSMotionMiscList, + "TEXT_LIST" : OOTCSMotionTextList, + "LIGHT_SETTING_LIST" : OOTCSMotionLightSettingList, + "TIME_LIST" : OOTCSMotionTimeList, + "FADE_OUT_SEQ_LIST" : OOTCSMotionFadeSeqList, + "RUMBLE_CONTROLLER_LIST" : OOTCSMotionRumbleControllerList, + } + # for each cutscene from the list returned by getParsedCutscenes(), # create classes containing the cutscene's informations # that will be used later when creating Blender objects to complete the import @@ -438,15 +461,71 @@ def setCameraShotData( return endIndex + 1 - def setListData(self, prop, typeName: str, startFrame: int, endFrame: int, type: str): - prop.startFrame = startFrame - prop.endFrame = endFrame - if typeName is not None and type is not None: - try: - setattr(prop, typeName, type) - except TypeError: - setattr(prop, typeName, "Custom") - setattr(prop, f"{typeName}Custom", type) + def setSubPropertyData(self, subPropsData: dict[str, str], newSubElem, entry): + customNames = [ + "csMiscType", + "csTextType", + "ocarinaAction", + "transitionType", + "csSeqID", + "csSeqPlayer", + "transition", + ] + + for key, value in subPropsData.items(): + if value is not None: + if key in customNames: + valueToSet = getattr(entry, value) + try: + setattr(newSubElem, key, valueToSet) + except TypeError: + setattr(newSubElem, key, "Custom") + setattr(newSubElem, f"{key}Custom", valueToSet) + else: + setattr(newSubElem, key, getattr(entry, value)) + + def setPropertyData( + self, csProp: "OOTCutsceneProperty", cutscene: OOTCSMotionCutscene, propDataList: list[PropertyData] + ): + for data in propDataList: + listName = f"{data.listType[0].lower() + data.listType[1:]}List" + dataList = getattr(cutscene, (listName if data.listType != "FadeOutSeq" else "fadeSeqList")) + for list in dataList: + newElem: "OOTCSListProperty" = csProp.csLists.add() + + if data.listType == "Seq": + type = "StartSeqList" if list.type == "start" else "StopSeqList" + else: + type = f"{data.listType}List" if data.listType != "Transition" else data.listType + newElem.listType = type + + if data.listType == "Transition": + newElem.transitionStartFrame = list.startFrame + newElem.transitionEndFrame = list.endFrame + self.setSubPropertyData(data.subPropsData, newElem, list) + else: + list.entries.sort(key=lambda elem: elem.startFrame) + for entry in list.entries: + newSubElem = getattr(newElem, "seqList" if "fadeOut" in listName else listName).add() + newSubElem.startFrame = entry.startFrame + + if data.useEndFrame: + newSubElem.endFrame = entry.endFrame + + if data.listType == "Text": + data.subPropsData["textboxType"] = "id" + match entry.id: + case "Text": + newSubElem.textID = f"0x{entry.textId:04X}" + data.subPropsData["csTextType"] = "type" + case "None": + data.subPropsData["csTextType"] = None + case "OcarinaAction": + newSubElem.ocarinaMessageId = f"0x{entry.messageId:04X}" + data.subPropsData["ocarinaAction"] = "ocarinaActionId" + case _: + raise PluginError("ERROR: Unknown text type!") + self.setSubPropertyData(data.subPropsData, newSubElem, entry) def setCutsceneData(self, csNumber): """Creates the cutscene empty objects from the file data""" @@ -458,19 +537,16 @@ def setCutsceneData(self, csNumber): return csNumber for i, cutscene in enumerate(cutsceneList, csNumber): - print(f'Found Cutscene "{cutscene.name}"!') + print(f'Found Cutscene "{cutscene.name}"! Importing...') self.validateCameraData(cutscene) csName = f"Cutscene.{cutscene.name}" csObj = self.getNewCutsceneObject(csName, cutscene.frameCount, None) csProp = csObj.ootCutsceneProperty csNumber = i - print("Importing Actor Cues...") self.setActorCueData(csObj, cutscene.actorCueList, "Actor", i) self.setActorCueData(csObj, cutscene.playerCueList, "Player", i) - print("Done!") - print("Importing Camera Shots...") if len(cutscene.camEyeSplineList) > 0: lastIndex = self.setCameraShotData( csObj, cutscene.camEyeSplineList, cutscene.camATSplineList, "splineEyeOrAT", 1, i @@ -491,102 +567,30 @@ def setCutsceneData(self, csNumber): csObj, cutscene.camEyeList, cutscene.camATList, "eyeOrAT", lastIndex, i ) - for miscList in cutscene.miscList: - miscElem: "OOTCSListProperty" = csProp.csLists.add() - miscElem.listType = "MiscList" - for miscCmd in miscList.entries: - miscProp = miscElem.miscList.add() - self.setListData(miscProp, "csMiscType", miscCmd.startFrame, miscCmd.endFrame, miscCmd.type) - - for transition in cutscene.transitionList: - transitionElem: "OOTCSListProperty" = csProp.csLists.add() - transitionElem.listType = "Transition" - transitionElem.transitionStartFrame = transition.startFrame - transitionElem.transitionEndFrame = transition.endFrame - try: - transitionElem.transitionType = transition.type - except TypeError: - transitionElem.transitionType = "Custom" - transitionElem.transitionTypeCustom = transition.type - - for textList in cutscene.textList: - textElem: "OOTCSListProperty" = csProp.csLists.add() - textElem.listType = "TextList" - textList.entries.sort(key=lambda elem: elem.startFrame) - for textCmd in textList.entries: - textProp = textElem.textList.add() - textProp.textboxType = textCmd.id - match textCmd.id: - case "Text": - textProp.textID = f"0x{textCmd.textId:04X}" - typeName = "csTextType" - type = textCmd.type - case "None": - typeName = type = None - case "OcarinaAction": - textProp.ocarinaMessageId = f"0x{textCmd.messageId:04X}" - typeName = "ocarinaAction" - type = textCmd.ocarinaActionId - case _: - raise PluginError("ERROR: Unknown text type!") - self.setListData(textProp, typeName, textCmd.startFrame, textCmd.endFrame, type) - - for lightList in cutscene.lightSettingsList: - lightElem: "OOTCSListProperty" = csProp.csLists.add() - lightElem.listType = "LightSettingsList" - for lightCmd in lightList.entries: - lightProp = lightElem.lightSettingsList.add() - lightProp.lightSettingsIndex = lightCmd.lightSetting - lightProp.startFrame = lightCmd.startFrame - - for timeList in cutscene.timeList: - timeElem: "OOTCSListProperty" = csProp.csLists.add() - timeElem.listType = "TimeList" - for timeCmd in timeList.entries: - timeProp = timeElem.timeList.add() - timeProp.hour = timeCmd.hour - timeProp.minute = timeCmd.minute - timeProp.startFrame = timeCmd.startFrame - - for seqList in cutscene.seqList: - seqElem: "OOTCSListProperty" = csProp.csLists.add() - seqElem.listType = "StartSeqList" if seqList.type == "start" else "StopSeqList" - for seqCmd in seqList.entries: - seqProp = seqElem.seqList.add() - try: - seqProp.csSeqID = seqCmd.seqId - except TypeError: - seqProp.csSeqID = "Custom" - transitionElem.csSeqIDCustom = seqCmd.seqId - seqProp.startFrame = seqCmd.startFrame - - for fadeList in cutscene.fadeSeqList: - fadeElem: "OOTCSListProperty" = csProp.csLists.add() - fadeElem.listType = "FadeOutSeqList" - for fadeCmd in fadeList.entries: - fadeProp = fadeElem.seqList.add() - try: - fadeProp.csSeqPlayer = fadeCmd.seqPlayer - except TypeError: - fadeProp.csSeqPlayer = "Custom" - transitionElem.csSeqPlayerCustom = fadeCmd.seqPlayer - fadeProp.startFrame = fadeCmd.startFrame - fadeProp.endFrame = fadeCmd.endFrame - - for rumbleList in cutscene.rumbleList: - rumbleElem: "OOTCSListProperty" = csProp.csLists.add() - rumbleElem.listType = "RumbleList" - for rumbleCmd in rumbleList.entries: - rumbleProp = rumbleElem.rumbleList.add() - rumbleProp.startFrame = rumbleCmd.startFrame - rumbleProp.rumbleSourceStrength = rumbleCmd.sourceStrength - rumbleProp.rumbleDuration = rumbleCmd.duration - rumbleProp.rumbleDecreaseRate = rumbleCmd.decreaseRate + propDataList = [ + PropertyData("Text", {"textboxType": "id"}, True), + PropertyData("Misc", {"csMiscType": "type"}, True), + PropertyData("Transition", {"transitionType": "type"}, True), + PropertyData("LightSettings", {"lightSettingsIndex": "lightSetting"}, False), + PropertyData("Time", {"hour": "hour", "minute": "minute"}, False), + PropertyData("Seq", {"csSeqID": "seqId"}, False), + PropertyData("FadeOutSeq", {"csSeqPlayer": "seqPlayer"}, True), + PropertyData( + "Rumble", + { + "rumbleSourceStrength": "sourceStrength", + "rumbleDuration": "duration", + "rumbleDecreaseRate": "decreaseRate", + }, + False, + ), + ] + self.setPropertyData(csProp, cutscene, propDataList) # Init camera + preview objects and setup the scene setupCutscene(csObj) - print("Done!") bpy.ops.object.select_all(action="DESELECT") + print("Success!") # ``csNumber`` makes sure there's no duplicates return csNumber + 1 From 0a8714aad52e9f8d3b8db0eb47e8e048243c0639 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Thu, 19 Oct 2023 22:42:20 +0200 Subject: [PATCH 23/39] enhanced exporter + fixed issues --- .../oot/cutscene/exporter/__init__.py | 2 +- .../oot/cutscene/exporter/functions.py | 18 +- .../oot/cutscene/motion/constants.py | 61 +++++ .../oot/cutscene/motion/exporter/classes.py | 222 ++++++++++++++++-- .../oot/cutscene/motion/exporter/functions.py | 7 +- .../oot/cutscene/motion/importer/classes.py | 77 +----- .../oot/cutscene/motion/io_classes.py | 182 ++++++++------ fast64_internal/oot/cutscene/operators.py | 11 +- fast64_internal/oot/cutscene/properties.py | 2 +- fast64_internal/oot/oot_level_classes.py | 3 +- fast64_internal/oot/oot_level_writer.py | 7 +- .../oot/scene/exporter/to_c/scene_commands.py | 2 +- .../oot/scene/exporter/to_c/scene_cutscene.py | 99 +------- 13 files changed, 400 insertions(+), 293 deletions(-) diff --git a/fast64_internal/oot/cutscene/exporter/__init__.py b/fast64_internal/oot/cutscene/exporter/__init__.py index eefb84717..79c7cb6ff 100644 --- a/fast64_internal/oot/cutscene/exporter/__init__.py +++ b/fast64_internal/oot/cutscene/exporter/__init__.py @@ -1,4 +1,4 @@ -from .functions import convertCutsceneObject, readCutsceneData +from .functions import readCutsceneData from .classes import ( OOTCSList, diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index d1241179c..b16fa5bd6 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -1,4 +1,4 @@ -from ...oot_utility import getCutsceneName, getCustomProperty +from ...oot_utility import getCustomProperty from ...oot_constants import ootData from .classes import ( @@ -9,7 +9,6 @@ OOTCSSeq, OOTCSMisc, OOTCSRumble, - OOTCutscene, ) @@ -101,18 +100,3 @@ def readCutsceneData(csParentOut, csParentIn): entryOut.rumbleDecreaseRate = entryIn.rumbleDecreaseRate listOut.entries.append(entryOut) csParentOut.csLists.append(listOut) - - -def convertCutsceneObject(obj): - cs = OOTCutscene() - - cs.name = getCutsceneName(obj) - csprop = obj.ootCutsceneProperty - cs.csEndFrame = getCustomProperty(csprop, "csEndFrame") - cs.csUseDestination = getCustomProperty(csprop, "csUseDestination") - value = getCustomProperty(csprop, "csDestination") - cs.csDestination = ootData.enumData.enumByKey["csDestination"].itemByKey[value] if value != "Custom" else value - cs.csDestinationStartFrame = getCustomProperty(csprop, "csDestinationStartFrame") - readCutsceneData(cs, csprop) - - return cs diff --git a/fast64_internal/oot/cutscene/motion/constants.py b/fast64_internal/oot/cutscene/motion/constants.py index 2e0cf84df..bc924b353 100644 --- a/fast64_internal/oot/cutscene/motion/constants.py +++ b/fast64_internal/oot/cutscene/motion/constants.py @@ -1,4 +1,32 @@ from ...oot_constants import ootData +from .io_classes import ( + OOTCSMotionActorCueList, + OOTCSMotionActorCue, + OOTCSMotionCamEyeSpline, + OOTCSMotionCamATSpline, + OOTCSMotionCamEyeSplineRelToPlayer, + OOTCSMotionCamATSplineRelToPlayer, + OOTCSMotionCamEye, + OOTCSMotionCamAT, + OOTCSMotionCamPoint, + OOTCSMotionMisc, + OOTCSMotionMiscList, + OOTCSMotionTransition, + OOTCSMotionText, + OOTCSMotionTextNone, + OOTCSMotionTextOcarinaAction, + OOTCSMotionTextList, + OOTCSMotionLightSetting, + OOTCSMotionLightSettingList, + OOTCSMotionTime, + OOTCSMotionTimeList, + OOTCSMotionStartStopSeq, + OOTCSMotionStartStopSeqList, + OOTCSMotionFadeSeq, + OOTCSMotionFadeSeqList, + OOTCSMotionRumbleController, + OOTCSMotionRumbleControllerList, +) ootEnumCSMotionCamMode = [ ("splineEyeOrAT", "Eye/AT Spline", "Eye/AT Spline"), @@ -100,3 +128,36 @@ ootCSMotionListAndSingleCommands = ootCSMotionSingleCommands + ootCSMotionListCommands ootCSMotionListAndSingleCommands.remove("CS_BEGIN_CUTSCENE") ootCSMotionCSCommands = ootCSMotionSingleCommands + ootCSMotionListCommands + ootCSMotionListEntryCommands + +cmdToClass = { + "CS_CAM_POINT": OOTCSMotionCamPoint, + "CS_MISC": OOTCSMotionMisc, + "CS_LIGHT_SETTING": OOTCSMotionLightSetting, + "CS_TIME": OOTCSMotionTime, + "CS_FADE_OUT_SEQ": OOTCSMotionFadeSeq, + "CS_RUMBLE_CONTROLLER": OOTCSMotionRumbleController, + "CS_TEXT": OOTCSMotionText, + "CS_TEXT_NONE": OOTCSMotionTextNone, + "CS_TEXT_OCARINA_ACTION": OOTCSMotionTextOcarinaAction, + "CS_START_SEQ": OOTCSMotionStartStopSeq, + "CS_STOP_SEQ": OOTCSMotionStartStopSeq, + "CS_ACTOR_CUE": OOTCSMotionActorCue, + "CS_PLAYER_CUE": OOTCSMotionActorCue, + "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, + "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, + "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, + "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, + "CS_CAM_EYE": OOTCSMotionCamEye, + "CS_CAM_AT": OOTCSMotionCamAT, + "CS_MISC_LIST": OOTCSMotionMiscList, + "CS_TRANSITION": OOTCSMotionTransition, + "CS_TEXT_LIST": OOTCSMotionTextList, + "CS_LIGHT_SETTING_LIST": OOTCSMotionLightSettingList, + "CS_TIME_LIST": OOTCSMotionTimeList, + "CS_FADE_OUT_SEQ_LIST": OOTCSMotionFadeSeqList, + "CS_RUMBLE_CONTROLLER_LIST": OOTCSMotionRumbleControllerList, + "CS_START_SEQ_LIST": OOTCSMotionStartStopSeqList, + "CS_STOP_SEQ_LIST": OOTCSMotionStartStopSeqList, + "CS_ACTOR_CUE_LIST": OOTCSMotionActorCueList, + "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, +} diff --git a/fast64_internal/oot/cutscene/motion/exporter/classes.py b/fast64_internal/oot/cutscene/motion/exporter/classes.py index 67a3feaf9..d26903e0a 100644 --- a/fast64_internal/oot/cutscene/motion/exporter/classes.py +++ b/fast64_internal/oot/cutscene/motion/exporter/classes.py @@ -2,11 +2,24 @@ import bpy from dataclasses import dataclass +from typing import TYPE_CHECKING from bpy.types import Object from .....utility import PluginError, indent from ....oot_constants import ootData +from ...constants import ootEnumCSListTypeListC + +if TYPE_CHECKING: + from ...properties import OOTCutsceneProperty, OOTCSTextProperty from ..io_classes import ( + OOTCSMotionTransition, + OOTCSMotionRumbleController, + OOTCSMotionMisc, + OOTCSMotionTime, + OOTCSMotionLightSetting, + OOTCSMotionText, + OOTCSMotionTextNone, + OOTCSMotionTextOcarinaAction, OOTCSMotionActorCueList, OOTCSMotionActorCue, OOTCSMotionCamEyeSpline, @@ -22,15 +35,68 @@ class OOTCSMotionExportCommands: """This class contains functions to create the cutscene commands""" + def getEnumValue(self, enumKey: str, owner, propName: str): + item = ootData.enumData.enumByKey[enumKey].itemByKey.get(getattr(owner, propName)) + return item.id if item is not None else getattr(owner, f"{propName}Custom") + + def getGenericListCmd(self, cmdName: str, entryTotal: int): + return indent * 2 + f"{cmdName}({entryTotal}),\n" + + def getGenericSeqCmd(self, cmdName: str, type: str, startFrame: int, endFrame: int): + return indent * 3 + f"{cmdName}({type}, {startFrame}, {endFrame}" + ", 0" * 8 + "),\n" + + def getTransitionCmd(self, transition: OOTCSMotionTransition): + return indent * 2 + f"CS_TRANSITION({transition.type}, {transition.startFrame}, {transition.endFrame}),\n" + + def getRumbleControllerCmd(self, rumble: OOTCSMotionRumbleController): + return indent * 3 + ( + f"CS_RUMBLE_CONTROLLER(" + + f"0, {rumble.startFrame}, 0, " + + f"{rumble.sourceStrength}, {rumble.duration}, {rumble.decreaseRate}, 0, 0),\n" + ) + + def getMiscCmd(self, misc: OOTCSMotionMisc): + return indent * 3 + (f"CS_MISC(" + f"{misc.type}, {misc.startFrame}, {misc.endFrame}" + ", 0" * 11 + "),\n") + + def getTimeCmd(self, time: OOTCSMotionTime): + return indent * 3 + (f"CS_TIME(" + f"0, {time.startFrame}, 0, {time.hour}, {time.minute}" + "),\n") + + def getLightSettingCmd(self, lightSetting: OOTCSMotionLightSetting): + return indent * 3 + ( + f"CS_LIGHT_SETTING(" + f"{lightSetting.lightSetting}, {lightSetting.startFrame}" + ", 0" * 9 + "),\n" + ) + + def getTextCmd(self, text: OOTCSMotionText): + return indent * 3 + ( + f"CS_TEXT(" + + f"{text.textId}, {text.startFrame}, {text.endFrame}, {text.type}, {text.altTextId1}, {text.altTextId2}" + + "),\n" + ) + + def getTextNoneCmd(self, textNone: OOTCSMotionTextNone): + return indent * 3 + f"CS_TEXT_NONE({textNone.startFrame}, {textNone.endFrame}),\n" + + def getTextOcarinaActionCmd(self, ocarinaAction: OOTCSMotionTextOcarinaAction): + return indent * 3 + ( + f"CS_TEXT_OCARINA_ACTION(" + + f"{ocarinaAction.ocarinaActionId}, {ocarinaAction.startFrame}, " + + f"{ocarinaAction.endFrame}, {ocarinaAction.messageId}" + + "),\n" + ) + + def getDestinationCmd(self, csProp: "OOTCutsceneProperty"): + dest = self.getEnumValue("csDestination", csProp, "csDestination") + return indent * 2 + f"CS_DESTINATION({dest}, {csProp.csDestinationStartFrame}, 0),\n" + def getActorCueListCmd(self, actorCueList: OOTCSMotionActorCueList, isPlayerActor: bool): - return indent + ( + return indent * 2 + ( f"CS_{'PLAYER' if isPlayerActor else 'ACTOR'}_CUE_LIST(" + f"{actorCueList.commandType + ', ' if not isPlayerActor else ''}" + f"{actorCueList.entryTotal}),\n" ) def getActorCueCmd(self, actorCue: OOTCSMotionActorCue, isPlayerActor: bool): - return indent * 2 + ( + return indent * 3 + ( f"CS_{'PLAYER' if isPlayerActor else 'ACTOR'}_CUE(" + f"{actorCue.actionID}, {actorCue.startFrame}, {actorCue.endFrame}, " + "".join(f"{rot}, " for rot in actorCue.rot) @@ -40,7 +106,7 @@ def getActorCueCmd(self, actorCue: OOTCSMotionActorCue, isPlayerActor: bool): ) def getCamListCmd(self, cmdName: str, startFrame: int, endFrame: int): - return indent + f"{cmdName}({startFrame}, {endFrame}),\n" + return indent * 2 + f"{cmdName}({startFrame}, {endFrame}),\n" def getCamEyeSplineCmd(self, camEyeSpline: OOTCSMotionCamEyeSpline): return self.getCamListCmd("CS_CAM_EYE_SPLINE", camEyeSpline.startFrame, camEyeSpline.endFrame) @@ -65,7 +131,7 @@ def getCamATCmd(self, camAT: OOTCSMotionCamAT): return self.getCamListCmd("CS_CAM_AT", camAT.startFrame, camAT.endFrame) def getCamPointCmd(self, camPoint: OOTCSMotionCamPoint): - return indent * 2 + ( + return indent * 3 + ( f"CS_CAM_POINT(" + f"{camPoint.continueFlag}, {camPoint.camRoll}, {camPoint.frame}, {camPoint.viewAngle}f, " + "".join(f"{pos}, " for pos in camPoint.pos) @@ -79,9 +145,10 @@ class OOTCSMotionExport(OOTCSMotionExportCommands): csMotionObjects: dict[str, list[Object]] useDecomp: bool - addBeginEndCmds: bool + motionOnly: bool entryTotal: int = 0 frameCount: int = 0 + motionFrameCount: int = 0 camEndFrame: int = 0 def getOoTRotation(self, obj: Object): @@ -143,7 +210,8 @@ def getActorCueListData(self, isPlayer: bool): elif self.useDecomp: commandType = ootData.enumData.enumByKey["csCmd"].itemByKey[commandType].id - actorCueList = OOTCSMotionActorCueList(commandType, entryTotal - 1) # ignoring dummy cue + # ignoring dummy cue + actorCueList = OOTCSMotionActorCueList(None, entryTotal=entryTotal - 1, commandType=commandType) actorCueData += self.getActorCueListCmd(actorCueList, isPlayer) for i, childObj in enumerate(obj.children, 1): @@ -161,6 +229,7 @@ def getActorCueListData(self, isPlayer: bool): actionID = childObj.ootCSMotionProperty.actorCueProp.cueActionID actorCue = OOTCSMotionActorCue( + None, startFrame, endFrame, actionID, @@ -186,6 +255,9 @@ def getCameraShotPointData(self, bones, useAT: bool): shotPoints.append( OOTCSMotionCamPoint( + None, + None, + None, ("CS_CAM_CONTINUE" if self.useDecomp else "0"), bone.ootCamShotPointProp.shotPointRoll if useAT else 0, bone.ootCamShotPointProp.shotPointFrame, @@ -195,7 +267,9 @@ def getCameraShotPointData(self, bones, useAT: bool): ) # NOTE: because of the game's bug explained in the importer we need to add an extra dummy point when exporting - shotPoints.append(OOTCSMotionCamPoint("CS_CAM_STOP" if self.useDecomp else "-1", 0, 0, 0.0, [0, 0, 0])) + shotPoints.append( + OOTCSMotionCamPoint(None, None, None, "CS_CAM_STOP" if self.useDecomp else "-1", 0, 0, 0.0, [0, 0, 0]) + ) return shotPoints def getCamCmdFunc(self, camMode: str, useAT: bool): @@ -240,7 +314,7 @@ def getCamListData(self, shotObj: Object, useAT: bool): pointData.frame = 0 self.camEndFrame = endFrame - camData = self.getCamClass(shotObj.data.ootCamShotProp.shotCamMode, useAT)(startFrame, endFrame) + camData = self.getCamClass(shotObj.data.ootCamShotProp.shotCamMode, useAT)(None, startFrame, endFrame) return self.getCamCmdFunc(shotObj.data.ootCamShotProp.shotCamMode, useAT)(camData) + "".join( self.getCamPointCmd(pointData) for pointData in camPointList ) @@ -252,21 +326,135 @@ def getCameraShotData(self): cameraShotData = "" if len(shotObjects) > 0: - frameCount = -1 + motionFrameCount = -1 for shotObj in shotObjects: cameraShotData += self.getCamListData(shotObj, False) + self.getCamListData(shotObj, True) - frameCount = max(frameCount, self.camEndFrame + 1) - self.frameCount += frameCount + motionFrameCount = max(motionFrameCount, self.camEndFrame + 1) + self.motionFrameCount += motionFrameCount self.entryTotal += len(shotObjects) * 2 return cameraShotData + def getTextListData(self, textEntry: "OOTCSTextProperty"): + match textEntry.textboxType: + case "Text": + return self.getTextCmd( + OOTCSMotionText( + None, + textEntry.startFrame, + textEntry.endFrame, + textEntry.textID, + self.getEnumValue("csTextType", textEntry, "csTextType"), + textEntry.topOptionTextID, + textEntry.bottomOptionTextID, + ) + ) + case "None": + return self.getTextNoneCmd(OOTCSMotionTextNone(None, textEntry.startFrame, textEntry.endFrame)) + case "OcarinaAction": + return self.getTextOcarinaActionCmd( + OOTCSMotionTextOcarinaAction( + None, + textEntry.startFrame, + textEntry.endFrame, + self.getEnumValue("ocarinaSongActionId", textEntry, "ocarinaAction"), + textEntry.ocarinaMessageId, + ) + ) + + def getCutsceneData(self): + csProp: "OOTCutsceneProperty" = self.csMotionObjects["Cutscene"][0].ootCutsceneProperty + self.frameCount = csProp.csEndFrame + data = "" + + if csProp.csUseDestination: + data += self.getDestinationCmd(csProp) + self.entryTotal += 1 + + for entry in csProp.csLists: + subData = "" + listCmd = "" + entryTotal = 0 + match entry.listType: + case "StartSeqList" | "StopSeqList" | "FadeOutSeqList": + entryTotal = len(entry.seqList) + for elem in entry.seqList: + enumKey = "csFadeOutSeqPlayer" if entry.listType == "FadeOutSeqList" else "seqId" + propName = "csSeqPlayer" if entry.listType == "FadeOutSeqList" else "csSeqID" + subData += self.getGenericSeqCmd( + ootEnumCSListTypeListC[entry.listType].removesuffix("_LIST"), + self.getEnumValue(enumKey, elem, propName), + elem.startFrame, + elem.endFrame, + ) + case "Transition": + subData += self.getTransitionCmd( + OOTCSMotionTransition( + None, + entry.transitionStartFrame, + entry.transitionEndFrame, + self.getEnumValue("csTransitionType", entry, "transitionType"), + ) + ) + case _: + curList = getattr(entry, (entry.listType[0].lower() + entry.listType[1:])) + entryTotal = len(curList) + for elem in curList: + match entry.listType: + case "TextList": + subData += self.getTextListData(elem) + case "LightSettingsList": + subData += self.getLightSettingCmd( + OOTCSMotionLightSetting( + None, elem.startFrame, elem.endFrame, None, elem.lightSettingsIndex + ) + ) + case "TimeList": + subData += self.getTimeCmd( + OOTCSMotionTime(None, elem.startFrame, elem.endFrame, elem.hour, elem.minute) + ) + case "MiscList": + subData += self.getMiscCmd( + OOTCSMotionMisc( + None, + elem.startFrame, + elem.endFrame, + self.getEnumValue("csMiscType", elem, "csMiscType"), + ) + ) + case "RumbleList": + subData += self.getRumbleControllerCmd( + OOTCSMotionRumbleController( + None, + elem.startFrame, + elem.endFrame, + elem.rumbleSourceStrength, + elem.rumbleDuration, + elem.rumbleDecreaseRate, + ) + ) + case _: + raise PluginError("ERROR: Unknown Cutscene List Type!") + if entry.listType != "Transition": + listCmd = self.getGenericListCmd(ootEnumCSListTypeListC[entry.listType], entryTotal) + self.entryTotal += 1 + data += listCmd + subData + + return data + def getExportData(self): """Returns the cutscene data""" - data = self.getActorCueListData(False) + self.getActorCueListData(True) + self.getCameraShotData() - if self.addBeginEndCmds: - data = ( - indent + f"CS_BEGIN_CUTSCENE({self.entryTotal}, {self.frameCount}),\n" + data + indent + "CS_END(),\n" - ) - return data + csData = "" + if not self.motionOnly: + csData = self.getCutsceneData() + csData += self.getActorCueListData(False) + self.getActorCueListData(True) + self.getCameraShotData() + + if self.motionFrameCount > self.frameCount: + self.frameCount += self.motionFrameCount - self.frameCount + + return ( + (indent + f"CS_BEGIN_CUTSCENE({self.entryTotal}, {self.frameCount}),\n") + + csData + + (indent + "CS_END(),\n") + ) diff --git a/fast64_internal/oot/cutscene/motion/exporter/functions.py b/fast64_internal/oot/cutscene/motion/exporter/functions.py index 8996254a7..49e0a2a07 100644 --- a/fast64_internal/oot/cutscene/motion/exporter/functions.py +++ b/fast64_internal/oot/cutscene/motion/exporter/functions.py @@ -32,15 +32,18 @@ def getCSMotionObjects(csName: str): if obj.type == "ARMATURE" and obj.parent.ootEmptyType == "Cutscene": csMotionObjects["camShot"].append(obj) + if len(csMotionObjects["Cutscene"]) != 1: + raise PluginError("ERROR: No cutscene found or several cutscenes in the object list!") + return csMotionObjects -def getCutsceneMotionData(csName: str, addBeginEndCmds: bool): +def getCutsceneMotionData(csName: str, motionOnly: bool): """Returns the initialised cutscene exporter""" # this allows us to change the exporter's variables to get what we need return OOTCSMotionExport( getCSMotionObjects(csName), bpy.context.scene.fast64.oot.hackerFeaturesEnabled or bpy.context.scene.useDecompFeatures, - addBeginEndCmds, + motionOnly, ) diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/motion/importer/classes.py index f953d7a89..18f3fdf70 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/motion/importer/classes.py @@ -4,8 +4,8 @@ from typing import TYPE_CHECKING from bpy.types import Object, Armature from .....utility import PluginError -from ....oot_constants import ootData from ..utility import setupCutscene, getBlenderPosition, getInteger +from ..constants import cmdToClass if TYPE_CHECKING: from ...properties import OOTCSListProperty, OOTCutsceneProperty @@ -21,33 +21,9 @@ from ..io_classes import ( OOTCSMotionActorCueList, - OOTCSMotionActorCue, - OOTCSMotionCamEyeSpline, - OOTCSMotionCamATSpline, - OOTCSMotionCamEyeSplineRelToPlayer, - OOTCSMotionCamATSplineRelToPlayer, - OOTCSMotionCamEye, - OOTCSMotionCamAT, OOTCSMotionCamPoint, OOTCSMotionCutscene, OOTCSMotionObjectFactory, - OOTCSMotionMisc, - OOTCSMotionMiscList, - OOTCSMotionTransition, - OOTCSMotionText, - OOTCSMotionTextNone, - OOTCSMotionTextOcarinaAction, - OOTCSMotionTextList, - OOTCSMotionLightSetting, - OOTCSMotionLightSettingList, - OOTCSMotionTime, - OOTCSMotionTimeList, - OOTCSMotionStartStopSeq, - OOTCSMotionStartStopSeqList, - OOTCSMotionFadeSeq, - OOTCSMotionFadeSeqList, - OOTCSMotionRumbleController, - OOTCSMotionRumbleControllerList, ) @@ -207,55 +183,6 @@ def getCutsceneList(self): cutsceneList: list[OOTCSMotionCutscene] = [] - cmdToClass = { - "CS_CAM_POINT": OOTCSMotionCamPoint, - "CS_MISC": OOTCSMotionMisc, - "CS_LIGHT_SETTING": OOTCSMotionLightSetting, - "CS_TIME": OOTCSMotionTime, - "CS_FADE_OUT_SEQ": OOTCSMotionFadeSeq, - "CS_RUMBLE_CONTROLLER": OOTCSMotionRumbleController, - "CS_TEXT": OOTCSMotionText, - "CS_TEXT_NONE": OOTCSMotionTextNone, - "CS_TEXT_OCARINA_ACTION": OOTCSMotionTextOcarinaAction, - "CS_START_SEQ": OOTCSMotionStartStopSeq, - "CS_STOP_SEQ": OOTCSMotionStartStopSeq, - "CS_ACTOR_CUE": OOTCSMotionActorCue, - "CS_PLAYER_CUE": OOTCSMotionActorCue, - "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, - "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, - "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, - "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, - "CS_CAM_EYE": OOTCSMotionCamEye, - "CS_CAM_AT": OOTCSMotionCamAT, - "CS_MISC_LIST": OOTCSMotionMiscList, - "CS_TRANSITION": OOTCSMotionTransition, - "CS_TEXT_LIST": OOTCSMotionTextList, - "CS_LIGHT_SETTING_LIST": OOTCSMotionLightSettingList, - "CS_TIME_LIST": OOTCSMotionTimeList, - "CS_FADE_OUT_SEQ_LIST": OOTCSMotionFadeSeqList, - "CS_RUMBLE_CONTROLLER_LIST": OOTCSMotionRumbleControllerList, - "CS_START_SEQ_LIST": OOTCSMotionStartStopSeqList, - "CS_STOP_SEQ_LIST": OOTCSMotionStartStopSeqList, - "CS_ACTOR_CUE_LIST": OOTCSMotionActorCueList, - "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, - } - - cmdToDefinition = { - "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, - "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, - "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, - "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, - "CS_CAM_EYE": OOTCSMotionCamEye, - "CS_CAM_AT": OOTCSMotionCamAT, - "TRANSITION": OOTCSMotionTransition, - "MISC_LIST" : OOTCSMotionMiscList, - "TEXT_LIST" : OOTCSMotionTextList, - "LIGHT_SETTING_LIST" : OOTCSMotionLightSettingList, - "TIME_LIST" : OOTCSMotionTimeList, - "FADE_OUT_SEQ_LIST" : OOTCSMotionFadeSeqList, - "RUMBLE_CONTROLLER_LIST" : OOTCSMotionRumbleControllerList, - } - # for each cutscene from the list returned by getParsedCutscenes(), # create classes containing the cutscene's informations # that will be used later when creating Blender objects to complete the import @@ -406,7 +333,7 @@ def validateCameraData(self, cutscene: OOTCSMotionCutscene): # NOTE: There is a bug in the game where when incrementing to the next set of key points, # the key point which checked for whether it's the last point or not is the last point # of the next set, not the last point of the old set. This means we need to remove - # the extra point at the end that will only tell the game that this camera shot stops. + # the extra point at the end that will only tell the game that this camera shot stops. del eyeListEntry.entries[-1] del atListEntry.entries[-1] diff --git a/fast64_internal/oot/cutscene/motion/io_classes.py b/fast64_internal/oot/cutscene/motion/io_classes.py index c0aa28c96..dff96f04a 100644 --- a/fast64_internal/oot/cutscene/motion/io_classes.py +++ b/fast64_internal/oot/cutscene/motion/io_classes.py @@ -42,11 +42,12 @@ class OOTCSMotionCamPoint(OOTCSMotionBase): paramNumber: int = 8 def __post_init__(self): - self.continueFlag = self.params[0] - self.camRoll = getInteger(self.params[1]) - self.frame = getInteger(self.params[2]) - self.viewAngle = float(self.params[3][:-1]) - self.pos = [getInteger(self.params[4]), getInteger(self.params[5]), getInteger(self.params[6])] + if self.params is not None: + self.continueFlag = self.params[0] + self.camRoll = getInteger(self.params[1]) + self.frame = getInteger(self.params[2]) + self.viewAngle = float(self.params[3][:-1]) + self.pos = [getInteger(self.params[4]), getInteger(self.params[5]), getInteger(self.params[6])] @dataclass @@ -60,12 +61,13 @@ class OOTCSMotionActorCue(OOTCSMotionBase): paramNumber: int = 15 def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.actionID = getInteger(self.params[0]) - self.rot = [getRotation(self.params[3]), getRotation(self.params[4]), getRotation(self.params[5])] - self.startPos = [getInteger(self.params[6]), getInteger(self.params[7]), getInteger(self.params[8])] - self.endPos = [getInteger(self.params[9]), getInteger(self.params[10]), getInteger(self.params[11])] + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.actionID = getInteger(self.params[0]) + self.rot = [getRotation(self.params[3]), getRotation(self.params[4]), getRotation(self.params[5])] + self.startPos = [getInteger(self.params[6]), getInteger(self.params[7]), getInteger(self.params[8])] + self.endPos = [getInteger(self.params[9]), getInteger(self.params[10]), getInteger(self.params[11])] @dataclass @@ -80,16 +82,17 @@ class OOTCSMotionActorCueList(OOTCSMotionBase): listName: str = "actorCueList" def __post_init__(self): - if self.isPlayer: - self.commandType = "Player" - self.entryTotal = getInteger(self.params[0]) - else: - self.commandType = self.params[0] - if self.commandType.startswith("0x"): - # make it a 4 digit hex - self.commandType = self.commandType.removeprefix("0x") - self.commandType = "0x" + "0" * (4 - len(self.commandType)) + self.commandType - self.entryTotal = getInteger(self.params[1].strip()) + if self.params is not None: + if self.isPlayer: + self.commandType = "Player" + self.entryTotal = getInteger(self.params[0]) + else: + self.commandType = self.params[0] + if self.commandType.startswith("0x"): + # make it a 4 digit hex + self.commandType = self.commandType.removeprefix("0x") + self.commandType = "0x" + "0" * (4 - len(self.commandType)) + self.commandType + self.entryTotal = getInteger(self.params[1].strip()) @dataclass @@ -101,8 +104,9 @@ class OOTCSMotionCamEyeSpline(OOTCSMotionBase): listName: str = "camEyeSplineList" def __post_init__(self): - self.startFrame = getInteger(self.params[0]) - self.endFrame = getInteger(self.params[1]) + if self.params is not None: + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -114,8 +118,9 @@ class OOTCSMotionCamATSpline(OOTCSMotionBase): listName: str = "camATSplineList" def __post_init__(self): - self.startFrame = getInteger(self.params[0]) - self.endFrame = getInteger(self.params[1]) + if self.params is not None: + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -127,8 +132,9 @@ class OOTCSMotionCamEyeSplineRelToPlayer(OOTCSMotionBase): listName: str = "camEyeSplineRelPlayerList" def __post_init__(self): - self.startFrame = getInteger(self.params[0]) - self.endFrame = getInteger(self.params[1]) + if self.params is not None: + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -140,8 +146,9 @@ class OOTCSMotionCamATSplineRelToPlayer(OOTCSMotionBase): listName: str = "camATSplineRelPlayerList" def __post_init__(self): - self.startFrame = getInteger(self.params[0]) - self.endFrame = getInteger(self.params[1]) + if self.params is not None: + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -154,8 +161,9 @@ class OOTCSMotionCamEye(OOTCSMotionBase): listName: str = "camEyeList" def __post_init__(self): - self.startFrame = getInteger(self.params[0]) - self.endFrame = getInteger(self.params[1]) + if self.params is not None: + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -168,8 +176,9 @@ class OOTCSMotionCamAT(OOTCSMotionBase): listName: str = "camATList" def __post_init__(self): - self.startFrame = getInteger(self.params[0]) - self.endFrame = getInteger(self.params[1]) + if self.params is not None: + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -180,9 +189,10 @@ class OOTCSMotionMisc(OOTCSMotionBase): paramNumber: int = 14 def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.type = self.getEnumValue("csMiscType", 0) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.type = self.getEnumValue("csMiscType", 0) @dataclass @@ -195,7 +205,8 @@ class OOTCSMotionMiscList(OOTCSMotionBase): listName: str = "miscList" def __post_init__(self): - self.entryTotal = getInteger(self.params[0]) + if self.params is not None: + self.entryTotal = getInteger(self.params[0]) @dataclass @@ -207,9 +218,10 @@ class OOTCSMotionTransition(OOTCSMotionBase): listName: str = "transitionList" def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.type = self.getEnumValue("csTransitionType", 0) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.type = self.getEnumValue("csTransitionType", 0) @dataclass @@ -224,12 +236,13 @@ class OOTCSMotionText(OOTCSMotionBase): id: str = "Text" def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.textId = getInteger(self.params[0]) - self.type = self.getEnumValue("csTextType", 3) - self.altTextId1 = (getInteger(self.params[4]),) - self.altTextId2 = (getInteger(self.params[5]),) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.textId = getInteger(self.params[0]) + self.type = self.getEnumValue("csTextType", 3) + self.altTextId1 = (getInteger(self.params[4]),) + self.altTextId2 = (getInteger(self.params[5]),) @dataclass @@ -240,8 +253,9 @@ class OOTCSMotionTextNone(OOTCSMotionBase): id: str = "None" def __post_init__(self): - self.startFrame = getInteger(self.params[0]) - self.endFrame = getInteger(self.params[1]) + if self.params is not None: + self.startFrame = getInteger(self.params[0]) + self.endFrame = getInteger(self.params[1]) @dataclass @@ -254,10 +268,11 @@ class OOTCSMotionTextOcarinaAction(OOTCSMotionBase): id: str = "OcarinaAction" def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.ocarinaActionId = self.getEnumValue("ocarinaSongActionId", 0) - self.messageId = getInteger(self.params[3]) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.ocarinaActionId = self.getEnumValue("ocarinaSongActionId", 0) + self.messageId = getInteger(self.params[3]) @dataclass @@ -270,7 +285,8 @@ class OOTCSMotionTextList(OOTCSMotionBase): listName: str = "textList" def __post_init__(self): - self.entryTotal = getInteger(self.params[0]) + if self.params is not None: + self.entryTotal = getInteger(self.params[0]) @dataclass @@ -282,11 +298,12 @@ class OOTCSMotionLightSetting(OOTCSMotionBase): paramNumber: int = 11 def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.lightSetting = getInteger(self.params[0]) - if self.isLegacy: - self.lightSetting -= 1 + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.lightSetting = getInteger(self.params[0]) + if self.isLegacy: + self.lightSetting -= 1 @dataclass @@ -299,7 +316,8 @@ class OOTCSMotionLightSettingList(OOTCSMotionBase): listName: str = "lightSettingsList" def __post_init__(self): - self.entryTotal = getInteger(self.params[0]) + if self.params is not None: + self.entryTotal = getInteger(self.params[0]) @dataclass @@ -311,10 +329,11 @@ class OOTCSMotionTime(OOTCSMotionBase): paramNumber: int = 5 def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.hour = getInteger(self.params[3]) - self.minute = getInteger(self.params[4]) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.hour = getInteger(self.params[3]) + self.minute = getInteger(self.params[4]) @dataclass @@ -327,7 +346,8 @@ class OOTCSMotionTimeList(OOTCSMotionBase): listName: str = "timeList" def __post_init__(self): - self.entryTotal = getInteger(self.params[0]) + if self.params is not None: + self.entryTotal = getInteger(self.params[0]) @dataclass @@ -339,9 +359,10 @@ class OOTCSMotionStartStopSeq(OOTCSMotionBase): paramNumber: int = 11 def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.seqId = self.getEnumValue("seqId", 0, self.isLegacy) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.seqId = self.getEnumValue("seqId", 0, self.isLegacy) @dataclass @@ -355,7 +376,8 @@ class OOTCSMotionStartStopSeqList(OOTCSMotionBase): listName: str = "seqList" def __post_init__(self): - self.entryTotal = getInteger(self.params[0]) + if self.params is not None: + self.entryTotal = getInteger(self.params[0]) @dataclass @@ -367,9 +389,10 @@ class OOTCSMotionFadeSeq(OOTCSMotionBase): enumKey: str = "csFadeOutSeqPlayer" def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.seqPlayer = self.getEnumValue("csFadeOutSeqPlayer", 0) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.seqPlayer = self.getEnumValue("csFadeOutSeqPlayer", 0) @dataclass @@ -382,7 +405,8 @@ class OOTCSMotionFadeSeqList(OOTCSMotionBase): listName: str = "fadeSeqList" def __post_init__(self): - self.entryTotal = getInteger(self.params[0]) + if self.params is not None: + self.entryTotal = getInteger(self.params[0]) @dataclass @@ -395,11 +419,12 @@ class OOTCSMotionRumbleController(OOTCSMotionBase): paramNumber: int = 8 def __post_init__(self): - self.startFrame = getInteger(self.params[1]) - self.endFrame = getInteger(self.params[2]) - self.sourceStrength = getInteger(self.params[3]) - self.duration = getInteger(self.params[4]) - self.decreaseRate = getInteger(self.params[5]) + if self.params is not None: + self.startFrame = getInteger(self.params[1]) + self.endFrame = getInteger(self.params[2]) + self.sourceStrength = getInteger(self.params[3]) + self.duration = getInteger(self.params[4]) + self.decreaseRate = getInteger(self.params[5]) @dataclass @@ -412,7 +437,8 @@ class OOTCSMotionRumbleControllerList(OOTCSMotionBase): listName: str = "rumbleList" def __post_init__(self): - self.entryTotal = getInteger(self.params[0]) + if self.params is not None: + self.entryTotal = getInteger(self.params[0]) @dataclass diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index 8c9fd0611..663e08f5c 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -8,10 +8,9 @@ from bpy.types import Scene, Operator, Context, UILayout from bpy.utils import register_class, unregister_class from ...utility import CData, PluginError, writeCData, raisePluginError -from ..oot_utility import getCollection +from ..oot_utility import getCollection, getCutsceneName from ..oot_constants import ootData from ..scene.exporter.to_c import ootCutsceneDataToC -from .exporter import convertCutsceneObject from .constants import ootEnumCSTextboxType, ootEnumCSListType, ootEnumCSListTypeIcons from .motion.importer import importCutsceneData from .motion.exporter import getCutsceneMotionData @@ -77,7 +76,7 @@ def insertCutsceneData(filePath: str, csName: str): fileLines = [] foundCutscene = False - motionExporter = getCutsceneMotionData(csName, False) + motionExporter = getCutsceneMotionData(csName) beginIndex = 0 for i, line in enumerate(fileLines): @@ -199,12 +198,11 @@ def execute(self, context): cpath, hpath, headerfilename = checkGetFilePaths(context) csdata = ootCutsceneIncludes(headerfilename) - converted = convertCutsceneObject(activeObj) if context.scene.exportMotionOnly: csdata.append(insertCutsceneData(cpath, activeObj.name.removeprefix("Cutscene."))) else: - csdata.append(ootCutsceneDataToC(converted, converted.name)) + csdata.append(ootCutsceneDataToC(getCutsceneName(activeObj))) writeCData(csdata, hpath, cpath) self.report({"INFO"}, "Successfully exported cutscene") @@ -234,11 +232,10 @@ def execute(self, context): print(f"Parent: {obj.parent.name}, Object: {obj.name}") raise PluginError("Cutscene object must not be parented to anything") - converted = convertCutsceneObject(obj) if context.scene.exportMotionOnly: raise PluginError("ERROR: Not implemented yet.") else: - csdata.append(ootCutsceneDataToC(converted, converted.name)) + csdata.append(ootCutsceneDataToC(getCutsceneName(obj))) count += 1 if count == 0: diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 8e9ada4de..195ba4ff1 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -29,7 +29,7 @@ class OOTCutsceneCommon: subprops = ["startFrame", "endFrame"] expandTab: BoolProperty(default=True) startFrame: IntProperty(name="", default=0, min=0) - endFrame: IntProperty(name="", default=1, min=0) + endFrame: IntProperty(name="", default=0, min=0) def getName(self): pass diff --git a/fast64_internal/oot/oot_level_classes.py b/fast64_internal/oot/oot_level_classes.py index 12ba953f7..7410c6e66 100644 --- a/fast64_internal/oot/oot_level_classes.py +++ b/fast64_internal/oot/oot_level_classes.py @@ -111,7 +111,8 @@ def __init__(self, name, model): self.cameraList = [] self.writeCutscene = False - self.csWriteType = "Embedded" + self.csWriteType = "Object" + self.csName = "" self.csWriteCustom = "" self.csWriteObject = None self.csEndFrame = 100 diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index 534748783..e60bcc0ab 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -4,7 +4,7 @@ from .scene.properties import OOTSceneProperties, OOTSceneHeaderProperty, OOTAlternateSceneHeaderProperty from .room.properties import OOTRoomHeaderProperty, OOTAlternateRoomHeaderProperty from .oot_constants import ootData -from .cutscene.exporter import convertCutsceneObject, readCutsceneData +from .cutscene.exporter import readCutsceneData from .oot_spline import assertCurveValid, ootConvertPath from .oot_model_classes import OOTModel from .oot_collision import OOTCameraData, exportCollisionCommon @@ -288,12 +288,9 @@ def readSceneData( elif sceneHeader.csWriteObject.parent is not None: raise PluginError("Cutscene empty object should not be parented to anything") else: - scene.csWriteObject = convertCutsceneObject(sceneHeader.csWriteObject) + scene.csName = sceneHeader.csWriteObject.name.removeprefix("Cutscene.") if alternateSceneHeaders is not None: - for ec in sceneHeader.extraCutscenes: - scene.extraCutscenes.append(convertCutsceneObject(ec.csObject)) - scene.collision.cameraData = OOTCameraData(scene.name) if not alternateSceneHeaders.childNightHeader.usePreviousHeader: diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_commands.py b/fast64_internal/oot/scene/exporter/to_c/scene_commands.py index e3e812c72..7f98314a4 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_commands.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_commands.py @@ -68,7 +68,7 @@ def getCutsceneDataCmd(outScene: OOTScene, headerIndex: int): case "Embedded": csDataName = outScene.cutsceneDataName(headerIndex) case "Object": - csDataName = outScene.csWriteObject.name + csDataName = outScene.csName case _: csDataName = outScene.csWriteCustom diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 3b3e9f53f..529d67ec7 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -1,20 +1,13 @@ -from .....utility import CData, PluginError, indent +import bpy + +from .....utility import CData from ....oot_level_classes import OOTScene -from ....cutscene.constants import ootEnumCSTextboxTypeEntryC, ootEnumCSListTypeListC, ootEnumCSListTypeEntryC -from ....cutscene.exporter import OOTCutscene from ....cutscene.motion.exporter import getCutsceneMotionData -def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): - motionExporter = getCutsceneMotionData(csName, False) - motionData = motionExporter.getExportData() +def ootCutsceneDataToC(csName: str): csData = CData() declarationBase = f"CutsceneData {csName}[]" - nentries = len(csParent.csLists) + (1 if csParent.csUseDestination else 0) - - frameDiff = 0 - if motionExporter.frameCount > csParent.csEndFrame: - frameDiff = motionExporter.frameCount - csParent.csEndFrame # .h csData.header = f"extern {declarationBase};\n" @@ -23,80 +16,10 @@ def ootCutsceneDataToC(csParent: OOTCutscene | OOTScene, csName: str): csData.source = ( declarationBase + " = {\n" - + (indent + f"CS_BEGIN_CUTSCENE({nentries + motionExporter.entryTotal}, {csParent.csEndFrame + frameDiff}),\n") - + ( - (indent * 2) + f"CS_DESTINATION({csParent.csDestination}, {csParent.csDestinationStartFrame}, 0),\n" - if csParent.csUseDestination - else "" - ) + + getCutsceneMotionData(csName, bpy.context.scene.exportMotionOnly).getExportData() + + "};\n\n" ) - for list in csParent.csLists: - # CS "XXXX List" Command - csData.source += ( - (indent * 2) - + ootEnumCSListTypeListC[list.listType] - + "(" - + ( - f"{list.transitionType}, {list.transitionStartFrame}, {list.transitionEndFrame}" - if list.listType == "Transition" - else str(len(list.entries)) - ) - + "),\n" - ) - - for e in list.entries: - csData.source += ( - indent * 3 - + ( - ootEnumCSTextboxTypeEntryC[e.textboxType] - # @TODO make a separate variable for ``ootEnumCSListTypeEntryC`` - if list.listType == "TextList" - else ootEnumCSListTypeEntryC[list.listType.replace("List", "")] - ) - + "(" - ) - - if list.listType == "TextList": - if e.textboxType == "Text": - csData.source += f"{e.textID}, {e.startFrame}, {e.endFrame}, {e.textType}, {e.topOptionTextID}, {e.bottomOptionTextID}" - - elif e.textboxType == "None": - csData.source += f"{e.startFrame}, {e.endFrame}" - - elif e.textboxType == "OcarinaAction": - csData.source += f"{e.ocarinaAction}, {e.startFrame}, {e.endFrame}, {e.ocarinaMessageId}" - - elif list.listType == "LightSettingsList": - # the endFrame variable is not used in the implementation of the command - # so the value doesn't matter - csData.source += f"{e.lightSettingsIndex}, {e.startFrame}" + (", 0" * 9) - - elif list.listType == "TimeList": - # same as above - csData.source += f"0, {e.startFrame}, 0, {e.hour}, {e.minute}" - - elif list.listType == "RumbleList": - # same as above - csData.source += ( - f"0, {e.startFrame}, 0, {e.rumbleSourceStrength}, {e.rumbleDuration}, {e.rumbleDecreaseRate}, 0, 0" - ) - - elif list.listType in ["StartSeqList", "StopSeqList", "FadeOutSeqList"]: - endFrame = e.endFrame if list.listType == "FadeOutSeqList" else "0" - firstArg = e.csSeqPlayer if list.listType == "FadeOutSeqList" else e.csSeqID - csData.source += f"{firstArg}, {e.startFrame}, {endFrame}" + (", 0" * 8) - - elif list.listType == "MiscList": - csData.source += f"{e.csMiscType}, {e.startFrame}, {e.endFrame}" + (", 0" * 11) - - else: - raise PluginError("Internal error: invalid cutscene list type " + list.listType) - - csData.source += "),\n" - - csData.source += motionData - csData.source += indent + "CS_END(),\n};\n\n" return csData @@ -116,14 +39,14 @@ def getSceneCutscenes(outScene: OOTScene): # or one of the alternate / cutscene headers. if curHeader is not None and curHeader.writeCutscene: if curHeader.csWriteType == "Embedded": - cutscenes.append(ootCutsceneDataToC(curHeader, curHeader.cutsceneDataName(i))) - elif curHeader.csWriteType == "Object" and curHeader.csWriteObject.name not in csObjects: - cutscenes.append(ootCutsceneDataToC(curHeader.csWriteObject, curHeader.csWriteObject.name)) - csObjects.append(curHeader.csWriteObject.name) + cutscenes.append(ootCutsceneDataToC(curHeader.cutsceneDataName(i))) + elif curHeader.csWriteType == "Object" and curHeader.csName not in csObjects: + cutscenes.append(ootCutsceneDataToC(curHeader.csName)) + csObjects.append(curHeader.csName) for extraCs in outScene.extraCutscenes: if not extraCs.name in csObjects: - cutscenes.append(ootCutsceneDataToC(extraCs, extraCs.name)) + cutscenes.append(ootCutsceneDataToC(extraCs.name)) csObjects.append(extraCs.name) return cutscenes From 6c483771243bbd8e287912efb086cc873c4ea05f Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 20 Oct 2023 02:42:21 +0200 Subject: [PATCH 24/39] ui improvements and import cs destination --- fast64_internal/oot/cutscene/constants.py | 31 ++++++--- .../oot/cutscene/motion/constants.py | 2 + .../oot/cutscene/motion/importer/classes.py | 33 ++++++--- .../oot/cutscene/motion/io_classes.py | 15 +++++ .../oot/cutscene/motion/operators.py | 8 +-- .../oot/cutscene/motion/preview.py | 2 +- .../oot/cutscene/motion/utility.py | 9 +++ fast64_internal/oot/cutscene/preview.py | 7 +- fast64_internal/oot/cutscene/properties.py | 67 ++++++++++++++----- 9 files changed, 125 insertions(+), 49 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index a2b6091b6..43d4f35c6 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -34,18 +34,31 @@ ("Object", "Object", "Reference to Blender object representing cutscene"), ] +# order here sets order on the UI ootEnumCSListType = [ - ("TextList", "Text List", "Textbox"), - ("Transition", "Transition", "Transition"), - ("LightSettingsList", "Light Settings List", "Lighting"), - ("TimeList", "Time List", "Time"), - ("StartSeqList", "Start Seq List", "Play BGM"), - ("StopSeqList", "Stop Seq List", "Stop BGM"), - ("FadeOutSeqList", "Fade-Out Seq List", "Fade BGM"), - ("MiscList", "Misc List", "Misc"), - ("RumbleList", "Rumble List", "Rumble Controller"), + ("TextList", "Text List", "Textbox", "ALIGN_BOTTOM", 0), + ("TimeList", "Time List", "Time", "TIME", 3), + ("FadeOutSeqList", "Fade-Out Seq List", "Fade BGM", "IPO_EASE_IN_OUT", 6), + ("Transition", "Transition", "Transition", "COLORSET_10_VEC", 1), + ("StartSeqList", "Start Seq List", "Play BGM", "PLAY", 4), + ("MiscList", "Misc List", "Misc", "OPTIONS", 7), + ("LightSettingsList", "Light Settings List", "Lighting", "LIGHT_SUN", 2), + ("StopSeqList", "Stop Seq List", "Stop BGM", "SNAP_FACE", 5), + ("RumbleList", "Rumble List", "Rumble Controller", "OUTLINER_OB_FORCE_FIELD", 8), ] +csListTypeToIcon = { + "TextList": "ALIGN_BOTTOM", + "Transition": "COLORSET_10_VEC", + "LightSettingsList": "LIGHT_SUN", + "TimeList": "TIME", + "StartSeqList": "PLAY", + "StopSeqList": "SNAP_FACE", + "FadeOutSeqList": "IPO_EASE_IN_OUT", + "MiscList": "OPTIONS", + "RumbleList": "OUTLINER_OB_FORCE_FIELD", +} + ootEnumCSListTypeIcons = [ "ALIGN_BOTTOM", "COLORSET_10_VEC", diff --git a/fast64_internal/oot/cutscene/motion/constants.py b/fast64_internal/oot/cutscene/motion/constants.py index bc924b353..d7edfa170 100644 --- a/fast64_internal/oot/cutscene/motion/constants.py +++ b/fast64_internal/oot/cutscene/motion/constants.py @@ -26,6 +26,7 @@ OOTCSMotionFadeSeqList, OOTCSMotionRumbleController, OOTCSMotionRumbleControllerList, + OOTCSMotionDestination, ) ootEnumCSMotionCamMode = [ @@ -160,4 +161,5 @@ "CS_STOP_SEQ_LIST": OOTCSMotionStartStopSeqList, "CS_ACTOR_CUE_LIST": OOTCSMotionActorCueList, "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, + "CS_DESTINATION": OOTCSMotionDestination, } diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/motion/importer/classes.py index 18f3fdf70..c1cc3784c 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/motion/importer/classes.py @@ -216,7 +216,7 @@ def getCutsceneList(self): else: commandData = cmd(params) - if cmdListName != "CS_TRANSITION": + if cmdListName != "CS_TRANSITION" and cmdListName != "CS_DESTINATION": foundEndCmd = False for d in cmdData: cmdEntryName = d.strip().split("(")[0] @@ -239,7 +239,10 @@ def getCutsceneList(self): else: listEntry = entryCmd(params) commandData.entries.append(listEntry) - cmdList.append(commandData) + if cmdListName == "CS_DESTINATION": + cutscene.destination = commandData + else: + cmdList.append(commandData) else: print(f"WARNING: `{cmdListName}` is not implemented yet!") @@ -387,6 +390,13 @@ def setCameraShotData( endIndex = i return endIndex + 1 + + def setPropOrCustom(self, prop, propName: str, value): + try: + setattr(prop, propName, value) + except TypeError: + setattr(prop, propName, "Custom") + setattr(prop, f"{propName}Custom", value) def setSubPropertyData(self, subPropsData: dict[str, str], newSubElem, entry): customNames = [ @@ -403,11 +413,7 @@ def setSubPropertyData(self, subPropsData: dict[str, str], newSubElem, entry): if value is not None: if key in customNames: valueToSet = getattr(entry, value) - try: - setattr(newSubElem, key, valueToSet) - except TypeError: - setattr(newSubElem, key, "Custom") - setattr(newSubElem, f"{key}Custom", valueToSet) + self.setPropOrCustom(newSubElem, key, valueToSet) else: setattr(newSubElem, key, getattr(entry, value)) @@ -440,16 +446,16 @@ def setPropertyData( newSubElem.endFrame = entry.endFrame if data.listType == "Text": - data.subPropsData["textboxType"] = "id" + self.setPropOrCustom(newSubElem, "textboxType", entry.id) match entry.id: case "Text": newSubElem.textID = f"0x{entry.textId:04X}" - data.subPropsData["csTextType"] = "type" + self.setPropOrCustom(newSubElem, "csTextType", entry.type) case "None": - data.subPropsData["csTextType"] = None + pass case "OcarinaAction": newSubElem.ocarinaMessageId = f"0x{entry.messageId:04X}" - data.subPropsData["ocarinaAction"] = "ocarinaActionId" + self.setPropOrCustom(newSubElem, "ocarinaAction", entry.ocarinaActionId) case _: raise PluginError("ERROR: Unknown text type!") self.setSubPropertyData(data.subPropsData, newSubElem, entry) @@ -494,6 +500,11 @@ def setCutsceneData(self, csNumber): csObj, cutscene.camEyeList, cutscene.camATList, "eyeOrAT", lastIndex, i ) + if cutscene.destination is not None: + csProp.csUseDestination = True + csProp.csDestinationStartFrame = cutscene.destination.startFrame + self.setPropOrCustom(csProp, "csDestination", cutscene.destination.id) + propDataList = [ PropertyData("Text", {"textboxType": "id"}, True), PropertyData("Misc", {"csMiscType": "type"}, True), diff --git a/fast64_internal/oot/cutscene/motion/io_classes.py b/fast64_internal/oot/cutscene/motion/io_classes.py index dff96f04a..56e8aa62e 100644 --- a/fast64_internal/oot/cutscene/motion/io_classes.py +++ b/fast64_internal/oot/cutscene/motion/io_classes.py @@ -441,6 +441,20 @@ def __post_init__(self): self.entryTotal = getInteger(self.params[0]) +@dataclass +class OOTCSMotionDestination(OOTCSMotionBase): + """This class contains Destination command data""" + + id: str = None + paramNumber: int = 3 + listName: str = "destination" + + def __post_init__(self): + if self.params is not None: + self.id = self.getEnumValue("csDestination", 0) + self.startFrame = getInteger(self.params[1]) + + @dataclass class OOTCSMotionCutscene: """This class contains a Cutscene's data, including every commands' data""" @@ -450,6 +464,7 @@ class OOTCSMotionCutscene: frameCount: int paramNumber: int = 2 + destination: OOTCSMotionDestination = None actorCueList: list[OOTCSMotionActorCueList] = field(default_factory=list) playerCueList: list[OOTCSMotionActorCueList] = field(default_factory=list) camEyeSplineList: list[OOTCSMotionCamEyeSpline] = field(default_factory=list) diff --git a/fast64_internal/oot/cutscene/motion/operators.py b/fast64_internal/oot/cutscene/motion/operators.py index e028b6976..f6d3e987c 100644 --- a/fast64_internal/oot/cutscene/motion/operators.py +++ b/fast64_internal/oot/cutscene/motion/operators.py @@ -16,6 +16,7 @@ createNewBone, createNewCameraShot, getCutsceneEndFrame, + getCutsceneCamera, ) @@ -68,11 +69,8 @@ def execute(self, context): if csObj is not None: # get and set the camera - cameraObj = None - for childObj in csObj.children: - if childObj.type == "CAMERA": - cameraObj = childObj - break + cameraObj = getCutsceneCamera(csObj) + cameraObj.data.passepartout_alpha = 1.0 if context.scene.ootCsUseOpaqueCamBg else 0.95 # from https://blender.stackexchange.com/a/259103 space = None diff --git a/fast64_internal/oot/cutscene/motion/preview.py b/fast64_internal/oot/cutscene/motion/preview.py index 9c9007d73..57011b587 100644 --- a/fast64_internal/oot/cutscene/motion/preview.py +++ b/fast64_internal/oot/cutscene/motion/preview.py @@ -185,7 +185,7 @@ def previewFrameHandler(scene: Scene): if obj.type == "CAMERA": pos, rot_quat, viewAngle = getCutsceneCamState(parentObj, scene.frame_current) - if parentObj.ootCutsceneProperty.preview.useWidescreen: + if scene.ootCsUseWidescreen: viewAngle *= 4 / 3 if pos is not None: diff --git a/fast64_internal/oot/cutscene/motion/utility.py b/fast64_internal/oot/cutscene/motion/utility.py index c2b06c19e..c21baa0bc 100644 --- a/fast64_internal/oot/cutscene/motion/utility.py +++ b/fast64_internal/oot/cutscene/motion/utility.py @@ -286,3 +286,12 @@ def setupCutscene(csObj: Object): context.scene.render.resolution_y = 240 context.scene.frame_set(context.scene.frame_start) context.scene.camera = camObj + + +def getCutsceneCamera(csObj: Object) -> Object | None: + cameraObj = None + for childObj in csObj.children: + if childObj.type == "CAMERA": + cameraObj = childObj + break + return cameraObj diff --git a/fast64_internal/oot/cutscene/preview.py b/fast64_internal/oot/cutscene/preview.py index 68443f342..65af37c4c 100644 --- a/fast64_internal/oot/cutscene/preview.py +++ b/fast64_internal/oot/cutscene/preview.py @@ -4,6 +4,7 @@ from bpy.types import Scene, Object, Node from bpy.app.handlers import persistent from ...utility import gammaInverse, hexOrDecInt +from .motion.utility import getCutsceneCamera def getLerp(max: float, min: float, val: float): @@ -224,11 +225,7 @@ def cutscenePreviewFrameHandler(scene: Scene): return # populate ``cameraObjects`` with the cutscene camera and the first found prerend fixed camera - cameraObjects = [None, None] - for obj in csObj.children: - if obj.type == "CAMERA": - cameraObjects[1] = obj - break + cameraObjects = [None, getCutsceneCamera(csObj)] foundObj = None for obj in bpy.data.objects: diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 195ba4ff1..de15ce2da 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -6,8 +6,9 @@ from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName from ..oot_constants import ootData from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps, upgradeCutsceneProperty -from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, drawCSListAddOp +from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, OOTCSListAdd from .motion.preview import previewFrameHandler +from .motion.utility import getCutsceneCamera from .motion.operators import ( OOTCSMotionPlayPreview, @@ -21,6 +22,7 @@ ootEnumCSListType, ootEnumCSTextboxTypeIcons, ootCSSubPropToName, + csListTypeToIcon, ) @@ -288,10 +290,6 @@ class OOTCutsceneMiscProperty(OOTCutsceneCommandBase, PropertyGroup): class OOTCutscenePreviewProperty(PropertyGroup): - useWidescreen: BoolProperty( - name="Use Widescreen Camera", default=False, update=lambda self, context: self.updateWidescreen(context) - ) - transitionList: CollectionProperty(type=OOTCutsceneTransitionProperty) miscList: CollectionProperty(type=OOTCutsceneMiscProperty) @@ -300,16 +298,6 @@ class OOTCutscenePreviewProperty(PropertyGroup): prevFrame: IntProperty(default=-1) nextFrame: IntProperty(default=1) - def updateWidescreen(self, context: Context): - if self.useWidescreen: - context.scene.render.resolution_x = 426 - else: - context.scene.render.resolution_x = 320 - context.scene.render.resolution_y = 240 - - # force a refresh of the current frame - previewFrameHandler(context.scene) - class OOTCutsceneProperty(PropertyGroup): csEndFrame: IntProperty(name="End Frame", min=0, default=100) @@ -320,6 +308,7 @@ class OOTCutsceneProperty(PropertyGroup): csDestinationCustom: StringProperty(default="CS_DEST_CUSTOM") csDestinationStartFrame: IntProperty(name="Start Frame", min=0, default=99) csLists: CollectionProperty(type=OOTCSListProperty, name="Cutscene Lists") + menuTab: EnumProperty(items=ootEnumCSListType) preview: PointerProperty(type=OOTCutscenePreviewProperty) @@ -353,7 +342,8 @@ def draw_props(self, layout: UILayout, obj: Object): split.operator(OOTCSMotionCreatePlayerCueList.bl_idname) split.operator(OOTCSMotionCreateActorCueList.bl_idname) - layout.prop(self.preview, "useWidescreen") + layout.prop(bpy.context.scene, "ootCsUseWidescreen") + layout.prop(bpy.context.scene, "ootCsUseOpaqueCamBg") layout.prop(self, "csEndFrame") @@ -373,11 +363,19 @@ def draw_props(self, layout: UILayout, obj: Object): r = csDestLayout.row() r.prop(self, "csDestinationStartFrame") - drawCSListAddOp(layout, obj.name, "Cutscene") + menuBox = layout.box() + menuBox.label(text="Cutscene Commands") + menuBox.column_flow(columns=3, align=True).prop(self, "menuTab", expand=True) + label = f"Add New {self.menuTab.replace('List', ' List')}" + op = menuBox.operator(OOTCSListAdd.bl_idname, text=label, icon=csListTypeToIcon[self.menuTab]) + op.collectionType = "Cutscene" + op.listType = self.menuTab + op.objName = obj.name for i, csListProp in enumerate(self.csLists): # ``csListProp`` type: OOTCSListProperty - csListProp.draw_props(layout, i, obj.name, "Cutscene") + if csListProp.listType == self.menuTab: + csListProp.draw_props(menuBox, i, obj.name, "Cutscene") classes = ( @@ -395,6 +393,26 @@ def draw_props(self, layout: UILayout, obj: Object): ) +def updateWidescreen(self, context: Context): + if context.scene.ootCsUseWidescreen: + context.scene.render.resolution_x = 426 + else: + context.scene.render.resolution_x = 320 + context.scene.render.resolution_y = 240 + + # force a refresh of the current frame + previewFrameHandler(context.scene) + + +def updateCamBackground(self, context: Context): + camObj = getCutsceneCamera(context.view_layer.objects.active) + if camObj is not None: + if context.scene.ootCsUseOpaqueCamBg: + camObj.data.passepartout_alpha = 1.0 + else: + camObj.data.passepartout_alpha = 0.95 + + def cutscene_props_register(): for cls in classes: register_class(cls) @@ -403,8 +421,21 @@ def cutscene_props_register(): Scene.ootCSPreviewNodesReady = BoolProperty(default=False) Scene.ootCSPreviewCSObj = PointerProperty(type=Object) + Scene.ootCsUseWidescreen = BoolProperty( + name="Use Widescreen Camera", default=False, update=updateWidescreen + ) + + Scene.ootCsUseOpaqueCamBg = BoolProperty( + name="Use Opaque Camera Background", + description="Can be used to simulate the letterbox with widescreen mode enabled", + default=False, + update=updateCamBackground + ) + def cutscene_props_unregister(): + del Scene.ootCsUseOpaqueCamBg + del Scene.ootCsUseWidescreen del Scene.ootCSPreviewCSObj del Scene.ootCSPreviewNodesReady del Object.ootCutsceneProperty From 849b464597d081aab9e3dcff4472416071b8990d Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 20 Oct 2023 02:42:39 +0200 Subject: [PATCH 25/39] black --- fast64_internal/oot/cutscene/motion/exporter/classes.py | 4 +--- fast64_internal/oot/cutscene/motion/importer/classes.py | 2 +- fast64_internal/oot/cutscene/properties.py | 8 +++----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/fast64_internal/oot/cutscene/motion/exporter/classes.py b/fast64_internal/oot/cutscene/motion/exporter/classes.py index d26903e0a..4436f53ed 100644 --- a/fast64_internal/oot/cutscene/motion/exporter/classes.py +++ b/fast64_internal/oot/cutscene/motion/exporter/classes.py @@ -454,7 +454,5 @@ def getExportData(self): self.frameCount += self.motionFrameCount - self.frameCount return ( - (indent + f"CS_BEGIN_CUTSCENE({self.entryTotal}, {self.frameCount}),\n") - + csData - + (indent + "CS_END(),\n") + (indent + f"CS_BEGIN_CUTSCENE({self.entryTotal}, {self.frameCount}),\n") + csData + (indent + "CS_END(),\n") ) diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/motion/importer/classes.py index c1cc3784c..2cb9279ed 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/motion/importer/classes.py @@ -390,7 +390,7 @@ def setCameraShotData( endIndex = i return endIndex + 1 - + def setPropOrCustom(self, prop, propName: str, value): try: setattr(prop, propName, value) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index de15ce2da..e650c577f 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -421,15 +421,13 @@ def cutscene_props_register(): Scene.ootCSPreviewNodesReady = BoolProperty(default=False) Scene.ootCSPreviewCSObj = PointerProperty(type=Object) - Scene.ootCsUseWidescreen = BoolProperty( - name="Use Widescreen Camera", default=False, update=updateWidescreen - ) + Scene.ootCsUseWidescreen = BoolProperty(name="Use Widescreen Camera", default=False, update=updateWidescreen) Scene.ootCsUseOpaqueCamBg = BoolProperty( name="Use Opaque Camera Background", description="Can be used to simulate the letterbox with widescreen mode enabled", - default=False, - update=updateCamBackground + default=False, + update=updateCamBackground, ) From 278338fcf554b8a9fcd66d3d3afc0ec7d8d8cbfd Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 20 Oct 2023 23:38:20 +0200 Subject: [PATCH 26/39] remove "embedded" code --- fast64_internal/oot/cutscene/constants.py | 41 ++----- .../oot/cutscene/exporter/__init__.py | 12 --- .../oot/cutscene/exporter/classes.py | 66 ------------ .../oot/cutscene/exporter/functions.py | 102 ------------------ fast64_internal/oot/cutscene/operators.py | 23 +--- fast64_internal/oot/cutscene/properties.py | 2 +- fast64_internal/oot/oot_level_classes.py | 8 -- fast64_internal/oot/oot_level_writer.py | 12 +-- fast64_internal/oot/oot_upgrade.py | 10 +- .../oot/scene/exporter/to_c/scene_commands.py | 2 - .../oot/scene/exporter/to_c/scene_cutscene.py | 4 +- fast64_internal/oot/scene/properties.py | 38 +------ 12 files changed, 25 insertions(+), 295 deletions(-) delete mode 100644 fast64_internal/oot/cutscene/exporter/__init__.py delete mode 100644 fast64_internal/oot/cutscene/exporter/classes.py delete mode 100644 fast64_internal/oot/cutscene/exporter/functions.py diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 43d4f35c6..fd320113d 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -1,9 +1,3 @@ -ootEnumCSTextboxTypeEntryC = { - "Text": "CS_TEXT", - "None": "CS_TEXT_NONE", - "OcarinaAction": "CS_TEXT_OCARINA_ACTION", -} - ootEnumCSListTypeListC = { "TextList": "CS_TEXT_LIST", "Transition": "CS_TRANSITION", @@ -16,21 +10,8 @@ "RumbleList": "CS_RUMBLE_CONTROLLER_LIST", } -ootEnumCSListTypeEntryC = { - "Text": None, # special case - "Transition": None, # no list entries - "LightSettings": "CS_LIGHT_SETTING", - "Time": "CS_TIME", - "StartSeq": "CS_START_SEQ", - "StopSeq": "CS_STOP_SEQ", - "FadeOutSeq": "CS_FADE_OUT_SEQ", - "Misc": "CS_MISC", - "Rumble": "CS_RUMBLE_CONTROLLER", -} - ootEnumCSWriteType = [ ("Custom", "Custom", "Provide the name of a cutscene header variable"), - ("Embedded", "(Deprecated) Embedded", "Cutscene data is within scene header"), ("Object", "Object", "Reference to Blender object representing cutscene"), ] @@ -59,18 +40,6 @@ "RumbleList": "OUTLINER_OB_FORCE_FIELD", } -ootEnumCSListTypeIcons = [ - "ALIGN_BOTTOM", - "COLORSET_10_VEC", - "LIGHT_SUN", - "TIME", - "PLAY", - "SNAP_FACE", - "IPO_EASE_IN_OUT", - "OPTIONS", - "OUTLINER_OB_FORCE_FIELD", -] - ootEnumCSTextboxType = [ ("Text", "Text", "Text"), ("None", "None", "None"), @@ -103,4 +72,14 @@ "rumbleSourceStrength": "Source Strength", "rumbleDuration": "Duration", "rumbleDecreaseRate": "Decrease Rate", + # Lists + "TextList": "Text List", + "TimeList": "Time List", + "FadeOutSeqList": "Fade-Out Seq List", + "Transition": "Transition", + "StartSeqList": "Start Seq List", + "MiscList": "Misc List", + "LightSettingsList": "Light Settings List", + "StopSeqList": "Stop Seq Lis", + "RumbleList": "Rumble List", } diff --git a/fast64_internal/oot/cutscene/exporter/__init__.py b/fast64_internal/oot/cutscene/exporter/__init__.py deleted file mode 100644 index 79c7cb6ff..000000000 --- a/fast64_internal/oot/cutscene/exporter/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .functions import readCutsceneData - -from .classes import ( - OOTCSList, - OOTCSText, - OOTCSLightSettings, - OOTCSTime, - OOTCSSeq, - OOTCSMisc, - OOTCSRumble, - OOTCutscene, -) diff --git a/fast64_internal/oot/cutscene/exporter/classes.py b/fast64_internal/oot/cutscene/exporter/classes.py deleted file mode 100644 index df8f150cc..000000000 --- a/fast64_internal/oot/cutscene/exporter/classes.py +++ /dev/null @@ -1,66 +0,0 @@ -class OOTCSText: - def __init__(self): - self.textboxType = "0x0000" - self.textID = "0x0000" - self.ocarinaAction = "0x0000" - self.startFrame = 0 - self.endFrame = 1 - self.textType = "0x0000" - self.topOptionTextID = "0x0000" - self.bottomOptionTextID = "0x0000" - self.ocarinaMessageId = "0x0000" - - -class OOTCSLightSettings: - def __init__(self): - self.lightSettingsIndex = 1 - self.startFrame = 0 - - -class OOTCSTime: - def __init__(self): - self.startFrame = 0 - self.hour = 23 - self.minute = 59 - - -class OOTCSSeq: - def __init__(self): - self.csSeqID = "0x0000" - self.csSeqPlayer = "0x0000" - self.startFrame = 0 - self.endFrame = 1 - - -class OOTCSMisc: - def __init__(self): - self.csMiscType = 1 - self.startFrame = 0 - self.endFrame = 1 - - -class OOTCSRumble: - def __init__(self): - self.startFrame = 0 - self.rumbleSourceStrength = "0x00" - self.rumbleDuration = "0x00" - self.rumbleDecreaseRate = "0x00" - - -class OOTCSList: - def __init__(self): - self.listType = None - self.entries = [] - self.transitionType = "1" - self.transitionStartFrame = 0 - self.transitionEndFrame = 0 - - -class OOTCutscene: - def __init__(self): - self.name = "" - self.csEndFrame = 100 - self.csUseDestination = False - self.csDestination = 0 - self.csDestinationStartFrame = 99 - self.csLists = [] diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py deleted file mode 100644 index b16fa5bd6..000000000 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ /dev/null @@ -1,102 +0,0 @@ -from ...oot_utility import getCustomProperty -from ...oot_constants import ootData - -from .classes import ( - OOTCSList, - OOTCSText, - OOTCSLightSettings, - OOTCSTime, - OOTCSSeq, - OOTCSMisc, - OOTCSRumble, -) - - -def readCutsceneData(csParentOut, csParentIn): - for listIn in csParentIn.csLists: - listOut = OOTCSList() - listOut.listType = listIn.listType - - value = getCustomProperty(listIn, "transitionType") - listOut.transitionType, listOut.transitionStartFrame, listOut.transitionEndFrame = ( - ootData.enumData.enumByKey["csTransitionType"].itemByKey[value] if value != "Custom" else value, - listIn.transitionStartFrame, - listIn.transitionEndFrame, - ) - - listData = [] - if listOut.listType == "TextList": - for entryIn in listIn.textList: - entryOut = OOTCSText() - entryOut.textboxType = entryIn.textboxType - entryOut.textID = entryIn.textID - - value = getCustomProperty(entryIn, "ocarinaAction") - entryOut.ocarinaAction = ( - ootData.enumData.enumByKey["ocarinaSongActionId"].itemByKey[value] if value != "Custom" else value - ) - - entryOut.startFrame = entryIn.startFrame - entryOut.endFrame = entryIn.endFrame - - value = getCustomProperty(entryIn, "csTextType") - entryOut.textType = ( - ootData.enumData.enumByKey["csTextType"].itemByKey[value] if value != "Custom" else value - ) - - if entryOut.textType == "choice": - entryOut.topOptionTextID = entryIn.topOptionTextID - entryOut.bottomOptionTextID = entryIn.bottomOptionTextID - - entryOut.ocarinaMessageId = entryIn.ocarinaMessageId - listOut.entries.append(entryOut) - elif listOut.listType == "LightSettingsList": - for entryIn in listIn.lightSettingsList: - entryOut = OOTCSLightSettings() - entryOut.lightSettingsIndex = entryIn.lightSettingsIndex - entryOut.startFrame = entryIn.startFrame - listOut.entries.append(entryOut) - elif listOut.listType == "TimeList": - for entryIn in listIn.timeList: - entryOut = OOTCSTime() - entryOut.startFrame = entryIn.startFrame - entryOut.hour = entryIn.hour - entryOut.minute = entryIn.minute - listOut.entries.append(entryOut) - elif listOut.listType in {"StartSeqList", "StopSeqList", "FadeOutSeqList"}: - for entryIn in listIn.seqList: - entryOut = OOTCSSeq() - entryOut.csSeqID = getCustomProperty(entryIn, "csSeqID") - - value = getCustomProperty(entryIn, "csSeqPlayer") - entryOut.csSeqPlayer = ( - ootData.enumData.enumByKey["csFadeOutSeqPlayer"].itemByKey[value] if value != "Custom" else value - ) - - entryOut.startFrame = entryIn.startFrame - entryOut.endFrame = entryIn.endFrame - listOut.entries.append(entryOut) - elif listOut.listType == "MiscList": - for entryIn in listIn.miscList: - entryOut = OOTCSMisc() - value = getCustomProperty(entryIn, "csMiscType") - entryOut.csMiscType = ( - ootData.enumData.enumByKey["csMiscType"].itemByKey[value] if value != "Custom" else value - ) - entryOut.startFrame = entryIn.startFrame - entryOut.endFrame = entryIn.endFrame - listOut.entries.append(entryOut) - elif listOut.listType == "RumbleList": - for entryIn in listIn.rumbleList: - entryOut = OOTCSRumble() - entryOut.startFrame = entryIn.startFrame - entryOut.rumbleSourceStrength = entryIn.rumbleSourceStrength - - # the duration's unit are vertical retraces, this happens 3 times per frame - # so we're multiplying the value by 3 to get a frame unit on the UI - # to keep consistency between start frame and duration - entryOut.rumbleDuration = entryIn.rumbleDuration * 3 - - entryOut.rumbleDecreaseRate = entryIn.rumbleDecreaseRate - listOut.entries.append(entryOut) - csParentOut.csLists.append(listOut) diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index 663e08f5c..fa513df95 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -5,13 +5,13 @@ from bpy.path import abspath from bpy.ops import object from bpy.props import StringProperty, EnumProperty, IntProperty -from bpy.types import Scene, Operator, Context, UILayout +from bpy.types import Scene, Operator, Context from bpy.utils import register_class, unregister_class from ...utility import CData, PluginError, writeCData, raisePluginError from ..oot_utility import getCollection, getCutsceneName from ..oot_constants import ootData from ..scene.exporter.to_c import ootCutsceneDataToC -from .constants import ootEnumCSTextboxType, ootEnumCSListType, ootEnumCSListTypeIcons +from .constants import ootEnumCSTextboxType, ootEnumCSListType from .motion.importer import importCutsceneData from .motion.exporter import getCutsceneMotionData @@ -43,25 +43,6 @@ def ootCutsceneIncludes(headerfilename): return ret -def drawCSListAddOp(layout: UILayout, objName: str, collectionType: str): - def addButton(row): - nonlocal l - op = row.operator(OOTCSListAdd.bl_idname, text=ootEnumCSListType[l][1], icon=ootEnumCSListTypeIcons[l]) - op.collectionType = collectionType - op.listType = ootEnumCSListType[l][0] - op.objName = objName - l += 1 - - box = layout.box() - l = 0 - row = box.row(align=True) - row.label(text="Cutscene Commands") - for _ in range(3): - row = box.row(align=True) - for _ in range(3): - addButton(row) - - def insertCutsceneData(filePath: str, csName: str): """Inserts the motion data in the cutscene and returns the new data""" fileLines = [] diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index e650c577f..0b5921d46 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -366,7 +366,7 @@ def draw_props(self, layout: UILayout, obj: Object): menuBox = layout.box() menuBox.label(text="Cutscene Commands") menuBox.column_flow(columns=3, align=True).prop(self, "menuTab", expand=True) - label = f"Add New {self.menuTab.replace('List', ' List')}" + label = ootCSSubPropToName[self.menuTab] op = menuBox.operator(OOTCSListAdd.bl_idname, text=label, icon=csListTypeToIcon[self.menuTab]) op.collectionType = "Cutscene" op.listType = self.menuTab diff --git a/fast64_internal/oot/oot_level_classes.py b/fast64_internal/oot/oot_level_classes.py index 7410c6e66..2f2e2f9a5 100644 --- a/fast64_internal/oot/oot_level_classes.py +++ b/fast64_internal/oot/oot_level_classes.py @@ -114,11 +114,6 @@ def __init__(self, name, model): self.csWriteType = "Object" self.csName = "" self.csWriteCustom = "" - self.csWriteObject = None - self.csEndFrame = 100 - self.csUseDestination = False - self.csDestinationStartFrame = 99 - self.csLists = [] self.extraCutscenes = [] self.sceneTableEntry = OOTSceneTableEntry() @@ -160,9 +155,6 @@ def pathListName(self, headerIndex: int): def cameraListName(self): return self.sceneName() + "_cameraList" - def cutsceneDataName(self, headerIndex): - return self.sceneName() + "_header" + format(headerIndex, "02") + "_cutscene" - def alternateHeadersName(self): return self.sceneName() + "_alternateHeaders" diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index e60bcc0ab..a7651fd81 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -4,7 +4,6 @@ from .scene.properties import OOTSceneProperties, OOTSceneHeaderProperty, OOTAlternateSceneHeaderProperty from .room.properties import OOTRoomHeaderProperty, OOTAlternateRoomHeaderProperty from .oot_constants import ootData -from .cutscene.exporter import readCutsceneData from .oot_spline import assertCurveValid, ootConvertPath from .oot_model_classes import OOTModel from .oot_collision import OOTCameraData, exportCollisionCommon @@ -271,16 +270,9 @@ def readSceneData( if scene.writeCutscene: scene.csWriteType = getattr(sceneHeader, "csWriteType") - if scene.csWriteType == "Embedded": - scene.csEndFrame = getCustomProperty(sceneHeader, "csEndFrame") - scene.csUseDestination = getCustomProperty(sceneHeader, "csUseDestination") - scene.csDestinationStartFrame = getCustomProperty(sceneHeader, "csDestinationStartFrame") - readCutsceneData(scene, sceneHeader) - - elif scene.csWriteType == "Custom": + if scene.csWriteType == "Custom": scene.csWriteCustom = getCustomProperty(sceneHeader, "csWriteCustom") - - elif scene.csWriteType == "Object": + else: if sceneHeader.csWriteObject is None: raise PluginError("No object selected for cutscene reference") elif sceneHeader.csWriteObject.ootEmptyType != "Cutscene": diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index f08030f52..cee3ee879 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -1,10 +1,14 @@ from dataclasses import dataclass +from typing import TYPE_CHECKING from bpy.types import Object, CollectionProperty from .data import OoT_ObjectData from .oot_utility import getEvalParams -from .oot_constants import ootData, ootEnumMusicSeq +from .oot_constants import ootData from .cutscene.motion.constants import ootEnumCSMotionCamMode +if TYPE_CHECKING: + from .cutscene.properties import OOTCutsceneProperty + ##################################### # Room Header @@ -206,9 +210,7 @@ def upgradeCSListProps(csListProp): ) -def upgradeCutsceneProperty(csProp): - # ``csProp`` type: ``OOTCutsceneProperty`` - +def upgradeCutsceneProperty(csProp: "OOTCutsceneProperty"): csPropOldToNew = { "csWriteTerminator": "csUseDestination", "csTermStart": "csDestinationStartFrame", diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_commands.py b/fast64_internal/oot/scene/exporter/to_c/scene_commands.py index 7f98314a4..1082bb0ff 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_commands.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_commands.py @@ -65,8 +65,6 @@ def getLightSettingsCmd(outScene: OOTScene, headerIndex: int): def getCutsceneDataCmd(outScene: OOTScene, headerIndex: int): match outScene.csWriteType: - case "Embedded": - csDataName = outScene.cutsceneDataName(headerIndex) case "Object": csDataName = outScene.csName case _: diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 529d67ec7..6fb3d221f 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -38,9 +38,7 @@ def getSceneCutscenes(outScene: OOTScene): # curHeader is either None or an OOTScene. This can either be the main scene itself, # or one of the alternate / cutscene headers. if curHeader is not None and curHeader.writeCutscene: - if curHeader.csWriteType == "Embedded": - cutscenes.append(ootCutsceneDataToC(curHeader.cutsceneDataName(i))) - elif curHeader.csWriteType == "Object" and curHeader.csName not in csObjects: + if curHeader.csWriteType == "Object" and curHeader.csName not in csObjects: cutscenes.append(ootCutsceneDataToC(curHeader.csName)) csObjects.append(curHeader.csName) diff --git a/fast64_internal/oot/scene/properties.py b/fast64_internal/oot/scene/properties.py index fcd4dce5b..93efd282f 100644 --- a/fast64_internal/oot/scene/properties.py +++ b/fast64_internal/oot/scene/properties.py @@ -1,4 +1,4 @@ -import os, bpy +import bpy from bpy.types import PropertyGroup, Object, Light, UILayout, Scene from bpy.props import ( EnumProperty, @@ -12,8 +12,6 @@ from bpy.utils import register_class, unregister_class from ...render_settings import on_update_oot_render_settings from ...utility import prop_split, customExportWarning -from ..cutscene.properties import OOTCSListProperty -from ..cutscene.operators import drawCSListAddOp from ..cutscene.constants import ootEnumCSWriteType from ..oot_utility import ( @@ -22,7 +20,6 @@ drawCollectionOps, drawEnumWithCustom, drawAddButton, - getEnumName, ) from ..oot_constants import ( @@ -266,7 +263,7 @@ class OOTSceneHeaderProperty(PropertyGroup): exitList: CollectionProperty(type=OOTExitProperty, name="Exit List") writeCutscene: BoolProperty(name="Write Cutscene") - csWriteType: EnumProperty(name="Cutscene Data Type", items=ootEnumCSWriteType, default="Embedded") + csWriteType: EnumProperty(name="Cutscene Data Type", items=ootEnumCSWriteType, default="Object") csWriteCustom: StringProperty(name="CS hdr var:", default="") csWriteObject: PointerProperty( name="Cutscene Object", @@ -274,19 +271,8 @@ class OOTSceneHeaderProperty(PropertyGroup): poll=lambda self, object: object.type == "EMPTY" and object.ootEmptyType == "Cutscene", ) - # These properties are for the deprecated "Embedded" cutscene type. They have - # not been removed as doing so would break any existing scenes made with this - # type of cutscene data. - csEndFrame: IntProperty(name="End Frame", min=0, default=100) - csUseDestination: BoolProperty(name="Write Terminator (Code Execution)") - csDestination: IntProperty(name="Index", min=0) - csDestinationStartFrame: IntProperty(name="Start Frm", min=0, default=99) - csLists: CollectionProperty(type=OOTCSListProperty, name="Cutscene Lists") - extraCutscenes: CollectionProperty(type=OOTExtraCutsceneProperty, name="Extra Cutscenes") - sceneTableEntry: PointerProperty(type=OOTSceneTableEntryProperty) - menuTab: EnumProperty(name="Menu", items=ootEnumSceneMenu, update=onMenuTabChange) altMenuTab: EnumProperty(name="Menu", items=ootEnumSceneMenuAlternate) @@ -362,26 +348,8 @@ def draw_props(self, layout: UILayout, dropdownLabel: str, headerIndex: int, obj r.prop(self, "csWriteType", text="Data") if self.csWriteType == "Custom": cutscene.prop(self, "csWriteCustom") - elif self.csWriteType == "Object": - cutscene.prop(self, "csWriteObject") else: - # This is the GUI setup / drawing for the properties for the - # deprecated "Embedded" cutscene type. They have not been removed - # as doing so would break any existing scenes made with this type - # of cutscene data. - cutscene.label(text='Embedded cutscenes are deprecated. Please use "Object" instead.') - cutscene.prop(self, "csEndFrame", text="End Frame") - cutscene.prop(self, "csUseDestination", text="Write Terminator (Code Execution)") - if self.csUseDestination: - r = cutscene.row() - r.prop(self, "csDestination", text="Index") - r.prop(self, "csDestinationStartFrame", text="Start Frm") - collectionType = "CSHdr." + str(0 if headerIndex is None else headerIndex) - - drawCSListAddOp(cutscene, objName, collectionType) - - for i, p in enumerate(self.csLists): - p.draw_props(cutscene, i, objName, collectionType) + cutscene.prop(self, "csWriteObject") if headerIndex is None or headerIndex == 0: cutscene.label(text="Extra cutscenes (not in any header):") From c8ad752f976e4de213f3c33fd17b182b831eac56 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 00:25:10 +0200 Subject: [PATCH 27/39] fixed extra cutscenes & minor enum issue --- fast64_internal/oot/cutscene/constants.py | 4 ++-- .../oot/cutscene/motion/exporter/functions.py | 2 +- fast64_internal/oot/cutscene/operators.py | 6 +++--- fast64_internal/oot/oot_level_classes.py | 8 ++++++-- fast64_internal/oot/oot_level_writer.py | 3 +++ .../oot/scene/exporter/to_c/__init__.py | 2 +- .../oot/scene/exporter/to_c/scene_cutscene.py | 15 ++++++++------- 7 files changed, 24 insertions(+), 16 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index fd320113d..d1cd26c0c 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -11,8 +11,8 @@ } ootEnumCSWriteType = [ - ("Custom", "Custom", "Provide the name of a cutscene header variable"), - ("Object", "Object", "Reference to Blender object representing cutscene"), + ("Custom", "Custom", "Provide the name of a cutscene header variable", "", 0), + ("Object", "Object", "Reference to Blender object representing cutscene", "", 2), ] # order here sets order on the UI diff --git a/fast64_internal/oot/cutscene/motion/exporter/functions.py b/fast64_internal/oot/cutscene/motion/exporter/functions.py index 49e0a2a07..599b3120f 100644 --- a/fast64_internal/oot/cutscene/motion/exporter/functions.py +++ b/fast64_internal/oot/cutscene/motion/exporter/functions.py @@ -33,7 +33,7 @@ def getCSMotionObjects(csName: str): csMotionObjects["camShot"].append(obj) if len(csMotionObjects["Cutscene"]) != 1: - raise PluginError("ERROR: No cutscene found or several cutscenes in the object list!") + raise PluginError(f"ERROR: Expected 1 Cutscene Object, found {len(csMotionObjects['Cutscene'])} ({csName}).") return csMotionObjects diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index fa513df95..9ed87a2fd 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -10,7 +10,7 @@ from ...utility import CData, PluginError, writeCData, raisePluginError from ..oot_utility import getCollection, getCutsceneName from ..oot_constants import ootData -from ..scene.exporter.to_c import ootCutsceneDataToC +from ..scene.exporter.to_c import getCutsceneC from .constants import ootEnumCSTextboxType, ootEnumCSListType from .motion.importer import importCutsceneData from .motion.exporter import getCutsceneMotionData @@ -183,7 +183,7 @@ def execute(self, context): if context.scene.exportMotionOnly: csdata.append(insertCutsceneData(cpath, activeObj.name.removeprefix("Cutscene."))) else: - csdata.append(ootCutsceneDataToC(getCutsceneName(activeObj))) + csdata.append(getCutsceneC(getCutsceneName(activeObj))) writeCData(csdata, hpath, cpath) self.report({"INFO"}, "Successfully exported cutscene") @@ -216,7 +216,7 @@ def execute(self, context): if context.scene.exportMotionOnly: raise PluginError("ERROR: Not implemented yet.") else: - csdata.append(ootCutsceneDataToC(getCutsceneName(obj))) + csdata.append(getCutsceneC(getCutsceneName(obj))) count += 1 if count == 0: diff --git a/fast64_internal/oot/oot_level_classes.py b/fast64_internal/oot/oot_level_classes.py index 2f2e2f9a5..399ce8676 100644 --- a/fast64_internal/oot/oot_level_classes.py +++ b/fast64_internal/oot/oot_level_classes.py @@ -1,5 +1,9 @@ -import bpy, os, shutil +import bpy +import os +import shutil + from typing import Optional +from bpy.types import Object from ..utility import PluginError, toAlnum, indent from .oot_collision_classes import OOTCollision from .oot_model_classes import OOTModel @@ -114,7 +118,7 @@ def __init__(self, name, model): self.csWriteType = "Object" self.csName = "" self.csWriteCustom = "" - self.extraCutscenes = [] + self.extraCutscenes: list[Object] = [] self.sceneTableEntry = OOTSceneTableEntry() diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index a7651fd81..822da03cc 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -302,6 +302,9 @@ def readSceneData( cutsceneHeader = scene.getAlternateHeaderScene(scene.name) readSceneData(cutsceneHeader, scene_properties, cutsceneHeaderProp, None) scene.cutsceneHeaders.append(cutsceneHeader) + + for extraCS in sceneHeader.extraCutscenes: + scene.extraCutscenes.append(extraCS.csObject) else: if len(sceneHeader.extraCutscenes) > 0: raise PluginError( diff --git a/fast64_internal/oot/scene/exporter/to_c/__init__.py b/fast64_internal/oot/scene/exporter/to_c/__init__.py index e9f7106ad..61a8fed1f 100644 --- a/fast64_internal/oot/scene/exporter/to_c/__init__.py +++ b/fast64_internal/oot/scene/exporter/to_c/__init__.py @@ -3,4 +3,4 @@ from .spec import editSpecFile from .scene_folder import modifySceneFiles, deleteSceneFiles from .scene_bootup import setBootupScene, clearBootupScene -from .scene_cutscene import ootCutsceneDataToC +from .scene_cutscene import getCutsceneC diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 6fb3d221f..2526b17aa 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -5,7 +5,7 @@ from ....cutscene.motion.exporter import getCutsceneMotionData -def ootCutsceneDataToC(csName: str): +def getCutsceneC(csName: str): csData = CData() declarationBase = f"CutsceneData {csName}[]" @@ -34,17 +34,18 @@ def getSceneCutscenes(outScene: OOTScene): altHeaders.extend(outScene.cutsceneHeaders) csObjects = [] - for i, curHeader in enumerate(altHeaders): + for curHeader in altHeaders: # curHeader is either None or an OOTScene. This can either be the main scene itself, # or one of the alternate / cutscene headers. if curHeader is not None and curHeader.writeCutscene: if curHeader.csWriteType == "Object" and curHeader.csName not in csObjects: - cutscenes.append(ootCutsceneDataToC(curHeader.csName)) + cutscenes.append(getCutsceneC(curHeader.csName)) csObjects.append(curHeader.csName) - for extraCs in outScene.extraCutscenes: - if not extraCs.name in csObjects: - cutscenes.append(ootCutsceneDataToC(extraCs.name)) - csObjects.append(extraCs.name) + for csObj in outScene.extraCutscenes: + name = csObj.name.removeprefix("Cutscene.") + if not name in csObjects: + cutscenes.append(getCutsceneC(name)) + csObjects.append(name) return cutscenes From 1c8b678ff16be872ebb518d0f43e340f31e08748 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 01:59:11 +0200 Subject: [PATCH 28/39] move exporter/importer outside motion folder --- fast64_internal/oot/cutscene/constants.py | 167 ++++++++++++++++++ .../{motion => }/exporter/__init__.py | 0 .../cutscene/{motion => }/exporter/classes.py | 8 +- .../{motion => }/exporter/functions.py | 2 +- .../{motion => }/importer/__init__.py | 0 .../cutscene/{motion => }/importer/classes.py | 8 +- .../{motion => }/importer/functions.py | 0 .../oot/cutscene/{motion => }/io_classes.py | 4 +- .../oot/cutscene/motion/constants.py | 165 ----------------- .../oot/cutscene/motion/operators.py | 4 +- .../oot/cutscene/motion/properties.py | 2 +- .../oot/cutscene/motion/utility.py | 6 +- fast64_internal/oot/cutscene/operators.py | 4 +- fast64_internal/oot/oot_level_parser.py | 2 +- fast64_internal/oot/oot_upgrade.py | 2 +- .../oot/scene/exporter/to_c/scene_cutscene.py | 2 +- 16 files changed, 189 insertions(+), 187 deletions(-) rename fast64_internal/oot/cutscene/{motion => }/exporter/__init__.py (100%) rename fast64_internal/oot/cutscene/{motion => }/exporter/classes.py (98%) rename fast64_internal/oot/cutscene/{motion => }/exporter/functions.py (97%) rename fast64_internal/oot/cutscene/{motion => }/importer/__init__.py (100%) rename fast64_internal/oot/cutscene/{motion => }/importer/classes.py (99%) rename fast64_internal/oot/cutscene/{motion => }/importer/functions.py (100%) rename fast64_internal/oot/cutscene/{motion => }/io_classes.py (99%) delete mode 100644 fast64_internal/oot/cutscene/motion/constants.py diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index d1cd26c0c..28fda5db0 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -1,3 +1,35 @@ +from ..oot_constants import ootData +from .io_classes import ( + OOTCSMotionActorCueList, + OOTCSMotionActorCue, + OOTCSMotionCamEyeSpline, + OOTCSMotionCamATSpline, + OOTCSMotionCamEyeSplineRelToPlayer, + OOTCSMotionCamATSplineRelToPlayer, + OOTCSMotionCamEye, + OOTCSMotionCamAT, + OOTCSMotionCamPoint, + OOTCSMotionMisc, + OOTCSMotionMiscList, + OOTCSMotionTransition, + OOTCSMotionText, + OOTCSMotionTextNone, + OOTCSMotionTextOcarinaAction, + OOTCSMotionTextList, + OOTCSMotionLightSetting, + OOTCSMotionLightSettingList, + OOTCSMotionTime, + OOTCSMotionTimeList, + OOTCSMotionStartStopSeq, + OOTCSMotionStartStopSeqList, + OOTCSMotionFadeSeq, + OOTCSMotionFadeSeqList, + OOTCSMotionRumbleController, + OOTCSMotionRumbleControllerList, + OOTCSMotionDestination, +) + + ootEnumCSListTypeListC = { "TextList": "CS_TEXT_LIST", "Transition": "CS_TRANSITION", @@ -83,3 +115,138 @@ "StopSeqList": "Stop Seq Lis", "RumbleList": "Rumble List", } + +ootEnumCSMotionCamMode = [ + ("splineEyeOrAT", "Eye/AT Spline", "Eye/AT Spline"), + ("splineEyeOrATRelPlayer", "Spline Rel. Player", "Relative to Player's location/yaw"), + ("eyeOrAT", "Eye/AT Point", "Single Eye/AT point (not recommended)"), +] + +ootEnumCSActorCueListCommandType = [ + item for item in ootData.enumData.ootEnumCsCmd if "actor_cue" in item[0] or "player_cue" in item[0] +] +ootEnumCSActorCueListCommandType.sort() +ootEnumCSActorCueListCommandType.insert(0, ("Custom", "Custom", "Custom")) + +ootCSMotionLegacyToNewCmdNames = { + "CS_CAM_POS_LIST": "CS_CAM_EYE_SPLINE", + "CS_CAM_FOCUS_POINT_LIST": "CS_CAM_AT_SPLINE", + "CS_CAM_POS_PLAYER_LIST": "CS_CAM_EYE_SPLINE_REL_TO_PLAYER", + "CS_CAM_FOCUS_POINT_PLAYER_LIST": "CS_CAM_AT_SPLINE_REL_TO_PLAYER", + "CS_NPC_ACTION_LIST": "CS_ACTOR_CUE_LIST", + "CS_PLAYER_ACTION_LIST": "CS_PLAYER_CUE_LIST", + "CS_CMD_07": "CS_CAM_EYE", + "CS_CMD_08": "CS_CAM_AT", + "CS_CAM_POS": "CS_CAM_POINT", + "CS_CAM_FOCUS_POINT": "CS_CAM_POINT", + "CS_CAM_POS_PLAYER": "CS_CAM_POINT", + "CS_CAM_FOCUS_POINT_PLAYER": "CS_CAM_POINT", + "CS_NPC_ACTION": "CS_ACTOR_CUE", + "CS_PLAYER_ACTION": "CS_PLAYER_CUE", + "CS_CMD_09_LIST": "CS_RUMBLE_CONTROLLER_LIST", + "CS_CMD_09": "CS_RUMBLE_CONTROLLER", + "CS_TEXT_DISPLAY_TEXTBOX": "CS_TEXT", + "CS_TEXT_LEARN_SONG": "CS_TEXT_OCARINA_ACTION", + "CS_SCENE_TRANS_FX": "CS_TRANSITION", + "CS_FADE_BGM_LIST": "CS_FADE_OUT_SEQ_LIST", + "CS_FADE_BGM": "CS_FADE_OUT_SEQ", + "CS_TERMINATOR": "CS_DESTINATION", + "CS_LIGHTING_LIST": "CS_LIGHT_SETTING_LIST", + "CS_LIGHTING": "L_CS_LIGHT_SETTING", + "CS_PLAY_BGM_LIST": "CS_START_SEQ_LIST", + "CS_PLAY_BGM": "L_CS_START_SEQ", + "CS_STOP_BGM_LIST": "CS_STOP_SEQ_LIST", + "CS_STOP_BGM": "L_CS_STOP_SEQ", +} + +ootCSMotionListCommands = [ + "CS_ACTOR_CUE_LIST", + "CS_PLAYER_CUE_LIST", + "CS_CAM_EYE_SPLINE", + "CS_CAM_AT_SPLINE", + "CS_CAM_EYE_SPLINE_REL_TO_PLAYER", + "CS_CAM_AT_SPLINE_REL_TO_PLAYER", + "CS_CAM_EYE", + "CS_CAM_AT", + "CS_MISC_LIST", + "CS_LIGHT_SETTING_LIST", + "CS_RUMBLE_CONTROLLER_LIST", + "CS_TEXT_LIST", + "CS_START_SEQ_LIST", + "CS_STOP_SEQ_LIST", + "CS_FADE_OUT_SEQ_LIST", + "CS_TIME_LIST", + "CS_UNK_DATA_LIST", + "CS_PLAY_BGM_LIST", + "CS_STOP_BGM_LIST", + "CS_LIGHTING_LIST", +] + +ootCSMotionListEntryCommands = [ + "CS_ACTOR_CUE", + "CS_PLAYER_CUE", + "CS_CAM_POINT", + "CS_MISC", + "CS_LIGHT_SETTING", + "CS_RUMBLE_CONTROLLER", + "CS_TEXT", + "CS_TEXT_NONE", + "CS_TEXT_OCARINA_ACTION", + "CS_START_SEQ", + "CS_STOP_SEQ", + "CS_FADE_OUT_SEQ", + "CS_TIME", + "CS_UNK_DATA", + "CS_PLAY_BGM", + "CS_STOP_BGM", + "CS_LIGHTING", + # some old commands need to remove 1 to the first argument to stay accurate + "L_CS_LIGHT_SETTING", + "L_CS_START_SEQ", + "L_CS_STOP_SEQ", +] + +ootCSMotionSingleCommands = [ + "CS_BEGIN_CUTSCENE", + "CS_END", + "CS_TRANSITION", + "CS_DESTINATION", +] + +ootCSMotionListAndSingleCommands = ootCSMotionSingleCommands + ootCSMotionListCommands +ootCSMotionListAndSingleCommands.remove("CS_BEGIN_CUTSCENE") +ootCSMotionCSCommands = ootCSMotionSingleCommands + ootCSMotionListCommands + ootCSMotionListEntryCommands + +cmdToClass = { + "CS_CAM_POINT": OOTCSMotionCamPoint, + "CS_MISC": OOTCSMotionMisc, + "CS_LIGHT_SETTING": OOTCSMotionLightSetting, + "CS_TIME": OOTCSMotionTime, + "CS_FADE_OUT_SEQ": OOTCSMotionFadeSeq, + "CS_RUMBLE_CONTROLLER": OOTCSMotionRumbleController, + "CS_TEXT": OOTCSMotionText, + "CS_TEXT_NONE": OOTCSMotionTextNone, + "CS_TEXT_OCARINA_ACTION": OOTCSMotionTextOcarinaAction, + "CS_START_SEQ": OOTCSMotionStartStopSeq, + "CS_STOP_SEQ": OOTCSMotionStartStopSeq, + "CS_ACTOR_CUE": OOTCSMotionActorCue, + "CS_PLAYER_CUE": OOTCSMotionActorCue, + "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, + "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, + "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, + "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, + "CS_CAM_EYE": OOTCSMotionCamEye, + "CS_CAM_AT": OOTCSMotionCamAT, + "CS_MISC_LIST": OOTCSMotionMiscList, + "CS_TRANSITION": OOTCSMotionTransition, + "CS_TEXT_LIST": OOTCSMotionTextList, + "CS_LIGHT_SETTING_LIST": OOTCSMotionLightSettingList, + "CS_TIME_LIST": OOTCSMotionTimeList, + "CS_FADE_OUT_SEQ_LIST": OOTCSMotionFadeSeqList, + "CS_RUMBLE_CONTROLLER_LIST": OOTCSMotionRumbleControllerList, + "CS_START_SEQ_LIST": OOTCSMotionStartStopSeqList, + "CS_STOP_SEQ_LIST": OOTCSMotionStartStopSeqList, + "CS_ACTOR_CUE_LIST": OOTCSMotionActorCueList, + "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, + "CS_DESTINATION": OOTCSMotionDestination, +} diff --git a/fast64_internal/oot/cutscene/motion/exporter/__init__.py b/fast64_internal/oot/cutscene/exporter/__init__.py similarity index 100% rename from fast64_internal/oot/cutscene/motion/exporter/__init__.py rename to fast64_internal/oot/cutscene/exporter/__init__.py diff --git a/fast64_internal/oot/cutscene/motion/exporter/classes.py b/fast64_internal/oot/cutscene/exporter/classes.py similarity index 98% rename from fast64_internal/oot/cutscene/motion/exporter/classes.py rename to fast64_internal/oot/cutscene/exporter/classes.py index 4436f53ed..8af3d46db 100644 --- a/fast64_internal/oot/cutscene/motion/exporter/classes.py +++ b/fast64_internal/oot/cutscene/exporter/classes.py @@ -4,12 +4,12 @@ from dataclasses import dataclass from typing import TYPE_CHECKING from bpy.types import Object -from .....utility import PluginError, indent -from ....oot_constants import ootData -from ...constants import ootEnumCSListTypeListC +from ....utility import PluginError, indent +from ...oot_constants import ootData +from ..constants import ootEnumCSListTypeListC if TYPE_CHECKING: - from ...properties import OOTCutsceneProperty, OOTCSTextProperty + from ..properties import OOTCutsceneProperty, OOTCSTextProperty from ..io_classes import ( OOTCSMotionTransition, diff --git a/fast64_internal/oot/cutscene/motion/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py similarity index 97% rename from fast64_internal/oot/cutscene/motion/exporter/functions.py rename to fast64_internal/oot/cutscene/exporter/functions.py index 599b3120f..a3630adde 100644 --- a/fast64_internal/oot/cutscene/motion/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -1,7 +1,7 @@ import bpy from bpy.types import Object -from .....utility import PluginError +from ....utility import PluginError from .classes import OOTCSMotionExport diff --git a/fast64_internal/oot/cutscene/motion/importer/__init__.py b/fast64_internal/oot/cutscene/importer/__init__.py similarity index 100% rename from fast64_internal/oot/cutscene/motion/importer/__init__.py rename to fast64_internal/oot/cutscene/importer/__init__.py diff --git a/fast64_internal/oot/cutscene/motion/importer/classes.py b/fast64_internal/oot/cutscene/importer/classes.py similarity index 99% rename from fast64_internal/oot/cutscene/motion/importer/classes.py rename to fast64_internal/oot/cutscene/importer/classes.py index 2cb9279ed..03e22f254 100644 --- a/fast64_internal/oot/cutscene/motion/importer/classes.py +++ b/fast64_internal/oot/cutscene/importer/classes.py @@ -3,12 +3,11 @@ from dataclasses import dataclass from typing import TYPE_CHECKING from bpy.types import Object, Armature -from .....utility import PluginError -from ..utility import setupCutscene, getBlenderPosition, getInteger -from ..constants import cmdToClass +from ....utility import PluginError +from ..motion.utility import setupCutscene, getBlenderPosition, getInteger if TYPE_CHECKING: - from ...properties import OOTCSListProperty, OOTCutsceneProperty + from ..properties import OOTCSListProperty, OOTCutsceneProperty from ..constants import ( ootCSMotionLegacyToNewCmdNames, @@ -17,6 +16,7 @@ ootCSMotionListEntryCommands, ootCSMotionSingleCommands, ootCSMotionListAndSingleCommands, + cmdToClass, ) from ..io_classes import ( diff --git a/fast64_internal/oot/cutscene/motion/importer/functions.py b/fast64_internal/oot/cutscene/importer/functions.py similarity index 100% rename from fast64_internal/oot/cutscene/motion/importer/functions.py rename to fast64_internal/oot/cutscene/importer/functions.py diff --git a/fast64_internal/oot/cutscene/motion/io_classes.py b/fast64_internal/oot/cutscene/io_classes.py similarity index 99% rename from fast64_internal/oot/cutscene/motion/io_classes.py rename to fast64_internal/oot/cutscene/io_classes.py index 56e8aa62e..ae625895a 100644 --- a/fast64_internal/oot/cutscene/motion/io_classes.py +++ b/fast64_internal/oot/cutscene/io_classes.py @@ -2,8 +2,8 @@ from dataclasses import dataclass, field from bpy.types import Object -from ...oot_constants import ootData -from .utility import getBlenderPosition, getBlenderRotation, getRotation, getInteger +from ..oot_constants import ootData +from .motion.utility import getBlenderPosition, getBlenderRotation, getRotation, getInteger # NOTE: ``paramNumber`` is the expected number of parameters inside the parsed commands, diff --git a/fast64_internal/oot/cutscene/motion/constants.py b/fast64_internal/oot/cutscene/motion/constants.py deleted file mode 100644 index d7edfa170..000000000 --- a/fast64_internal/oot/cutscene/motion/constants.py +++ /dev/null @@ -1,165 +0,0 @@ -from ...oot_constants import ootData -from .io_classes import ( - OOTCSMotionActorCueList, - OOTCSMotionActorCue, - OOTCSMotionCamEyeSpline, - OOTCSMotionCamATSpline, - OOTCSMotionCamEyeSplineRelToPlayer, - OOTCSMotionCamATSplineRelToPlayer, - OOTCSMotionCamEye, - OOTCSMotionCamAT, - OOTCSMotionCamPoint, - OOTCSMotionMisc, - OOTCSMotionMiscList, - OOTCSMotionTransition, - OOTCSMotionText, - OOTCSMotionTextNone, - OOTCSMotionTextOcarinaAction, - OOTCSMotionTextList, - OOTCSMotionLightSetting, - OOTCSMotionLightSettingList, - OOTCSMotionTime, - OOTCSMotionTimeList, - OOTCSMotionStartStopSeq, - OOTCSMotionStartStopSeqList, - OOTCSMotionFadeSeq, - OOTCSMotionFadeSeqList, - OOTCSMotionRumbleController, - OOTCSMotionRumbleControllerList, - OOTCSMotionDestination, -) - -ootEnumCSMotionCamMode = [ - ("splineEyeOrAT", "Eye/AT Spline", "Eye/AT Spline"), - ("splineEyeOrATRelPlayer", "Spline Rel. Player", "Relative to Player's location/yaw"), - ("eyeOrAT", "Eye/AT Point", "Single Eye/AT point (not recommended)"), -] - -ootEnumCSActorCueListCommandType = [ - item for item in ootData.enumData.ootEnumCsCmd if "actor_cue" in item[0] or "player_cue" in item[0] -] -ootEnumCSActorCueListCommandType.sort() -ootEnumCSActorCueListCommandType.insert(0, ("Custom", "Custom", "Custom")) - -ootCSMotionLegacyToNewCmdNames = { - "CS_CAM_POS_LIST": "CS_CAM_EYE_SPLINE", - "CS_CAM_FOCUS_POINT_LIST": "CS_CAM_AT_SPLINE", - "CS_CAM_POS_PLAYER_LIST": "CS_CAM_EYE_SPLINE_REL_TO_PLAYER", - "CS_CAM_FOCUS_POINT_PLAYER_LIST": "CS_CAM_AT_SPLINE_REL_TO_PLAYER", - "CS_NPC_ACTION_LIST": "CS_ACTOR_CUE_LIST", - "CS_PLAYER_ACTION_LIST": "CS_PLAYER_CUE_LIST", - "CS_CMD_07": "CS_CAM_EYE", - "CS_CMD_08": "CS_CAM_AT", - "CS_CAM_POS": "CS_CAM_POINT", - "CS_CAM_FOCUS_POINT": "CS_CAM_POINT", - "CS_CAM_POS_PLAYER": "CS_CAM_POINT", - "CS_CAM_FOCUS_POINT_PLAYER": "CS_CAM_POINT", - "CS_NPC_ACTION": "CS_ACTOR_CUE", - "CS_PLAYER_ACTION": "CS_PLAYER_CUE", - "CS_CMD_09_LIST": "CS_RUMBLE_CONTROLLER_LIST", - "CS_CMD_09": "CS_RUMBLE_CONTROLLER", - "CS_TEXT_DISPLAY_TEXTBOX": "CS_TEXT", - "CS_TEXT_LEARN_SONG": "CS_TEXT_OCARINA_ACTION", - "CS_SCENE_TRANS_FX": "CS_TRANSITION", - "CS_FADE_BGM_LIST": "CS_FADE_OUT_SEQ_LIST", - "CS_FADE_BGM": "CS_FADE_OUT_SEQ", - "CS_TERMINATOR": "CS_DESTINATION", - "CS_LIGHTING_LIST": "CS_LIGHT_SETTING_LIST", - "CS_LIGHTING": "L_CS_LIGHT_SETTING", - "CS_PLAY_BGM_LIST": "CS_START_SEQ_LIST", - "CS_PLAY_BGM": "L_CS_START_SEQ", - "CS_STOP_BGM_LIST": "CS_STOP_SEQ_LIST", - "CS_STOP_BGM": "L_CS_STOP_SEQ", -} - -ootCSMotionListCommands = [ - "CS_ACTOR_CUE_LIST", - "CS_PLAYER_CUE_LIST", - "CS_CAM_EYE_SPLINE", - "CS_CAM_AT_SPLINE", - "CS_CAM_EYE_SPLINE_REL_TO_PLAYER", - "CS_CAM_AT_SPLINE_REL_TO_PLAYER", - "CS_CAM_EYE", - "CS_CAM_AT", - "CS_MISC_LIST", - "CS_LIGHT_SETTING_LIST", - "CS_RUMBLE_CONTROLLER_LIST", - "CS_TEXT_LIST", - "CS_START_SEQ_LIST", - "CS_STOP_SEQ_LIST", - "CS_FADE_OUT_SEQ_LIST", - "CS_TIME_LIST", - "CS_UNK_DATA_LIST", - "CS_PLAY_BGM_LIST", - "CS_STOP_BGM_LIST", - "CS_LIGHTING_LIST", -] - -ootCSMotionListEntryCommands = [ - "CS_ACTOR_CUE", - "CS_PLAYER_CUE", - "CS_CAM_POINT", - "CS_MISC", - "CS_LIGHT_SETTING", - "CS_RUMBLE_CONTROLLER", - "CS_TEXT", - "CS_TEXT_NONE", - "CS_TEXT_OCARINA_ACTION", - "CS_START_SEQ", - "CS_STOP_SEQ", - "CS_FADE_OUT_SEQ", - "CS_TIME", - "CS_UNK_DATA", - "CS_PLAY_BGM", - "CS_STOP_BGM", - "CS_LIGHTING", - # some old commands need to remove 1 to the first argument to stay accurate - "L_CS_LIGHT_SETTING", - "L_CS_START_SEQ", - "L_CS_STOP_SEQ", -] - -ootCSMotionSingleCommands = [ - "CS_BEGIN_CUTSCENE", - "CS_END", - "CS_TRANSITION", - "CS_DESTINATION", -] - -ootCSMotionListAndSingleCommands = ootCSMotionSingleCommands + ootCSMotionListCommands -ootCSMotionListAndSingleCommands.remove("CS_BEGIN_CUTSCENE") -ootCSMotionCSCommands = ootCSMotionSingleCommands + ootCSMotionListCommands + ootCSMotionListEntryCommands - -cmdToClass = { - "CS_CAM_POINT": OOTCSMotionCamPoint, - "CS_MISC": OOTCSMotionMisc, - "CS_LIGHT_SETTING": OOTCSMotionLightSetting, - "CS_TIME": OOTCSMotionTime, - "CS_FADE_OUT_SEQ": OOTCSMotionFadeSeq, - "CS_RUMBLE_CONTROLLER": OOTCSMotionRumbleController, - "CS_TEXT": OOTCSMotionText, - "CS_TEXT_NONE": OOTCSMotionTextNone, - "CS_TEXT_OCARINA_ACTION": OOTCSMotionTextOcarinaAction, - "CS_START_SEQ": OOTCSMotionStartStopSeq, - "CS_STOP_SEQ": OOTCSMotionStartStopSeq, - "CS_ACTOR_CUE": OOTCSMotionActorCue, - "CS_PLAYER_CUE": OOTCSMotionActorCue, - "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, - "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, - "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, - "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, - "CS_CAM_EYE": OOTCSMotionCamEye, - "CS_CAM_AT": OOTCSMotionCamAT, - "CS_MISC_LIST": OOTCSMotionMiscList, - "CS_TRANSITION": OOTCSMotionTransition, - "CS_TEXT_LIST": OOTCSMotionTextList, - "CS_LIGHT_SETTING_LIST": OOTCSMotionLightSettingList, - "CS_TIME_LIST": OOTCSMotionTimeList, - "CS_FADE_OUT_SEQ_LIST": OOTCSMotionFadeSeqList, - "CS_RUMBLE_CONTROLLER_LIST": OOTCSMotionRumbleControllerList, - "CS_START_SEQ_LIST": OOTCSMotionStartStopSeqList, - "CS_STOP_SEQ_LIST": OOTCSMotionStartStopSeqList, - "CS_ACTOR_CUE_LIST": OOTCSMotionActorCueList, - "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, - "CS_DESTINATION": OOTCSMotionDestination, -} diff --git a/fast64_internal/oot/cutscene/motion/operators.py b/fast64_internal/oot/cutscene/motion/operators.py index f6d3e987c..827f74857 100644 --- a/fast64_internal/oot/cutscene/motion/operators.py +++ b/fast64_internal/oot/cutscene/motion/operators.py @@ -5,8 +5,8 @@ from bpy.props import StringProperty, EnumProperty, BoolProperty from ....utility import PluginError from ...oot_constants import ootData -from .io_classes import OOTCSMotionObjectFactory -from .constants import ootEnumCSActorCueListCommandType +from ..io_classes import OOTCSMotionObjectFactory +from ..constants import ootEnumCSActorCueListCommandType from ..preview import initFirstFrame, setupCompositorNodes from .utility import ( setupActorCuePreview, diff --git a/fast64_internal/oot/cutscene/motion/properties.py b/fast64_internal/oot/cutscene/motion/properties.py index 0138cdafd..f06b29859 100644 --- a/fast64_internal/oot/cutscene/motion/properties.py +++ b/fast64_internal/oot/cutscene/motion/properties.py @@ -6,7 +6,7 @@ from ...oot_upgrade import upgradeCutsceneMotion from ...oot_utility import getEnumName from ...oot_constants import ootData -from .constants import ootEnumCSMotionCamMode, ootEnumCSActorCueListCommandType +from ..constants import ootEnumCSMotionCamMode, ootEnumCSActorCueListCommandType from .operators import ( OOTCSMotionAddActorCue, diff --git a/fast64_internal/oot/cutscene/motion/utility.py b/fast64_internal/oot/cutscene/motion/utility.py index c21baa0bc..8a768f704 100644 --- a/fast64_internal/oot/cutscene/motion/utility.py +++ b/fast64_internal/oot/cutscene/motion/utility.py @@ -57,7 +57,7 @@ def createNewBone(cameraShotObj: Object, name: str, headPos: list[float], tailPo def createNewCameraShot(csObj: Object): - from .io_classes import OOTCSMotionObjectFactory # circular import fix + from ..io_classes import OOTCSMotionObjectFactory # circular import fix index, csPrefix = getNameInformations(csObj, "Camera Shot", None) @@ -180,7 +180,7 @@ def metersToBlend(context: Context, value: float): def setupActorCuePreview(csObj: Object, actorOrPlayer: str, selectObject: bool, cueList: Object): - from .io_classes import OOTCSMotionObjectFactory # circular import fix + from ..io_classes import OOTCSMotionObjectFactory # circular import fix # check if the cue actually moves, if not it's not necessary to create a preview object isCueMoving = False @@ -258,7 +258,7 @@ def getCutsceneEndFrame(csObj: Object): def setupCutscene(csObj: Object): - from .io_classes import OOTCSMotionObjectFactory # circular import fix + from ..io_classes import OOTCSMotionObjectFactory # circular import fix objFactory = OOTCSMotionObjectFactory() context = bpy.context diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index 9ed87a2fd..ff3e6a615 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -12,8 +12,8 @@ from ..oot_constants import ootData from ..scene.exporter.to_c import getCutsceneC from .constants import ootEnumCSTextboxType, ootEnumCSListType -from .motion.importer import importCutsceneData -from .motion.exporter import getCutsceneMotionData +from .importer import importCutsceneData +from .exporter import getCutsceneMotionData def checkGetFilePaths(context: Context): diff --git a/fast64_internal/oot/oot_level_parser.py b/fast64_internal/oot/oot_level_parser.py index 51857ec66..cfbcb8958 100644 --- a/fast64_internal/oot/oot_level_parser.py +++ b/fast64_internal/oot/oot_level_parser.py @@ -12,7 +12,7 @@ from .scene.properties import OOTSceneHeaderProperty, OOTLightProperty, OOTImportSceneSettingsProperty from .room.properties import OOTRoomHeaderProperty from .actor.properties import OOTActorProperty, OOTActorHeaderProperty -from .cutscene.motion.importer import importCutsceneData +from .cutscene.importer import importCutsceneData from .oot_utility import ( getHeaderSettings, diff --git a/fast64_internal/oot/oot_upgrade.py b/fast64_internal/oot/oot_upgrade.py index cee3ee879..f5ed62064 100644 --- a/fast64_internal/oot/oot_upgrade.py +++ b/fast64_internal/oot/oot_upgrade.py @@ -4,7 +4,7 @@ from .data import OoT_ObjectData from .oot_utility import getEvalParams from .oot_constants import ootData -from .cutscene.motion.constants import ootEnumCSMotionCamMode +from .cutscene.constants import ootEnumCSMotionCamMode if TYPE_CHECKING: from .cutscene.properties import OOTCutsceneProperty diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 2526b17aa..2a49edd0b 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -2,7 +2,7 @@ from .....utility import CData from ....oot_level_classes import OOTScene -from ....cutscene.motion.exporter import getCutsceneMotionData +from ....cutscene.exporter import getCutsceneMotionData def getCutsceneC(csName: str): From 7ab85ee63f0b24554dab2c6169808774d03bcb73 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 02:03:00 +0200 Subject: [PATCH 29/39] OOTCSMotion -> CutsceneCmd --- fast64_internal/oot/cutscene/constants.py | 116 ++++++++--------- .../oot/cutscene/exporter/classes.py | 106 +++++++-------- .../oot/cutscene/exporter/functions.py | 4 +- .../oot/cutscene/importer/classes.py | 26 ++-- .../oot/cutscene/importer/functions.py | 4 +- fast64_internal/oot/cutscene/io_classes.py | 122 +++++++++--------- .../oot/cutscene/motion/operators.py | 34 ++--- fast64_internal/oot/cutscene/motion/panels.py | 6 +- .../oot/cutscene/motion/properties.py | 40 +++--- .../oot/cutscene/motion/utility.py | 12 +- fast64_internal/oot/cutscene/properties.py | 16 +-- fast64_internal/oot/props_panel_main.py | 8 +- 12 files changed, 247 insertions(+), 247 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 28fda5db0..0672532e8 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -1,32 +1,32 @@ from ..oot_constants import ootData from .io_classes import ( - OOTCSMotionActorCueList, - OOTCSMotionActorCue, - OOTCSMotionCamEyeSpline, - OOTCSMotionCamATSpline, - OOTCSMotionCamEyeSplineRelToPlayer, - OOTCSMotionCamATSplineRelToPlayer, - OOTCSMotionCamEye, - OOTCSMotionCamAT, - OOTCSMotionCamPoint, - OOTCSMotionMisc, - OOTCSMotionMiscList, - OOTCSMotionTransition, - OOTCSMotionText, - OOTCSMotionTextNone, - OOTCSMotionTextOcarinaAction, - OOTCSMotionTextList, - OOTCSMotionLightSetting, - OOTCSMotionLightSettingList, - OOTCSMotionTime, - OOTCSMotionTimeList, - OOTCSMotionStartStopSeq, - OOTCSMotionStartStopSeqList, - OOTCSMotionFadeSeq, - OOTCSMotionFadeSeqList, - OOTCSMotionRumbleController, - OOTCSMotionRumbleControllerList, - OOTCSMotionDestination, + CutsceneCmdActorCueList, + CutsceneCmdActorCue, + CutsceneCmdCamEyeSpline, + CutsceneCmdCamATSpline, + CutsceneCmdCamEyeSplineRelToPlayer, + CutsceneCmdCamATSplineRelToPlayer, + CutsceneCmdCamEye, + CutsceneCmdCamAT, + CutsceneCmdCamPoint, + CutsceneCmdMisc, + CutsceneCmdMiscList, + CutsceneCmdTransition, + CutsceneCmdText, + CutsceneCmdTextNone, + CutsceneCmdTextOcarinaAction, + CutsceneCmdTextList, + CutsceneCmdLightSetting, + CutsceneCmdLightSettingList, + CutsceneCmdTime, + CutsceneCmdTimeList, + CutsceneCmdStartStopSeq, + CutsceneCmdStartStopSeqList, + CutsceneCmdFadeSeq, + CutsceneCmdFadeSeqList, + CutsceneCmdRumbleController, + CutsceneCmdRumbleControllerList, + CutsceneCmdDestination, ) @@ -218,35 +218,35 @@ ootCSMotionCSCommands = ootCSMotionSingleCommands + ootCSMotionListCommands + ootCSMotionListEntryCommands cmdToClass = { - "CS_CAM_POINT": OOTCSMotionCamPoint, - "CS_MISC": OOTCSMotionMisc, - "CS_LIGHT_SETTING": OOTCSMotionLightSetting, - "CS_TIME": OOTCSMotionTime, - "CS_FADE_OUT_SEQ": OOTCSMotionFadeSeq, - "CS_RUMBLE_CONTROLLER": OOTCSMotionRumbleController, - "CS_TEXT": OOTCSMotionText, - "CS_TEXT_NONE": OOTCSMotionTextNone, - "CS_TEXT_OCARINA_ACTION": OOTCSMotionTextOcarinaAction, - "CS_START_SEQ": OOTCSMotionStartStopSeq, - "CS_STOP_SEQ": OOTCSMotionStartStopSeq, - "CS_ACTOR_CUE": OOTCSMotionActorCue, - "CS_PLAYER_CUE": OOTCSMotionActorCue, - "CS_CAM_EYE_SPLINE": OOTCSMotionCamEyeSpline, - "CS_CAM_AT_SPLINE": OOTCSMotionCamATSpline, - "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": OOTCSMotionCamEyeSplineRelToPlayer, - "CS_CAM_AT_SPLINE_REL_TO_PLAYER": OOTCSMotionCamATSplineRelToPlayer, - "CS_CAM_EYE": OOTCSMotionCamEye, - "CS_CAM_AT": OOTCSMotionCamAT, - "CS_MISC_LIST": OOTCSMotionMiscList, - "CS_TRANSITION": OOTCSMotionTransition, - "CS_TEXT_LIST": OOTCSMotionTextList, - "CS_LIGHT_SETTING_LIST": OOTCSMotionLightSettingList, - "CS_TIME_LIST": OOTCSMotionTimeList, - "CS_FADE_OUT_SEQ_LIST": OOTCSMotionFadeSeqList, - "CS_RUMBLE_CONTROLLER_LIST": OOTCSMotionRumbleControllerList, - "CS_START_SEQ_LIST": OOTCSMotionStartStopSeqList, - "CS_STOP_SEQ_LIST": OOTCSMotionStartStopSeqList, - "CS_ACTOR_CUE_LIST": OOTCSMotionActorCueList, - "CS_PLAYER_CUE_LIST": OOTCSMotionActorCueList, - "CS_DESTINATION": OOTCSMotionDestination, + "CS_CAM_POINT": CutsceneCmdCamPoint, + "CS_MISC": CutsceneCmdMisc, + "CS_LIGHT_SETTING": CutsceneCmdLightSetting, + "CS_TIME": CutsceneCmdTime, + "CS_FADE_OUT_SEQ": CutsceneCmdFadeSeq, + "CS_RUMBLE_CONTROLLER": CutsceneCmdRumbleController, + "CS_TEXT": CutsceneCmdText, + "CS_TEXT_NONE": CutsceneCmdTextNone, + "CS_TEXT_OCARINA_ACTION": CutsceneCmdTextOcarinaAction, + "CS_START_SEQ": CutsceneCmdStartStopSeq, + "CS_STOP_SEQ": CutsceneCmdStartStopSeq, + "CS_ACTOR_CUE": CutsceneCmdActorCue, + "CS_PLAYER_CUE": CutsceneCmdActorCue, + "CS_CAM_EYE_SPLINE": CutsceneCmdCamEyeSpline, + "CS_CAM_AT_SPLINE": CutsceneCmdCamATSpline, + "CS_CAM_EYE_SPLINE_REL_TO_PLAYER": CutsceneCmdCamEyeSplineRelToPlayer, + "CS_CAM_AT_SPLINE_REL_TO_PLAYER": CutsceneCmdCamATSplineRelToPlayer, + "CS_CAM_EYE": CutsceneCmdCamEye, + "CS_CAM_AT": CutsceneCmdCamAT, + "CS_MISC_LIST": CutsceneCmdMiscList, + "CS_TRANSITION": CutsceneCmdTransition, + "CS_TEXT_LIST": CutsceneCmdTextList, + "CS_LIGHT_SETTING_LIST": CutsceneCmdLightSettingList, + "CS_TIME_LIST": CutsceneCmdTimeList, + "CS_FADE_OUT_SEQ_LIST": CutsceneCmdFadeSeqList, + "CS_RUMBLE_CONTROLLER_LIST": CutsceneCmdRumbleControllerList, + "CS_START_SEQ_LIST": CutsceneCmdStartStopSeqList, + "CS_STOP_SEQ_LIST": CutsceneCmdStartStopSeqList, + "CS_ACTOR_CUE_LIST": CutsceneCmdActorCueList, + "CS_PLAYER_CUE_LIST": CutsceneCmdActorCueList, + "CS_DESTINATION": CutsceneCmdDestination, } diff --git a/fast64_internal/oot/cutscene/exporter/classes.py b/fast64_internal/oot/cutscene/exporter/classes.py index 8af3d46db..27984527c 100644 --- a/fast64_internal/oot/cutscene/exporter/classes.py +++ b/fast64_internal/oot/cutscene/exporter/classes.py @@ -12,27 +12,27 @@ from ..properties import OOTCutsceneProperty, OOTCSTextProperty from ..io_classes import ( - OOTCSMotionTransition, - OOTCSMotionRumbleController, - OOTCSMotionMisc, - OOTCSMotionTime, - OOTCSMotionLightSetting, - OOTCSMotionText, - OOTCSMotionTextNone, - OOTCSMotionTextOcarinaAction, - OOTCSMotionActorCueList, - OOTCSMotionActorCue, - OOTCSMotionCamEyeSpline, - OOTCSMotionCamATSpline, - OOTCSMotionCamEyeSplineRelToPlayer, - OOTCSMotionCamATSplineRelToPlayer, - OOTCSMotionCamEye, - OOTCSMotionCamAT, - OOTCSMotionCamPoint, + CutsceneCmdTransition, + CutsceneCmdRumbleController, + CutsceneCmdMisc, + CutsceneCmdTime, + CutsceneCmdLightSetting, + CutsceneCmdText, + CutsceneCmdTextNone, + CutsceneCmdTextOcarinaAction, + CutsceneCmdActorCueList, + CutsceneCmdActorCue, + CutsceneCmdCamEyeSpline, + CutsceneCmdCamATSpline, + CutsceneCmdCamEyeSplineRelToPlayer, + CutsceneCmdCamATSplineRelToPlayer, + CutsceneCmdCamEye, + CutsceneCmdCamAT, + CutsceneCmdCamPoint, ) -class OOTCSMotionExportCommands: +class CutsceneCmdExportCommands: """This class contains functions to create the cutscene commands""" def getEnumValue(self, enumKey: str, owner, propName: str): @@ -45,38 +45,38 @@ def getGenericListCmd(self, cmdName: str, entryTotal: int): def getGenericSeqCmd(self, cmdName: str, type: str, startFrame: int, endFrame: int): return indent * 3 + f"{cmdName}({type}, {startFrame}, {endFrame}" + ", 0" * 8 + "),\n" - def getTransitionCmd(self, transition: OOTCSMotionTransition): + def getTransitionCmd(self, transition: CutsceneCmdTransition): return indent * 2 + f"CS_TRANSITION({transition.type}, {transition.startFrame}, {transition.endFrame}),\n" - def getRumbleControllerCmd(self, rumble: OOTCSMotionRumbleController): + def getRumbleControllerCmd(self, rumble: CutsceneCmdRumbleController): return indent * 3 + ( f"CS_RUMBLE_CONTROLLER(" + f"0, {rumble.startFrame}, 0, " + f"{rumble.sourceStrength}, {rumble.duration}, {rumble.decreaseRate}, 0, 0),\n" ) - def getMiscCmd(self, misc: OOTCSMotionMisc): + def getMiscCmd(self, misc: CutsceneCmdMisc): return indent * 3 + (f"CS_MISC(" + f"{misc.type}, {misc.startFrame}, {misc.endFrame}" + ", 0" * 11 + "),\n") - def getTimeCmd(self, time: OOTCSMotionTime): + def getTimeCmd(self, time: CutsceneCmdTime): return indent * 3 + (f"CS_TIME(" + f"0, {time.startFrame}, 0, {time.hour}, {time.minute}" + "),\n") - def getLightSettingCmd(self, lightSetting: OOTCSMotionLightSetting): + def getLightSettingCmd(self, lightSetting: CutsceneCmdLightSetting): return indent * 3 + ( f"CS_LIGHT_SETTING(" + f"{lightSetting.lightSetting}, {lightSetting.startFrame}" + ", 0" * 9 + "),\n" ) - def getTextCmd(self, text: OOTCSMotionText): + def getTextCmd(self, text: CutsceneCmdText): return indent * 3 + ( f"CS_TEXT(" + f"{text.textId}, {text.startFrame}, {text.endFrame}, {text.type}, {text.altTextId1}, {text.altTextId2}" + "),\n" ) - def getTextNoneCmd(self, textNone: OOTCSMotionTextNone): + def getTextNoneCmd(self, textNone: CutsceneCmdTextNone): return indent * 3 + f"CS_TEXT_NONE({textNone.startFrame}, {textNone.endFrame}),\n" - def getTextOcarinaActionCmd(self, ocarinaAction: OOTCSMotionTextOcarinaAction): + def getTextOcarinaActionCmd(self, ocarinaAction: CutsceneCmdTextOcarinaAction): return indent * 3 + ( f"CS_TEXT_OCARINA_ACTION(" + f"{ocarinaAction.ocarinaActionId}, {ocarinaAction.startFrame}, " @@ -88,14 +88,14 @@ def getDestinationCmd(self, csProp: "OOTCutsceneProperty"): dest = self.getEnumValue("csDestination", csProp, "csDestination") return indent * 2 + f"CS_DESTINATION({dest}, {csProp.csDestinationStartFrame}, 0),\n" - def getActorCueListCmd(self, actorCueList: OOTCSMotionActorCueList, isPlayerActor: bool): + def getActorCueListCmd(self, actorCueList: CutsceneCmdActorCueList, isPlayerActor: bool): return indent * 2 + ( f"CS_{'PLAYER' if isPlayerActor else 'ACTOR'}_CUE_LIST(" + f"{actorCueList.commandType + ', ' if not isPlayerActor else ''}" + f"{actorCueList.entryTotal}),\n" ) - def getActorCueCmd(self, actorCue: OOTCSMotionActorCue, isPlayerActor: bool): + def getActorCueCmd(self, actorCue: CutsceneCmdActorCue, isPlayerActor: bool): return indent * 3 + ( f"CS_{'PLAYER' if isPlayerActor else 'ACTOR'}_CUE(" + f"{actorCue.actionID}, {actorCue.startFrame}, {actorCue.endFrame}, " @@ -108,29 +108,29 @@ def getActorCueCmd(self, actorCue: OOTCSMotionActorCue, isPlayerActor: bool): def getCamListCmd(self, cmdName: str, startFrame: int, endFrame: int): return indent * 2 + f"{cmdName}({startFrame}, {endFrame}),\n" - def getCamEyeSplineCmd(self, camEyeSpline: OOTCSMotionCamEyeSpline): + def getCamEyeSplineCmd(self, camEyeSpline: CutsceneCmdCamEyeSpline): return self.getCamListCmd("CS_CAM_EYE_SPLINE", camEyeSpline.startFrame, camEyeSpline.endFrame) - def getCamATSplineCmd(self, camATSpline: OOTCSMotionCamATSpline): + def getCamATSplineCmd(self, camATSpline: CutsceneCmdCamATSpline): return self.getCamListCmd("CS_CAM_AT_SPLINE", camATSpline.startFrame, camATSpline.endFrame) - def getCamEyeSplineRelToPlayerCmd(self, camEyeSplinePlayer: OOTCSMotionCamEyeSplineRelToPlayer): + def getCamEyeSplineRelToPlayerCmd(self, camEyeSplinePlayer: CutsceneCmdCamEyeSplineRelToPlayer): return self.getCamListCmd( "CS_CAM_EYE_SPLINE_REL_TO_PLAYER", camEyeSplinePlayer.startFrame, camEyeSplinePlayer.endFrame ) - def getCamATSplineRelToPlayerCmd(self, camATSplinePlayer: OOTCSMotionCamATSplineRelToPlayer): + def getCamATSplineRelToPlayerCmd(self, camATSplinePlayer: CutsceneCmdCamATSplineRelToPlayer): return self.getCamListCmd( "CS_CAM_AT_SPLINE_REL_TO_PLAYER", camATSplinePlayer.startFrame, camATSplinePlayer.endFrame ) - def getCamEyeCmd(self, camEye: OOTCSMotionCamEye): + def getCamEyeCmd(self, camEye: CutsceneCmdCamEye): return self.getCamListCmd("CS_CAM_EYE", camEye.startFrame, camEye.endFrame) - def getCamATCmd(self, camAT: OOTCSMotionCamAT): + def getCamATCmd(self, camAT: CutsceneCmdCamAT): return self.getCamListCmd("CS_CAM_AT", camAT.startFrame, camAT.endFrame) - def getCamPointCmd(self, camPoint: OOTCSMotionCamPoint): + def getCamPointCmd(self, camPoint: CutsceneCmdCamPoint): return indent * 3 + ( f"CS_CAM_POINT(" + f"{camPoint.continueFlag}, {camPoint.camRoll}, {camPoint.frame}, {camPoint.viewAngle}f, " @@ -140,7 +140,7 @@ def getCamPointCmd(self, camPoint: OOTCSMotionCamPoint): @dataclass -class OOTCSMotionExport(OOTCSMotionExportCommands): +class CutsceneCmdExport(CutsceneCmdExportCommands): """This class contains functions to create the new cutscene data""" csMotionObjects: dict[str, list[Object]] @@ -211,7 +211,7 @@ def getActorCueListData(self, isPlayer: bool): commandType = ootData.enumData.enumByKey["csCmd"].itemByKey[commandType].id # ignoring dummy cue - actorCueList = OOTCSMotionActorCueList(None, entryTotal=entryTotal - 1, commandType=commandType) + actorCueList = CutsceneCmdActorCueList(None, entryTotal=entryTotal - 1, commandType=commandType) actorCueData += self.getActorCueListCmd(actorCueList, isPlayer) for i, childObj in enumerate(obj.children, 1): @@ -228,7 +228,7 @@ def getActorCueListData(self, isPlayer: bool): if actionID is None: actionID = childObj.ootCSMotionProperty.actorCueProp.cueActionID - actorCue = OOTCSMotionActorCue( + actorCue = CutsceneCmdActorCue( None, startFrame, endFrame, @@ -244,7 +244,7 @@ def getActorCueListData(self, isPlayer: bool): def getCameraShotPointData(self, bones, useAT: bool): """Returns the Camera Point data from the bone data""" - shotPoints: list[OOTCSMotionCamPoint] = [] + shotPoints: list[CutsceneCmdCamPoint] = [] if len(bones) < 4: raise RuntimeError("Camera Armature needs at least 4 bones!") @@ -254,7 +254,7 @@ def getCameraShotPointData(self, bones, useAT: bool): raise RuntimeError("Camera Armature bones are not allowed to have parent bones!") shotPoints.append( - OOTCSMotionCamPoint( + CutsceneCmdCamPoint( None, None, None, @@ -268,7 +268,7 @@ def getCameraShotPointData(self, bones, useAT: bool): # NOTE: because of the game's bug explained in the importer we need to add an extra dummy point when exporting shotPoints.append( - OOTCSMotionCamPoint(None, None, None, "CS_CAM_STOP" if self.useDecomp else "-1", 0, 0, 0.0, [0, 0, 0]) + CutsceneCmdCamPoint(None, None, None, "CS_CAM_STOP" if self.useDecomp else "-1", 0, 0, 0.0, [0, 0, 0]) ) return shotPoints @@ -289,11 +289,11 @@ def getCamClass(self, camMode: str, useAT: bool): """Returns the camera dataclass depending on the camera mode""" camCmdClassMap = { - "splineEyeOrAT": OOTCSMotionCamATSpline if useAT else OOTCSMotionCamEyeSpline, - "splineEyeOrATRelPlayer": OOTCSMotionCamATSplineRelToPlayer + "splineEyeOrAT": CutsceneCmdCamATSpline if useAT else CutsceneCmdCamEyeSpline, + "splineEyeOrATRelPlayer": CutsceneCmdCamATSplineRelToPlayer if useAT - else OOTCSMotionCamEyeSplineRelToPlayer, - "eyeOrAT": OOTCSMotionCamAT if useAT else OOTCSMotionCamEye, + else CutsceneCmdCamEyeSplineRelToPlayer, + "eyeOrAT": CutsceneCmdCamAT if useAT else CutsceneCmdCamEye, } return camCmdClassMap[camMode] @@ -339,7 +339,7 @@ def getTextListData(self, textEntry: "OOTCSTextProperty"): match textEntry.textboxType: case "Text": return self.getTextCmd( - OOTCSMotionText( + CutsceneCmdText( None, textEntry.startFrame, textEntry.endFrame, @@ -350,10 +350,10 @@ def getTextListData(self, textEntry: "OOTCSTextProperty"): ) ) case "None": - return self.getTextNoneCmd(OOTCSMotionTextNone(None, textEntry.startFrame, textEntry.endFrame)) + return self.getTextNoneCmd(CutsceneCmdTextNone(None, textEntry.startFrame, textEntry.endFrame)) case "OcarinaAction": return self.getTextOcarinaActionCmd( - OOTCSMotionTextOcarinaAction( + CutsceneCmdTextOcarinaAction( None, textEntry.startFrame, textEntry.endFrame, @@ -389,7 +389,7 @@ def getCutsceneData(self): ) case "Transition": subData += self.getTransitionCmd( - OOTCSMotionTransition( + CutsceneCmdTransition( None, entry.transitionStartFrame, entry.transitionEndFrame, @@ -405,17 +405,17 @@ def getCutsceneData(self): subData += self.getTextListData(elem) case "LightSettingsList": subData += self.getLightSettingCmd( - OOTCSMotionLightSetting( + CutsceneCmdLightSetting( None, elem.startFrame, elem.endFrame, None, elem.lightSettingsIndex ) ) case "TimeList": subData += self.getTimeCmd( - OOTCSMotionTime(None, elem.startFrame, elem.endFrame, elem.hour, elem.minute) + CutsceneCmdTime(None, elem.startFrame, elem.endFrame, elem.hour, elem.minute) ) case "MiscList": subData += self.getMiscCmd( - OOTCSMotionMisc( + CutsceneCmdMisc( None, elem.startFrame, elem.endFrame, @@ -424,7 +424,7 @@ def getCutsceneData(self): ) case "RumbleList": subData += self.getRumbleControllerCmd( - OOTCSMotionRumbleController( + CutsceneCmdRumbleController( None, elem.startFrame, elem.endFrame, diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index a3630adde..11f32cd39 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -2,7 +2,7 @@ from bpy.types import Object from ....utility import PluginError -from .classes import OOTCSMotionExport +from .classes import CutsceneCmdExport def getCSMotionObjects(csName: str): @@ -42,7 +42,7 @@ def getCutsceneMotionData(csName: str, motionOnly: bool): """Returns the initialised cutscene exporter""" # this allows us to change the exporter's variables to get what we need - return OOTCSMotionExport( + return CutsceneCmdExport( getCSMotionObjects(csName), bpy.context.scene.fast64.oot.hackerFeaturesEnabled or bpy.context.scene.useDecompFeatures, motionOnly, diff --git a/fast64_internal/oot/cutscene/importer/classes.py b/fast64_internal/oot/cutscene/importer/classes.py index 03e22f254..b3723f384 100644 --- a/fast64_internal/oot/cutscene/importer/classes.py +++ b/fast64_internal/oot/cutscene/importer/classes.py @@ -20,10 +20,10 @@ ) from ..io_classes import ( - OOTCSMotionActorCueList, - OOTCSMotionCamPoint, - OOTCSMotionCutscene, - OOTCSMotionObjectFactory, + CutsceneCmdActorCueList, + CutsceneCmdCamPoint, + Cutscene, + CutsceneObjectFactory, ) @@ -42,7 +42,7 @@ class PropertyData: useEndFrame: bool -class OOTCSMotionImportCommands: +class CutsceneCmdImportCommands: """This class contains functions to create the cutscene dataclasses""" def getCmdParams(self, data: str, cmdName: str, paramNumber: int): @@ -59,12 +59,12 @@ def getCmdParams(self, data: str, cmdName: str, paramNumber: int): return params def getNewCutscene(self, csData: str, name: str): - params = self.getCmdParams(csData, "CS_BEGIN_CUTSCENE", OOTCSMotionCutscene.paramNumber) - return OOTCSMotionCutscene(name, getInteger(params[0]), getInteger(params[1])) + params = self.getCmdParams(csData, "CS_BEGIN_CUTSCENE", Cutscene.paramNumber) + return Cutscene(name, getInteger(params[0]), getInteger(params[1])) @dataclass -class OOTCSMotionImport(OOTCSMotionImportCommands, OOTCSMotionObjectFactory): +class CutsceneCmdImport(CutsceneCmdImportCommands, CutsceneObjectFactory): """This class contains functions to create the new cutscene Blender data""" filePath: str # used when importing from the panel @@ -181,7 +181,7 @@ def getCutsceneList(self): # if it's none then there's no cutscene in the file return None - cutsceneList: list[OOTCSMotionCutscene] = [] + cutsceneList: list[Cutscene] = [] # for each cutscene from the list returned by getParsedCutscenes(), # create classes containing the cutscene's informations @@ -251,7 +251,7 @@ def getCutsceneList(self): cutsceneList.append(cutscene) return cutsceneList - def setActorCueData(self, csObj: Object, actorCueList: list[OOTCSMotionActorCueList], cueName: str, csNbr: int): + def setActorCueData(self, csObj: Object, actorCueList: list[CutsceneCmdActorCueList], cueName: str, csNbr: int): """Creates the objects from the Actor Cue List data""" cueObjList = [] @@ -311,7 +311,7 @@ def setActorCueData(self, csObj: Object, actorCueList: list[OOTCSMotionActorCueL if endFrame != getEndFrame and obj.ootEmptyType != "CS Dummy Cue": print(f"WARNING: `{obj.name}`'s end frame do not match the one from the script!") - def validateCameraData(self, cutscene: OOTCSMotionCutscene): + def validateCameraData(self, cutscene: Cutscene): """Safety checks to make sure the camera data is correct""" camLists: list[tuple[str, list, list]] = [ @@ -341,7 +341,7 @@ def validateCameraData(self, cutscene: OOTCSMotionCutscene): del atListEntry.entries[-1] def setBoneData( - self, cameraShotObj: Object, boneData: list[tuple[OOTCSMotionCamPoint, OOTCSMotionCamPoint]], csNbr: int + self, cameraShotObj: Object, boneData: list[tuple[CutsceneCmdCamPoint, CutsceneCmdCamPoint]], csNbr: int ): """Creates the bones from the Camera Point data""" @@ -418,7 +418,7 @@ def setSubPropertyData(self, subPropsData: dict[str, str], newSubElem, entry): setattr(newSubElem, key, getattr(entry, value)) def setPropertyData( - self, csProp: "OOTCutsceneProperty", cutscene: OOTCSMotionCutscene, propDataList: list[PropertyData] + self, csProp: "OOTCutsceneProperty", cutscene: Cutscene, propDataList: list[PropertyData] ): for data in propDataList: listName = f"{data.listType[0].lower() + data.listType[1:]}List" diff --git a/fast64_internal/oot/cutscene/importer/functions.py b/fast64_internal/oot/cutscene/importer/functions.py index 16a5fbcca..40dfacf61 100644 --- a/fast64_internal/oot/cutscene/importer/functions.py +++ b/fast64_internal/oot/cutscene/importer/functions.py @@ -1,10 +1,10 @@ import bpy -from .classes import OOTCSMotionImport +from .classes import CutsceneCmdImport def importCutsceneData(filePath: str, sceneData: str): """Initialises and imports the cutscene data from either a file or the scene data""" # NOTE: ``sceneData`` is the data read when importing a scene - csMotionImport = OOTCSMotionImport(filePath, sceneData) + csMotionImport = CutsceneCmdImport(filePath, sceneData) return csMotionImport.setCutsceneData(bpy.context.scene.ootCSNumber) diff --git a/fast64_internal/oot/cutscene/io_classes.py b/fast64_internal/oot/cutscene/io_classes.py index ae625895a..f761b18c0 100644 --- a/fast64_internal/oot/cutscene/io_classes.py +++ b/fast64_internal/oot/cutscene/io_classes.py @@ -11,7 +11,7 @@ @dataclass -class OOTCSMotionBase: +class CutsceneCmdBase: """This class contains common Cutscene data""" params: list[str] @@ -31,7 +31,7 @@ def getEnumValue(self, enumKey: str, index: int, isSeqLegacy: bool = False): @dataclass -class OOTCSMotionCamPoint(OOTCSMotionBase): +class CutsceneCmdCamPoint(CutsceneCmdBase): """This class contains a single Camera Point command data""" continueFlag: str = None @@ -51,7 +51,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionActorCue(OOTCSMotionBase): +class CutsceneCmdActorCue(CutsceneCmdBase): """This class contains a single Actor Cue command data""" actionID: int = None @@ -71,13 +71,13 @@ def __post_init__(self): @dataclass -class OOTCSMotionActorCueList(OOTCSMotionBase): +class CutsceneCmdActorCueList(CutsceneCmdBase): """This class contains the Actor Cue List command data""" isPlayer: bool = False commandType: str = None entryTotal: int = None - entries: list[OOTCSMotionActorCue] = field(default_factory=list) + entries: list[CutsceneCmdActorCue] = field(default_factory=list) paramNumber: int = 2 listName: str = "actorCueList" @@ -96,10 +96,10 @@ def __post_init__(self): @dataclass -class OOTCSMotionCamEyeSpline(OOTCSMotionBase): +class CutsceneCmdCamEyeSpline(CutsceneCmdBase): """This class contains the Camera Eye Spline data""" - entries: list[OOTCSMotionCamPoint] = field(default_factory=list) + entries: list[CutsceneCmdCamPoint] = field(default_factory=list) paramNumber: int = 2 listName: str = "camEyeSplineList" @@ -110,10 +110,10 @@ def __post_init__(self): @dataclass -class OOTCSMotionCamATSpline(OOTCSMotionBase): +class CutsceneCmdCamATSpline(CutsceneCmdBase): """This class contains the Camera AT (look-at) Spline data""" - entries: list[OOTCSMotionCamPoint] = field(default_factory=list) + entries: list[CutsceneCmdCamPoint] = field(default_factory=list) paramNumber: int = 2 listName: str = "camATSplineList" @@ -124,10 +124,10 @@ def __post_init__(self): @dataclass -class OOTCSMotionCamEyeSplineRelToPlayer(OOTCSMotionBase): +class CutsceneCmdCamEyeSplineRelToPlayer(CutsceneCmdBase): """This class contains the Camera Eye Spline Relative to the Player data""" - entries: list[OOTCSMotionCamPoint] = field(default_factory=list) + entries: list[CutsceneCmdCamPoint] = field(default_factory=list) paramNumber: int = 2 listName: str = "camEyeSplineRelPlayerList" @@ -138,10 +138,10 @@ def __post_init__(self): @dataclass -class OOTCSMotionCamATSplineRelToPlayer(OOTCSMotionBase): +class CutsceneCmdCamATSplineRelToPlayer(CutsceneCmdBase): """This class contains the Camera AT Spline Relative to the Player data""" - entries: list[OOTCSMotionCamPoint] = field(default_factory=list) + entries: list[CutsceneCmdCamPoint] = field(default_factory=list) paramNumber: int = 2 listName: str = "camATSplineRelPlayerList" @@ -152,7 +152,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionCamEye(OOTCSMotionBase): +class CutsceneCmdCamEye(CutsceneCmdBase): """This class contains a single Camera Eye point""" # This feature is not used in the final game and lacks polish, it is recommended to use splines in all cases. @@ -167,7 +167,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionCamAT(OOTCSMotionBase): +class CutsceneCmdCamAT(CutsceneCmdBase): """This class contains a single Camera AT point""" # This feature is not used in the final game and lacks polish, it is recommended to use splines in all cases. @@ -182,7 +182,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionMisc(OOTCSMotionBase): +class CutsceneCmdMisc(CutsceneCmdBase): """This class contains a single misc command entry""" type: str = None # see ``CutsceneMiscType`` in decomp @@ -196,11 +196,11 @@ def __post_init__(self): @dataclass -class OOTCSMotionMiscList(OOTCSMotionBase): +class CutsceneCmdMiscList(CutsceneCmdBase): """This class contains Misc command data""" entryTotal: int = None - entries: list[OOTCSMotionMisc] = field(default_factory=list) + entries: list[CutsceneCmdMisc] = field(default_factory=list) paramNumber: int = 1 listName: str = "miscList" @@ -210,7 +210,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionTransition(OOTCSMotionBase): +class CutsceneCmdTransition(CutsceneCmdBase): """This class contains Transition command data""" type: str = None @@ -225,7 +225,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionText(OOTCSMotionBase): +class CutsceneCmdText(CutsceneCmdBase): """This class contains Text command data""" textId: int = None @@ -246,7 +246,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionTextNone(OOTCSMotionBase): +class CutsceneCmdTextNone(CutsceneCmdBase): """This class contains Text None command data""" paramNumber: int = 2 @@ -259,7 +259,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionTextOcarinaAction(OOTCSMotionBase): +class CutsceneCmdTextOcarinaAction(CutsceneCmdBase): """This class contains Text Ocarina Action command data""" ocarinaActionId: str = None @@ -276,11 +276,11 @@ def __post_init__(self): @dataclass -class OOTCSMotionTextList(OOTCSMotionBase): +class CutsceneCmdTextList(CutsceneCmdBase): """This class contains Text List command data""" entryTotal: int = None - entries: list[OOTCSMotionText | OOTCSMotionTextNone | OOTCSMotionTextOcarinaAction] = field(default_factory=list) + entries: list[CutsceneCmdText | CutsceneCmdTextNone | CutsceneCmdTextOcarinaAction] = field(default_factory=list) paramNumber: int = 1 listName: str = "textList" @@ -290,7 +290,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionLightSetting(OOTCSMotionBase): +class CutsceneCmdLightSetting(CutsceneCmdBase): """This class contains Light Setting command data""" isLegacy: bool = None @@ -307,11 +307,11 @@ def __post_init__(self): @dataclass -class OOTCSMotionLightSettingList(OOTCSMotionBase): +class CutsceneCmdLightSettingList(CutsceneCmdBase): """This class contains Light Setting List command data""" entryTotal: int = None - entries: list[OOTCSMotionLightSetting] = field(default_factory=list) + entries: list[CutsceneCmdLightSetting] = field(default_factory=list) paramNumber: int = 1 listName: str = "lightSettingsList" @@ -321,7 +321,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionTime(OOTCSMotionBase): +class CutsceneCmdTime(CutsceneCmdBase): """This class contains Time Ocarina Action command data""" hour: int = None @@ -337,11 +337,11 @@ def __post_init__(self): @dataclass -class OOTCSMotionTimeList(OOTCSMotionBase): +class CutsceneCmdTimeList(CutsceneCmdBase): """This class contains Time List command data""" entryTotal: int = None - entries: list[OOTCSMotionTime] = field(default_factory=list) + entries: list[CutsceneCmdTime] = field(default_factory=list) paramNumber: int = 1 listName: str = "timeList" @@ -351,7 +351,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionStartStopSeq(OOTCSMotionBase): +class CutsceneCmdStartStopSeq(CutsceneCmdBase): """This class contains Start/Stop Seq command data""" isLegacy: bool = None @@ -366,12 +366,12 @@ def __post_init__(self): @dataclass -class OOTCSMotionStartStopSeqList(OOTCSMotionBase): +class CutsceneCmdStartStopSeqList(CutsceneCmdBase): """This class contains Start/Stop Seq List command data""" entryTotal: int = None type: str = None - entries: list[OOTCSMotionStartStopSeq] = field(default_factory=list) + entries: list[CutsceneCmdStartStopSeq] = field(default_factory=list) paramNumber: int = 1 listName: str = "seqList" @@ -381,7 +381,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionFadeSeq(OOTCSMotionBase): +class CutsceneCmdFadeSeq(CutsceneCmdBase): """This class contains Fade Seq command data""" seqPlayer: str = None @@ -396,11 +396,11 @@ def __post_init__(self): @dataclass -class OOTCSMotionFadeSeqList(OOTCSMotionBase): +class CutsceneCmdFadeSeqList(CutsceneCmdBase): """This class contains Fade Seq List command data""" entryTotal: int = None - entries: list[OOTCSMotionFadeSeq] = field(default_factory=list) + entries: list[CutsceneCmdFadeSeq] = field(default_factory=list) paramNumber: int = 1 listName: str = "fadeSeqList" @@ -410,7 +410,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionRumbleController(OOTCSMotionBase): +class CutsceneCmdRumbleController(CutsceneCmdBase): """This class contains Rumble Controller command data""" sourceStrength: int = None @@ -428,11 +428,11 @@ def __post_init__(self): @dataclass -class OOTCSMotionRumbleControllerList(OOTCSMotionBase): +class CutsceneCmdRumbleControllerList(CutsceneCmdBase): """This class contains Rumble Controller List command data""" entryTotal: int = None - entries: list[OOTCSMotionRumbleController] = field(default_factory=list) + entries: list[CutsceneCmdRumbleController] = field(default_factory=list) paramNumber: int = 1 listName: str = "rumbleList" @@ -442,7 +442,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionDestination(OOTCSMotionBase): +class CutsceneCmdDestination(CutsceneCmdBase): """This class contains Destination command data""" id: str = None @@ -456,7 +456,7 @@ def __post_init__(self): @dataclass -class OOTCSMotionCutscene: +class Cutscene: """This class contains a Cutscene's data, including every commands' data""" name: str @@ -464,26 +464,26 @@ class OOTCSMotionCutscene: frameCount: int paramNumber: int = 2 - destination: OOTCSMotionDestination = None - actorCueList: list[OOTCSMotionActorCueList] = field(default_factory=list) - playerCueList: list[OOTCSMotionActorCueList] = field(default_factory=list) - camEyeSplineList: list[OOTCSMotionCamEyeSpline] = field(default_factory=list) - camATSplineList: list[OOTCSMotionCamATSpline] = field(default_factory=list) - camEyeSplineRelPlayerList: list[OOTCSMotionCamEyeSplineRelToPlayer] = field(default_factory=list) - camATSplineRelPlayerList: list[OOTCSMotionCamATSplineRelToPlayer] = field(default_factory=list) - camEyeList: list[OOTCSMotionCamEye] = field(default_factory=list) - camATList: list[OOTCSMotionCamAT] = field(default_factory=list) - miscList: list[OOTCSMotionMiscList] = field(default_factory=list) - transitionList: list[OOTCSMotionTransition] = field(default_factory=list) - textList: list[OOTCSMotionTextList] = field(default_factory=list) - lightSettingsList: list[OOTCSMotionLightSettingList] = field(default_factory=list) - timeList: list[OOTCSMotionTimeList] = field(default_factory=list) - seqList: list[OOTCSMotionStartStopSeqList] = field(default_factory=list) - fadeSeqList: list[OOTCSMotionFadeSeqList] = field(default_factory=list) - rumbleList: list[OOTCSMotionRumbleControllerList] = field(default_factory=list) - - -class OOTCSMotionObjectFactory: + destination: CutsceneCmdDestination = None + actorCueList: list[CutsceneCmdActorCueList] = field(default_factory=list) + playerCueList: list[CutsceneCmdActorCueList] = field(default_factory=list) + camEyeSplineList: list[CutsceneCmdCamEyeSpline] = field(default_factory=list) + camATSplineList: list[CutsceneCmdCamATSpline] = field(default_factory=list) + camEyeSplineRelPlayerList: list[CutsceneCmdCamEyeSplineRelToPlayer] = field(default_factory=list) + camATSplineRelPlayerList: list[CutsceneCmdCamATSplineRelToPlayer] = field(default_factory=list) + camEyeList: list[CutsceneCmdCamEye] = field(default_factory=list) + camATList: list[CutsceneCmdCamAT] = field(default_factory=list) + miscList: list[CutsceneCmdMiscList] = field(default_factory=list) + transitionList: list[CutsceneCmdTransition] = field(default_factory=list) + textList: list[CutsceneCmdTextList] = field(default_factory=list) + lightSettingsList: list[CutsceneCmdLightSettingList] = field(default_factory=list) + timeList: list[CutsceneCmdTimeList] = field(default_factory=list) + seqList: list[CutsceneCmdStartStopSeqList] = field(default_factory=list) + fadeSeqList: list[CutsceneCmdFadeSeqList] = field(default_factory=list) + rumbleList: list[CutsceneCmdRumbleControllerList] = field(default_factory=list) + + +class CutsceneObjectFactory: """This class contains functions to create new Blender objects""" def getNewObject(self, name: str, data, selectObject: bool, parentObj: Object) -> Object: diff --git a/fast64_internal/oot/cutscene/motion/operators.py b/fast64_internal/oot/cutscene/motion/operators.py index 827f74857..1791c890f 100644 --- a/fast64_internal/oot/cutscene/motion/operators.py +++ b/fast64_internal/oot/cutscene/motion/operators.py @@ -5,7 +5,7 @@ from bpy.props import StringProperty, EnumProperty, BoolProperty from ....utility import PluginError from ...oot_constants import ootData -from ..io_classes import OOTCSMotionObjectFactory +from ..io_classes import CutsceneObjectFactory from ..constants import ootEnumCSActorCueListCommandType from ..preview import initFirstFrame, setupCompositorNodes from .utility import ( @@ -35,7 +35,7 @@ def getActorCueList(operator: Operator, context: Context) -> Object | None: def createNewActorCueList(csObj: Object, isPlayer: bool): """Creates a new Actor or Player Cue List and adds one basic cue and the dummy one""" - objFactory = OOTCSMotionObjectFactory() + objFactory = CutsceneObjectFactory() playerOrActor = "Player" if isPlayer else "Actor" newActorCueListObj = objFactory.getNewActorCueListObject(f"New {playerOrActor} Cue List", "actor_cue_0_0", None) index, csPrefix = getNameInformations(csObj, f"{playerOrActor} Cue List", None) @@ -57,7 +57,7 @@ def createNewActorCueList(csObj: Object, isPlayer: bool): newActorCueListObj.parent = csObj -class OOTCSMotionPlayPreview(Operator): +class CutsceneCmdPlayPreview(Operator): """Camera Preview Playback""" bl_idname = "object.play_preview" @@ -97,7 +97,7 @@ def execute(self, context): return {"CANCELLED"} -class OOTCSMotionAddBone(Operator): +class CutsceneCmdAddBone(Operator): """Add a bone to an armature""" bl_idname = "object.add_bone" @@ -143,7 +143,7 @@ def execute(self, context): return {"CANCELLED"} -class OOTCSMotionAddActorCue(Operator): +class CutsceneCmdAddActorCue(Operator): """Add an entry to a player or actor cue list""" bl_idname = "object.add_actor_cue_point" @@ -160,7 +160,7 @@ def execute(self, context): actorCueListObj = actorCueListObj.parent # start by creating the new object with basic values - objFactory = OOTCSMotionObjectFactory() + objFactory = CutsceneObjectFactory() newActorCueObj = objFactory.getNewActorCueObject( f"New {'Player' if self.isPlayer else 'Actor'} Cue", 0, @@ -224,7 +224,7 @@ def execute(self, context): return {"CANCELLED"} -class OOTCSMotionCreateActorCuePreview(Operator): +class CutsceneCmdCreateActorCuePreview(Operator): """Create a preview empty object for a player or an actor cue list""" bl_idname = "object.create_actor_cue_preview" @@ -243,7 +243,7 @@ def execute(self, context): return {"CANCELLED"} -class OOTCSMotionCreateCameraShot(Operator): +class CutsceneCmdCreateCameraShot(Operator): """Create and initialize a camera shot armature""" bl_idname = "object.create_camera_shot" @@ -260,7 +260,7 @@ def execute(self, context): return {"CANCELLED"} -class OOTCSMotionCreatePlayerCueList(Operator): +class CutsceneCmdCreatePlayerCueList(Operator): """Create a cutscene player cue list""" bl_idname = "object.create_player_cue_list" @@ -281,7 +281,7 @@ def execute(self, context): return {"CANCELLED"} -class OOTCSMotionCreateActorCueList(Operator): +class CutsceneCmdCreateActorCueList(Operator): """Create a cutscene actor cue list""" bl_idname = "object.create_actor_cue_list" @@ -347,13 +347,13 @@ def invoke(self, context, event): classes = ( - OOTCSMotionPlayPreview, - OOTCSMotionAddBone, - OOTCSMotionAddActorCue, - OOTCSMotionCreateActorCuePreview, - OOTCSMotionCreateCameraShot, - OOTCSMotionCreatePlayerCueList, - OOTCSMotionCreateActorCueList, + CutsceneCmdPlayPreview, + CutsceneCmdAddBone, + CutsceneCmdAddActorCue, + CutsceneCmdCreateActorCuePreview, + CutsceneCmdCreateCameraShot, + CutsceneCmdCreatePlayerCueList, + CutsceneCmdCreateActorCueList, OOT_SearchActorCueCmdTypeEnumOperator, OOT_SearchPlayerCueIdEnumOperator, ) diff --git a/fast64_internal/oot/cutscene/motion/panels.py b/fast64_internal/oot/cutscene/motion/panels.py index 8b5a975ae..660187319 100644 --- a/fast64_internal/oot/cutscene/motion/panels.py +++ b/fast64_internal/oot/cutscene/motion/panels.py @@ -1,6 +1,6 @@ from bpy.types import Panel from bpy.utils import register_class, unregister_class -from .properties import OOTCSMotionCameraShotProperty, OOTCSMotionCameraShotPointProperty +from .properties import CutsceneCmdCameraShotProperty, CutsceneCmdCameraShotPointProperty class OOT_CSMotionCameraShotPanel(Panel): @@ -16,8 +16,8 @@ def draw(self, context): layout = self.layout if obj.type == "ARMATURE": - camShotProp: OOTCSMotionCameraShotProperty = obj.data.ootCamShotProp - camShotPointProp: OOTCSMotionCameraShotPointProperty = None + camShotProp: CutsceneCmdCameraShotProperty = obj.data.ootCamShotProp + camShotPointProp: CutsceneCmdCameraShotPointProperty = None activeBone = editBone = None box = layout.box() diff --git a/fast64_internal/oot/cutscene/motion/properties.py b/fast64_internal/oot/cutscene/motion/properties.py index f06b29859..f64be7081 100644 --- a/fast64_internal/oot/cutscene/motion/properties.py +++ b/fast64_internal/oot/cutscene/motion/properties.py @@ -9,10 +9,10 @@ from ..constants import ootEnumCSMotionCamMode, ootEnumCSActorCueListCommandType from .operators import ( - OOTCSMotionAddActorCue, - OOTCSMotionCreateActorCuePreview, + CutsceneCmdAddActorCue, + CutsceneCmdCreateActorCuePreview, OOT_SearchActorCueCmdTypeEnumOperator, - OOTCSMotionAddBone, + CutsceneCmdAddBone, OOT_SearchPlayerCueIdEnumOperator, ) @@ -30,7 +30,7 @@ def getNextCuesStartFrame(self): return -1 -class OOTCSMotionActorCueListProperty(PropertyGroup): +class CutsceneCmdActorCueListProperty(PropertyGroup): commandType: EnumProperty( items=ootEnumCSActorCueListCommandType, name="CS Actor Cue Command Type", default="actor_cue_0_0" ) @@ -66,16 +66,16 @@ def draw_props(self, layout: UILayout, isPreview: bool, labelPrefix: str, objNam if not isPreview: split = box.split(factor=0.5) - addCueOp = split.operator(OOTCSMotionAddActorCue.bl_idname, text=f"Add {labelPrefix} Cue") + addCueOp = split.operator(CutsceneCmdAddActorCue.bl_idname, text=f"Add {labelPrefix} Cue") addCueOp.isPlayer = isPlayer - split.operator(OOTCSMotionCreateActorCuePreview.bl_idname) + split.operator(CutsceneCmdCreateActorCuePreview.bl_idname) else: split = box.split(factor=0.5) split.label(text=f"{labelPrefix} Cue List to Preview") split.prop(self, f"{labelPrefix.lower()}CueListToPreview") -class OOTCSMotionActorCueProperty(PropertyGroup): +class CutsceneCmdActorCueProperty(PropertyGroup): cueStartFrame: IntProperty(name="Start Frame", description="Start frame of the Actor Cue", default=0, min=0) cueEndFrame: IntProperty( @@ -123,11 +123,11 @@ def draw_props(self, layout: UILayout, labelPrefix: str, isDummy: bool, objName: split.label(text=label) split.prop(self, "cueActionID", text="") - addCueOp = box.operator(OOTCSMotionAddActorCue.bl_idname, text=f"Add {labelPrefix} Cue") + addCueOp = box.operator(CutsceneCmdAddActorCue.bl_idname, text=f"Add {labelPrefix} Cue") addCueOp.isPlayer = isPlayer -class OOTCSMotionCameraShotProperty(PropertyGroup): +class CutsceneCmdCameraShotProperty(PropertyGroup): shotStartFrame: IntProperty(name="Start Frame", description="Shot start frame", default=0, min=0) # only used as a hint for users @@ -163,10 +163,10 @@ def draw_props(self, layout: UILayout, label: str): split.prop(self, "shotStartFrame") split.prop(self, "shotEndFrame") box.row().prop(self, "shotCamMode", expand=True) - box.operator(OOTCSMotionAddBone.bl_idname) + box.operator(CutsceneCmdAddBone.bl_idname) -class OOTCSMotionCameraShotPointProperty(PropertyGroup): +class CutsceneCmdCameraShotPointProperty(PropertyGroup): shotPointFrame: IntProperty( name="Frame", description="Key point frames value", @@ -231,8 +231,8 @@ def draw_props(self, layout: UILayout): class OOTCutsceneMotionProperty(PropertyGroup): - actorCueListProp: PointerProperty(type=OOTCSMotionActorCueListProperty) - actorCueProp: PointerProperty(type=OOTCSMotionActorCueProperty) + actorCueListProp: PointerProperty(type=CutsceneCmdActorCueListProperty) + actorCueProp: PointerProperty(type=CutsceneCmdActorCueProperty) @staticmethod def upgrade_object(csObj: Object): @@ -242,10 +242,10 @@ def upgrade_object(csObj: Object): classes = ( - OOTCSMotionActorCueListProperty, - OOTCSMotionActorCueProperty, - OOTCSMotionCameraShotProperty, - OOTCSMotionCameraShotPointProperty, + CutsceneCmdActorCueListProperty, + CutsceneCmdActorCueProperty, + CutsceneCmdCameraShotProperty, + CutsceneCmdCameraShotPointProperty, OOTCutsceneMotionProperty, ) @@ -255,9 +255,9 @@ def csMotion_props_register(): register_class(cls) Object.ootCSMotionProperty = PointerProperty(type=OOTCutsceneMotionProperty) - Armature.ootCamShotProp = PointerProperty(type=OOTCSMotionCameraShotProperty) - Bone.ootCamShotPointProp = PointerProperty(type=OOTCSMotionCameraShotPointProperty) - EditBone.ootCamShotPointProp = PointerProperty(type=OOTCSMotionCameraShotPointProperty) + Armature.ootCamShotProp = PointerProperty(type=CutsceneCmdCameraShotProperty) + Bone.ootCamShotPointProp = PointerProperty(type=CutsceneCmdCameraShotPointProperty) + EditBone.ootCamShotPointProp = PointerProperty(type=CutsceneCmdCameraShotPointProperty) Scene.previewPlayerAge = EnumProperty( items=[("link_adult", "Adult", "Adult Link (170 cm)", 0), ("link_child", "Child", "Child Link (130 cm)", 1)], name="Player Age for Preview", diff --git a/fast64_internal/oot/cutscene/motion/utility.py b/fast64_internal/oot/cutscene/motion/utility.py index 8a768f704..187927063 100644 --- a/fast64_internal/oot/cutscene/motion/utility.py +++ b/fast64_internal/oot/cutscene/motion/utility.py @@ -57,13 +57,13 @@ def createNewBone(cameraShotObj: Object, name: str, headPos: list[float], tailPo def createNewCameraShot(csObj: Object): - from ..io_classes import OOTCSMotionObjectFactory # circular import fix + from ..io_classes import CutsceneObjectFactory # circular import fix index, csPrefix = getNameInformations(csObj, "Camera Shot", None) # create a basic armature name = f"{csPrefix}.Camera Shot {index:02}" - newCameraShotObj = OOTCSMotionObjectFactory().getNewArmatureObject(name, True, csObj) + newCameraShotObj = CutsceneObjectFactory().getNewArmatureObject(name, True, csObj) # add 4 bones since it's the minimum required for i in range(1, 5): @@ -180,7 +180,7 @@ def metersToBlend(context: Context, value: float): def setupActorCuePreview(csObj: Object, actorOrPlayer: str, selectObject: bool, cueList: Object): - from ..io_classes import OOTCSMotionObjectFactory # circular import fix + from ..io_classes import CutsceneObjectFactory # circular import fix # check if the cue actually moves, if not it's not necessary to create a preview object isCueMoving = False @@ -205,7 +205,7 @@ def setupActorCuePreview(csObj: Object, actorOrPlayer: str, selectObject: bool, previewObj = obj break else: - previewObj = OOTCSMotionObjectFactory().getNewActorCuePreviewObject(name, selectObject, csObj) + previewObj = CutsceneObjectFactory().getNewActorCuePreviewObject(name, selectObject, csObj) actorHeight = 1.5 if actorOrPlayer == "Player": @@ -258,9 +258,9 @@ def getCutsceneEndFrame(csObj: Object): def setupCutscene(csObj: Object): - from ..io_classes import OOTCSMotionObjectFactory # circular import fix + from ..io_classes import CutsceneObjectFactory # circular import fix - objFactory = OOTCSMotionObjectFactory() + objFactory = CutsceneObjectFactory() context = bpy.context bpy.context.scene.ootCSPreviewCSObj = csObj camObj = objFactory.getNewCameraObject( diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 0b5921d46..db30b5a7a 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -11,10 +11,10 @@ from .motion.utility import getCutsceneCamera from .motion.operators import ( - OOTCSMotionPlayPreview, - OOTCSMotionCreateCameraShot, - OOTCSMotionCreatePlayerCueList, - OOTCSMotionCreateActorCueList, + CutsceneCmdPlayPreview, + CutsceneCmdCreateCameraShot, + CutsceneCmdCreatePlayerCueList, + CutsceneCmdCreateActorCueList, ) from .constants import ( @@ -335,12 +335,12 @@ def draw_props(self, layout: UILayout, obj: Object): split.prop(bpy.context.scene, "previewPlayerAge", text="") split = layout.split(factor=0.5) - split.operator(OOTCSMotionCreateCameraShot.bl_idname, icon="VIEW_CAMERA") - split.operator(OOTCSMotionPlayPreview.bl_idname, icon="RESTRICT_VIEW_OFF") + split.operator(CutsceneCmdCreateCameraShot.bl_idname, icon="VIEW_CAMERA") + split.operator(CutsceneCmdPlayPreview.bl_idname, icon="RESTRICT_VIEW_OFF") split = layout.split(factor=0.5) - split.operator(OOTCSMotionCreatePlayerCueList.bl_idname) - split.operator(OOTCSMotionCreateActorCueList.bl_idname) + split.operator(CutsceneCmdCreatePlayerCueList.bl_idname) + split.operator(CutsceneCmdCreateActorCueList.bl_idname) layout.prop(bpy.context.scene, "ootCsUseWidescreen") layout.prop(bpy.context.scene, "ootCsUseOpaqueCamBg") diff --git a/fast64_internal/oot/props_panel_main.py b/fast64_internal/oot/props_panel_main.py index 292586ea0..0cbdae8d2 100644 --- a/fast64_internal/oot/props_panel_main.py +++ b/fast64_internal/oot/props_panel_main.py @@ -9,8 +9,8 @@ from .cutscene.properties import OOTCutsceneProperty from .cutscene.motion.properties import ( OOTCutsceneMotionProperty, - OOTCSMotionActorCueListProperty, - OOTCSMotionActorCueProperty, + CutsceneCmdActorCueListProperty, + CutsceneCmdActorCueProperty, ) from .actor.properties import ( @@ -156,12 +156,12 @@ def draw(self, context): "CS Player Cue Preview", ]: labelPrefix = "Player" if "Player" in obj.ootEmptyType else "Actor" - actorCueListProp: OOTCSMotionActorCueListProperty = obj.ootCSMotionProperty.actorCueListProp + actorCueListProp: CutsceneCmdActorCueListProperty = obj.ootCSMotionProperty.actorCueListProp actorCueListProp.draw_props(box, obj.ootEmptyType == f"CS {labelPrefix} Cue Preview", labelPrefix, obj.name) elif obj.ootEmptyType in ["CS Actor Cue", "CS Player Cue", "CS Dummy Cue"]: labelPrefix = "Player" if obj.parent.ootEmptyType == "CS Player Cue List" else "Actor" - actorCueProp: OOTCSMotionActorCueProperty = obj.ootCSMotionProperty.actorCueProp + actorCueProp: CutsceneCmdActorCueProperty = obj.ootCSMotionProperty.actorCueProp actorCueProp.draw_props(box, labelPrefix, obj.ootEmptyType == "CS Dummy Cue", obj.name) elif obj.ootEmptyType == "None": From 8400cf282a236f3b87bd44b60da016c766ccd821 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 02:23:10 +0200 Subject: [PATCH 30/39] removed "motion" where it's relevant --- .../cutscene/{io_classes.py => classes.py} | 0 fast64_internal/oot/cutscene/constants.py | 16 +++---- .../oot/cutscene/exporter/__init__.py | 2 +- .../oot/cutscene/exporter/classes.py | 14 +++--- .../oot/cutscene/exporter/functions.py | 24 +++++----- .../oot/cutscene/importer/classes.py | 44 +++++++++---------- .../oot/cutscene/importer/functions.py | 4 +- .../oot/cutscene/motion/operators.py | 2 +- .../oot/cutscene/motion/utility.py | 6 +-- fast64_internal/oot/cutscene/operators.py | 4 +- .../oot/scene/exporter/to_c/scene_cutscene.py | 4 +- 11 files changed, 58 insertions(+), 62 deletions(-) rename fast64_internal/oot/cutscene/{io_classes.py => classes.py} (100%) diff --git a/fast64_internal/oot/cutscene/io_classes.py b/fast64_internal/oot/cutscene/classes.py similarity index 100% rename from fast64_internal/oot/cutscene/io_classes.py rename to fast64_internal/oot/cutscene/classes.py diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 0672532e8..35adb20b1 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -1,5 +1,5 @@ from ..oot_constants import ootData -from .io_classes import ( +from .classes import ( CutsceneCmdActorCueList, CutsceneCmdActorCue, CutsceneCmdCamEyeSpline, @@ -128,7 +128,7 @@ ootEnumCSActorCueListCommandType.sort() ootEnumCSActorCueListCommandType.insert(0, ("Custom", "Custom", "Custom")) -ootCSMotionLegacyToNewCmdNames = { +ootCSLegacyToNewCmdNames = { "CS_CAM_POS_LIST": "CS_CAM_EYE_SPLINE", "CS_CAM_FOCUS_POINT_LIST": "CS_CAM_AT_SPLINE", "CS_CAM_POS_PLAYER_LIST": "CS_CAM_EYE_SPLINE_REL_TO_PLAYER", @@ -159,7 +159,7 @@ "CS_STOP_BGM": "L_CS_STOP_SEQ", } -ootCSMotionListCommands = [ +ootCSListCommands = [ "CS_ACTOR_CUE_LIST", "CS_PLAYER_CUE_LIST", "CS_CAM_EYE_SPLINE", @@ -182,7 +182,7 @@ "CS_LIGHTING_LIST", ] -ootCSMotionListEntryCommands = [ +ootCSListEntryCommands = [ "CS_ACTOR_CUE", "CS_PLAYER_CUE", "CS_CAM_POINT", @@ -206,16 +206,16 @@ "L_CS_STOP_SEQ", ] -ootCSMotionSingleCommands = [ +ootCSSingleCommands = [ "CS_BEGIN_CUTSCENE", "CS_END", "CS_TRANSITION", "CS_DESTINATION", ] -ootCSMotionListAndSingleCommands = ootCSMotionSingleCommands + ootCSMotionListCommands -ootCSMotionListAndSingleCommands.remove("CS_BEGIN_CUTSCENE") -ootCSMotionCSCommands = ootCSMotionSingleCommands + ootCSMotionListCommands + ootCSMotionListEntryCommands +ootCSListAndSingleCommands = ootCSSingleCommands + ootCSListCommands +ootCSListAndSingleCommands.remove("CS_BEGIN_CUTSCENE") +ootCutsceneCommandsC = ootCSSingleCommands + ootCSListCommands + ootCSListEntryCommands cmdToClass = { "CS_CAM_POINT": CutsceneCmdCamPoint, diff --git a/fast64_internal/oot/cutscene/exporter/__init__.py b/fast64_internal/oot/cutscene/exporter/__init__.py index b4ff461e0..6a6aed48e 100644 --- a/fast64_internal/oot/cutscene/exporter/__init__.py +++ b/fast64_internal/oot/cutscene/exporter/__init__.py @@ -1 +1 @@ -from .functions import getCutsceneMotionData +from .functions import getNewCutsceneExport diff --git a/fast64_internal/oot/cutscene/exporter/classes.py b/fast64_internal/oot/cutscene/exporter/classes.py index 27984527c..c038de11b 100644 --- a/fast64_internal/oot/cutscene/exporter/classes.py +++ b/fast64_internal/oot/cutscene/exporter/classes.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from ..properties import OOTCutsceneProperty, OOTCSTextProperty -from ..io_classes import ( +from ..classes import ( CutsceneCmdTransition, CutsceneCmdRumbleController, CutsceneCmdMisc, @@ -32,7 +32,7 @@ ) -class CutsceneCmdExportCommands: +class CutsceneCmdToC: """This class contains functions to create the cutscene commands""" def getEnumValue(self, enumKey: str, owner, propName: str): @@ -140,10 +140,10 @@ def getCamPointCmd(self, camPoint: CutsceneCmdCamPoint): @dataclass -class CutsceneCmdExport(CutsceneCmdExportCommands): +class CutsceneExport(CutsceneCmdToC): """This class contains functions to create the new cutscene data""" - csMotionObjects: dict[str, list[Object]] + csObjects: dict[str, list[Object]] useDecomp: bool motionOnly: bool entryTotal: int = 0 @@ -187,7 +187,7 @@ def getActorCueListData(self, isPlayer: bool): """Returns the Actor Cue List commands from the corresponding objects""" playerOrActor = f"{'Player' if isPlayer else 'Actor'}" - actorCueListObjects = self.csMotionObjects[f"CS {playerOrActor} Cue List"] + actorCueListObjects = self.csObjects[f"CS {playerOrActor} Cue List"] actorCueListObjects.sort(key=lambda o: o.ootCSMotionProperty.actorCueProp.cueStartFrame) actorCueData = "" @@ -322,7 +322,7 @@ def getCamListData(self, shotObj: Object, useAT: bool): def getCameraShotData(self): """Returns every Camera Shot commands""" - shotObjects = self.csMotionObjects["camShot"] + shotObjects = self.csObjects["camShot"] cameraShotData = "" if len(shotObjects) > 0: @@ -363,7 +363,7 @@ def getTextListData(self, textEntry: "OOTCSTextProperty"): ) def getCutsceneData(self): - csProp: "OOTCutsceneProperty" = self.csMotionObjects["Cutscene"][0].ootCutsceneProperty + csProp: "OOTCutsceneProperty" = self.csObjects["Cutscene"][0].ootCutsceneProperty self.frameCount = csProp.csEndFrame data = "" diff --git a/fast64_internal/oot/cutscene/exporter/functions.py b/fast64_internal/oot/cutscene/exporter/functions.py index 11f32cd39..4512f1512 100644 --- a/fast64_internal/oot/cutscene/exporter/functions.py +++ b/fast64_internal/oot/cutscene/exporter/functions.py @@ -2,13 +2,13 @@ from bpy.types import Object from ....utility import PluginError -from .classes import CutsceneCmdExport +from .classes import CutsceneExport -def getCSMotionObjects(csName: str): +def getCutsceneObjects(csName: str): """Returns the object list containing every object from the cutscene to export""" - csMotionObjects: dict[str, list[Object]] = { + csObjects: dict[str, list[Object]] = { "Cutscene": [], "CS Actor Cue List": [], "CS Player Cue List": [], @@ -26,24 +26,24 @@ def getCSMotionObjects(csName: str): csObjCheck = isEmptyObj and obj.ootEmptyType == "Cutscene" and obj.name == f"Cutscene.{csName}" if parentCheck or csObjCheck: # add the relevant objects based on the empty type or if it's an armature - if isEmptyObj and obj.ootEmptyType in csMotionObjects.keys(): - csMotionObjects[obj.ootEmptyType].append(obj) + if isEmptyObj and obj.ootEmptyType in csObjects.keys(): + csObjects[obj.ootEmptyType].append(obj) if obj.type == "ARMATURE" and obj.parent.ootEmptyType == "Cutscene": - csMotionObjects["camShot"].append(obj) + csObjects["camShot"].append(obj) - if len(csMotionObjects["Cutscene"]) != 1: - raise PluginError(f"ERROR: Expected 1 Cutscene Object, found {len(csMotionObjects['Cutscene'])} ({csName}).") + if len(csObjects["Cutscene"]) != 1: + raise PluginError(f"ERROR: Expected 1 Cutscene Object, found {len(csObjects['Cutscene'])} ({csName}).") - return csMotionObjects + return csObjects -def getCutsceneMotionData(csName: str, motionOnly: bool): +def getNewCutsceneExport(csName: str, motionOnly: bool): """Returns the initialised cutscene exporter""" # this allows us to change the exporter's variables to get what we need - return CutsceneCmdExport( - getCSMotionObjects(csName), + return CutsceneExport( + getCutsceneObjects(csName), bpy.context.scene.fast64.oot.hackerFeaturesEnabled or bpy.context.scene.useDecompFeatures, motionOnly, ) diff --git a/fast64_internal/oot/cutscene/importer/classes.py b/fast64_internal/oot/cutscene/importer/classes.py index b3723f384..fd2d1d4c5 100644 --- a/fast64_internal/oot/cutscene/importer/classes.py +++ b/fast64_internal/oot/cutscene/importer/classes.py @@ -10,16 +10,16 @@ from ..properties import OOTCSListProperty, OOTCutsceneProperty from ..constants import ( - ootCSMotionLegacyToNewCmdNames, - ootCSMotionListCommands, - ootCSMotionCSCommands, - ootCSMotionListEntryCommands, - ootCSMotionSingleCommands, - ootCSMotionListAndSingleCommands, + ootCSLegacyToNewCmdNames, + ootCSListCommands, + ootCutsceneCommandsC, + ootCSListEntryCommands, + ootCSSingleCommands, + ootCSListAndSingleCommands, cmdToClass, ) -from ..io_classes import ( +from ..classes import ( CutsceneCmdActorCueList, CutsceneCmdCamPoint, Cutscene, @@ -42,8 +42,12 @@ class PropertyData: useEndFrame: bool -class CutsceneCmdImportCommands: - """This class contains functions to create the cutscene dataclasses""" +@dataclass +class CutsceneImport(CutsceneObjectFactory): + """This class contains functions to create the new cutscene Blender data""" + + filePath: str # used when importing from the panel + fileData: str # used when importing the cutscenes when importing a scene def getCmdParams(self, data: str, cmdName: str, paramNumber: int): """Returns the list of every parameter of the given command""" @@ -62,14 +66,6 @@ def getNewCutscene(self, csData: str, name: str): params = self.getCmdParams(csData, "CS_BEGIN_CUTSCENE", Cutscene.paramNumber) return Cutscene(name, getInteger(params[0]), getInteger(params[1])) - -@dataclass -class CutsceneCmdImport(CutsceneCmdImportCommands, CutsceneObjectFactory): - """This class contains functions to create the new cutscene Blender data""" - - filePath: str # used when importing from the panel - fileData: str # used when importing the cutscenes when importing a scene - def getParsedCutscenes(self): """Returns the parsed commands read from every cutscene we can find""" @@ -84,11 +80,11 @@ def getParsedCutscenes(self): raise PluginError("ERROR: File data can't be found!") # replace old names - oldNames = list(ootCSMotionLegacyToNewCmdNames.keys()) + oldNames = list(ootCSLegacyToNewCmdNames.keys()) fileData = fileData.replace("CS_CMD_CONTINUE", "CS_CAM_CONTINUE") fileData = fileData.replace("CS_CMD_STOP", "CS_CAM_STOP") for oldName in oldNames: - fileData = fileData.replace(f"{oldName}(", f"{ootCSMotionLegacyToNewCmdNames[oldName]}(") + fileData = fileData.replace(f"{oldName}(", f"{ootCSLegacyToNewCmdNames[oldName]}(") # parse cutscenes fileLines = fileData.split("\n") @@ -136,13 +132,13 @@ def getParsedCutscenes(self): # NOTE: ``CS_UNK_DATA()`` are commands that are completely useless, so we're ignoring those if csName is not None and not "CS_UNK_DATA" in curCmd: - if curCmd in ootCSMotionCSCommands: + if curCmd in ootCutsceneCommandsC: line = line.removesuffix(",") + "\n" - if curCmd in ootCSMotionSingleCommands and curCmd != "CS_END": + if curCmd in ootCSSingleCommands and curCmd != "CS_END": parsedData += line - if not cmdListFound and curCmd in ootCSMotionListCommands: + if not cmdListFound and curCmd in ootCSListCommands: cmdListFound = True parsedData = "" @@ -157,11 +153,11 @@ def getParsedCutscenes(self): if curCmdPrefix is not None: if curCmdPrefix in curCmd: parsedData += line - elif not cmdListFound and curCmd in ootCSMotionListEntryCommands: + elif not cmdListFound and curCmd in ootCSListEntryCommands: print(f"{csName}, command:\n{line}") raise PluginError(f"ERROR: Found a list entry outside a list inside ``{csName}``!") - if cmdListFound and nextCmd == "CS_END" or nextCmd in ootCSMotionListAndSingleCommands: + if cmdListFound and nextCmd == "CS_END" or nextCmd in ootCSListAndSingleCommands: cmdListFound = False parsedCS.append(parsedData) parsedData = "" diff --git a/fast64_internal/oot/cutscene/importer/functions.py b/fast64_internal/oot/cutscene/importer/functions.py index 40dfacf61..402176e5d 100644 --- a/fast64_internal/oot/cutscene/importer/functions.py +++ b/fast64_internal/oot/cutscene/importer/functions.py @@ -1,10 +1,10 @@ import bpy -from .classes import CutsceneCmdImport +from .classes import CutsceneImport def importCutsceneData(filePath: str, sceneData: str): """Initialises and imports the cutscene data from either a file or the scene data""" # NOTE: ``sceneData`` is the data read when importing a scene - csMotionImport = CutsceneCmdImport(filePath, sceneData) + csMotionImport = CutsceneImport(filePath, sceneData) return csMotionImport.setCutsceneData(bpy.context.scene.ootCSNumber) diff --git a/fast64_internal/oot/cutscene/motion/operators.py b/fast64_internal/oot/cutscene/motion/operators.py index 1791c890f..3b5386b71 100644 --- a/fast64_internal/oot/cutscene/motion/operators.py +++ b/fast64_internal/oot/cutscene/motion/operators.py @@ -5,7 +5,7 @@ from bpy.props import StringProperty, EnumProperty, BoolProperty from ....utility import PluginError from ...oot_constants import ootData -from ..io_classes import CutsceneObjectFactory +from ..classes import CutsceneObjectFactory from ..constants import ootEnumCSActorCueListCommandType from ..preview import initFirstFrame, setupCompositorNodes from .utility import ( diff --git a/fast64_internal/oot/cutscene/motion/utility.py b/fast64_internal/oot/cutscene/motion/utility.py index 187927063..b485890c8 100644 --- a/fast64_internal/oot/cutscene/motion/utility.py +++ b/fast64_internal/oot/cutscene/motion/utility.py @@ -57,7 +57,7 @@ def createNewBone(cameraShotObj: Object, name: str, headPos: list[float], tailPo def createNewCameraShot(csObj: Object): - from ..io_classes import CutsceneObjectFactory # circular import fix + from ..classes import CutsceneObjectFactory # circular import fix index, csPrefix = getNameInformations(csObj, "Camera Shot", None) @@ -180,7 +180,7 @@ def metersToBlend(context: Context, value: float): def setupActorCuePreview(csObj: Object, actorOrPlayer: str, selectObject: bool, cueList: Object): - from ..io_classes import CutsceneObjectFactory # circular import fix + from ..classes import CutsceneObjectFactory # circular import fix # check if the cue actually moves, if not it's not necessary to create a preview object isCueMoving = False @@ -258,7 +258,7 @@ def getCutsceneEndFrame(csObj: Object): def setupCutscene(csObj: Object): - from ..io_classes import CutsceneObjectFactory # circular import fix + from ..classes import CutsceneObjectFactory # circular import fix objFactory = CutsceneObjectFactory() context = bpy.context diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index ff3e6a615..667f06ec9 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -13,7 +13,7 @@ from ..scene.exporter.to_c import getCutsceneC from .constants import ootEnumCSTextboxType, ootEnumCSListType from .importer import importCutsceneData -from .exporter import getCutsceneMotionData +from .exporter import getNewCutsceneExport def checkGetFilePaths(context: Context): @@ -57,7 +57,7 @@ def insertCutsceneData(filePath: str, csName: str): fileLines = [] foundCutscene = False - motionExporter = getCutsceneMotionData(csName) + motionExporter = getNewCutsceneExport(csName) beginIndex = 0 for i, line in enumerate(fileLines): diff --git a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py index 2a49edd0b..8f0ab5c09 100644 --- a/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py +++ b/fast64_internal/oot/scene/exporter/to_c/scene_cutscene.py @@ -2,7 +2,7 @@ from .....utility import CData from ....oot_level_classes import OOTScene -from ....cutscene.exporter import getCutsceneMotionData +from ....cutscene.exporter import getNewCutsceneExport def getCutsceneC(csName: str): @@ -16,7 +16,7 @@ def getCutsceneC(csName: str): csData.source = ( declarationBase + " = {\n" - + getCutsceneMotionData(csName, bpy.context.scene.exportMotionOnly).getExportData() + + getNewCutsceneExport(csName, bpy.context.scene.exportMotionOnly).getExportData() + "};\n\n" ) From 4f01575f1cd9dcab23962728aa2e7af5d589b177 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 03:07:16 +0200 Subject: [PATCH 31/39] ui stuff --- fast64_internal/oot/__init__.py | 6 +- .../oot/cutscene/motion/properties.py | 9 +-- fast64_internal/oot/cutscene/panels.py | 60 +++++++++++++++- fast64_internal/oot/cutscene/properties.py | 69 ++++--------------- 4 files changed, 75 insertions(+), 69 deletions(-) diff --git a/fast64_internal/oot/__init__.py b/fast64_internal/oot/__init__.py index ecd7b5fa9..22a324464 100644 --- a/fast64_internal/oot/__init__.py +++ b/fast64_internal/oot/__init__.py @@ -82,18 +82,19 @@ class OOT_Properties(bpy.types.PropertyGroup): def oot_panel_register(): oot_operator_panel_register() + cutscene_panels_register() + scene_panels_register() f3d_panels_register() collision_panels_register() oot_obj_panel_register() - scene_panels_register() spline_panels_register() anim_panels_register() skeleton_panels_register() - cutscene_panels_register() def oot_panel_unregister(): oot_operator_panel_unregister() + cutscene_panels_unregister() collision_panels_unregister() oot_obj_panel_unregister() scene_panels_unregister() @@ -101,7 +102,6 @@ def oot_panel_unregister(): f3d_panels_unregister() anim_panels_unregister() skeleton_panels_unregister() - cutscene_panels_unregister() def oot_register(registerPanels): diff --git a/fast64_internal/oot/cutscene/motion/properties.py b/fast64_internal/oot/cutscene/motion/properties.py index f64be7081..c8c9c30b6 100644 --- a/fast64_internal/oot/cutscene/motion/properties.py +++ b/fast64_internal/oot/cutscene/motion/properties.py @@ -258,16 +258,9 @@ def csMotion_props_register(): Armature.ootCamShotProp = PointerProperty(type=CutsceneCmdCameraShotProperty) Bone.ootCamShotPointProp = PointerProperty(type=CutsceneCmdCameraShotPointProperty) EditBone.ootCamShotPointProp = PointerProperty(type=CutsceneCmdCameraShotPointProperty) - Scene.previewPlayerAge = EnumProperty( - items=[("link_adult", "Adult", "Adult Link (170 cm)", 0), ("link_child", "Child", "Child Link (130 cm)", 1)], - name="Player Age for Preview", - description="For setting Link's height for preview", - default="link_adult", - ) - + def csMotion_props_unregister(): - del Scene.previewPlayerAge del EditBone.ootCamShotPointProp del Bone.ootCamShotPointProp del Armature.ootCamShotProp diff --git a/fast64_internal/oot/cutscene/panels.py b/fast64_internal/oot/cutscene/panels.py index 4a0dddbd9..e1fee8aab 100644 --- a/fast64_internal/oot/cutscene/panels.py +++ b/fast64_internal/oot/cutscene/panels.py @@ -1,9 +1,25 @@ from bpy.utils import register_class, unregister_class -from bpy.types import Scene -from bpy.props import BoolProperty +from bpy.types import Scene, Context +from bpy.props import BoolProperty, EnumProperty from ...utility import prop_split from ...panels import OOT_Panel from .operators import OOT_ExportCutscene, OOT_ExportAllCutscenes, OOT_ImportCutscene +from .motion.preview import previewFrameHandler +from .motion.utility import getCutsceneCamera + + +class OoT_PreviewSettingsPanel(OOT_Panel): + bl_idname = "OOT_PT_preview_settings" + bl_label = "OOT CS Preview Settings" + + def draw(self, context): + previewBox = self.layout.box() + previewBox.box().label(text="Preview Settings") + split = previewBox.split(factor=0.5) + split.label(text="Player Age for Preview") + split.prop(context.scene, "previewPlayerAge", text="") + previewBox.prop(context.scene, "ootCsUseWidescreen") + previewBox.prop(context.scene, "ootCsUseOpaqueCamBg") class OOT_CutscenePanel(OOT_Panel): @@ -51,13 +67,33 @@ def draw(self, context): col.operator(OOT_ImportCutscene.bl_idname) -oot_cutscene_panel_classes = (OOT_CutscenePanel,) +oot_cutscene_panel_classes = (OoT_PreviewSettingsPanel, OOT_CutscenePanel,) + +def updateWidescreen(self, context: Context): + if context.scene.ootCsUseWidescreen: + context.scene.render.resolution_x = 426 + else: + context.scene.render.resolution_x = 320 + context.scene.render.resolution_y = 240 + + # force a refresh of the current frame + previewFrameHandler(context.scene) + + +def updateCamBackground(self, context: Context): + camObj = getCutsceneCamera(context.view_layer.objects.active) + if camObj is not None: + if context.scene.ootCsUseOpaqueCamBg: + camObj.data.passepartout_alpha = 1.0 + else: + camObj.data.passepartout_alpha = 0.95 def cutscene_panels_register(): Scene.useDecompFeatures = BoolProperty( name="Use Decomp for Export", description="Use names and macros from decomp when exporting", default=True ) + Scene.exportMotionOnly = BoolProperty( name="Export Motion Data Only", description=( @@ -66,11 +102,29 @@ def cutscene_panels_register(): ), ) + Scene.ootCsUseWidescreen = BoolProperty(name="Use Widescreen Camera", default=False, update=updateWidescreen) + Scene.ootCsUseOpaqueCamBg = BoolProperty( + name="Use Opaque Camera Background", + description="Can be used to simulate the letterbox with widescreen mode enabled", + default=False, + update=updateCamBackground, + ) + + Scene.previewPlayerAge = EnumProperty( + items=[("link_adult", "Adult", "Adult Link (170 cm)", 0), ("link_child", "Child", "Child Link (130 cm)", 1)], + name="Player Age for Preview", + description="For setting Link's height for preview", + default="link_adult", + ) + for cls in oot_cutscene_panel_classes: register_class(cls) def cutscene_panels_unregister(): + del Scene.previewPlayerAge + del Scene.ootCsUseOpaqueCamBg + del Scene.ootCsUseWidescreen del Scene.exportMotionOnly del Scene.useDecompFeatures diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index db30b5a7a..56057aa12 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -1,5 +1,4 @@ -import bpy -from bpy.types import PropertyGroup, Object, UILayout, Scene, Context +from bpy.types import PropertyGroup, Object, UILayout, Scene from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty, CollectionProperty, PointerProperty from bpy.utils import register_class, unregister_class from ...utility import PluginError, prop_split @@ -7,8 +6,6 @@ from ..oot_constants import ootData from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps, upgradeCutsceneProperty from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, OOTCSListAdd -from .motion.preview import previewFrameHandler -from .motion.utility import getCutsceneCamera from .motion.operators import ( CutsceneCmdPlayPreview, @@ -330,9 +327,6 @@ def upgrade_object(obj): upgradeCutsceneSubProps(csListSubProp) def draw_props(self, layout: UILayout, obj: Object): - split = layout.split(factor=0.5) - split.label(text="Player Age for Preview") - split.prop(bpy.context.scene, "previewPlayerAge", text="") split = layout.split(factor=0.5) split.operator(CutsceneCmdCreateCameraShot.bl_idname, icon="VIEW_CAMERA") @@ -342,17 +336,19 @@ def draw_props(self, layout: UILayout, obj: Object): split.operator(CutsceneCmdCreatePlayerCueList.bl_idname) split.operator(CutsceneCmdCreateActorCueList.bl_idname) - layout.prop(bpy.context.scene, "ootCsUseWidescreen") - layout.prop(bpy.context.scene, "ootCsUseOpaqueCamBg") + split = layout.split(factor=0.5) + split.label(text="Cutscene End Frame") + split.prop(self, "csEndFrame") - layout.prop(self, "csEndFrame") + commandsBox = layout.box() + commandsBox.box().label(text="Cutscene Commands") - csDestLayout = layout.box() - csDestLayout.prop(self, "csUseDestination") + b = commandsBox.box() + b.prop(self, "csUseDestination") if self.csUseDestination: - r = csDestLayout.row() + b.prop(self, "csDestinationStartFrame") - searchBox = r.box() + searchBox = b.box() boxRow = searchBox.row() searchOp = boxRow.operator(OOT_SearchCSDestinationEnumOperator.bl_idname, icon="VIEWZOOM", text="") searchOp.objName = obj.name @@ -360,14 +356,9 @@ def draw_props(self, layout: UILayout, obj: Object): if self.csDestination == "Custom": prop_split(searchBox.column(), self, "csDestinationCustom", "Cutscene Destination Custom") - r = csDestLayout.row() - r.prop(self, "csDestinationStartFrame") - - menuBox = layout.box() - menuBox.label(text="Cutscene Commands") - menuBox.column_flow(columns=3, align=True).prop(self, "menuTab", expand=True) - label = ootCSSubPropToName[self.menuTab] - op = menuBox.operator(OOTCSListAdd.bl_idname, text=label, icon=csListTypeToIcon[self.menuTab]) + commandsBox.column_flow(columns=3, align=True).prop(self, "menuTab", expand=True) + label = f"Add New {ootCSSubPropToName[self.menuTab]}" + op = commandsBox.operator(OOTCSListAdd.bl_idname, text=label, icon=csListTypeToIcon[self.menuTab]) op.collectionType = "Cutscene" op.listType = self.menuTab op.objName = obj.name @@ -375,7 +366,7 @@ def draw_props(self, layout: UILayout, obj: Object): for i, csListProp in enumerate(self.csLists): # ``csListProp`` type: OOTCSListProperty if csListProp.listType == self.menuTab: - csListProp.draw_props(menuBox, i, obj.name, "Cutscene") + csListProp.draw_props(commandsBox, i, obj.name, "Cutscene") classes = ( @@ -392,27 +383,6 @@ def draw_props(self, layout: UILayout, obj: Object): OOTCutsceneProperty, ) - -def updateWidescreen(self, context: Context): - if context.scene.ootCsUseWidescreen: - context.scene.render.resolution_x = 426 - else: - context.scene.render.resolution_x = 320 - context.scene.render.resolution_y = 240 - - # force a refresh of the current frame - previewFrameHandler(context.scene) - - -def updateCamBackground(self, context: Context): - camObj = getCutsceneCamera(context.view_layer.objects.active) - if camObj is not None: - if context.scene.ootCsUseOpaqueCamBg: - camObj.data.passepartout_alpha = 1.0 - else: - camObj.data.passepartout_alpha = 0.95 - - def cutscene_props_register(): for cls in classes: register_class(cls) @@ -421,19 +391,8 @@ def cutscene_props_register(): Scene.ootCSPreviewNodesReady = BoolProperty(default=False) Scene.ootCSPreviewCSObj = PointerProperty(type=Object) - Scene.ootCsUseWidescreen = BoolProperty(name="Use Widescreen Camera", default=False, update=updateWidescreen) - - Scene.ootCsUseOpaqueCamBg = BoolProperty( - name="Use Opaque Camera Background", - description="Can be used to simulate the letterbox with widescreen mode enabled", - default=False, - update=updateCamBackground, - ) - def cutscene_props_unregister(): - del Scene.ootCsUseOpaqueCamBg - del Scene.ootCsUseWidescreen del Scene.ootCSPreviewCSObj del Scene.ootCSPreviewNodesReady del Object.ootCutsceneProperty From f64578e51a0388bcb59ad39afaac7af216d363db Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 03:07:26 +0200 Subject: [PATCH 32/39] black --- fast64_internal/oot/cutscene/importer/classes.py | 4 +--- fast64_internal/oot/cutscene/motion/properties.py | 2 +- fast64_internal/oot/cutscene/panels.py | 6 +++++- fast64_internal/oot/cutscene/properties.py | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fast64_internal/oot/cutscene/importer/classes.py b/fast64_internal/oot/cutscene/importer/classes.py index fd2d1d4c5..066494895 100644 --- a/fast64_internal/oot/cutscene/importer/classes.py +++ b/fast64_internal/oot/cutscene/importer/classes.py @@ -413,9 +413,7 @@ def setSubPropertyData(self, subPropsData: dict[str, str], newSubElem, entry): else: setattr(newSubElem, key, getattr(entry, value)) - def setPropertyData( - self, csProp: "OOTCutsceneProperty", cutscene: Cutscene, propDataList: list[PropertyData] - ): + def setPropertyData(self, csProp: "OOTCutsceneProperty", cutscene: Cutscene, propDataList: list[PropertyData]): for data in propDataList: listName = f"{data.listType[0].lower() + data.listType[1:]}List" dataList = getattr(cutscene, (listName if data.listType != "FadeOutSeq" else "fadeSeqList")) diff --git a/fast64_internal/oot/cutscene/motion/properties.py b/fast64_internal/oot/cutscene/motion/properties.py index c8c9c30b6..d18a48282 100644 --- a/fast64_internal/oot/cutscene/motion/properties.py +++ b/fast64_internal/oot/cutscene/motion/properties.py @@ -258,7 +258,7 @@ def csMotion_props_register(): Armature.ootCamShotProp = PointerProperty(type=CutsceneCmdCameraShotProperty) Bone.ootCamShotPointProp = PointerProperty(type=CutsceneCmdCameraShotPointProperty) EditBone.ootCamShotPointProp = PointerProperty(type=CutsceneCmdCameraShotPointProperty) - + def csMotion_props_unregister(): del EditBone.ootCamShotPointProp diff --git a/fast64_internal/oot/cutscene/panels.py b/fast64_internal/oot/cutscene/panels.py index e1fee8aab..42338f398 100644 --- a/fast64_internal/oot/cutscene/panels.py +++ b/fast64_internal/oot/cutscene/panels.py @@ -67,7 +67,11 @@ def draw(self, context): col.operator(OOT_ImportCutscene.bl_idname) -oot_cutscene_panel_classes = (OoT_PreviewSettingsPanel, OOT_CutscenePanel,) +oot_cutscene_panel_classes = ( + OoT_PreviewSettingsPanel, + OOT_CutscenePanel, +) + def updateWidescreen(self, context: Context): if context.scene.ootCsUseWidescreen: diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 56057aa12..44ddf6f4c 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -327,7 +327,6 @@ def upgrade_object(obj): upgradeCutsceneSubProps(csListSubProp) def draw_props(self, layout: UILayout, obj: Object): - split = layout.split(factor=0.5) split.operator(CutsceneCmdCreateCameraShot.bl_idname, icon="VIEW_CAMERA") split.operator(CutsceneCmdPlayPreview.bl_idname, icon="RESTRICT_VIEW_OFF") @@ -383,6 +382,7 @@ def draw_props(self, layout: UILayout, obj: Object): OOTCutsceneProperty, ) + def cutscene_props_register(): for cls in classes: register_class(cls) From b2688b9f3e031e0dcc79ee740bb2bbf843001217 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 17:21:15 +0200 Subject: [PATCH 33/39] moved preview settings to a propertygroup --- .../oot/cutscene/motion/operators.py | 9 +-- .../oot/cutscene/motion/preview.py | 2 +- .../oot/cutscene/motion/utility.py | 4 +- fast64_internal/oot/cutscene/panels.py | 52 +------------- fast64_internal/oot/cutscene/preview.py | 21 +++--- fast64_internal/oot/cutscene/properties.py | 68 ++++++++++++++++--- 6 files changed, 81 insertions(+), 75 deletions(-) diff --git a/fast64_internal/oot/cutscene/motion/operators.py b/fast64_internal/oot/cutscene/motion/operators.py index 3b5386b71..ad9205a5f 100644 --- a/fast64_internal/oot/cutscene/motion/operators.py +++ b/fast64_internal/oot/cutscene/motion/operators.py @@ -69,8 +69,9 @@ def execute(self, context): if csObj is not None: # get and set the camera + previewSettings = context.scene.ootPreviewSettingsProperty cameraObj = getCutsceneCamera(csObj) - cameraObj.data.passepartout_alpha = 1.0 if context.scene.ootCsUseOpaqueCamBg else 0.95 + cameraObj.data.passepartout_alpha = 1.0 if previewSettings.useOpaqueCamBg else 0.95 # from https://blender.stackexchange.com/a/259103 space = None @@ -86,10 +87,10 @@ def execute(self, context): endFrame = getCutsceneEndFrame(csObj) context.scene.frame_end = endFrame if endFrame > -1 else context.scene.frame_end context.scene.frame_set(context.scene.frame_start) - bpy.context.scene.ootCSPreviewCSObj = csObj - bpy.context.scene.ootCSPreviewNodesReady = False + previewSettings.ootCSPreviewCSObj = csObj + previewSettings.ootCSPreviewNodesReady = False setupCompositorNodes() - initFirstFrame(csObj, bpy.context.scene.ootCSPreviewNodesReady, cameraObj) + initFirstFrame(csObj, previewSettings.ootCSPreviewNodesReady, cameraObj) bpy.ops.screen.animation_cancel() bpy.ops.screen.animation_play() return {"FINISHED"} diff --git a/fast64_internal/oot/cutscene/motion/preview.py b/fast64_internal/oot/cutscene/motion/preview.py index 57011b587..95d5818a8 100644 --- a/fast64_internal/oot/cutscene/motion/preview.py +++ b/fast64_internal/oot/cutscene/motion/preview.py @@ -185,7 +185,7 @@ def previewFrameHandler(scene: Scene): if obj.type == "CAMERA": pos, rot_quat, viewAngle = getCutsceneCamState(parentObj, scene.frame_current) - if scene.ootCsUseWidescreen: + if scene.ootPreviewSettingsProperty.useWidescreen: viewAngle *= 4 / 3 if pos is not None: diff --git a/fast64_internal/oot/cutscene/motion/utility.py b/fast64_internal/oot/cutscene/motion/utility.py index b485890c8..fa8b7c06d 100644 --- a/fast64_internal/oot/cutscene/motion/utility.py +++ b/fast64_internal/oot/cutscene/motion/utility.py @@ -209,7 +209,7 @@ def setupActorCuePreview(csObj: Object, actorOrPlayer: str, selectObject: bool, actorHeight = 1.5 if actorOrPlayer == "Player": - actorHeight = 1.7 if bpy.context.scene.previewPlayerAge == "link_adult" else 1.3 + actorHeight = 1.7 if bpy.context.scene.ootPreviewSettingsProperty.previewPlayerAge == "link_adult" else 1.3 previewObj.empty_display_type = "SINGLE_ARROW" previewObj.empty_display_size = metersToBlend(bpy.context, actorHeight) @@ -262,7 +262,7 @@ def setupCutscene(csObj: Object): objFactory = CutsceneObjectFactory() context = bpy.context - bpy.context.scene.ootCSPreviewCSObj = csObj + bpy.context.scene.ootPreviewSettingsProperty.ootCSPreviewCSObj = csObj camObj = objFactory.getNewCameraObject( f"{csObj.name}.Camera", metersToBlend(context, 0.25), diff --git a/fast64_internal/oot/cutscene/panels.py b/fast64_internal/oot/cutscene/panels.py index 42338f398..76685144a 100644 --- a/fast64_internal/oot/cutscene/panels.py +++ b/fast64_internal/oot/cutscene/panels.py @@ -1,11 +1,9 @@ from bpy.utils import register_class, unregister_class -from bpy.types import Scene, Context -from bpy.props import BoolProperty, EnumProperty +from bpy.types import Scene +from bpy.props import BoolProperty from ...utility import prop_split from ...panels import OOT_Panel from .operators import OOT_ExportCutscene, OOT_ExportAllCutscenes, OOT_ImportCutscene -from .motion.preview import previewFrameHandler -from .motion.utility import getCutsceneCamera class OoT_PreviewSettingsPanel(OOT_Panel): @@ -13,13 +11,7 @@ class OoT_PreviewSettingsPanel(OOT_Panel): bl_label = "OOT CS Preview Settings" def draw(self, context): - previewBox = self.layout.box() - previewBox.box().label(text="Preview Settings") - split = previewBox.split(factor=0.5) - split.label(text="Player Age for Preview") - split.prop(context.scene, "previewPlayerAge", text="") - previewBox.prop(context.scene, "ootCsUseWidescreen") - previewBox.prop(context.scene, "ootCsUseOpaqueCamBg") + context.scene.ootPreviewSettingsProperty.draw_props(self.layout) class OOT_CutscenePanel(OOT_Panel): @@ -73,26 +65,6 @@ def draw(self, context): ) -def updateWidescreen(self, context: Context): - if context.scene.ootCsUseWidescreen: - context.scene.render.resolution_x = 426 - else: - context.scene.render.resolution_x = 320 - context.scene.render.resolution_y = 240 - - # force a refresh of the current frame - previewFrameHandler(context.scene) - - -def updateCamBackground(self, context: Context): - camObj = getCutsceneCamera(context.view_layer.objects.active) - if camObj is not None: - if context.scene.ootCsUseOpaqueCamBg: - camObj.data.passepartout_alpha = 1.0 - else: - camObj.data.passepartout_alpha = 0.95 - - def cutscene_panels_register(): Scene.useDecompFeatures = BoolProperty( name="Use Decomp for Export", description="Use names and macros from decomp when exporting", default=True @@ -106,29 +78,11 @@ def cutscene_panels_register(): ), ) - Scene.ootCsUseWidescreen = BoolProperty(name="Use Widescreen Camera", default=False, update=updateWidescreen) - Scene.ootCsUseOpaqueCamBg = BoolProperty( - name="Use Opaque Camera Background", - description="Can be used to simulate the letterbox with widescreen mode enabled", - default=False, - update=updateCamBackground, - ) - - Scene.previewPlayerAge = EnumProperty( - items=[("link_adult", "Adult", "Adult Link (170 cm)", 0), ("link_child", "Child", "Child Link (130 cm)", 1)], - name="Player Age for Preview", - description="For setting Link's height for preview", - default="link_adult", - ) - for cls in oot_cutscene_panel_classes: register_class(cls) def cutscene_panels_unregister(): - del Scene.previewPlayerAge - del Scene.ootCsUseOpaqueCamBg - del Scene.ootCsUseWidescreen del Scene.exportMotionOnly del Scene.useDecompFeatures diff --git a/fast64_internal/oot/cutscene/preview.py b/fast64_internal/oot/cutscene/preview.py index 65af37c4c..9d3a28830 100644 --- a/fast64_internal/oot/cutscene/preview.py +++ b/fast64_internal/oot/cutscene/preview.py @@ -56,7 +56,7 @@ def setupCompositorNodes(): space.shading.use_compositor = "CAMERA" # if everything's fine and nodes are already ready to use stop there - if bpy.context.scene.ootCSPreviewNodesReady: + if bpy.context.scene.ootPreviewSettingsProperty.ootCSPreviewNodesReady: return # get the existing nodes @@ -94,7 +94,7 @@ def setupCompositorNodes(): # misc settings nodeMixRGBMisc.use_alpha = True nodeMixRGBMisc.blend_type = "COLOR" - bpy.context.scene.ootCSPreviewNodesReady = True + bpy.context.scene.ootPreviewSettingsProperty.ootCSPreviewNodesReady = True def initFirstFrame(csObj: Object, useNodeFeatures: bool, defaultCam: Object): @@ -219,7 +219,8 @@ def processCurrentFrame(csObj: Object, curFrame: float, useNodeFeatures: bool, c @persistent def cutscenePreviewFrameHandler(scene: Scene): """Preview frame handler, executes each frame when the cutscene is played""" - csObj: Object = bpy.context.scene.ootCSPreviewCSObj + previewSettings = scene.ootPreviewSettingsProperty + csObj: Object = previewSettings.ootCSPreviewCSObj if csObj is None or not csObj.type == "EMPTY" and not csObj.ootEmptyType == "Cutscene": return @@ -248,7 +249,7 @@ def cutscenePreviewFrameHandler(scene: Scene): cameraObjects[0] = foundObj # setup nodes - bpy.context.scene.ootCSPreviewNodesReady = False + previewSettings.ootCSPreviewNodesReady = False setupCompositorNodes() previewProp = csObj.ootCutsceneProperty.preview @@ -262,20 +263,20 @@ def cutscenePreviewFrameHandler(scene: Scene): newProp.endFrame = item.transitionEndFrame newProp.type = item.transitionType elif item.listType == "MiscList": - for normalMisc in item.miscList: + for miscEntry in item.miscList: newProp = previewProp.miscList.add() - newProp.startFrame = normalMisc.startFrame - newProp.endFrame = normalMisc.endFrame - newProp.type = normalMisc.csMiscType + newProp.startFrame = miscEntry.startFrame + newProp.endFrame = miscEntry.endFrame + newProp.type = miscEntry.csMiscType # execute the main preview logic curFrame = bpy.context.scene.frame_current if isclose(curFrame, previewProp.prevFrame, abs_tol=1) and isclose(curFrame, previewProp.nextFrame, abs_tol=1): - processCurrentFrame(csObj, curFrame, bpy.context.scene.ootCSPreviewNodesReady, cameraObjects) + processCurrentFrame(csObj, curFrame, previewSettings.ootCSPreviewNodesReady, cameraObjects) else: # Simulate cutscene for all frames up to present for i in range(bpy.context.scene.frame_current): - processCurrentFrame(csObj, i, bpy.context.scene.ootCSPreviewNodesReady, cameraObjects) + processCurrentFrame(csObj, i, previewSettings.ootCSPreviewNodesReady, cameraObjects) # since we reached the end of the function, the current frame becomes the previous one previewProp.nextFrame = curFrame + 2 if curFrame > previewProp.prevFrame else curFrame - 2 diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 44ddf6f4c..486e54d32 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -1,4 +1,4 @@ -from bpy.types import PropertyGroup, Object, UILayout, Scene +from bpy.types import PropertyGroup, Object, UILayout, Scene, Context from bpy.props import StringProperty, EnumProperty, IntProperty, BoolProperty, CollectionProperty, PointerProperty from bpy.utils import register_class, unregister_class from ...utility import PluginError, prop_split @@ -6,6 +6,8 @@ from ..oot_constants import ootData from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps, upgradeCutsceneProperty from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, OOTCSListAdd +from .motion.preview import previewFrameHandler +from .motion.utility import getCutsceneCamera from .motion.operators import ( CutsceneCmdPlayPreview, @@ -236,7 +238,7 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT else: raise PluginError("Internal error: invalid listType " + self.listType) - dat = getattr(self, attrName) + data = getattr(self, attrName) if self.listType == "TextList": subBox = box.box() @@ -258,18 +260,18 @@ def draw_props(self, layout: UILayout, listIndex: int, objName: str, collectionT addOp = box.operator( OOTCollectionAdd.bl_idname, text="Add item to " + getEnumName(ootEnumCSListType, self.listType) ) - addOp.option = len(dat) + addOp.option = len(data) addOp.collectionType = collectionType + "." + attrName addOp.subIndex = listIndex addOp.objName = objName - for i, p in enumerate(dat): + for i, p in enumerate(data): # ``p`` type: # OOTCSTextProperty | OOTCSLightSettingsProperty | OOTCSTimeProperty | # OOTCSSeqProperty | OOTCSMiscProperty | OOTCSRumbleProperty p.draw_props(box, self, listIndex, i, objName, collectionType, enumName.removesuffix(" List")) - if len(dat) == 0: + if len(data) == 0: box.label(text="No items in " + getEnumName(ootEnumCSListType, self.listType)) @@ -296,6 +298,55 @@ class OOTCutscenePreviewProperty(PropertyGroup): nextFrame: IntProperty(default=1) +class OOTCutscenePreviewSettingsProperty(PropertyGroup): + useWidescreen: BoolProperty( + name="Use Widescreen Camera", default=False, update=lambda self, context: self.updateWidescreen(context) + ) + + useOpaqueCamBg: BoolProperty( + name="Use Opaque Camera Background", + description="Can be used to simulate the letterbox with widescreen mode enabled", + default=False, + update=lambda self, context: self.updateCamBackground(context), + ) + + previewPlayerAge: EnumProperty( + items=[("link_adult", "Adult", "Adult Link (170 cm)", 0), ("link_child", "Child", "Child Link (130 cm)", 1)], + name="Player Age for Preview", + description="For setting Link's height for preview", + default="link_adult", + ) + + # internal only + ootCSPreviewNodesReady: BoolProperty(default=False) + ootCSPreviewCSObj: PointerProperty(type=Object) + + def updateWidescreen(self, context: Context): + if self.useWidescreen: + context.scene.render.resolution_x = 426 + else: + context.scene.render.resolution_x = 320 + context.scene.render.resolution_y = 240 + + # force a refresh of the current frame + previewFrameHandler(context.scene) + + def updateCamBackground(self, context: Context): + camObj = getCutsceneCamera(context.view_layer.objects.active) + if camObj is not None: + if self.useOpaqueCamBg: + camObj.data.passepartout_alpha = 1.0 + else: + camObj.data.passepartout_alpha = 0.95 + + def draw_props(self, layout: UILayout): + previewBox = layout.box() + previewBox.box().label(text="Preview Settings") + prop_split(previewBox, self, "previewPlayerAge", "Player Age for Preview") + previewBox.prop(self, "useWidescreen") + previewBox.prop(self, "useOpaqueCamBg") + + class OOTCutsceneProperty(PropertyGroup): csEndFrame: IntProperty(name="End Frame", min=0, default=100) csUseDestination: BoolProperty(name="Cutscene Destination (Scene Change)") @@ -379,6 +430,7 @@ def draw_props(self, layout: UILayout, obj: Object): OOTCutsceneTransitionProperty, OOTCutsceneMiscProperty, OOTCutscenePreviewProperty, + OOTCutscenePreviewSettingsProperty, OOTCutsceneProperty, ) @@ -388,13 +440,11 @@ def cutscene_props_register(): register_class(cls) Object.ootCutsceneProperty = PointerProperty(type=OOTCutsceneProperty) - Scene.ootCSPreviewNodesReady = BoolProperty(default=False) - Scene.ootCSPreviewCSObj = PointerProperty(type=Object) + Scene.ootPreviewSettingsProperty = PointerProperty(type=OOTCutscenePreviewSettingsProperty) def cutscene_props_unregister(): - del Scene.ootCSPreviewCSObj - del Scene.ootCSPreviewNodesReady + del Scene.ootPreviewSettingsProperty del Object.ootCutsceneProperty for cls in reversed(classes): From d74c46dd8813db028cdd4f81e2ca4786f1be2c62 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 17:48:57 +0200 Subject: [PATCH 34/39] cs seq search op --- fast64_internal/oot/cutscene/constants.py | 2 +- fast64_internal/oot/cutscene/operators.py | 26 ++++++++++++++++++++++ fast64_internal/oot/cutscene/properties.py | 7 +++++- fast64_internal/oot/scene/operators.py | 8 ++++--- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 35adb20b1..7e2243241 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -112,7 +112,7 @@ "StartSeqList": "Start Seq List", "MiscList": "Misc List", "LightSettingsList": "Light Settings List", - "StopSeqList": "Stop Seq Lis", + "StopSeqList": "Stop Seq List", "RumbleList": "Rumble List", } diff --git a/fast64_internal/oot/cutscene/operators.py b/fast64_internal/oot/cutscene/operators.py index 667f06ec9..9076b7413 100644 --- a/fast64_internal/oot/cutscene/operators.py +++ b/fast64_internal/oot/cutscene/operators.py @@ -252,6 +252,31 @@ def invoke(self, context, event): return {"RUNNING_MODAL"} +class OOT_SearchCSSeqOperator(Operator): + bl_idname = "object.oot_search_cs_seq_enum_operator" + bl_label = "Search Music Sequence" + bl_property = "seqId" + bl_options = {"REGISTER", "UNDO"} + + seqId: EnumProperty(items=ootData.enumData.ootEnumSeqId, default="general_sfx") + itemIndex: IntProperty() + listType: StringProperty() + + def execute(self, context): + csProp = context.view_layer.objects.active.ootCutsceneProperty + for elem in csProp.csLists: + if elem.listType == self.listType: + elem.seqList[self.itemIndex].csSeqID = self.seqId + break + context.region.tag_redraw() + self.report({"INFO"}, "Selected: " + self.seqId) + return {"FINISHED"} + + def invoke(self, context, event): + context.window_manager.invoke_search_popup(self) + return {"RUNNING_MODAL"} + + oot_cutscene_classes = ( OOTCSTextAdd, OOTCSListAdd, @@ -259,6 +284,7 @@ def invoke(self, context, event): OOT_ExportCutscene, OOT_ExportAllCutscenes, OOT_SearchCSDestinationEnumOperator, + OOT_SearchCSSeqOperator, ) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index 486e54d32..d4feeccfe 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -5,7 +5,7 @@ from ..oot_utility import OOTCollectionAdd, drawCollectionOps, getEnumName from ..oot_constants import ootData from ..oot_upgrade import upgradeCutsceneSubProps, upgradeCSListProps, upgradeCutsceneProperty -from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, OOTCSListAdd +from .operators import OOTCSTextAdd, OOT_SearchCSDestinationEnumOperator, OOTCSListAdd, OOT_SearchCSSeqOperator from .motion.preview import previewFrameHandler from .motion.utility import getCutsceneCamera @@ -76,6 +76,11 @@ def draw_props( prop_split(box, self, p, displayName) + if name == "csSeqID": + seqOp = box.operator(OOT_SearchCSSeqOperator.bl_idname) + seqOp.itemIndex = cmdIndex + seqOp.listType = listProp.listType + customValues = [ "csMiscType", "csTextType", diff --git a/fast64_internal/oot/scene/operators.py b/fast64_internal/oot/scene/operators.py index 5c478b580..2973f4e66 100644 --- a/fast64_internal/oot/scene/operators.py +++ b/fast64_internal/oot/scene/operators.py @@ -1,13 +1,15 @@ -import bpy, os +import bpy +import os + from bpy.path import abspath -from bpy.types import Operator, UILayout +from bpy.types import Operator from bpy.props import EnumProperty, IntProperty, StringProperty from bpy.utils import register_class, unregister_class from bpy.ops import object from mathutils import Matrix, Vector from ...f3d.f3d_gbi import DLFormat from ...utility import PluginError, raisePluginError, ootGetSceneOrRoomHeader -from ..oot_utility import ExportInfo, sceneNameFromID, getEnumName +from ..oot_utility import ExportInfo, sceneNameFromID from ..oot_level_writer import ootExportSceneToC from ..oot_constants import ootEnumMusicSeq, ootEnumSceneID from ..oot_level_parser import parseScene From acb4635a88ee5d76f79257376223764a15549408 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Sat, 21 Oct 2023 18:01:28 +0200 Subject: [PATCH 35/39] bugfix --- fast64_internal/oot/cutscene/properties.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fast64_internal/oot/cutscene/properties.py b/fast64_internal/oot/cutscene/properties.py index d4feeccfe..f2f6c3c58 100644 --- a/fast64_internal/oot/cutscene/properties.py +++ b/fast64_internal/oot/cutscene/properties.py @@ -92,7 +92,7 @@ def draw_props( if name in customValues and value == "Custom": prop_split(box, self, f"{name}Custom", f"{displayName} Custom") - if name == "csTextType" and value != "CS_TEXT_CHOICE": + if name == "csTextType" and value != "choice": break From 05408cdebcc1bf0eed2bc3b5b68749497a072883 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Tue, 26 Dec 2023 04:00:31 +0100 Subject: [PATCH 36/39] fix order of the cs commands --- fast64_internal/oot/cutscene/constants.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fast64_internal/oot/cutscene/constants.py b/fast64_internal/oot/cutscene/constants.py index 7e2243241..b3525246a 100644 --- a/fast64_internal/oot/cutscene/constants.py +++ b/fast64_internal/oot/cutscene/constants.py @@ -50,14 +50,14 @@ # order here sets order on the UI ootEnumCSListType = [ ("TextList", "Text List", "Textbox", "ALIGN_BOTTOM", 0), - ("TimeList", "Time List", "Time", "TIME", 3), - ("FadeOutSeqList", "Fade-Out Seq List", "Fade BGM", "IPO_EASE_IN_OUT", 6), - ("Transition", "Transition", "Transition", "COLORSET_10_VEC", 1), - ("StartSeqList", "Start Seq List", "Play BGM", "PLAY", 4), ("MiscList", "Misc List", "Misc", "OPTIONS", 7), + ("RumbleList", "Rumble List", "Rumble Controller", "OUTLINER_OB_FORCE_FIELD", 8), + ("Transition", "Transition", "Transition", "COLORSET_10_VEC", 1), ("LightSettingsList", "Light Settings List", "Lighting", "LIGHT_SUN", 2), + ("TimeList", "Time List", "Time", "TIME", 3), + ("StartSeqList", "Start Seq List", "Play BGM", "PLAY", 4), ("StopSeqList", "Stop Seq List", "Stop BGM", "SNAP_FACE", 5), - ("RumbleList", "Rumble List", "Rumble Controller", "OUTLINER_OB_FORCE_FIELD", 8), + ("FadeOutSeqList", "Fade-Out Seq List", "Fade BGM", "IPO_EASE_IN_OUT", 6), ] csListTypeToIcon = { From b1234f51e8c97f8519f3c1a69ab54216ff9acaa1 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:43:36 +0100 Subject: [PATCH 37/39] review & minor bugfix --- fast64_internal/oot/cutscene/classes.py | 87 +++++++++++++------------ 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/fast64_internal/oot/cutscene/classes.py b/fast64_internal/oot/cutscene/classes.py index f761b18c0..a47cac222 100644 --- a/fast64_internal/oot/cutscene/classes.py +++ b/fast64_internal/oot/cutscene/classes.py @@ -2,6 +2,7 @@ from dataclasses import dataclass, field from bpy.types import Object +from typing import Optional from ..oot_constants import ootData from .motion.utility import getBlenderPosition, getBlenderRotation, getRotation, getInteger @@ -16,8 +17,8 @@ class CutsceneCmdBase: params: list[str] - startFrame: int = None - endFrame: int = None + startFrame: Optional[int] = None + endFrame: Optional[int] = None def getEnumValue(self, enumKey: str, index: int, isSeqLegacy: bool = False): enum = ootData.enumData.enumByKey[enumKey] @@ -34,11 +35,11 @@ def getEnumValue(self, enumKey: str, index: int, isSeqLegacy: bool = False): class CutsceneCmdCamPoint(CutsceneCmdBase): """This class contains a single Camera Point command data""" - continueFlag: str = None - camRoll: int = None - frame: int = None - viewAngle: float = None - pos: list[int, int, int] = field(default_factory=list) + continueFlag: Optional[str] = None + camRoll: Optional[int] = None + frame: Optional[int] = None + viewAngle: Optional[float] = None + pos: tuple[int, int, int] = field(default_factory=tuple) paramNumber: int = 8 def __post_init__(self): @@ -54,10 +55,10 @@ def __post_init__(self): class CutsceneCmdActorCue(CutsceneCmdBase): """This class contains a single Actor Cue command data""" - actionID: int = None - rot: list[str, str, str] = field(default_factory=list) - startPos: list[int, int, int] = field(default_factory=list) - endPos: list[int, int, int] = field(default_factory=list) + actionID: Optional[int] = None + rot: tuple[str, str, str] = field(default_factory=tuple) + startPos: tuple[int, int, int] = field(default_factory=tuple) + endPos: tuple[int, int, int] = field(default_factory=tuple) paramNumber: int = 15 def __post_init__(self): @@ -75,8 +76,8 @@ class CutsceneCmdActorCueList(CutsceneCmdBase): """This class contains the Actor Cue List command data""" isPlayer: bool = False - commandType: str = None - entryTotal: int = None + commandType: Optional[str] = None + entryTotal: Optional[int] = None entries: list[CutsceneCmdActorCue] = field(default_factory=list) paramNumber: int = 2 listName: str = "actorCueList" @@ -92,6 +93,8 @@ def __post_init__(self): # make it a 4 digit hex self.commandType = self.commandType.removeprefix("0x") self.commandType = "0x" + "0" * (4 - len(self.commandType)) + self.commandType + else: + self.commandType = ootData.enumData.enumByKey["csCmd"].itemById[self.commandType].key self.entryTotal = getInteger(self.params[1].strip()) @@ -185,7 +188,7 @@ def __post_init__(self): class CutsceneCmdMisc(CutsceneCmdBase): """This class contains a single misc command entry""" - type: str = None # see ``CutsceneMiscType`` in decomp + type: Optional[str] = None # see ``CutsceneMiscType`` in decomp paramNumber: int = 14 def __post_init__(self): @@ -199,7 +202,7 @@ def __post_init__(self): class CutsceneCmdMiscList(CutsceneCmdBase): """This class contains Misc command data""" - entryTotal: int = None + entryTotal: Optional[int] = None entries: list[CutsceneCmdMisc] = field(default_factory=list) paramNumber: int = 1 listName: str = "miscList" @@ -213,7 +216,7 @@ def __post_init__(self): class CutsceneCmdTransition(CutsceneCmdBase): """This class contains Transition command data""" - type: str = None + type: Optional[str] = None paramNumber: int = 3 listName: str = "transitionList" @@ -228,10 +231,10 @@ def __post_init__(self): class CutsceneCmdText(CutsceneCmdBase): """This class contains Text command data""" - textId: int = None - type: str = None - altTextId1: int = None - altTextId2: int = None + textId: Optional[int] = None + type: Optional[str] = None + altTextId1: Optional[int] = None + altTextId2: Optional[int] = None paramNumber: int = 6 id: str = "Text" @@ -262,8 +265,8 @@ def __post_init__(self): class CutsceneCmdTextOcarinaAction(CutsceneCmdBase): """This class contains Text Ocarina Action command data""" - ocarinaActionId: str = None - messageId: int = None + ocarinaActionId: Optional[str] = None + messageId: Optional[int] = None paramNumber: int = 4 id: str = "OcarinaAction" @@ -279,7 +282,7 @@ def __post_init__(self): class CutsceneCmdTextList(CutsceneCmdBase): """This class contains Text List command data""" - entryTotal: int = None + entryTotal: Optional[int] = None entries: list[CutsceneCmdText | CutsceneCmdTextNone | CutsceneCmdTextOcarinaAction] = field(default_factory=list) paramNumber: int = 1 listName: str = "textList" @@ -293,8 +296,8 @@ def __post_init__(self): class CutsceneCmdLightSetting(CutsceneCmdBase): """This class contains Light Setting command data""" - isLegacy: bool = None - lightSetting: int = None + isLegacy: Optional[bool] = None + lightSetting: Optional[int] = None paramNumber: int = 11 def __post_init__(self): @@ -310,7 +313,7 @@ def __post_init__(self): class CutsceneCmdLightSettingList(CutsceneCmdBase): """This class contains Light Setting List command data""" - entryTotal: int = None + entryTotal: Optional[int] = None entries: list[CutsceneCmdLightSetting] = field(default_factory=list) paramNumber: int = 1 listName: str = "lightSettingsList" @@ -324,8 +327,8 @@ def __post_init__(self): class CutsceneCmdTime(CutsceneCmdBase): """This class contains Time Ocarina Action command data""" - hour: int = None - minute: int = None + hour: Optional[int] = None + minute: Optional[int] = None paramNumber: int = 5 def __post_init__(self): @@ -340,7 +343,7 @@ def __post_init__(self): class CutsceneCmdTimeList(CutsceneCmdBase): """This class contains Time List command data""" - entryTotal: int = None + entryTotal: Optional[int] = None entries: list[CutsceneCmdTime] = field(default_factory=list) paramNumber: int = 1 listName: str = "timeList" @@ -354,8 +357,8 @@ def __post_init__(self): class CutsceneCmdStartStopSeq(CutsceneCmdBase): """This class contains Start/Stop Seq command data""" - isLegacy: bool = None - seqId: str = None + isLegacy: Optional[bool] = None + seqId: Optional[str] = None paramNumber: int = 11 def __post_init__(self): @@ -369,8 +372,8 @@ def __post_init__(self): class CutsceneCmdStartStopSeqList(CutsceneCmdBase): """This class contains Start/Stop Seq List command data""" - entryTotal: int = None - type: str = None + entryTotal: Optional[int] = None + type: Optional[str] = None entries: list[CutsceneCmdStartStopSeq] = field(default_factory=list) paramNumber: int = 1 listName: str = "seqList" @@ -384,7 +387,7 @@ def __post_init__(self): class CutsceneCmdFadeSeq(CutsceneCmdBase): """This class contains Fade Seq command data""" - seqPlayer: str = None + seqPlayer: Optional[str] = None paramNumber: int = 11 enumKey: str = "csFadeOutSeqPlayer" @@ -399,7 +402,7 @@ def __post_init__(self): class CutsceneCmdFadeSeqList(CutsceneCmdBase): """This class contains Fade Seq List command data""" - entryTotal: int = None + entryTotal: Optional[int] = None entries: list[CutsceneCmdFadeSeq] = field(default_factory=list) paramNumber: int = 1 listName: str = "fadeSeqList" @@ -413,9 +416,9 @@ def __post_init__(self): class CutsceneCmdRumbleController(CutsceneCmdBase): """This class contains Rumble Controller command data""" - sourceStrength: int = None - duration: int = None - decreaseRate: int = None + sourceStrength: Optional[int] = None + duration: Optional[int] = None + decreaseRate: Optional[int] = None paramNumber: int = 8 def __post_init__(self): @@ -431,7 +434,7 @@ def __post_init__(self): class CutsceneCmdRumbleControllerList(CutsceneCmdBase): """This class contains Rumble Controller List command data""" - entryTotal: int = None + entryTotal: Optional[int] = None entries: list[CutsceneCmdRumbleController] = field(default_factory=list) paramNumber: int = 1 listName: str = "rumbleList" @@ -445,7 +448,7 @@ def __post_init__(self): class CutsceneCmdDestination(CutsceneCmdBase): """This class contains Destination command data""" - id: str = None + id: Optional[str] = None paramNumber: int = 3 listName: str = "destination" @@ -473,14 +476,14 @@ class Cutscene: camATSplineRelPlayerList: list[CutsceneCmdCamATSplineRelToPlayer] = field(default_factory=list) camEyeList: list[CutsceneCmdCamEye] = field(default_factory=list) camATList: list[CutsceneCmdCamAT] = field(default_factory=list) + textList: list[CutsceneCmdTextList] = field(default_factory=list) miscList: list[CutsceneCmdMiscList] = field(default_factory=list) + rumbleList: list[CutsceneCmdRumbleControllerList] = field(default_factory=list) transitionList: list[CutsceneCmdTransition] = field(default_factory=list) - textList: list[CutsceneCmdTextList] = field(default_factory=list) lightSettingsList: list[CutsceneCmdLightSettingList] = field(default_factory=list) timeList: list[CutsceneCmdTimeList] = field(default_factory=list) seqList: list[CutsceneCmdStartStopSeqList] = field(default_factory=list) fadeSeqList: list[CutsceneCmdFadeSeqList] = field(default_factory=list) - rumbleList: list[CutsceneCmdRumbleControllerList] = field(default_factory=list) class CutsceneObjectFactory: From 656625701b7ca55a26e80cd58653bcf0bc6e0202 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:43:58 +0100 Subject: [PATCH 38/39] black --- fast64_internal/oot/oot_level_writer.py | 4 +++- fast64_internal/oot/oot_utility.py | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index 65fcd594c..35da2d588 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -502,7 +502,9 @@ def ootConvertScene(originalSceneObj, transformMatrix, sceneName, DLFormat, conv if bpy.context.scene.exportHiddenGeometry: restoreHiddenState(hiddenState) - roomObjs = [child for child in sceneObj.children_recursive if child.type == "EMPTY" and child.ootEmptyType == "Room"] + roomObjs = [ + child for child in sceneObj.children_recursive if child.type == "EMPTY" and child.ootEmptyType == "Room" + ] if len(roomObjs) == 0: raise PluginError("The scene has no child empties with the 'Room' empty type.") diff --git a/fast64_internal/oot/oot_utility.py b/fast64_internal/oot/oot_utility.py index 2d22bf642..96c50f21b 100644 --- a/fast64_internal/oot/oot_utility.py +++ b/fast64_internal/oot/oot_utility.py @@ -333,9 +333,7 @@ def ootDuplicateHierarchy(obj, ignoreAttr, includeEmpties, objectCategorizer): def ootSelectMeshChildrenOnly(obj, includeEmpties): isMesh = obj.type == "MESH" - isEmpty = ( - obj.type == "EMPTY" or obj.type == "CAMERA" or obj.type == "CURVE" - ) and includeEmpties + isEmpty = (obj.type == "EMPTY" or obj.type == "CAMERA" or obj.type == "CURVE") and includeEmpties if isMesh or isEmpty: obj.select_set(True) obj.original_name = obj.name From e7feb881166e390b473c8fe99db7ea9d6f600684 Mon Sep 17 00:00:00 2001 From: Yanis42 <35189056+Yanis42@users.noreply.github.com> Date: Fri, 29 Dec 2023 20:15:08 +0100 Subject: [PATCH 39/39] tuple -> list --- fast64_internal/oot/cutscene/classes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fast64_internal/oot/cutscene/classes.py b/fast64_internal/oot/cutscene/classes.py index a47cac222..bdfc5ebb3 100644 --- a/fast64_internal/oot/cutscene/classes.py +++ b/fast64_internal/oot/cutscene/classes.py @@ -39,7 +39,7 @@ class CutsceneCmdCamPoint(CutsceneCmdBase): camRoll: Optional[int] = None frame: Optional[int] = None viewAngle: Optional[float] = None - pos: tuple[int, int, int] = field(default_factory=tuple) + pos: list[int] = field(default_factory=list) paramNumber: int = 8 def __post_init__(self): @@ -56,9 +56,9 @@ class CutsceneCmdActorCue(CutsceneCmdBase): """This class contains a single Actor Cue command data""" actionID: Optional[int] = None - rot: tuple[str, str, str] = field(default_factory=tuple) - startPos: tuple[int, int, int] = field(default_factory=tuple) - endPos: tuple[int, int, int] = field(default_factory=tuple) + rot: list[str] = field(default_factory=list) + startPos: list[int] = field(default_factory=list) + endPos: list[int] = field(default_factory=list) paramNumber: int = 15 def __post_init__(self):