From 6a9b07ecf4264727d99c7e04ea087d3072b7725f Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Fri, 4 Jul 2025 06:08:42 +1000 Subject: [PATCH 1/8] Change `tastudio.getmarker` to return `nil`, not `""`, on fail --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index be91c0e09fc..1136e4313e9 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -446,8 +446,8 @@ public void LoadBranch(int index) } [LuaMethodExample("local sttasget = tastudio.getmarker( 500 );")] - [LuaMethod("getmarker", "returns the marker text at the given frame, or an empty string if there is no marker for the given frame")] - public string GetMarker(int frame) + [LuaMethod("getmarker", "returns the marker text at the given frame, or nil if there is no marker for the given frame")] + public string/*?*/ GetMarker(int frame) { if (Engaged()) { @@ -458,7 +458,7 @@ public string GetMarker(int frame) } } - return ""; + return null; } [LuaMethodExample("tastudio.removemarker( 500 );")] From fff66c3720368333582d39462295cdd1345611cd Mon Sep 17 00:00:00 2001 From: c7fab <26490633+c7fab@users.noreply.github.com> Date: Wed, 12 Mar 2025 02:44:56 +0100 Subject: [PATCH 2/8] Initial implementation of new Lua functions for TAStudio markers --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index 1136e4313e9..853967118f0 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -461,6 +461,75 @@ public void LoadBranch(int index) return null; } + [LuaMethodExample("local markerframe = tastudio.getmarkerabove(100).Frame")] + [LuaMethod("getmarkerabove", "returns a table of the marker at or above the given frame with fields Frame and Text")] + public LuaTable GetMarkerAbove(int frame) + { + var table = _th.CreateTable(); + if (!Engaged()) return table; + + var marker = Tastudio.CurrentTasMovie.Markers.PreviousOrCurrent(frame); + table["Frame"] = marker.Frame; + table["Text"] = marker.Message; + + return table; + } + + [LuaMethodExample("local branchmarkertext = tastudio.getbranchmarkerabove(0, 100).Text")] + [LuaMethod("getbranchmarkerabove", "returns a table of the marker at or above the given frame for the given branch index, starting at 0, with fields Frame and Text")] + public LuaTable GetBranchMarkerAbove(int index, int frame) + { + var table = _th.CreateTable(); + if (!Engaged()) return table; + + if (index >= Tastudio.CurrentTasMovie.Branches.Count) return table; + + var branch = Tastudio.CurrentTasMovie.Branches[index]; + var marker = branch.Markers.PreviousOrCurrent(frame); + table["Frame"] = marker.Frame; + table["Text"] = marker.Message; + + return table; + } + + [LuaMethodExample("local markertext = tastudio.getmarkers()[0].Text")] + [LuaMethod("getmarkers", "returns a table of all markers with fields Frame and Text")] + public LuaTable GetMarkers() + { + if (!Engaged()) return _th.CreateTable(); + + return _th.EnumerateToLuaTable( + Tastudio.CurrentTasMovie.Markers.Select(m => + { + var table = _th.CreateTable(); + table["Frame"] = m.Frame; + table["Text"] = m.Message; + return table; + }), + indexFrom: 0); + } + + [LuaMethodExample("local branchmarkerframe = tastudio.getmarkers(0)[0].Frame")] + [LuaMethod("getbranchmarkers", "returns a table of all markers for the given branch index, starting at 0, with fields Frame and Text")] + public LuaTable GetBranchMarkers(int index) + { + if (!Engaged()) return _th.CreateTable(); + + if (index >= Tastudio.CurrentTasMovie.Branches.Count) return _th.CreateTable(); + + var branch = Tastudio.CurrentTasMovie.Branches[index]; + + return _th.EnumerateToLuaTable( + branch.Markers.Select(m => + { + var table = _th.CreateTable(); + table["Frame"] = m.Frame; + table["Text"] = m.Message; + return table; + }), + indexFrom: 0); + } + [LuaMethodExample("tastudio.removemarker( 500 );")] [LuaMethod("removemarker", "if there is a marker for the given frame, it will be removed")] public void RemoveMarker(int frame) From da1b08fac1c46609550398ce2b4815ddb7b84bb9 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sun, 23 Mar 2025 04:29:32 +1000 Subject: [PATCH 3/8] Code style fixes --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 71 +++++-------------- 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index 853967118f0..cec4e0c2923 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -461,74 +461,41 @@ public void LoadBranch(int index) return null; } - [LuaMethodExample("local markerframe = tastudio.getmarkerabove(100).Frame")] - [LuaMethod("getmarkerabove", "returns a table of the marker at or above the given frame with fields Frame and Text")] - public LuaTable GetMarkerAbove(int frame) + private LuaTable CreateMarkerTuple(TasMovieMarker marker) { var table = _th.CreateTable(); - if (!Engaged()) return table; - - var marker = Tastudio.CurrentTasMovie.Markers.PreviousOrCurrent(frame); table["Frame"] = marker.Frame; table["Text"] = marker.Message; - return table; } + [LuaMethodExample("local markerframe = tastudio.getmarkerabove(100).Frame")] + [LuaMethod("getmarkerabove", "returns a table of the marker at or above the given frame with fields Frame and Text")] + public LuaTable GetMarkerAbove(int frame) + => Engaged() + ? CreateMarkerTuple(Tastudio.CurrentTasMovie.Markers.PreviousOrCurrent(frame)) + : _th.CreateTable(); + [LuaMethodExample("local branchmarkertext = tastudio.getbranchmarkerabove(0, 100).Text")] [LuaMethod("getbranchmarkerabove", "returns a table of the marker at or above the given frame for the given branch index, starting at 0, with fields Frame and Text")] public LuaTable GetBranchMarkerAbove(int index, int frame) - { - var table = _th.CreateTable(); - if (!Engaged()) return table; - - if (index >= Tastudio.CurrentTasMovie.Branches.Count) return table; - - var branch = Tastudio.CurrentTasMovie.Branches[index]; - var marker = branch.Markers.PreviousOrCurrent(frame); - table["Frame"] = marker.Frame; - table["Text"] = marker.Message; - - return table; - } + => Engaged() + ? CreateMarkerTuple(Tastudio.CurrentTasMovie.Branches[index].Markers.PreviousOrCurrent(frame)) + : _th.CreateTable(); - [LuaMethodExample("local markertext = tastudio.getmarkers()[0].Text")] + [LuaMethodExample("local markertext = tastudio.getmarkers()[1].Text")] [LuaMethod("getmarkers", "returns a table of all markers with fields Frame and Text")] public LuaTable GetMarkers() - { - if (!Engaged()) return _th.CreateTable(); - - return _th.EnumerateToLuaTable( - Tastudio.CurrentTasMovie.Markers.Select(m => - { - var table = _th.CreateTable(); - table["Frame"] = m.Frame; - table["Text"] = m.Message; - return table; - }), - indexFrom: 0); - } + => Engaged() + ? _th.EnumerateToLuaTable(Tastudio.CurrentTasMovie.Markers.Select(CreateMarkerTuple)) + : _th.CreateTable(); - [LuaMethodExample("local branchmarkerframe = tastudio.getmarkers(0)[0].Frame")] + [LuaMethodExample("local branchmarkerframe = tastudio.getmarkers(0)[1].Frame")] [LuaMethod("getbranchmarkers", "returns a table of all markers for the given branch index, starting at 0, with fields Frame and Text")] public LuaTable GetBranchMarkers(int index) - { - if (!Engaged()) return _th.CreateTable(); - - if (index >= Tastudio.CurrentTasMovie.Branches.Count) return _th.CreateTable(); - - var branch = Tastudio.CurrentTasMovie.Branches[index]; - - return _th.EnumerateToLuaTable( - branch.Markers.Select(m => - { - var table = _th.CreateTable(); - table["Frame"] = m.Frame; - table["Text"] = m.Message; - return table; - }), - indexFrom: 0); - } + => Engaged() + ? _th.EnumerateToLuaTable(Tastudio.CurrentTasMovie.Branches[index].Markers.Select(CreateMarkerTuple)) + : _th.CreateTable(); [LuaMethodExample("tastudio.removemarker( 500 );")] [LuaMethod("removemarker", "if there is a marker for the given frame, it will be removed")] From ac5e389cc9f5a210286cac2dcb805e44c4dce476 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Wed, 28 May 2025 00:14:10 +1000 Subject: [PATCH 4/8] Return frame numbers, merge branch and non-, rename, and update docs Co-Authored-By: c7fab <26490633+c7fab@users.noreply.github.com> --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 59 +++++++++---------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index cec4e0c2923..89efb6e41df 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -461,40 +461,35 @@ public void LoadBranch(int index) return null; } - private LuaTable CreateMarkerTuple(TasMovieMarker marker) - { - var table = _th.CreateTable(); - table["Frame"] = marker.Frame; - table["Text"] = marker.Message; - return table; - } - - [LuaMethodExample("local markerframe = tastudio.getmarkerabove(100).Frame")] - [LuaMethod("getmarkerabove", "returns a table of the marker at or above the given frame with fields Frame and Text")] - public LuaTable GetMarkerAbove(int frame) + /// assumes a TAStudio project is loaded + private TasMovieMarkerList MarkerListForBranch(int? branchIndex) + => branchIndex is int i + ? Tastudio.CurrentTasMovie.Branches[i].Markers + : Tastudio.CurrentTasMovie.Markers; + + [LuaMethodExample(""" + local marker_label = tastudio.getmarker(tastudio.find_marker_on_or_before(100)); + """)] + [LuaMethod( + name: "find_marker_on_or_before", + description: "Returns the frame number of the marker closest to the given frame (including that frame, but not after it)." + + " This may be the power-on marker at 0. Returns nil if the arguments are invalid or TAStudio isn't active." + + " If branchIndex is specified, searches the markers in that branch instead.")] + public int? FindMarkerOnOrBefore(int frame, int? branchIndex = null) => Engaged() - ? CreateMarkerTuple(Tastudio.CurrentTasMovie.Markers.PreviousOrCurrent(frame)) - : _th.CreateTable(); - - [LuaMethodExample("local branchmarkertext = tastudio.getbranchmarkerabove(0, 100).Text")] - [LuaMethod("getbranchmarkerabove", "returns a table of the marker at or above the given frame for the given branch index, starting at 0, with fields Frame and Text")] - public LuaTable GetBranchMarkerAbove(int index, int frame) - => Engaged() - ? CreateMarkerTuple(Tastudio.CurrentTasMovie.Branches[index].Markers.PreviousOrCurrent(frame)) - : _th.CreateTable(); - - [LuaMethodExample("local markertext = tastudio.getmarkers()[1].Text")] - [LuaMethod("getmarkers", "returns a table of all markers with fields Frame and Text")] - public LuaTable GetMarkers() - => Engaged() - ? _th.EnumerateToLuaTable(Tastudio.CurrentTasMovie.Markers.Select(CreateMarkerTuple)) - : _th.CreateTable(); - - [LuaMethodExample("local branchmarkerframe = tastudio.getmarkers(0)[1].Frame")] - [LuaMethod("getbranchmarkers", "returns a table of all markers for the given branch index, starting at 0, with fields Frame and Text")] - public LuaTable GetBranchMarkers(int index) + ? MarkerListForBranch(branchIndex).PreviousOrCurrent(frame)?.Frame + : null; + + [LuaMethodExample(""" + local marker_label = tastudio.getmarker(tastudio.get_frames_with_markers()[2]); + """)] + [LuaMethod( + name: "get_frames_with_markers", + description: "Returns a list of all the frames which have markers on them." + + " If branchIndex is specified, instead returns the frames which have markers in that branch.")] + public LuaTable GetFramesWithMarkers(int? branchIndex = null) => Engaged() - ? _th.EnumerateToLuaTable(Tastudio.CurrentTasMovie.Branches[index].Markers.Select(CreateMarkerTuple)) + ? _th.EnumerateToLuaTable(MarkerListForBranch(branchIndex).Select(static m => m.Frame)) : _th.CreateTable(); [LuaMethodExample("tastudio.removemarker( 500 );")] From babc51f1f96754b5df0b31ee4cfc94adb00227ef Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sat, 12 Jul 2025 11:11:51 +1000 Subject: [PATCH 5/8] Avoid throwing when new functions called with nonexistent branch index --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index 89efb6e41df..80a6cbfc2a5 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -462,9 +462,9 @@ public void LoadBranch(int index) } /// assumes a TAStudio project is loaded - private TasMovieMarkerList MarkerListForBranch(int? branchIndex) + private TasMovieMarkerList/*?*/ MarkerListForBranch(int? branchIndex) => branchIndex is int i - ? Tastudio.CurrentTasMovie.Branches[i].Markers + ? Tastudio.CurrentTasMovie.Branches.ElementAtOrDefault(i)?.Markers : Tastudio.CurrentTasMovie.Markers; [LuaMethodExample(""" @@ -476,8 +476,8 @@ private TasMovieMarkerList MarkerListForBranch(int? branchIndex) + " This may be the power-on marker at 0. Returns nil if the arguments are invalid or TAStudio isn't active." + " If branchIndex is specified, searches the markers in that branch instead.")] public int? FindMarkerOnOrBefore(int frame, int? branchIndex = null) - => Engaged() - ? MarkerListForBranch(branchIndex).PreviousOrCurrent(frame)?.Frame + => Engaged() && MarkerListForBranch(branchIndex) is TasMovieMarkerList markers + ? markers.PreviousOrCurrent(frame)?.Frame : null; [LuaMethodExample(""" @@ -488,8 +488,8 @@ private TasMovieMarkerList MarkerListForBranch(int? branchIndex) description: "Returns a list of all the frames which have markers on them." + " If branchIndex is specified, instead returns the frames which have markers in that branch.")] public LuaTable GetFramesWithMarkers(int? branchIndex = null) - => Engaged() - ? _th.EnumerateToLuaTable(MarkerListForBranch(branchIndex).Select(static m => m.Frame)) + => Engaged() && MarkerListForBranch(branchIndex) is TasMovieMarkerList markers + ? _th.EnumerateToLuaTable(markers.Select(static m => m.Frame)) : _th.CreateTable(); [LuaMethodExample("tastudio.removemarker( 500 );")] From b914bd1a60164ccc4a161120029711cab71a5dcb Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sat, 12 Jul 2025 11:14:27 +1000 Subject: [PATCH 6/8] Use UUIDs instead of indices for branch params in new functions --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index 80a6cbfc2a5..c25ac4ffeba 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -462,10 +462,10 @@ public void LoadBranch(int index) } /// assumes a TAStudio project is loaded - private TasMovieMarkerList/*?*/ MarkerListForBranch(int? branchIndex) - => branchIndex is int i - ? Tastudio.CurrentTasMovie.Branches.ElementAtOrDefault(i)?.Markers - : Tastudio.CurrentTasMovie.Markers; + private TasMovieMarkerList/*?*/ MarkerListForBranch(string/*?*/ branchID) + => Guid.TryParseExact(branchID, format: "D", out var parsed) + ? Tastudio.CurrentTasMovie.Branches.FirstOrDefault(branch => branch.Uuid == parsed)?.Markers + : branchID is null ? Tastudio.CurrentTasMovie.Markers : null; // not a typo; null `branchID` indicates main log [LuaMethodExample(""" local marker_label = tastudio.getmarker(tastudio.find_marker_on_or_before(100)); @@ -474,9 +474,9 @@ public void LoadBranch(int index) name: "find_marker_on_or_before", description: "Returns the frame number of the marker closest to the given frame (including that frame, but not after it)." + " This may be the power-on marker at 0. Returns nil if the arguments are invalid or TAStudio isn't active." - + " If branchIndex is specified, searches the markers in that branch instead.")] - public int? FindMarkerOnOrBefore(int frame, int? branchIndex = null) - => Engaged() && MarkerListForBranch(branchIndex) is TasMovieMarkerList markers + + " If branchID is specified, searches the markers in that branch instead.")] + public int? FindMarkerOnOrBefore(int frame, string/*?*/ branchID = null) + => Engaged() && MarkerListForBranch(branchID) is TasMovieMarkerList markers ? markers.PreviousOrCurrent(frame)?.Frame : null; @@ -486,9 +486,9 @@ public void LoadBranch(int index) [LuaMethod( name: "get_frames_with_markers", description: "Returns a list of all the frames which have markers on them." - + " If branchIndex is specified, instead returns the frames which have markers in that branch.")] - public LuaTable GetFramesWithMarkers(int? branchIndex = null) - => Engaged() && MarkerListForBranch(branchIndex) is TasMovieMarkerList markers + + " If branchID is specified, instead returns the frames which have markers in that branch.")] + public LuaTable GetFramesWithMarkers(string/*?*/ branchID = null) + => Engaged() && MarkerListForBranch(branchID) is TasMovieMarkerList markers ? _th.EnumerateToLuaTable(markers.Select(static m => m.Frame)) : _th.CreateTable(); From a073e6b49864b1fbbdf5a2879ab0e21c300e0d84 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sat, 12 Jul 2025 11:17:16 +1000 Subject: [PATCH 7/8] Add `branchID` parameter to `tastudio.getmarker` and rewrite docs --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index c25ac4ffeba..1e938149bfd 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -446,12 +446,16 @@ public void LoadBranch(int index) } [LuaMethodExample("local sttasget = tastudio.getmarker( 500 );")] - [LuaMethod("getmarker", "returns the marker text at the given frame, or nil if there is no marker for the given frame")] - public string/*?*/ GetMarker(int frame) + [LuaMethod( + name: "getmarker", + description: "Returns the label of the marker on the given frame." + + " If that frame doesn't have a marker (or TAStudio isn't running), returns nil." + + " If branchID is specified, searches the markers in that branch instead.")] + public string/*?*/ GetMarker(int frame, string/*?*/ branchID = null) { if (Engaged()) { - var marker = Tastudio.CurrentTasMovie.Markers.Get(frame); + var marker = MarkerListForBranch(branchID)?.Get(frame); if (marker != null) { return marker.Message; From 00c2a7b016d7b0804ca16c66a59f9e07e60e5f64 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Fri, 4 Jul 2025 07:51:35 +1000 Subject: [PATCH 8/8] Add `tastudio.get_branch_index_by_id` --- .../tools/Lua/Libraries/TAStudioLuaLibrary.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs index 1e938149bfd..fadcaab4b82 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/TAStudioLuaLibrary.cs @@ -403,6 +403,19 @@ public LuaTable GetBranches() indexFrom: 0); } + [LuaMethodExample(""" + tastudio.setbranchtext("New label", tastudio.get_branch_index_by_id(branch_id)); + """)] + [LuaMethod( + name: "get_branch_index_by_id", + description: "Finds the branch with the given UUID (0-indexed). Returns -1 if not found.")] + public int GetBranchIndexByID(string id) + { + if (!Guid.TryParseExact(id, format: "D", out var parsed)) return -1; + return Tastudio.CurrentTasMovie.Branches.Index() + .FirstOrNull(tuple => tuple.Item.Uuid == parsed)?.Index ?? -1; + } + [LuaMethodExample("local nltasget = tastudio.getbranchinput( \"97021544-2454-4483-824f-47f75e7fcb6a\", 500 );")] [LuaMethod("getbranchinput", "Gets the controller state of the given frame with the given branch identifier")] public LuaTable GetBranchInput(string branchId, int frame)